Knowledge base‎ > ‎

Spring + GWT: integration with ease

posted Apr 20, 2010, 5:00 AM by Szabolcs Szádeczky-Kardoss   [ updated Apr 22, 2010, 2:56 AM by István Soós ]
On the company website, we have indicated the intention to share some of our work as open source. This blog seems to be a good opportunity to start with that process, especially when the toolkit is as simple as our GWT integration solution with Spring framework. (Have you noticed that springframework.org is redirected to springsource.org? I wonder if the packages will be renamed too, just to break backwards compatibility - *evil*)

There was always a fuss about how GWT and Spring can be integrated. There are solutions who go with the hard way: defining the services as servlet paths with some hacking to access the application context, or following the Spring MVC, as separate controllers. A year ago, at the time when the Spring annotation support gained more awareness, there were only a few solution to use that with GWT. At that time, we have developed a GWT application that required a Spring integration, so we took the ideas from Chris Lee's blog, and extended it to our needs. Now, it is our time to share that with the open source community, hoping that we can say something new or at least less-known...

Chris and Martin (check the blogs comments) however started a much more interesting way, which was near perfect for us: define your service interface in GWT, implement it as a normal class on the server side, and let Spring do the magic with the binding and such. You need to have the following:
  • GwtServiceHandlerMapping - for mapping the service with a given servlet path
  • GwtServiceHandlerAdapter - for processing the request on that url and delegating the request to the invoked method
  • RpcProxyWrapper - that handles the client side magic
Above these, we had a requirement to pass a bunch of GWT serialized object to the HTML content (through Freemarker), so we have specified a GwtObjectSerializer interface, that can help us just to do that. And why would be this important? In case you are targetting search engines with you GWT-enabled application, it is definitely important to have some mixed content model with HTML content and GWT too. It is not hard at all, so we share that source here too. You can find these sources and compiled version as an attachment on this page (temporally, as we had no better idea where to place it).
Pretty simple, not too much documented, sometimes it feels like it hasn't been cleaned up (some System.out.println(s) are there for some lazy developer who checked back its debug codes) - which is true, as the project received a slightly different version of it. We might clean it up later...

Anyway, how can you use it?

Add the following lines in your servlet config xml:
<bean class="org.squaredframework.gwt.rpc.server.GwtServiceHandlerAdapter"/>
<bean class="org.squaredframework.gwt.rpc.server.GwtServiceHandlerMapping"/>
Suppose you have a Service interface:
public interface SimpleSearchService extends RemoteService {

public SearchResult search(String text);

/**
* Utility class for simplifying access to the instance of async service.
*/
public static class Util {
private static SimpleSearchServiceAsync instance;

public static SimpleSearchServiceAsync getInstance() {
if (instance == null) { // gwt client calls are single-threaded
instance = GWT.create(SimpleSearchService.class);
RpcProxyWrapper.get().wrapProxy(instance);
}
return instance;
}
}
}
With the async pair:
public interface SimpleSearchServiceAsync {
public void search(String text, AsyncCallback<SearchResult> callback);
}
Just implement the service (and observe that nothing special is added in the implementation):
@Controller
public class SimpleGwtSearchServiceImpl implements SimpleSearchService {
...
}
And that is it. On the client, you can use the following code to invoke the service:
SimpleSearchService.Util.getInstance().search(searchText,
new AsyncCallback&;t;SearchResult>() {
public void onFailure(Throwable caught) {
// display error message
}
public void onSuccess(SearchResult result) {
// display result
}
});
And we are done. Pretty simple, isn't it? Once the Spring magic is in place, both the service implementation and the client code cannot be more simple. (If it can, please let me know!) And what happens inside?

The services are mapped in a special way, which is automatically known to both the server and the client: with some prefix and postfix, we will just transform the my.server.Service to the /gwt-rpc/my/server/Service URL. Simple is that, details are in the RpcProxyWrapper and GwtServiceHandlerMapping classes. As a bonus, you are now refactoring-safe.

Oh, and those of you who are wondering what this squaredframework.org is: this is our registered domain that was thought to host our open source initiatives. We are not sure how we will proceed on that, but at least we name our shared classes in that way.

Update (on July 19): I've just recently encountered Dustin's project: spring4gwt. He had very similar ideas, it might be reasonable to merge these, so if he takes the initiative, expect some merges on his page...


published: 2009-07-13, a:István, y:2009, l:gwt, l:rpc, l:spring

ċ
squaredframework-gwt.jar
(18k)
István Soós,
Apr 22, 2010, 2:53 AM
Comments