TurboManage

David Chandler's Journal of Java Web and Mobile Development

  • David M. Chandler


    Web app developer since 1994 and former Developer Advocate with Google currently residing in Peru. I am currently the Developer Advocate for Sencha GXT and enjoy working on Android, GWT, and App Engine projects.

  • Subscribe

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 228 other followers

  • Sleepless Nights…

    March 2010
    S M T W T F S
    « Feb   Apr »
     123456
    78910111213
    14151617181920
    21222324252627
    28293031  
  • Blog Stats

    • 687,455 hits

Tips for using CachingDispatchAsync with gwt-dispatch

Posted by David Chandler on March 2, 2010

In Chris Lowe’s excellent tutorial on MVP with gwt-presenter and gwt-dispatch, he provides a CachingDispatchAsync which nicely demonstrates the power of the Command pattern. When you call executeWithCache(), the dispatcher will first check to see if the Result associated with the Action has previously been cached, and if so, will return it and save a trip to the server.

When I first played with CachingDispatchAsync, I thought it wasn’t working because I never saw anything returned from cache, but it turns out I’d overlooked one of the fundamental rules of using Collections (see Josh Bloch’s Effective Java, Item 9: When you override equals(), override hashCode()). CachingDispatchAsync uses a HashMap to implement the cache, so a cache “hit” succeeds only when the Actions being compared are the identical instance (==) or satisfy equals() and hashCode().

To succeed with CachingDispatchAsync, you can use something like this:

SomeAction<SomeResult> someAction = new SomeAction();
// pass Action instance, not "new SomeAction()"
cachingDispatch.executeWithCache(someAction, ...)
...
// Second time using SAME action instance as before instead of new SomeAction()
// so cache will be hit
cachingDispatch.executeWithCache(someAction, )

Most of the time, however, your dispatch calls will occur in separate classes and won’t have access to the same Action instance. In that case, you need to override equals() and hashCode(). This example Action has no fields; therefore hashCode() and equals() return the same values for any instance of the class.

package com.roa.app.shared.rpc;

import net.customware.gwt.dispatch.shared.Action;

public class FindUserListSubsAction implements Action<FindUserListSubsResult>
{

	public FindUserListSubsAction()
	{
		
	}

	@Override
	public boolean equals(Object obj)
	{
		return this.getClass().equals(obj.getClass());
	}

	@Override
	public int hashCode()
	{
		return this.getClass().hashCode();
	}

}

When used properly, CachingDispatchAsync greatly simplifies initialization. If several presenters need the same data, each can simply call for it and let the dispatcher figure out whether a server trip is needed. The alternatives are not pretty: timing problems (what if the user navigates directly here first…?), duplicate requests (easiest to implement, but not optimized), or roll-your-own caching in a service layer. If you choose the latter, I recommend you pass an AsyncCallback to your service calls in case the service needs to make an async call for data. I had been firing events from services instead, and this resulted in a lot of event classes and more event listeners than needed being notified, even circular events in some cases, which are more fodder for the book I will never write but certainly could have: 101 Ways to Write an Infinite Loop). Fortunately, CachingDispatchAsync simply and elegantly solves most of these problems.

As suggested by the Google I/O presentation that started the whole GWT MVP craze, I’ve further beefed up CachingDispatchAsync to do batching and queueing. Batching combines multiple requests for the same Action. This occurs when the first request has not yet returned and therefore has not yet cached the result. It happens a lot at startup. Queuing allows you to specify the order in which Actions are processed and ensures that all actions have been completed before any callbacks are called. This is very useful when doing client-side joins requiring multiple service calls, but that’s for another night… The combination of these three (queuing, batching, and caching) has yielded a robustness to my app that was previously elusive.

3 Responses to “Tips for using CachingDispatchAsync with gwt-dispatch”

  1. Eric said

    Thanks for this post and many others. Have you posted the source to your “beefed up” CachingDispatchAsync anywhere? If not, would you consider doing so?

    Thanks!,

    Eric

  2. […] by David Chandler on July 12, 2010 In a previous post, I mentioned that I’d beefed up CachingDispatchAsync to do batching and queueing of commands […]

  3. […] which requires each service impl to extend RemoteServiceServlet, and much less code than the Command pattern, which typically utilizes Action, Result, and handler classes for each service method (albeit the […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

Join 228 other followers

%d bloggers like this: