axon_logo.pngI have blogged before about the flex client I have created for the Axon framework addressbook sample project. If you did not read it before and want to learn more about the parsley framework, check this blog.

http://www.gridshore.nl/2010/02/25/creating-a-sample-for-axon-using-flex-and-parsley/

In this blog item I am describing changes based on a new feature made available in Axon. Allard has created support for a CommandBus and command handlers. Basic idea is that you dispatch items on the bus, and a registeredhandler picks it up and handles it. This makes the command query separation also more clear on the flex side of the application.

What are the big changes in relation to the previous version of the sample? The biggest change is that we have one endpoint to receive all command objects. The impact of this change is separated into two parts, the flex part and the server side part.

Changes on the server side

Spring

Spring is used to configure the command bus and a special bean to find all command handlers based on annotations. The following code block shows the beans needed to configure the bus as well as the annoattion support

    <bean class="org.axonframework.commandhandling.annotation.AnnotationCommandHandlerBeanPostProcessor">
        <property name="commandBus" ref="commandBus"/>
    </bean>

    <bean id="commandBus" class="org.axonframework.commandhandling.SimpleCommandBus"/>

    <bean id="contactCommandHandler" class="org.axonframework.sample.app.command.ContactCommandHandler">
        <property name="repository" ref="contactRepository"/>
    </bean>

Now we have a command bus that is wired into the CommandReceiver. We also configured the ContactCommandHandler that contains annotated methods that are registered as command handlers. The bean with class AnnotationCommandHandlerBeanPostProcessor finds all these annotated methods, creates a wrapper around these methods and registered them as handlers in the command bus.

Command objects

To make good use of the command part of CQRS, communication of changes is done using command objects. The application now has the following command objects.

  • ChangeContactNameCommand
  • ContactCommandHandler
  • CreateContactCommand
  • RegisterAddressCommand
  • RemoveAddressCommand
  • RemoveContactCommand

As described in the Axon reference manual each command needs it’s own handler. The next section discusses the handlers.

Command handlers

Axon provides a mechanism with annotation so you can group multiple handlers in one class. I use the ContactCommandHandler class to hold all handlers. The following code block gives an example of one of these handlers

    @CommandHandler
    public UUID handle(CreateContactCommand command) {
        logger.debug("Received a command for a new contact with name : {}", command.getNewContactName());
        Assert.notNull(command.getNewContactName(), "Name may not be null");
        Contact contact = new Contact(command.getNewContactName());
        repository.save(contact);
        return contact.getIdentifier();
    }

That is it, the CommandHandler annotation and the argument of the method. In this example we have the handler for CreateContactCommand objects. The implementation is straightforward. Notice the return of the identifier of the contact.

The flex client

BlazeDS is used to transform data from actionscript objects into java objects. Therefore we need an counter object for all command objects that we created. Just add the bindable and remoteclass tags to the actionscript class. For completeness the following code block shows the action script command class.

[Bindable]
[RemoteClass(alias="org.axonframework.sample.app.command.CreateContactCommand")]
public class CreateContactCommand {
    public var newContactName:String;   
    public function CreateContactCommand() {
    }
}

Now we need to tell parsley about the new remote service that accepts the new command objects. This is configured in the ParsleyConfiguration.mxml file.

    <mx:RemoteObject
            id="remoteCommandReceiver"
            destination="commandReceiver"
            endpoint="messagebroker/amf"
            showBusyCursor="true"/>

In the NewContactController we actually use this remote service to send the

    public function execute(message:NewContactCommandMessage):AsyncToken {
        if (message.contact.name.length < 1) {
            dispatcher(new ValidationMessage("Name field is required for contact"));
            return null;
        }
        this.contact = message.contact;
        var addContactCommand:CreateContactCommand = new CreateContactCommand();
        addContactCommand.newContactName = message.contact.name;
        return commandReceiver.sendCommand(addContactCommand); 
    }

What I like about this solution is that we have a remote service for accepting all command objects and other remote services for doing the querying. He CQRS at the flex side. Using this technique makes it a lot easier to create a task based application with each task being represented by a command. Because the server understands these tasks the flex part is very connected with the server part.

Tagged on: