| res ipsa loquitur

~ Latest Posts ~

Problem

There might be an instances where you want to connect to a WSO2 server (eg: WSO2 Identity Server) using an Axis2 client stub with an SSL connection. In that case you need to set a trust store for the client application to trust the server. Trusting the server or not is totally up to the client. And the default trust store of Java doesn’t have the self signed certificate of a default WSO2 server. Hence we usually use system properties to set the correct trust store.

There might be a requirement to totally ignore the certificate and trust whatever the server it connects to by ignoring the trust store. Most probably in a testing environment. Way to do this is some what different from a usual Java HTTP client when we use Axis2 client stub implementations.

Solution

In Axis2 there is a class for this specific purpose, to trust all the servers it connects to, TrustAllTrustManager. We can use that TrustManager to create an SSLContext which trust all the servers.

 SSLContext sslCtx = SSLContext.getInstance("http");
 sslCtx.init(null, new TrustManager[] {new TrustAllTrustManager()}, null);

Next we set SSLContext to axis2 stub implementation as follows.

stub._getServiceClient().getOptions().setProperty(
	HTTPConstants.CUSTOM_PROTOCOL_HANDLER,
	new Protocol("https", new SSLProtocolSocketFactory(sslCtx), 443)
	);

After that we can use this stub to communicate with the server without any failing SSL handshake issue.

Gotchas

Most common mistake we do when trying to ignore the trust store using Axis2 stubs is that we use something similar to following.

// SSLContext sslContext; created to trust all servers

// Then we set the context to HTTPSURLConnection
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

// Create all-trusting host name verifier
HostnameVerifier validateAllHosts = new HostnameVerifier() {

	public boolean verify(String hostname, SSLSession session) {
		return true;
	}
};

// Set the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(validateAllHosts);

Problem is underlying Axis2 client doesn’t use the HTTPSURLConnection hence this code has no effect to the underlying Axis2 client.

Extension points

There might be an instance where we need to add a given set of certificates to be trusted by our client application. We can use System properties to for that. Instead this can be also achieved by adding our own implementation of TrustManager as follows.


// Create the custom trust manager
TrustManager[] customTrustManager = new TrustManager[]{ new X509TrustManager() {

	public java.security.cert.X509Certificate[] getAcceptedIssuers() {
		X509Certificate[] trustedCerts;
		// Set trusted certificates. Or you might return an already
		// created array of trusted certificates
		return trustedCerts;
	}

	public void checkClientTrusted(X509Certificate[] certs, String authType) {
	}

	public void checkServerTrusted(X509Certificate[] certs, String authType) {
	}
}};

// Create the SSL context and set the custom trust manager  
sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, customTrustManager, new java.security.SecureRandom());

// Set the SSLContext to the stub as mention above

That’s all for this gotcha!

Written by Asitha Nanayakkara

This is my go at explaining subtle coding issues that I face in everyday programming and how to properly overcome them. Idea is to make you aware of the pitfalls in coding so that you’ll be able to understand and do a better job when you come across similar puzzling moments.

Problem

I’ll start my series of gotchas with a Java long type related gotcha. Here is the Java code segment.

long referenceStart = 41 * 365 * 24 * 60 * 60 * 1000; //this is 2011
System.out.println("value: " + val);

What would be the output of this code segment? Yes this is a huge value. If we calculate, we get the following answer.

Expected output: value: 1292976000000

Unfortunately what we get as the output is the following

Actual output: value 190843904

Puzzled ???

First thing that comes to our mind is numeric overflow. Is this value 1,292,976,000,000 too big for a long to handle? If we look at the maximum value of a long, it is 9,223,372,036,854,775,807 that is 263 -1.

The expected value is less than the maximum value a long can hold. Therefore this can’t be a numeric overflow. Then why is this giving an incorrect answer?

Gotcha!

If we look at the calculation of referenceStart closely, we can see that JVM needs to do five multiplications before it assigns the final value to referenceStart, which is a long. But since the multipliers and multiplicands are integers JVM will do an integer multiplication, even though we assign it to a long. Maximum value of int type is 2,147,483,647 that is 231-1, which is lot less than our expected answer. This causes a numeric overflow. the value is converted to a long only when it assigns the value to referenceStart. That’s why we get this incorrect answer.

Solution

Solution is to make JVM do a long multiplication instead of integer multiplication. How do we do that? Easy, we add an L after each value.

// Make the calculation long to avoid numeric overflow
long referenceStart = 41L * 365L * 24L * 60L * 60L * 1000L;
System.out.println("value: " + val);

Takeaways

I came across this while I was meddling with some old code. It was lying around for some time going through some release cycles as well. Luckily this didn’t lead to any unpleasant scenarios. All along the IDE was complaining about a numeric overflow. Finally this led us to take another look at the code.

Takeaways from this is always be vigilant about the type of multiplication the JVM might do and be aware of IDE/compiler warnings.

Written by Asitha Nanayakkara

This is a short film I was a part of back in the uni days. First year in my graduate studies to be exact, Nothing to do with computer science though. It was a new experience for us, for the whole crew. Obviously there were lot of mistakes and lot of things to learn. All in all it was an action pack month of video production for us.