Saturday, April 17, 2010

Null Desperandum

A junior developer asked me this week when she should use Integer objects over int primitives. Many classes (eg, java.util.Calendar) use ints to represent quantities - eg, month, day of the month etc and this makes perfect sense since there is no point in time with a null month. But what about the other way around, she asked? When would you have to use Integers?

I was a bit stumped at first. Although it's intuitively obvious to me that there are such occasions, I couldn't think of an example off the top of my head. So, I just waffled about null having a semantic meaning in certain circumstances.

Later, I thought of this one: imagine an application for lawyers in which a class captures a defendant's answer. If it were modelled using an int, you might see something like this in the system:

Application: How many days has it been since you last beat your wife?

Defendant: I've never beaten my wife.

Application: OK, I'll just put you down as "0 days since you last beat your wife".

Null would have been a reasonable value here and hence I'd argue an Integer should be used. An int of -1 (ie, "-1 day(s) ago") favoured in some APIs could possibly be interpreted as "tomorrow".

Damn my slow, coffee-addled brain.

Calendar Grrrs!

Gainfully employed once more, my first task has been to diagnose why a trading application sometimes grinds to a halt. Avoiding all the speculation that generally surrounds non-deterministic exceptions and performance issues, I put together a JMeter suite and ran a soak test. After roughly 60 minutes of being stressed, the application starts to barf. Cool - it's reproducible. But the reason why it started choking surprised me.

The application does a lot of copying of object graphs using Serialization. Fine - JVMs are pretty good at memory management these days and creating objects, even large numbers of them, is normally OK. In fact, a Sun engineer once told me that you should only start worrying about Garbage Collection when it reaches a hefty 5% of running time. This trading application was spending about 1% of time collecting garbage despite JConsole showing that the Heap Memory was bouncing up and down like a yo-yo.

So, time to get more invasive and attach the amazing YourKit (sadly not open source but worth its weight in gold). It showed that when client connections were timing out, the server-side threads servicing them were contending for a monitor on java.util.Hashtable.get() (Hashtable unlike HashMap has its methods synchronized, of course).






Whatsmore, YourKit was telling me that it was java.util.Calendar.getInstance() that was calling this method on Hashtable. Firing up Eclipse and putting a breakpoint in java.util.Hashtable.get() showed exactly the path of execution that lead to this:

Thread [main] (Suspended (breakpoint at line 333 in Hashtable))
Hashtable.get(Object) line: 333
GregorianCalendar(Calendar).setWeekCountData(Locale) line: 2445
GregorianCalendar(Calendar).(TimeZone, Locale) line: 931
GregorianCalendar.(TimeZone, Locale) line: 574
Calendar.createCalendar(TimeZone, Locale) line: 1006
Calendar.getInstance() line: 943

Calendar.getInstance() creates a GregorianCalendar and the constructor of this accesses cachedLocaleData, a static field of type java.util.Hashtable. Since it's static, all threads in the JVM can contend for its monitor.

Ouch.

This monitor issue may seem trivial but if you're calling this method hundreds of times a second, it becomes an issue.

