Does Netty call System.exit?
Yesterday I struggled with a very frustrating issue. I was writing a NIO server using the excellent Netty framework and controlled it from jconsole using a custom MBean. To terminate the application I would call the MBean’s stop method and that would call the server’s stop method, which would shut everything down. No problems so far, but I needed to release several resources in a certain order and for some mysterious reason the JVM would terminate in the middle of the stop method, skipping several important steps!
I tracked the problem to Bootstrap.releaseExternalResources. A short time after that method was called the application would die. I moved the call around in the method and added sleep statements before and after and plenty of logging. Sure enough, whenever releaseExternalResources had been called the time was up.
Next I tried to find a call to System.exit in the Netty code. There was none. What could be causing this?
In hindsight it is obvious. The MBean server uses a daemon thread. When releaseExternalResources shuts down the Netty thread pools, the last non-daemon thread stops. At that point the JVM terminates.
I solved the problem by starting a new non-daemon thread from the MBean specifically for running the stop operation.
Unused namespaces begone!
We recently ran into a tricky problem with SOA Suite 11g: unused namespaces in XML files. Consider a simple input file like this one:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<a:A xmlns="http://www.example.org/A" xmlns:a="http://www.example.org/A"
xmlns:b="http://www.example.org/B">
<b:B xmlns="http://www.example.org/B">
<Name>Name 1</Name>
</b:B>
</a:A>
Now, we want to transform it into an output file that consists of the element B. The transformation is simple:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<xsl:stylesheet version="1.0" xmlns:a="http://www.example.org/A"
xmlns:b="http://www.example.org/B"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="a b">
<xsl:template match="b:B">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
Unfortunately the result is not so good:
<?xml version = '1.0' encoding = 'UTF-8'?>
<b:B xmlns="http://www.example.org/B" xmlns:b="http://www.example.org/B"
xmlns:a="http://www.example.org/A">
<Name>Name1</Name>
</b:B>
The resulting file refers to namespace A. This is allowed by the XSLT specification, but some XML engines fail to read the resulting file as they choke on the unknown namespace. What to do?
Fortunately SOA Suite 11g supports XSLT 2, at least partly. Change version to 2.0 and add copy-namespaces to the copy-of statement:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<xsl:stylesheet version="2.0"
xmlns:a="http://www.example.org/A"
xmlns:b="http://www.example.org/B"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="a b">
<xsl:template match="b:B">
<xsl:copy-of select="." copy-namespaces="no"/>
</xsl:template>
</xsl:stylesheet>
This produces the desired result. XSLT 2 has many other useful features, so it is well worth investigating even though it is not fully supported in SOA Suite yet.
Trust self-signed SSL certificates and skip host name verification with JAX-WS
Java takes security seriously, in spite of all the security holes that pop up every now and then. This is particularly true with SSL. Make a web service call with Java and the server certificate must be valid, trusted and for the right host. All very well, but it can be a pain in test and development, where few organizations buy real certificates. You can of course import the self-signed certificates or you can use global options, but both can be tricky in some environments and there are several drawbacks.
I prefer to disable the checks locally. This blog explains how to trust self-signed certs. In addition the host name verification must be disabled and both solutions must be integrated in the JAX-WS machinery.
After the lengthy introduction, here is some working code:
public class NaiveSSLHelper {
public static void makeWebServiceClientTrustEveryone(
Object webServicePort) {
if (webServicePort instanceof BindingProvider) {
BindingProvider bp = (BindingProvider) webServicePort;
Map requestContext = bp.getRequestContext();
requestContext.put(JAXWS_SSL_SOCKET_FACTORY,
getTrustingSSLSocketFactory());
requestContext.put(JAXWS_HOSTNAME_VERIFIER,
new NaiveHostnameVerifier());
} else {
throw new IllegalArgumentException(
"Web service port "
+ webServicePort.getClass().getName()
+ " does not implement "
+ BindingProvider.class.getName());
}
}
public static SSLSocketFactory getTrustingSSLSocketFactory() {
return SSLSocketFactoryHolder.INSTANCE;
}
private static SSLSocketFactory createSSLSocketFactory() {
TrustManager[] trustManagers = new TrustManager[] {
new NaiveTrustManager()
};
SSLContext sslContext;
try {
sslContext = SSLContext.getInstance("SSL");
sslContext.init(new KeyManager[0], trustManagers,
new SecureRandom());
return sslContext.getSocketFactory();
} catch (GeneralSecurityException e) {
return null;
}
}
private static interface SSLSocketFactoryHolder {
public static final SSLSocketFactory INSTANCE = createSSLSocketFactory();
}
private static class NaiveHostnameVerifier implements
HostnameVerifier {
@Override
public boolean verify(String hostName,
SSLSession session) {
return true;
}
}
private static class NaiveTrustManager implements
X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] certs,
String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] certs,
String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
private static final java.lang.String JAXWS_HOSTNAME_VERIFIER =
"com.sun.xml.internal.ws.transport.https.client.hostname.verifier";
private static final java.lang.String JAXWS_SSL_SOCKET_FACTORY =
"com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory";
}
The JAX-WS properties are defined by an internal Sun class, which may be missing (been there). Hard-coding the names may not work with another web service stack, but at least it won’t blow up. The worst that can happen is that the normal SSL verification remains in place.
Call makeWebServiceClientTrustEveryone with the web service port before making a call, and voila! The security checks are gone. Please note that this is a bad idea in production, as it opens up for man in the middle attacks. Use it where it makes sense!
Write XML files with specific encoding in SOA Suite
Outbound FTP adapters in Oracle SOA Suite normally use the default character encoding. Usually that means that all XML files are written in UTF-8. What do you do if you need to use something else, for example ISO-8859-1?
The logical solution would be to set an adapter property. In 11.1.1.6 there are three likely candidates: CharacterSet, Encoding and jca.message.encoding. Unfortunately none of them works. CharacterSet and Encoding only apply to attachments and are not even used by the adapter. The documentation states that they are meant for third-party applications that need to process the attachment. The jca.message.encoding is used, but only when the adapter reads files, not when it writes them.
What to do? The solution has been with us for a long time, the adapters in 10g worked in the same way. For native files the encoding can be specified in the schema with the nxsd:encoding attribute. It turns out that this works for normal XML files that have no need for native conversions too.
Simply add the following to the main XSD:
<xsd:schema
xmlns:nxsd="http://xmlns.oracle.com/pcbpel/nxsd"
nxsd:version="XSD" nxsd:encoding="ISO-8859-1"
...>
Problem solved, the adapter will use ISO-8859-1. A bit dirty (in particular when the schema is owned by someone else), but it works.
How to disable link detection for Windows 7
Modern network cards and operating systems usually support media sense or link detection, where the system detects if a network cable is plugged in or not. Often this is beneficial, but there are drawbacks as well. As a developer I’m often working with server software on my laptop and it can be tricky to get it working without a network.
Fortunately the feature can be disabled. For Windows 7, open a command prompt as an administrator and run:
netsh interface ipv4 set global dhcpmediasense=disabled
netsh interface ipv6 set global dhcpmediasense=disabled
Reboot. The network will still be shown as disconnected by ipconfig, but it will be possible to ping the address (if a static or alternate IP address is used) and run server software that depends on it.
To restore media sense, run:
netsh interface ipv4 set global dhcpmediasense=enabled
netsh interface ipv6 set global dhcpmediasense=enabled
Again a reboot is required.
Ignore Subversion files in Eclipse and ADT
Subversion creates .svn directories all over the place and by default Eclipse and ADT (Android Developer Tools, Eclipse-based) will copy them to target/classes and include them in output archives. I have tried to suppress that with project-specific exclude directives, but it is tricky to get it right and bothersome to repeat the process for every new project. A simple solution is to add “, .svn/” to Filtered resources (Windows/Preferences/Java/Compiler/Building, Output folder/Filtered resources) instead.
I found the tip in another blog some time ago, but it is gone.
Unexpected value from nativeGetEnabledTags
There is a bug in the Android SDK API 17 that floods LogCat with warning messages like:
Unexpected value from nativeGetEnabledTags: 0
This makes it hard to see real messages. The message does not appear with older API versions. Until the bug has been fixed the messages can be suppressed using this filter:
^(?!.*(nativeGetEnabledTags)).*$
