Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

A remote dynamic Command pattern with GWT and LinkSet

4.00/5 (1 vote)
19 Jan 2011LGPL32 min read 16.7K   214  
Command pattern is a very useful solution, but it causes some problems when used in a distributed environment.

Introduction

LinkSet as described in the previous article is a tiny library created in order to relieve programmers from declaring listener interfaces. It utilizes Java 5 features, and was designed to be a drop-in replacement for a conventional “listener interface + anonymous class” solution. Previously, it had an event bus support, and now it supports a remote dynamic Command pattern.

Introduction

Command pattern is a very useful solution, but it causes some problems when used in a distributed environment. When implemented in a classical way and performed over the wire, it causes almost all server code to reside on client side as well. It is unfavorable and often even impossible to implement when the client side uses a different technology than the server side (like JavaScript or Adobe Flex).

A solution

The most obvious way is to split the commands code from the execution code so that commands carry only a command name and data which can be easily transported over the wire. This solution raises, however, a different problem of easily dispatching commands on the server side. There is a solution to that, but type safety causes makes it too complicated. I found that dropping type safety makes it easier and simpler.

Using LinkSet as a dynamic command dispatcher with a GWT application

There are only two classes that make the magic happen. First is a CommandExecutor class that takes care of the binding commands to methods, and second is an Eexecutor annotation that is used for marking methods.

The class CommandExecutor has only one public constructor that takes a reference to an object containing methods that perform commands, and only one public method execute that causes real command execution to happen.

The code below is an axample of a GWT RPC service that uses the LinkSet Command pattern support.

A command interface

This interface is needed if you want your client side to be type safe.

Java
public interface Command<ReturnType extends Serializable> extends Serializable{
}

A service interface

Java
@RemoteServiceRelativePath("rpcservice")
public interface RPCService extends RemoteService {
    public <R extends Serializable> R execute(
      final Command<R> command) throws Throwable;
}

An asynchronous service interface

Java
public interface RPCServiceAsync {
    public <ReturnType extends Serializable> void execute(
            Command<ReturnType> command, AsyncCallback<ReturnType> callback);
}

A servlet class

This is the only place where LinkSet is actually used.

Java
public class RPCServiceServlet extends RemoteServiceServlet 
             implements RPCService {
        
    // Create an axecutor - the parameter is lamos always "this".
    private final CommandExecutor executor = new CommandExecutor(this); 
    
    @SuppressWarnings("unchecked")
    public <ReturnType extends Serializable> ReturnType execute(
            final Command<ReturnType> command) throws Throwable {

        // call executor and cast a return type.
        return (ReturnType) this.executor.execute(command);
    }
    // Boilerplate  code ends here - the rest is Your application's logic.
    
    // The method is annotated with it's parameter's class (a command's class).
    @Executor(cmdClass = InvalidateSession.class)
    public Null invalidateSession(final InvalidateSession cmd) {

        getThreadLocalRequest().getSession().invalidate();
            // LinkSet cannot exetuce void methods.
            // Use Null class or Object class as return type and return null.
        return null; 
    }

    @Executor(cmdClass = ListUsers.class)
    public ArrayList<User> listDomains(final ListUsers cmd) {

        final ArrayList<User> result = new ArrayList<User>();
        …
        return result;
    }
}

When a CommandExecutor object is created:

Java
CommandExecutor executor = new CommandExecutor(this);

it scans its parameter's class, looking for annotated methods:

Java
@Executor(cmdClass = ListUsers.class)
public ArrayList listDomains(final ListUsers cmd) {

and creates a mapping between a command's class and a method.

When the execute method is called:

Java
this.executor.execute(command);

it calls the appropriate method assigned to its parameter's type (via Reflection).

It is worth noting that LinkSet does not depend on any external library, and it does not enforce commands to subclass any particular class or implement any particular interface, so it is totally invisible to the client side of an application. It can be used not only with GWT, but also with Adobe Flex, EJB, RMI, and other frameworks.

Summary

LinkSet is a little experiment with a light, dynamic approach to Java. If you like it .. enjoy using it .. and report bugs at github.com/lbownik/linkset.

 

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)