Synchornous GWT, how can i do that

145 views
Skip to first unread message

ping2ravi

unread,
Mar 10, 2009, 12:03:06 PM3/10/09
to Google Web Toolkit
HI All GWT Experts,
Its long time i have been looking for some Synchronous way of making
RPC calls in GWT. Whenever its just one call to server, writing code
is not pain.
But lets say, to initiate one component i need to make following
calls.

1) Check if user is logged in
2) Get Some data List list1 e.g. getUserAddresses
3) Get some data List list2 e.g. getUserFriends
4) Get Some data List List3 e.g. getUserCommunities
5) now create the UI based on above data retrieved. Now as all GWT RPC
calls are asynchronous, so at the step 5 i am not sure whether all
the calls(1,2,3,4) have completed by the time i reached at step 5, and
there is no Thread object in GWT so i can not wait or join till all
call completes.
And writing such code can be pain.(e.g. writing a Asyncallback for
step 1 then if it success then call step 2 and write asyncallback 2
and in its successs function call step 3 and so on)
Do you guys have any suggestion, how i can achieve this. And on server
side i can not create single API to get all the data in one call, also
sometime i need to call different apis depending on the last call
result
Like if user logged in call above mentioned apis else call some other
apis. And using Asynccallback is really really painful.


I did some R&D and found this calls RequestBuilder which has function
doSend,
openError = XMLHTTPRequest.open(xmlHttpRequest, httpMethod, url,
true,....)
the above call in this function has one parameter as true, and i guess
if we make it false it can make the call synchronous.

Do you guys see any problem in this,
i am planning to have a global static variable defined which i will be
able to set anytime, and will use in this call
so whenever i want synchronous call i will set it as false and when
want asynchronous set it as true.

Now if its correct then i am wondering why GWT creator didnt gave such
options.

All comments/suggestion are welcome.

Ian Bambury

unread,
Mar 10, 2009, 12:12:28 PM3/10/09
to Google-We...@googlegroups.com
Do it on the server.

Make one request, check the user is logged in, get list1, get list2, get list3, return. In the callback, process what you get.

Lothar Kimmeringer

unread,
Mar 10, 2009, 12:13:04 PM3/10/09
to Google-We...@googlegroups.com
ping2ravi schrieb:

> 1) Check if user is logged in
> 2) Get Some data List list1 e.g. getUserAddresses
> 3) Get some data List list2 e.g. getUserFriends
> 4) Get Some data List List3 e.g. getUserCommunities
> 5) now create the UI based on above data retrieved. Now as all GWT RPC
> calls are asynchronous, so at the step 5 i am not sure whether all
> the calls(1,2,3,4) have completed by the time i reached at step 5, and
> there is no Thread object in GWT so i can not wait or join till all
> call completes.
> And writing such code can be pain.(e.g. writing a Asyncallback for
> step 1 then if it success then call step 2 and write asyncallback 2
> and in its successs function call step 3 and so on)

Do the UI-update in a method called updateUI where you check if all
necessary data (e.g. above lists) are present and call this method
in every onSuccess-method of the different AsyncCallback-classes.


Regards, Lothar

Ian Petersen

unread,
Mar 10, 2009, 12:17:32 PM3/10/09
to Google-We...@googlegroups.com
Synchronous RPC is a tremendously bad idea. Read this for more insight:

http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/faca1575f306ba0f/3be719c021aa19bd

The way I have addressed some of the problems you mention is with an
event-based model. For example, to display the results of
getUserAddresses(), I might have a ListBox widget backed by a model of
some sort. The list and model are tied together with event listeners
such that clicking in the UI updates the model and changes in the
model (adding and removing addresses, say) are reflected in the UI.
In such a setup, the completion of an RPC will eventually trigger a
model event that causes the list to redraw itself. Working this way
solves a lot of problems because most of my code is decoupled from the
RPC details and I don't have to worry about RPC being synchronous or
asynchronous.

Ian

ping2ravi

