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.