Tessell

Dispatch

The dispatch pattern is alternative to the usual GWT-RPC implementation where every remote service is a new servlet. You can learn more about it:

Tessell’s implementation of the dispatch pattern is not terribly unique, other than providing:

Overview

In short, instead of having an FooService/FooServiceAsync for every remote service your application calls:

You use the command pattern to make FooAction/FooResult DTOs that are submitted via a single DispatchService and then “dispatched” appropriately to the right command handler on the server-side:

While this seems more complex, the advantage is that making new FooAction/FooHandler classes should be easier than making new Foo/FooAsync classes.

Also, since the command pattern is used, your client-side application can pass the commands around to do interesting things (batching, caching, etc.).

Less Boilerplate

What Tessell adds to the dispatch pattern is a large reduction in the boilerplate for making new actions.

Where as traditionally every new action (distinct AJAX call) requires you need to hand-code a FooAction (with fields, getters, setters, equals, hashCode) and FooResult (also with fields, getters, setters, equals, and hashCode), with Tessell, you just specify a “spec” (specification):

@GenDispatch
public class FooSpec {
  @In(1)
  String inputParam1;
  @In(2)
  String inputParam2;

  @Out(1)
  String outputParam1;
  @Out(2)
  String outputParam2;
}

And tessell-apt will generate FooAction and FooResult DTOs with all of the necessary boilerplate for you.

Success Callback

Every AJAX call may fail, but it’s not a good idea to reimplement failure logic at each AJAX call site in your application. To help facilitate this, Tessell adds a SuccessCallback interface:

public interface SuccessCallback<T> {
  void onSuccess(T result);
}

Which is just like AsyncCallback without the onFailure method. So, instead of reimplementing AsyncCallback.onFailure each time you make an AJAX call, Tessell’s OutstandingDispatchAysnc accepts SuccessCallbacks and will provide a single onFailure implementation.

The default onFailure implementation fires a DispatchUnhandledFailureEvent on the applications EventBus, so anyone that is interested (e.g. an error popup listener) can listener for the failure and respond appropriately.

(Note that another common way of achieving this is to have an application-specific subclass of AsyncCallback that implements onFailure.)

Testing

Tessell provides a StubDispatchAsync that facilitates testing dispatch actions/results in a fairly succinct manner.

Again using ClientPresenterTest, testing save looks like:

@Test
public void saving() {
  bind();
  view.name().type("bar");
  view.submit().click();

  // ensure we sent the right data
  SaveClientAction sentAction =
    async.getAction(SaveClientAction.class);
  assertThat(sentAction.getClient().name, is("bar"));

  // save on the server is successful
  doSaveClientResult(true);

  // assert that we've moved to #clients
  assertThat(bus, hasPlaceRequests("clients"));
}

private void doSaveClientResult(boolean success) {
  async.getCallback(SaveClientAction.class).onSuccess(
    new SaveClientResult(success));
}

Where:

This allows fairly quick, easy testing of dispatch-style actions and results without a lot of fuss.

Request Factory

RequestFactory is another alternative to traditional GWT-RPC.

Nothing in Tessell prevents users from using RequestFactory, in fact it might work quite well, it just has not been actively explored yet.