unread,
Mar 10, 2009, 12:28:05 PM3/10/09
to Google Web Toolkit
Ian,
That is not an option for me, creating such API is not a good idea
from application maintenance as well as architect point of view.

Lothar,
Your suggestion sounds good and i can use it where i need to update
the UI, but what about if condition
if(IsUserloggedIn())
{
callApi1()
callApi2()
}
else
{
callApi4()
callApi3()
}

Writing then code in Success of asyncallback and then calling the
other function will be a good long chain of calls and asyncallbacks.

Do you see any problem in having synchronous calls.? except that it
may hang the UI for a second and that is acceptable.

Lothar Kimmeringer

unread,
Mar 10, 2009, 12:37:02 PM3/10/09
to Google-We...@googlegroups.com
ping2ravi schrieb:

> Do you see any problem in having synchronous calls.? except that it
> may hang the UI for a second and that is acceptable.

If the server is not available or the request get lost for some
other reason, the UI of the browser hangs for a couple of minutes
and not seconds.


Regards, Lothar

Ian Bambury

unread,
Mar 10, 2009, 12:40:16 PM3/10/09
to Google-We...@googlegroups.com
You said you didn't want to chain calls.

If you make more than 2 calls to the server, then the 3rd one onwards will be delayed.

The quickest and most efficient way is to do the work on the server in one call. The maintenance is no different, in fact it is easier, since you don't have to bother with all the internet traffic.

Why is it not a good idea from the architecture pov?

ping2ravi

unread,
Mar 10, 2009, 12:43:47 PM3/10/09
to Google Web Toolkit
Lothar,
good point but i think that's the beauty of GWT code,
they already have one parameter(timeoutMillis) in following call( i
have not tested it, if it works or not but i guess it will work.)

Request request = new Request(xmlHttpRequest, timeoutMillis,
callback);

So if call doesnt get finish in that time it will timeout and your UI
will be working fine.

I am copy pasting the full function here

private Request doSend(String requestData, RequestCallback callback)
throws RequestException {
JavaScriptObject xmlHttpRequest = httpRequest.createXmlHTTPRequest
();
String openError;
if (user != null && password != null) {
openError = XMLHTTPRequest.open(xmlHttpRequest, httpMethod, url,
true,
user, password);
} else if (user != null) {
openError = XMLHTTPRequest.open(xmlHttpRequest, httpMethod, url,
true,
user);
} else {
openError = XMLHTTPRequest.open(xmlHttpRequest, httpMethod, url,
true);
}
if (openError != null) {
RequestPermissionException requestPermissionException = new
RequestPermissionException(
url);
requestPermissionException.initCause(new RequestException
(openError));
throw requestPermissionException;
}

setHeaders(xmlHttpRequest);

Request request = new Request(xmlHttpRequest, timeoutMillis,
callback);

String sendError = XMLHTTPRequest.send(xmlHttpRequest, request,
requestData, callback);
if (sendError != null) {
throw new RequestException(sendError);
}

return request;

Jason Essington

unread,
Mar 10, 2009, 12:47:47 PM3/10/09
to Google-We...@googlegroups.com
Actually from a user's point of view, hanging the UI is NEVER
acceptable even if it is for less than a second.

In the case of waiting for a couple of seconds, depending on the
browser and version, you cannot change tabs, cannot close the browser
or anything. This is a VERY NAUGHTY thing to do intentionally.

In the case of a network failure this frozen state lasts indefinitely,
and that sort of thing really pisses off your users. particularly if
the only way they an figure out how to exit your web app is to reboot
their computer!

Learn to divide up your application into the things that need to
happen before the RPC is sent, and the things that happen after. place
those things in their own methods, then call the "after" methods from
your Callback. Your users will thank you for it later.

-jason

mikedshaffer

unread,
Mar 10, 2009, 1:01:35 PM3/10/09
to Google Web Toolkit
Lothar's original suggestion

"Do the UI-update in a method called updateUI where you check if all
necessary data (e.g. above lists) are present and call this method
in every onSuccess-method of the different AsyncCallback-classes. "

is the way to go.

How much extra code is too much? You have 5 async RPC calls each with
onsuccess handlers that increment a class level field and then call a
"redoUI" type of function. That function continues only when the
increment is 5. Done. We're talking a small amount of code here
really. And that's all good form and the way to do a good AJAX UI.
You can add all sorts of good UI user interaction this way, like wait
cursors to let the user know something is going on. If you
synchronize things, you'll lock up your users browser, and in general,
tick them off, like Jason articulates. Plus you'll have gnarly
looking code that fights the very asynchronous nature of the way
things work.

My thoughts...

Later,

Shaffer


On Mar 10, 10:47 am, Jason Essington <jason.essing...@gmail.com>
wrote:
> > may hang the UI for a second and that is acceptable.- Hide quoted text -
>
> - Show quoted text -

Matías Costa

unread,
Mar 10, 2009, 1:31:22 PM3/10/09
to Google-We...@googlegroups.com
On Tue, Mar 10, 2009 at 6:01 PM, mikedshaffer <mikeds...@gmail.com> wrote:
Lothar's original suggestion

"Do the UI-update in a method called updateUI where you check if all
necessary data (e.g. above lists) are present and call this method
in every onSuccess-method of the different AsyncCallback-classes. "

is the way to go.

I agree, 3 requests, 3 ui components fills, so the ui feels responsive and some kind of "magic" that impress users.

2 questions:

1) not only async is the way to go, but the only way to go? Due one-thread nature of javascript you can't do