Of course, it would have been better had the business domain objects that were being copied via serialization not implemented java.io.Externalizable and had their readExternal and writeExternal methods call Calendar.getInstance(). This was due to a crufty hack to satisfy an architectural problem (Sybase 12.5 not handling time zones in its timestamp data type, but that's another story).

So, we're faced with a few possible solutions. One of which the team mentioned was to use Joda time which is (in one form or another) going to make its way into the standard Java API.

Of course, I'd like to see a more architectural solution - grumble, grumble.

Thursday, February 18, 2010

Hibernate and dates

I've come back to a Hibernate problem that I had in my last role which revolves around how java.util.Dates are handled. The problem is this: you populate your POJO with java.util.Dates and persist it. Magically, these objects are turned into java.sql.Timestamps.

Sun warns you about this in a rather odd statement in the Java API.

"[I]t is recommended that code not view Timestamp values generically as an instance of java.util.Date. The inheritance relationship between Timestamp and java.util.Date really denotes implementation inheritance, and not type inheritance."

Therefore:

aDate.equals(aTimestamp)


does not mean

aTimestamp.equals(aDate)


So, what? Gavin King says:

"Note that no self-respecting code should EVER call equals on a Timestamp."

But when you start putting objects into java.util.Collections, you no longer directly control if or when an equals method is called on your objects.

This lead me to post a bug report (and proposed fix) since what I saw in our project was that upon each transaction, either our POJO had all its Dates or non at all, alternating with each call. Clearly not good! The call was supposed to be idempotent.

Sadly, there has been no interest in my bug report. And although my fix works (albeit somewhat inefficiently), it would be nice to see Hibernate keep java.util.Dates as java.util.Dates.

Thursday, February 11, 2010

Continuing GWT/Spring integration

Ok, so the serialization of objects of my own classes wasn't perfect (the framework had problems with my own Exceptions). So, after some more tracing through the code, I found a hack to fix it.

The trouble is, this hack is becoming more obviously ugly (hey, I've only been playing with the GWT framework for a week). However, it does appear to work. So, for the sake of completeness, I'll put it here with the above caveat. Maybe I'll use Aspects to automatically populate my GWT server-side classes with Spring beans...

Here's the modified Spring controller class that delegates to the GWT server-side classes (taken from Richard Bondi's proposal):


public class GWTController
extends RemoteServiceServlet
implements Controller, ServletContextAware
{
// Instance fields
private MyRemoteServiceServlet remoteService;
private Class remoteServiceClass;
private ServletContext servletContext;
private Map servletToSerializationPolicy = new HashMap();


private GWTController() {
super();
}

// Public methods
/**
* Implements Spring Controller interface method.
*
* Call GWT's RemoteService doPost() method and return null.
*
* @param request current HTTP request
* @param response current HTTP response
* @return a ModelAndView to render, or null if handled directly
* @throws Exception in case of errors
*/
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response)
throws Exception
{
doPost(request, response);
return null; // response handled by GWT RPC over XmlHttpRequest
}

/**
* Process the RPC request encoded into the payload string and return a string
* that encodes either the method return or an exception thrown by it.
*/
public String processCall(String payload) throws SerializationException
{
try
{
SerializationPolicyProvider serializationPolicyProvider = new SerializationPolicyProvider() {

@Override
public SerializationPolicy getSerializationPolicy(
String moduleBaseURL,
String serializationPolicyStrongName) {
remoteService.setPerThreadRequest(perThreadRequest);
SerializationPolicy serializationPolicy = remoteService.getSerializationPolicy(moduleBaseURL, serializationPolicyStrongName);
servletToSerializationPolicy.put(remoteService, serializationPolicy);
return serializationPolicy;
}
};
RPCRequest rpcRequest =
RPC.decodeRequest(payload, this.remoteServiceClass, serializationPolicyProvider);

// delegate work to the spring injected service
return RPC.invokeAndEncodeResponse(this.remoteService,
rpcRequest.getMethod(),
rpcRequest.getParameters(),
servletToSerializationPolicy.get(remoteService));
}
catch (IncompatibleRemoteServiceException e)
{
return RPC.encodeResponseForFailure(null, e);
}
}


/**
* Setter for Spring injection of the GWT RemoteService object.
* @param RemoteService the GWT RemoteService implementation
* that will be delegated to by
* the {@code GWTController}.
*/
public void setRemoteService( MyRemoteServiceServlet remoteService )
{
this.remoteService = remoteService;
this.remoteServiceClass = this.remoteService.getClass();
}

@Override
public ServletContext getServletContext() {
return servletContext;
}

public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}

}


Hope this helps.

Tuesday, February 9, 2010

Google Web Kit, Spring and Serialization

I've just started playing with Google's Web Toolkit and I am impressed. Even a back-end programmer like me can write rich, AJAX front-ends!

However, integrating it with Spring is not trivial. There are many suggestions on how to do this. The simplest appeared to be Richard Bondi's suggestion that you can find here. It worked fine. Until, that is, I tried to send one of my own objects from client to server. I started seeing this:


Exception while dispatching incoming RPC call
com.google.gwt.user.client.rpc.SerializationException: Type 'xxx.xx.xxx.MyClass'
was not assignable to 'com.google.gwt.user.client.rpc.IsSerializable'
and did not have a custom field serializer.
For security purposes, this type will not be serialized.



And, after stepping through the code (thank you, Google, for providing the source code by default with my Eclipse plug-in!) I saw that it was using the LegacySerializationPolicy that dates back to GWT 1.3, apparently.

That's no good! So, why wasn't Richard's excellent fix fully functional?

After a late night hacking session, I got a rough solution. I modified Richard's GWTController.processCall's try block such that it read:

SerializationPolicyProvider serializationPolicyProvider = new SerializationPolicyProvider() {
@Override
public SerializationPolicy getSerializationPolicy(
String moduleBaseURL,
String serializationPolicyStrongName) {
remoteService.setPerThreadRequest(perThreadRequest);
return remoteService.getSerializationPolicy(moduleBaseURL, serializationPolicyStrongName);
}
};
RPCRequest rpcRequest =
RPC.decodeRequest(payload, this.remoteServiceClass, serializationPolicyProvider);


Where your remoteService now has to inherit from this ugly class:

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import org.springframework.web.context.ServletContextAware;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

public class MyRemoteServiceServlet extends RemoteServiceServlet implements ServletContextAware {

private ServletContext servletContext;

public void setPerThreadRequest(ThreadLocal perThreadRequest) {
this.perThreadRequest = perThreadRequest;
}

@Override
public ServletContext getServletContext() {
return servletContext;
}

public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}

}


OK, it's not pretty but it works. And you had to extend RemoteServiceServlet anyway.

There may be a more elegant way but I've only just woke up so I will continue improving it and post any further thoughts later.