Archive for March 27th, 2011

Share on TwitterDigg This

So you are starting a new web project. You’ve picked GWT as your framework. GWT is really great when it comes to the client part, the DOM manipulation and etc. But the server implementation is a strange beast. I say this because it abstracts the whole protocol interaction for you (which is good) but it does that in a proprietary way, using it’s own protocol called GWT-RPC.

I have never worried too much about that, my previous GWT projects were all done using GWT-RPC, and mostly because I could not find an easy way out. But we always bumped into the integration problem. Besides GWT no one understands it’s protocol. When using RESTful services in the other hand, you could expose your services to the whole world. So we ended up with this:

How I used to combine REST with GWT

Let’s start with a very simple service: An UserService. Everyone has one of this on it’s project right? Here’s a simple interface definition, with only a couple of methods:

public interface UserService {
	public List<User> list();
	public User getUser( Integer id);
}

Now we need to put this service as a GWT service. A good Framework for that is spring4gwt, I’ve worked with it before and really enjoyed, it makes simple to expose your service. You have to make your interface extend a RemoteInterface and that’s it :) Simple right? Let’s see how to expose our service as a GWT-RPC Service:

@RemoteServiceRelativePath("springGwtServices/userService")
public interface UserService extends RemoteService{
	public List<User> list();
	public User getUser( Integer id);
}
public class UserServiceImpl implemens UserService {...}

But wait a minute! What the hell is that RemoteService doing there? I’m really ok on adding annotations to my interfaces, that’s the beauty of annotations, you can add them, and if there’s nothing to process it, the behavior of your class is preserved (that was one of the foundations of EJB 3.0), but extending another interface? So it means now that your code is coupled to a certain technology. I DON’T LIKE IT AT ALL

So, to circumvent that, I did some hacking to keep my interfaces clean, and here’s the recipe for that:

1 – Keep your original interface



I’ve kept my interface original with no extensions:

public interface UserService {
	public List<User> list();
	public User getUser( Integer id);
}


2 – Create a new interface extending your interface and the RemoteService


@RemoteServiceRelativePath("springGwtServices/userServiceRPC")
public interface UserServiceRPC extends RemoteService, UserService{
}


3 – Make your implementation implement the original interface


public class UserServiceImpl implements UserService {...}


4 – Time for some hacking … ProxyFactoryBean FTW



The problem with that approach, is that although you keep your code clean and purebred, spring4gwt will no longer work, as it requires the bean to be exposed to implement the RemoteService, and our bean is a purebred race. So I used proxies for that:

<bean id="userService" class="com.furiousbob.gwt.server.user.services.UserServiceImpl"/> <!-- Our purebred service -->
<bean id="userServiceRPC" class="org.springframework.aop.framework.ProxyFactoryBean">
		<property name="proxyInterfaces" value="com.furiousbob.gwt.server.user.services.UserServiceRPC"></property>
		<property name="target" ref="userService"></property>
	</bean>



Problem solved. Spring4gwt will now look for a bean named userServiceRPC (as used on the @RemoteRelativePath) and find a proxy that delegates all the calls to the actual implementation. The proxy itself implements the RemoteService interface and hence it’s ok to be exposed. I was able to keep my code clean, but at a price, I had to create an extra interface and use proxies.

Don’t take me wrong, sometimes this will be the best approach. The one thing I learned over the years is that the world is not black nor white it’s grey. So be prepared to face some trade-offs as you go :)

In my case, I did all this only to expose the service as RPC and REST at the same time, and preserve my interfaces. All that could be avoided if we could use REST in a simple way …


How I combine REST and GWT today



Ok, that was how I used to get things running. So, what about now? Well, after a very inspiring reading at this blog. I decided to give a try on several rest+gwt frameworks out there. The motivation behind are pretty much the same exposed by the blog author:

  • I don’t want to use a proprietary protocol
  • I want to be able to test my services using tools like the amazing Poster
  • I want to be able to see what’s being sent over the wire with developer tools from chrome and firebug



So I knew I want to integrate GWT with REST, but there was just one single requirement for this:

IT HAS TO BE SIMPLE

And when I say simple, I mean, transparent to the development team. So we now have our expectations, let’s meet our choices:

  1. Restlet extensions for GWT
  2. Use jQuery
  3. Use of GWT RequestBuilder
  4. Use resty-gwt


Restlet extensions for GWT

This one was discarded because at the time I was developing the system, there was no support for GWT 2.2, and that was a main requirement for us, so although it seemed promising we dropped it because of the lack of support

Use jQuery

Another one that was dropped straight away, the blog that mentions it at the end recommends the use of RequestBuilder, so we did not even tried this one.

Use RequestBuilder

RequestBuilder seemed to be a good choice, but it adds a burden of marshaling and unmarshaling to the developer. Every call we had to serialize our objects to json and back on the responses. So we drop this one as it would increase development time.

Use resty-gwt

Ladies and Gentlemen, here’s the winner. This amazing library can be found here, really did the trick. Our main requirement was the integration to be simple right? So let me demonstrate how simple it is:

The exposed service

@Path("/services/users")
public interface UserService {
 
	@GET
	@Produces("application/json")
	@Path("/list")
	public List<User> list();
 
	@GET
	@Produces("application/json")
	@Path("{id}")
	public User getUser(@PathParam("id") Integer id);
}

And to consume this service all you have to do is create a client proxy for it. Please remember that on original GWT-RPC you will also need an Async version of your service, this is the exact mapping, so no extra class is being added here, just replaced:

public interface UserServiceRest extends RestService {
	@GET
	public void list(MethodCallback<List<User>> callback);
 
	@GET
	public void get(Integer id, MethodCallback<User> callback);
}

And to use it:

Resource resource = new Resource("/services/users/1");
final UserServiceRest service = GWT.create(UserServiceRest.class);
((RestServiceProxy)service).setResource(resource);

The beauty behind this library, is that it mimics the same programming style used by GWT. You have an asynch interface on the client side that will call the methods on the server. It is REALLY easy for GWT developers to understand, and comparing to the GWT RPC invocation, it takes only 2 extras lines of code (just the Resource declaration part).

Conclusions

RestyGWT was clearly the winner here! If you are considering starting a new GWT project, you should really consider having most of your services as RESTful only services, you will eventually need a RPC based service once in a while, but you should try to keep as most as you can a single protocol and interfaces on your application. The next thing I’m interested in is integrating the RESTful links and GWT Places and Activities.


Happy coding!