Sunday, January 23, 2011

Distributed Command Pattern

So in my Test Infected Spring-based Web Service sample code project, I produced a convenient little framework for creating what I term "distributed command" objects.  At least *I* think it's useful.  I hesitate to call it a framework though, because it is extremely rudimentary.

Using the framework, a client program creates a command object, sets any data that needs to be set on it and then invokes its "execute()" method.  Classic GoF command design pattern.  The difference is in how the execute() method is implemented.  The implementation of the execute() method does not contain business logic; instead it invokes a "client command delegate" collaborator object.  This delegate object is responsibile for serializing the state of the command object and sending it to some endpoint location.  At the endpoint the command object will be reconstituted into a command object and its execute() method will be invoked.  Only this time the implementation of the execute() method really does contain the business logic.  This works because the consuming application actually has a "client command" object and the endpoint application de-serializes it into a "server command" object.  Both the client and server command classes extend from a common interface (i.e. they are compatible with each other from a type perspective).

The client application will interact with the command object via its interface, however it's implementation will be that of a "client command" object; one whose execute() implementation is to invoke a delegate.  When the endpoint receives the serialized command and is reconstituted, the endpoint (like the client application does) will interact with the command object via its interface, however its implementation will be that of a "server command" object; one whose execute() implementation contains the actual business logic.

Here's what the framework provides:
  • A generic command interface from which new commands can extend; classes implementing the extended interface would implement its business logic within the execute() method
  • A client command interface from which a client command class should implement; the implementation of the execute() method should be to invoke a delegate
  • 2 client delegate implementations (a delegate is what the client command's execute() method invokes): a local one in which the client and server command instances run within the same JVM, and one in which the command is serialized into a SOAP message and some web service endpoint is invoked.
  • An Spring-based SOAP marshaling endpoint class that can received XML serialized command instances, un-marshal them into corresponding command instances, execute them and return the results in a SOAP response.
If you don't require a distributed architecture for your application, you can still use this framework using local delegates with your client command objects.  The beauty of this is that at a later date, should you decide that you want the commands to execute in a distributed manner, you can do this without having to modify the client application code.  Just don't forget of course the performance implications - and how they might impact the design of your application.

The code for this framework is hosted on Google here
      The following diagrams attempt to clarify the structural and behavioral aspects of this little framework (these diagrams were created in Visio using Pavel Hruby's excellent UML stencils).

      Class Diagrams:



       Sequence Diagram (client using local delegate):

       Sequence Diagram (client using SOAP web service delegate):

       Deployment Diagram (local delegate):

       Deployment Diagram (SOAP web service delegate):