Mikael Couzic is a Java Developer fascinated by OOD, best practices and agile methods. Mikael has posted 1 posts at DZone. View Full User Profile

GWT Architecture Best Practices : A Tutorial to RPC-Oriented Command Pattern

06.29.2010
| 35078 views |
  • submit to reddit

A few months ago I was struggling over some GWT RPCs, and at some point I felt something was wrong. I guess every developer sometimes gets this feeling of "there must be a better way to do this". My first reflex was to google "GWT RPC best practices", and I found exactly what I was looking for in a famous presentation given by Ray Ryan at Google I/O 2009 :

Google Web Tookit Architecture: Best Practices For Architecting Your GWT App

In this video, Ray Ryan explains how to use the command pattern for your RPC calls. I will not discuss the advantages of this practise, I'll leave that to him. Personnally, I was instantly convinced by the beauty of it, and after seeing this video I just couldn't make a single old-style RPC call without feeling dirty inside.

Instead of implementing the pattern myself, I used an existing implementation : gwt-dispatch. This article will guide you step by step in using this library and the associated best practices I knew. Also, I believe working code to be the best documentation, so I created the corresponding Google Code project : gwt-dispatch-example. You might want to clone the Mercurial repository, or you can download and import the project folder.

 

Overview

Here's a simple view of what is going on :

 GWT-Dispatch Simple View

Here, the client instantiates an Action and passes it to the server. The Action is mapped to its ActionHandler, which processes the request encapsulated in Action and creates a new Result. The Result is then passed back to the client.

As you can see, the Action class is a client-side representation of a server-side "Command".

All the RPC calls are made through a single, generic RemoteService. Let's see how it works :

 

The Action is passed to the DispatchAsync, which sends it via RPC to the DispatchService. The service delegates the execution to the corresponding ActionHandler, and sends back the created Result to be processed by the AsyncCallback. 

When using gwt-dispatch, you will create your own sets of Actions, ActionHandlers and Results. However, standard Dispatch implementations are provided for both client and server.

 

Creating the Action, Response and ActionHandler 

First, we'll need to create the Action and Response implementations in the shared package. We'll use a very simple Action class. The Action and Response interfaces extend java.io.Serializable, so implementations need to provide a default constructor.

@SuppressWarnings("serial")
public class MyAction implements Action<MyResult> {

private String message;

@Deprecated // for serialization only
public MyAction() {}

public MyAction(String message) {
this.message = message;
}

public String getMessage() {
return this.message;
}

}
@SuppressWarnings("serial")
public class MyResult implements Result {

private String message;

@Deprecated // for serialization only
public MyResult() {}

public MyResult(String message) {
this.message = message;
}

public String getMessage() {
return message;
}

}

Finally, the ActionHandler class, in the server package :

public class MyActionHandler implements ActionHandler<MyAction, MyResult> {

public MyResult execute(MyAction action, ExecutionContext context) throws ActionException {
return new MyResult("Got message: " + action.getMessage());
}

public Class<MyAction> getActionType() {
return MyAction.class;
}

public void rollback(MyAction action, MyResult result, ExecutionContext context) throws ActionException {
// implement this if you want to use this action in compound actions
}

}

The getActionType method is used to bind the ActionHandler to its Handler. Don't mind the ExecutionContext parameter and rollback method for now, just remember that eventually you'll need them when using CompoundActions.

 

Server-side Wiring

As you might have guessed, there is some plumbing to do. Fortunately, gwt-dispatcher was designed to inject most of it automatically using great tools.

Google Guice

I have dreamed about it, Google made it. A light-weight, type-safe, easy and fun to use Dependency Injection tool for Java. Just Perfect. Watch the video and see for yourself.

Guice works with "Module" classes, where you configure all your bindings. We are going to use a ServletModule to let Guice create our DispatchServiceServlet, which will receive the RPC calls and delegate the calls to the appropriate ActionHandlers. It is an alternative approach to mapping a servlet in the web.xml.

public class DispatchServletModule extends ServletModule {

@Override
public void configureServlets() {
serve("/gwt_dispatch_example/dispatch").with(DispatchServiceServlet.class);
}

}

 We'll also use an ActionHandlerModule, a specific module for binding ActionHandlers :

public class MyActionHandlerModule extends ActionHandlerModule {

protected void configureHandlers() {
bindHandler(MyActionHandler.class);
}

}

This declaration feels strange, you were probably waiting for something like :

bindHandler(MyAction.class, MyActionHandler.class);

But remember that we have defined the corresponding Action in MyActionHandler.getActionType().

Now, we have two modules to configure our Injector with. We use GuiceServletContextListener to make sure an injector is created when the application is deployed :

public class MyGuiceServletContextListener extends GuiceServletContextListener {

protected Injector getInjector() {
return Guice.createInjector(new MyActionHandlerModule(), new DispatchServletModule());
}

}

Finally, add this to your web.xml to register the GuiceServletContextListener :

<filter>
<filter-name>guiceFilter</filter-name>
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>guiceFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<listener>
<listener-class>fr.micouz.gwt.dispatch.server.guice.MyGuiceServletContextListener</listener-class>
</listener>

 

Client-side Wiring

Google Gin

Gin (GWT Injection) is built on top of Guice and handles injection for client-side GWT code. They share almost the same interface, and used together they bring a very nice consistency.

From here it is going to be very simple. We define a Ginjector interface and set the GinModule to a standard gwt-dispatch module :

@GinModules(ClientDispatchModule.class)
public interface MyGinjector extends Ginjector {

public DispatchAsync getDispatchAsync();

}

That's it, we can now inject a standard DispatchAsync everywere we need to.

MyGinjector injector = GWT.create(MyGinjector.class);
DispatchAsync dispatcher = injector.getDispatchAsync();

There's another optional practice Ray Ryan introduced : creating your own AsyncCallback. It is great for encapsulating error handling :

public abstract class GotMyResult implements AsyncCallback<MyResult> {

public void onFailure(Throwable caught) {
Window.alert( "Error: " + caught.getMessage() );
}

public void onSuccess(MyResult myResult) {
got(myResult);
}

public abstract void got(MyResult result);

}

The best part is this : how your client code will make RPC calls :

dispatcher.execute(new MyAction("message"), new GotMyResult() {
public void got(MyResult result) {
Window.alert( "Received Result: "result.getMessage() );
}
});

If you haven't checked the example project by now, now is the time.

One last thing, for your own projects don't forget to inherit the following dependencies :

    <inherits name="com.google.gwt.inject.Inject" />
    <inherits name='net.customware.gwt.dispatch.Dispatch' />

 

Published at DZone with permission of its author, Mikael Couzic.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)