Parallel asynchronous calls in GWT

November 29th, 2010 Ben Northrop, Consultant  (email the author)

This entry is part 3 of 11 in the series Developing GWT Applications

The asynchronous nature of GWT makes for more powerful and usable web applications, but as a developer, it can take a little while to get used to. Here’s one example: imagine a scenario where some client-side class needs to call two service operations before it can do something. Simple, right? In a synchronous world, it would be:

public void someMethod() { 
  Service someSerive = new SomeService();
  String str1 = someService.foo();
  String str2 = someService.bar();
  doSomething(str1, str2);
}

In GWT, things are necessarily a little trickier. Using the standard RPC plumbing, calls from the client to a remote service are handled asynchronously, via GWT’s AsyncCallback mechanism. For example:

someService.foo(new AysncCallback() { 
    public void onFailure(Throwable caught) {}

    public void onSuccess(final String str1) {
      // do something here;
    }
});

This is relatively straight-forward. If we wanted to make two calls to some service, however, then do something after both have completed, our first instinct might be to just chain the service calls – e.g. when one service completes, call the second:

public void someGwtClientSideMethod() { 
  SomeServiceAsync someService = GWT.create(SomeService.class);
  someService.foo(new AsyncCallback<String>() { 

    public void onFailure(Throwable caught) {}

    public void onSuccess(final String str1) {
      service.bar(new AsyncCallback<String>() { 

        public void onFailure(Throwable caught) {}

        public void onSuccess(String str2) {
          doSomething(str1, str2);
        }
      });
    });
  }

While this works, it’s not ideal. First, it’s really ugly…and this is just for a case with 2 chained async calls – imagine if you had 3 or 4! Second, it’s slower than it needs to be, since the calls are made serially rather than in parallel.

One obvious solution is to just combine the two service operations into one (an argument for this here) – only one call is made to the server, and you don’t have to bother with the ugly nesting:

public void someGwtClientSideMethod() { 
  SomeServiceAsync someService = GWT.create(SomeService.class);
  someService.fooAndBar(new AsyncCallback<FooBarResult>() { 

    public void onFailure(Throwable caught) {}

    public void onSuccess(final FooBarResult fbr) {
      doSomething(fbr.getFooResult(), fbr.getBarResult());
    }
  });
}

This is better, but unfortunately combining service operations like this isn’t always possible (or practical). Services may not be under your control…and even if they are, it’s a lot of work to aggregate operations, and could result in a pretty complex/messy service if there are many such combinations.

Another possible solution would be to make the calls in parallel, and then only doSomething() when both service calls return. I developed two classes, ParallelCallback and ParentCallback, for this exact purpose. Using these, the code in the client would look like this:

public void someGwtClientSideMethod() { 
  SomeServiceAsync someService = GWT.create(SomeService.class);
  ParallelCallback fooCallback = new ParallelCallback();
  ParallelCallback barCallback = new ParallelCallback();
  ParentCallback parent = new ParentCallback(fooCallback, barCallback) { 
    public void handleSuccess() {
      doSomething(getCallbackData(0), getCallbackData(1));
    }
  };
  someService.foo(fooCallback);
  someService.bar(barCallback);
}

Without getting too mired in the implementation guts, essentially each service method has its own ParallelCallback, which is registered with a ParentCallback. When the service has completed, the ParallelCallback then informs the parent it’s done, and when the parent has heard back from each of is children, it calls its own handleSuccess() method, overridden and implemented by you. Return data from the individual service ParallelCallbacks can be extracted using the getCallbackData() method.

While this solution definitely still has some conceptual load, it eliminates the double-AsyncCallback-nesting, so seems a little simpler (to me!) than the chaining solution above. Also, as mentioned, RPC calls are made in parallel, so the overall latency should be less.

Anyway, the code is available here if you’re interested. Let me know what you think, or if you’ve found another better way to solve this issue.

Note: this issue was documented on StackOverflow, and there are some good insights there as well (like check out gwt-dispatch for one).

Be Sociable, Share!

Entry Filed under: Agile and Development

23 Comments Add your own

  • 1. Anees-ur-Rehman  |  November 29th, 2010 at 8:49 pm

    I am wondering why you need parallel calls. This sound to me a bad design. You can perform such complication on the facade layer and use one call on the GWT presentation layer

  • 2. Nicolas  |  November 30th, 2010 at 5:01 am

    Just call the 2 services. Use a generic mechanism like MVP or MVC (basically a listener mechanism or what GWT team call a bus) to handle the return of your call.

    It is more generic because it’s not the code that call the request (let say on a button click) that has to know how to deal with the response.

    Let imagine you clicked on the “refresh” button. If you don’t have a “refresh” service that will send back all updates in one request, maybe as a “dumb” implementation you request a refresh of you the 3 main parts of your UI. For prototyping or an intranet application a lan it may be enough.

    Maybe anyway, your request sender mechanism on the client side is abble to agregate several requests to the server in one http request, so you don’t even need to make a dedicated service to deal with theses two request at the same time.

    And that’s not the “refresh” button that is concerned about the new data, but the 3 differents parts of your UI. When you receive the response from the server, you convert them in UI events like “Data1Update”, “Data2Update”, “Data3Update”.

    Maybe Data2 is even used in several part of the UI, to display differents things. Let say it is a mail. The title of the browser window maybe has to be updated with the title of the mail. Then the mail list has to be updated with the title and sender of the mail. And the view that show the mail has to be updated with the mail body.

  • 3. Jim Kiley  |  November 30th, 2010 at 8:31 am

    As Ben suggests, there are times where the UI-side developer doesn’t have full control of the service layer.

    These classes would be useful to an end developer when the client-side code needs data from two different services in order to do further processing of its own and then put data on the screen. Therefore this isn’t a situation where each result can simply be dropped onto the user interface as it comes up.

  • 4. Ben Northrop  |  November 30th, 2010 at 9:24 am

    Thanks for the comments!

    Anees-ur-Rehman: I did consider the facade approach (“combining service operations”) in the post, but maybe too subtly. In some cases, using a facade is preferable…but, in my experience, it’s not always possible or practical. Again, services may not be in your control. Also, combining operations can be tedious and can result in more complexity. For example, if you have two service operations getX() and getY() that return objects of type X and Y respectively, then a combined operation in some facade, say, getXandY(), would either have to return a composite DTO that contains references to both X and Y (e.g. XY), or some other generic data structure that contains the X and Y objects (e.g. Map, List, etc.). In either case, extra code needs to written to assemble this new object (e.g. xy.setX(x), map.put(“x”, x), etc.) and dissessemble (e.g. xy.getX(), map.get(x), etc.). Lastly, if you have a large application, then this can result in a copious number of combined service methods in your facade (e.g. getXandY(), getXandZ(), getWandZandS(), etc.). It reminds me of the early J2EE days using SessionFacades…and it makes me cringe a bit.

    Nicolas: Good thoughts. I believe the approach here is actually orthogonal to the MVC/MVP pattern. We use the MVP pattern and this solution together.

    Jim: Thanks for helping to clarify!

  • 5. Jorge Lee  |  November 30th, 2010 at 1:41 pm

    Another alternative is to use command style RPC calls. By combining async calls to a same interface gives you the opportunity to aggregate your calls in a single request like a batch. This idea was proposed during Google I/O 2009

  • 6. Ashton  |  December 2nd, 2010 at 6:57 pm

    Thanks for the post!

    You learn something new every day, and today I learned you could have arguments of variable length and synchronized methods in java :)

    Although it doesn’t say much for my brief and patchy java career, your post and code examples will help me write better asynchronous code with gwt..

    Thanks!

  • 7. Ashton  |  February 20th, 2011 at 4:29 pm

    Just a follow up here. This post helped me solve a little bit different challenge. Using a synchronize object to keep track of returning requests that are not controlled by a parent object.

    I have an Activity that calls a service to get a list of objects. each object in the list will need to execute a request to get another list of different objects. Each layer is done within a different widget.

    Activity has ObjectAsWidget (Plural) which holds a List
    Each ObjectAWidget (singular) has a List

    The Activity needs to know when all the ObjetB’s for each ObjectA have been returned (Because one of the ObjectB’s is a newly added ObjectB and we want our encompassing ScrollPanel to scroll to it’s position)

    So if we don’t wait until all the ObjectB’s are returned, we wont be able to tell the ScrollPanel where to scroll to because we won’t have the DOM element for the ObjectB….

    So using s similar ObjectBSynchronizer just needs to now the number of ObjectA’s and then when each List for an ObjectA is returned we tell the ObjectBSynchronizer

    When all ObjectA’s have a List we fire an event that tells our Layout Shell to scroll to the element corresponding to ObjectB

    I guess there are challenges to embracing the completely Asynchronous world of GWT. A little Synchronization is nice every now and then..

  • 8. Ben Northrop  |  February 21st, 2011 at 8:32 am

    Thanks Ashton! Interesting issue…thanks for sharing that.

  • 9. Maghesh  |  March 18th, 2011 at 7:46 am

    Why the download code says “S3RuntimeException” on ParentCallback.java ?

    My compilations gives error. Then i changed this tio “RuntimeException”

    Please correct this if this is a mistake

  • 10. Ben Northrop  |  March 18th, 2011 at 11:25 am

    Maghesh – good catch. I fixed it now. Sorry about that.

  • 11. Creating a Facebook app w&hellip  |  March 27th, 2011 at 6:23 pm

    [...] a good explanation for this is the way it is.. Some talk about this problem can be found here and here. It seems some recommend moving logic to the server while other try to devise more neat solutions [...]

  • 12. Ashish  |  November 6th, 2011 at 7:35 am

    This is very good…Could not find a better way then this.
    THANKS!!!!!

  • 13. Rix  |  November 28th, 2011 at 12:14 pm

    Thanks alot very helpful

  • 14. Dustin  |  December 2nd, 2011 at 12:26 pm

    Hi Ben,

    Thanks for the post, it gave me some other way to think about my problem.

    I have a file browser in GWT, but the service provides ‘pages’ of data, which means I need to loop the asynchronous service calls. In your opinion, is this an appropriate way to do this? Create a list of callbacks and wait until they’re all done?

    Thank you!

  • 15. Nabeel  |  March 21st, 2012 at 12:40 pm

    Extremely well written and explained.

    Good job. Exposes a new pattern for a newbie like myself on AsyncCallback subject.

  • 16. girish  |  March 22nd, 2012 at 7:07 pm

    I din’t like the fact that My Service methods should know about ParallelCallBack.

  • 17. Joe  |  June 6th, 2012 at 6:24 pm

    Nice implementation!

  • 18. BlogDev  |  July 7th, 2012 at 10:08 am

    Thanks for your article.

    It’s a good solution when you can’t rewrite services.

  • 19. steve  |  August 21st, 2012 at 11:19 am

    Thanks for the post Ben, this stopped me writing some nasty code!

  • 20. Parallel asynchronous cal&hellip  |  December 6th, 2012 at 6:04 pm

    [...] FROM hERE [...]

  • 21. Derek Farren  |  July 21st, 2013 at 5:57 pm

    Thanks, this very useful.

  • 22. Steevy  |  July 25th, 2013 at 3:54 am

    This is a good idea for a “light” application because you don’t mention services complexity(on the server side).
    What will you do if one of the parrallelCallback fails ? stop the other ones ?

    Magic numbers aren’t efficient :” doSomething(getCallbackData(0), getCallbackData(1)); “, the code isn’t clear. If someone moves one line, he may forget changing index when calling parrallelCallbacks

  • 23. André Rothe  |  December 20th, 2013 at 7:24 am

    Nice article, it could be a good idea, to stack the Callbacks in a matter to have AND and OR relations between them. So it could be possible to wait for all or wait only for one of the callbacks.

Leave a Comment

Required

Required, hidden


9 + nine =

Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Trackback this post  |  Subscribe to the comments via RSS Feed

© 2010-2014 Summa All Rights Reserved