My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
GettingStarted  
A short introduction to the GWT Dispatch API.
Featured
Updated Apr 26, 2011 by robert.munteanu

Introduction

This is a quick walkthrough of configuring the GWT Dispatch library and creating your own Action/Result/Handler. The code for this project is available at the gwt-dispatch-sample Github page.

Details

This example is going to create a simple counter on the server. For simplicity, it will store it in memory.

Firstly, we'll create an IncrementCounter action.

public class IncrementCounter implements Action<IncrementCounterResult> {
    private int amount;

    /** For serialization only. */
    IncrementCounter() {
    }

    public IncrementCounter( int amount ) {
        this.amount = amount;
    }

    public int getAmount() {
        return amount;
    }
}

Next, we define the IncrementCounterResult, which will also return the current counter value.

public class IncrementCounterResult implements Result {
    private int amount;
    private int current;

    /** For serialization only. */
    IncrementCounterResult() {
    }

    public IncrementCounterResult( int amount, int current ) {
        this.amount = amount;
        this.current = current;
    }

    public int getAmount() {
        return amount;
    }

    public int getCurrent() {
        return current;
    }
}

Lastly, we define our IncrementCounterHandler class, which does the actual incrementing.

public class IncrementCounterHandler implements ActionHandler<IncrementCounter, IncrementCounterResult> {

    private int current = 0;

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

    public synchronized IncrementCounterResult execute( IncrementCounter action, ExecutionContext context ) throws ActionException {
        current += action.getAmount();
        return new IncrementCounterResult( action.getAmount(), current );
    }

    public synchronized void rollback( IncrementCounter action, IncrementCounterResult result, ExecutionContext context ) throws ActionException {
        // Reset to the previous value.
        current = result.getCurrent() - result.getAmount();
    }
}

Now, we have to hook up our action handler to the Dispatch service on the server side.

Firstly, we create an implementation of the StandardDispatchService, which is GWT-dispatch's entry point for executing actions

public class SimpleDispatchServlet extends RemoteServiceServlet implements StandardDispatchService {

    private Dispatch dispatch;

    public SimpleDispatchServlet() {

        InstanceActionHandlerRegistry registry = new DefaultActionHandlerRegistry();
        registry.addHandler(new IncrementCounterHandler());
        dispatch = new SimpleDispatch(registry);
    }

    public Result execute(Action<?> action) throws DispatchException {

        try {
            return dispatch.execute(action);
        } catch ( RuntimeException e) {
            log( "Exception while executing " + action.getClass().getName() + ": " + e.getMessage(), e );
            throw e;
        }
    }

}

The SimpleDispatchService is in itself a GWT Remote Service, so it extends RemoteServiceServlet. It holds an ActionHandlerRegistry, which is used to route Actions to ActionHandlers. The execute implementation is trivial, since the Dispatch object does all of the hard work.

Now, on the client-side, we first need to import the library into our *.gwt.xml file. Just add this:

<inherits name='net.customware.gwt.dispatch.Dispatch' />

When you will first compile, the GWT compiler will output errors regarding com.google.gwt.inject and com.google.inject imports not being resolved. These can be safely ignored, as these classes are not referenced in our example.

Next, you need to initialise an instance of DispatchAsync on the client side. The simplest way of doing this is to create an instance of StandardDispatchAsync:

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

Now, from your GWT client side code, use the dispatchAsync instance to execution Actions and handle Results.

myButton.addClickHandler( new ClickHandler() {
    public void onClick( ClickEvent evt ) {
        dispatchAsync.execute( new IncrementCounter( 1 ), new AsyncCallback<IncrementCounterResult>() {
            public void onFailure( Throwable e ) {
                Window.alert( "Error: " + e.getMessage() );
            }

            public void onSuccess( IncrementCounterResult result ) {
                Window.alert( "Incremented by " + result.getAmount() + ", new total is " + result.getCurrent() );
            }

        } );
    }
});

Server-sided integration

GWT-dispatch features rich integration with both Guice and Spring on the server side. Please see the manual configuration, Guice or Spring sections for details.

Comment by alex.dob...@gmail.com, Jul 30, 2009

Hi, great job with this project!

I was looking for this pattern, I even started implementing one of my own.

Following this tutorial to the end, I've encountered a problem: ERROR? Type 'net.customware.gwt.dispatch.shared.Result' was not serializable and has no concrete serializable subtypes

Do you know how to fix? Thanks, Alex

Comment by jdpatterson, Aug 8, 2009

Hi, just wanted to point out that you cannot synchronize on a primitive in your IncrementCounterHandler? class

Comment by esnu...@gmail.com, Aug 17, 2009

there is no method named "bindHandler" in the source code of ServerDispatchModule?

Comment by ivo.redu...@gmail.com, Aug 21, 2009

After browsing the source code, I think the bindHandler is now in ActionHandlerModule?. The following snippet should work:

public class CounterModule? extends ActionHandlerModule? {

@Override public void configureHandlers() {
bindHandler( IncrementCounterHandler?.class );
}
}

http://code.google.com/p/gwt-dispatch/source/detail?r=31&path=/trunk/src/main/java/net/customware/gwt/dispatch/server/guice/ServerDispatchModule.java

Comment by Bitmei...@gmail.com, Aug 23, 2009

@alex - You shouldn't be returning 'Result' directly - you need a concrete implementation. What method/class is causing the error?

@jdpatterson - Good point (I should post examples I've actually tested...). I'll update the example.

@esnunes/ivo - You are correct - the module structure changed a bit (and will probably change again shortly - I've been doing some work on it the last couple of days). I've updated the example to reflect the class name change to ActionHandlerModule?.

Comment by yesud...@gmail.com, Aug 26, 2009

jar:file:/wherever/war/WEB-INF/lib/gwt-dispatch-1.0.0-SNAPSHOT.jar!/net/customware/gwt/dispatch/client/DefaultDispatchAsync?.java

Computing all possible rebind results for 'net.customware.gwt.dispatch.client.service.DispatchService?'
Rebinding net.customware.gwt.dispatch.client.service.DispatchService?
Invoking <generate-with class='com.google.gwt.user.rebind.rpc.ServiceInterfaceProxyGenerator'/>
Generating client proxy for remote service interface 'net.customware.gwt.dispatch.client.service.DispatchService?'
Analyzing 'net.customware.gwt.dispatch.client.service.DispatchService?' for serializable types
Analyzing methods:
public abstract net.customware.gwt.dispatch.shared.Result execute(net.customware.gwt.dispatch.shared.Action<?> action) throws java.lang.Exception
Return type: net.customware.gwt.dispatch.shared.Result
net.customware.gwt.dispatch.shared.Result
ERROR? Type 'net.customware.gwt.dispatch.shared.Result' was not serializable and has no concrete serializable subtypes
Parameter: net.customware.gwt.dispatch.shared.Action<?> action
net.customware.gwt.dispatch.shared.Action<?>
ERROR? Type 'net.customware.gwt.dispatch.shared.Action<?>' was not serializable and has no concrete serializable subtypes
ERROR? Errors in 'jar:file:/wherever/war/WEB-INF/lib/gwt-dispatch-1.0.0-SNAPSHOT.jar!/net/customware/gwt/dispatch/client/DefaultDispatchAsync?.java'
ERROR? Line 21: Failed to resolve 'net.customware.gwt.dispatch.client.service.DispatchService?' via deferred binding
ERROR? Cannot proceed due to previous errors

This is what I'm getting using the library. Can you help with this please?

Comment by Bitmei...@gmail.com, Aug 26, 2009

@yesudeep: I believe you will get this if you haven't defined any Action/Result sub-classes which are being used on the client side.

The gwt-dispatch group is probably the best place for posting questions since I don't read these pages as regularly.

Comment by post2edb...@gmail.com, Sep 1, 2009

I think you might want to take the IncrementCounterHandler? and IncrementCounter? together in one object to make it a richer object. The IncrementCounter? object in your case is called an Action object but is actually just a value object... I don't really understand the separation....

Comment by Bitmei...@gmail.com, Sep 1, 2009

@post2: Having them separate is essentially the point of the library. Keep in mind that the IncrementCounterHandler is a server-side-only class, while IncrementCounter is able to be created on the client-side also. In some ways, the 'Action' class is like an object container for method parameters, and the 'Result' contains the return value. They are both just data objects - they don't contain any actual functionality. And as far as the client-side is concerned, it has no idea how the command/action is executed. It just provides the parameters and processes the result.

The ActionHandler, on the other hand, is where the real action happens. It's essentially the functionality of the command. As such, it's on the server-side where it can access the database, authenticate, etc.

Hope that makes things a bit clearer.

Comment by pgtabo...@gmail.com, Sep 16, 2009

I prefer to use Spring in the backend. With only a few changes it is perfectly possible to use it with spring:

http://pgt.de/2009/09/16/use-spring-with-gwt-dispatch/

Comments are welcome!

Comment by yuqikang...@gmail.com, Dec 7, 2009

thanks.that is very useful!

Comment by phil.i...@gmail.com, Jan 6, 2010

I created a full test project configured with guice (not gin) here. it may help you all get through some of the gotchas in configuration.

http://github.com/pives/GWT-guice-commandpattern

Comment by irwan_1...@yahoo.com, Apr 7, 2010

I have created a demonstration project of gwt-presenter and gwt-dispatch based on Google's MVP tutorial codes. I hope it will complement the tutorial provided here. You can download the demo codes at the given link. It is a CRUD application with about 40 java files.

Demo codes: http://code.google.com/p/mvp-gwt-adaptation

Google's MVP tutorial codes: http://code.google.com/webtoolkit/doc/latest/tutorial/mvp-architecture.html"

Comment by gauravma...@gmail.com, Jun 28, 2010

Hello, It is mentioned here that in DispatchServletModule? file we need to give "/path/to/dispatch". What is this exactly, can you please explain!

Comment by arugnone...@gmail.com, Aug 3, 2010

Hello, in the new version 1.1.0, DispatchServiceServlet? disappears. What is object to be used instead?

Thank you very much for attention.

Comment by Bitmei...@gmail.com, Aug 3, 2010

Yeah, we need to update the documentation. DispatchServiceServlet? has been replaced with either the StandardDispatchServiceServlet? or the SecureDispatchServiceServlet?, depending on your needs.

Comment by Abhi.Pre...@gmail.com, Nov 11, 2010

Not able to find either of StandardDispatchServiceServlet? or SecureDispatchServiceServlet? in the latest jar. Which class I should use instead?

Comment by FabioDCo...@gmail.com, Dec 1, 2010

Can use net.customware.gwt.dispatch.server.guice.GuiceStandardDispatchServlet? por guice or other engine implemented in net.customware.gwt.dispatch.server.(engine)


Sign in to add a comment
Powered by Google Project Hosting