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.

No comments:

Post a Comment