request.send(callbackObject);
while (field == null) Timer.sleep(100);
field.use()

because javascript is really frozen doing that sleep, there is no way to process the response. You have no notify() (yeah, no threads), nor continuations and setTimeout is no better, but worse.

2) Is it feasible to do some kind of "request chaingun"?. Adding request to a list, process responses with a generic callback and calling custom callback when all finish:

List<Request> chain = new ArrayList<Request>();
chain.add(service.getData1(arg));
chain.add(service.getData2(arg));
chain.add(service.getData3(arg));
gun.fire(chain, new ChainGunCallback {
  onSuccess(List<Object> results) {
   // do casts and stuff
  }
  onFailure(WhatEver cause) {
    // crash!
  }
});

...


al0

unread,
Mar 11, 2009, 5:46:11 AM3/11/09
to Google Web Toolkit
"How much extra code is too much?" - single line of (unnecessary)
extra code is way too much.

ping2ravi

unread,
Mar 11, 2009, 6:13:09 AM3/11/09
to Google Web Toolkit
I totally agree with you guys that Asynchronous is good, but i would
love to see mix up of synchrnous and asynchronous in GWT(my personal
view), where i can make an asynchronous call to one function which
internally can make synchronous calls and it will solve the problem of
UI hanging.(In case GWT peope can read it , please implement such
things), i am sure programmers will enjoy some synchronous calls too
such as avoiding inner classes or writing new classes for callbacks
for each call(again personal view). But yes User satisfaction has more
priority.
And guys i am really thankfull to all of you for giving suggestions

i guess i will implement some kind of chains as Matias Costa suggested
and once all chain object get result back will call our UpdateUi
function as suggested by Ian.


Ravi.

eggsy

unread,
Mar 11, 2009, 6:58:30 AM3/11/09
to Google Web Toolkit
I agree with all the previous posts that Asynchronous is the best way
and that is why GWT only implements this.

When I started with GWT I was asking a similar question and was
correctly advised to think in terms of Async not Sync the more
development you do with GWT you'll realise this.

However at the time we did come up with a basic transactional pattern
that performs the methods synchronously:

http://www.axonbirch.com/blog/2007/10/26/notification-end-of-rpc-call/

But as before I would advise that you simply look at this and try
*not* to implement your methods synchronously if possible.

Eggsy

Vitali Lovich

unread,
Mar 11, 2009, 7:13:32 AM3/11/09
to Google-We...@googlegroups.com
It's not really a matter of this being GWTs way.  I believe this is the only thing browsers support since they do not have multiple threads, at least so that the UI doesn't lock up.  And by UI lockup, I don't mean the page is unresponsive - I mean the whole browser used to freeze if a page was in a Javascript loop (actually still does on Firefox).

