Evolving Software

Last week I talked about The Anatomy of a GWT Project.  I thought it might be nice to delve into a little more detail about the practical application of  the components referenced.

Definition:

In object-oriented programming, the command pattern is a behavioral design pattern in which an object is used to represent and encapsulate all the information needed to call a method at a later time. This information includes the method name, the object that owns the method and values for the method parameters.  Four terms always associated with the command pattern are command, receiver, invoker and client. A concrete command object has a receiver object and invokes a method of the receiver in a way that is specific to that receiver’s class. The receiver then does the work. A concrete command object is separately passed to an invoker object, which invokes the command, and optionally does bookkeeping about the command execution. Any concrete command object can be passed to the same invoker object. Both an invoker object and several concrete command objects are held by a client object. The client contains the decision making about which commands to execute at which points. To execute a command, it passes the command object to the invoker object.

That is all fine and good but lets look at it in practical terms inside a GWT application.  I like to use the gwt-dispatch library.

Defining Actions

The first thing you need to think about is what are my actions.  In general actions are atomic, this will make it easiest to add a rollback function if you should choose to do so. Lets create a hypothetical action ‘AddUser.’

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class AddUserAction implements Action {
 
    private String username;
    private String password;
 
    /** For serialization only. */
    AddUserAction () {}
 
    public AddUserAction ( String username, String password ) {
        this.username= username;
        this.password= password;
    }
 
     [....]
}

Here we define the class that represents the action and implements Action<>. In the generic type for the interface we define the result we expect to receive from this action, in this case a UserResult. Then the class is a pretty boring bean, the only exception is to remember to include a no-arg constructor because the object will be serialized/deserialized automatically.

Defining Results

In the section above we said that invoking an AddUserAction would result in receiving a UserResult. So lets define one.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class UserResult implements Result {
    private int userid;
    private String username;
 
    /** For serialization only. */
    UserResult () {}
 
    public UserResult ( int userid, String username ) {
        this.userid= userid;
        this.username = username ;
    }
 
    [...]
}

Same as before we have constructed a pretty boring bean, just remember the no-arg constructor for serialization. Now you have fully defined the command.

Invoking Commands

Now that you have defined a command, let’s take a look at how to invoke one. The first step is getting a Dispatcher.

1
2
     private final DispatchAsync dispatchAsync = new StandardDispatchAsync(
                          new DefaultExceptionHandler());

The dispatcher is the class that takes actions and sends them to the server. Typically you can use it as a singleton on the client side. If you are using GIN, you can define it as an @Singleton and let it take care of the propagation of the dispatcher for you. Calling of the action is simple:

1
2
3
4
5
6
7
8
9
dispatchAsync.execute( new AddUserAction ( "user1", "password" ), new AsyncCallback() {
            public void onFailure( Throwable e ) {
                Window.alert( "Error: " + e.getMessage() );
            }
 
            public void onSuccess( UserResult result ) {
                Window.alert( "User Added: " + result.getUserId() );
            }
} );

And that is all that is required to invoke an action. The dispatcher automatically takes care of the serializing and processing the action as an asynchronous event. Simple.

Processing Commands

Adding a command processor is almost as easy, they are defined as implementing ActionHandler. Every ActionHandler is encapsulated in its own class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class AddUserActionHandler implements ActionHandler&lt;adduseraction, userresult=""&gt; {
 
    public Class getActionType() {
        return AddUserAction.class;
    }
 
    public synchronized UserResult execute( AddUserAction action, ExecutionContext context ) throws ActionException {
        [create user (action.getUsername(), ...)]
        return new UserResult( ... );
    }
 
    public synchronized void rollback( AddUserAction action, UserResult result, ExecutionContext context ) throws ActionException {
        // Undo the action.
        [delete user (result.getUserId())]
    }
}

The pseudo-code for actually doing work is abbreviated in [..], but as you can see the ActionHandler is written as a very simple class. Note also that the execute method is synchronous, this makes it easier to unit-test.

Binding Servlets

There is a small about of business in wiring the dispatch servlet into the runtime context, and there are several methods for doing it. Since Guice is listed in the things I can’t live without, I will show that version of it.

Step 1: Define the Servlet Endpoint
Define a ServletModule and bind it to the endpoint ‘/dispatch’

1
2
3
4
5
6
public class DispatchServletModule extends ServletModule {
    @Override
    protected void configureServlets() {    
        serve("/dispatch").with(GuiceStandardDispatchServlet.class);
    }
}

strong>Step 2: Define an Actions Module
Bind the Action to the ActionHandler.

1
2
3
4
5
6
public class ActionsModule extends ActionHandlerModule {
    @Override
    protected void configureHandlers() {
        bindHandler(AddUserAction.class, AddUserActionHandler.class);
    }
}

strong>Step 3: Install the Module
In the GuiceServletContextListener where Guice is initialized add the ActionModule to the list.

1
2
3
4
@Override
    protected Injector getInjector() {
        return Guice.createInjector(new ServerDispatchModule(), new ActionsModule(), new DispatchServletModule());
    }

Advanced Usage: Action Batching

Actions are great, they allow you to segment your applications into atomic actions. However sometimes it would be nice if you could execute multiple actions at once without having to nest the actions or wait for multiple round trips to finish. The gwt-dispatch library has a built-in batching function. In your ActionHandlerModule bind the following handler:

1
2
3
4
5
@Override
	protected void configureHandlers() {
		bindHandler(BatchAction.class, BatchActionHandler.class);
                [...]
        }

Now your application is ready to process BatchActions. A BatchAction takes in its constructor multiple actions, and the BatchResult returns a collection of results that correspond to the actions in the same order the were passed to the constructor.

Conclusions

Defining actions and Results is a simple way to encapsulate behavior and an easy way to extend the functionality of your website. I really like the fact that I didn’t have to define any handlers in the web.xml and the deployment is extremely easy and straightforward. Hopefully you can find several applied uses of the Command Pattern.

Categories: Software Engineering