New browsers have multi-threading, but I believe that multi-threaded Javascript constructs are still a ways away.

jmpeace

unread,
Mar 11, 2009, 9:53:32 AM3/11/09
to Google Web Toolkit
Please take a took to this code
I have written this code to be able to make RPC calls one after
another:

(you can use 'result' value to know if you can continue to next call)

/*ONE*/CustomWaitingOperation.execute(new
CustomWaitingOperation.ResultCallback(){
public void onResult(boolean result, Throwable caught) {
if(result)
{

/*TWO*/CustomWaitingOperation.execute(new
CustomWaitingOperation.ResultCallback(){
public void onResult(boolean result, Throwable caught) {
if(result)
{


}
}
});

}
}
});

CustomWitingOperation.java

public class CustomWaitingOperation {

/*Fields*/

public interface ResultCallback {
void onResult(boolean result,Throwable caught);
}

public CustomWaitingOperation(/*Parameters Here*/) {
/*Fields=Parameters*/
}

public void onResponse(boolean result,Throwable caught) {
return;
}

public static void execute(/*Parameters Here*/,final ResultCallback
resultCallback){

final AppServicesAsync serviceProxy = AppParameters.getServiceProxy
();

final CustomWaitingOperation wait = new CustomWaitingOperation(/
*Parameters Here*/){

@Override
public void onResponse(boolean result,Throwable caught) {
resultCallback.onResult(result, caught);
}
};

AsyncCallback<TempObject> callback = new AsyncCallback<TempObject>()
{

public void onFailure(Throwable caught) {
GWT.log("RPC error!", caught);
wait.onResponse(false, caught);//do not continue
}

public void onSuccess(final TempObject result) {
wait.onResponse(true, null);//continue
}

}

serviceProxy.executeCustomOperation(/*RPC call arguments*/,
callback);


}

alex

unread,
Mar 12, 2009, 6:39:47 AM3/12/09
to Google Web Toolkit
Why do you need sync`ed method calls?
I think that you actually need a way to find out when a RPC call has
returned (either one of onSuccess / onFailed).

One way to go with this is to have a simple event system where events
are thrown when changes are made - these changes can be UI
modifications, RPC calls that arrived at client code, etc.

Class Event { String eventName, ..... }
Interface EventHandler { public void handleEvent (Event
event); ...... }
Class EventDispatcher { here I have declared static members /
functions to register and dispatch incoming events }

Now all classes that need events would implement EventHandler.
Registering is done via constructor (or some other means).

We have implemented this system in a relatively large application and
it works like charm :)
Personally I have also used this paradigm for 2 personal projects, one
of them had no server-side and all reads were done with RequestBuilder
- everything went great

Of course, you can extend the system - what I am planning to do for
the library we are working on right now - to "freeze" the client code
until all conditions are satisfied.

Hope this helps,
Alex.

Magius

unread,
Mar 12, 2009, 10:52:30 AM3/12/09
to Google Web Toolkit
I've had the same problem some months ago.
I was developping a big application for a telco enterprise and most of
the application forms requiered loading several fields at the same
time during initialization.
For example, the "create a route between servers" form requieres to
load several drop-down lists: equipments, cards, business units,
market, ...

I don't want the user can work with the window until all the lists and
controls are loaded.
And I don't want to merge all services (getEquipments, getCards, ...)
in only one big service specific for this form.
It's easier to reuse code having atomic services.

I create a synchronizer class. During initialization I called
individual services (all calls are procesed in paralel and the total
time is slowest service time, not the sum).
I stored each asyncallback in the synchonizer, and finally create a
modal "loading" window. This modal window blocks the user but the
browser and the javascript engine aren't freezed.
When all the asyncalls are asnswered (succesfully or not), the
synchonizer close the modal "loading" window and the user can work the
full loaded form.

Hope it helps,
Reply all
Reply to author
Forward
0 new messages