Cancelling service calls (RPC) to the server side from the client

631 views
Skip to first unread message

Erez

unread,
Dec 23, 2006, 7:01:51 PM12/23/06
to Google Web Toolkit
I have a long-running service call to the server side from GWT.
Something like:

service.getUpdate(AsyncCallBack callback), which takes a long time to
return

On the client side, there are cases when I would like to cancel this
service call before it actually returns. Something like:

service.cancelCall(callId)
or maybe even:
GWT.cancelAllServiceCalls()

Is there any way to accomplish this?

Currently, we're sending in a call reference ID from the client to the
server during the service call:
service.getUpdate(int callId, AsyncCallBack callback)

Then, we're cancelling the call from the server-side via a call from
the client-side:
service.cancelCall(callId)

However, this becomes complicated when multiple back-end servers are
involved, since they all have to know about the unique callIds and
react when one of the back-ends gets a cancel message. It seems more
efficient if we can cancel the call from the client-side and cut off
the connection in GWT. (Sort of like hitting the STOP button on the
browser during a long page-load.)

Any ideas?
Erez

Rahul

unread,
Dec 25, 2006, 9:21:08 AM12/25/06
to Google Web Toolkit
Hi Erez,

With the amount of information that you have provided, I could not
understand what your application is actually trying to do. But yeah
getting control over fate of "Dispatched Request" is an accepted issue
with GWT. For more details you can refer to following thread:

http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/1eddae8a0a153bac/479958ecacecaf1a#479958ecacecaf1a

and it has already been filed as a bug at:
http://code.google.com/p/google-web-toolkit/issues/detail?id=535&can=2&q=

Also, Scot Blum from Google has given a sample code which could be
helpful in your case. I have not actually gone through it.

I hope this might be helpful.

-Rahul

Erez

unread,
Dec 25, 2006, 10:37:50 AM12/25/06
to Google Web Toolkit
Exactly. Scottb sounds like he has the perfect solution.
Return an object from the async RPC call and allow GWT to manipulate
the in-flight call via this object. So, if we want to cancel the
in-flight call, we can do:

RPCCall call = service.getUpdate(AsyncCallBack callback);
...
later on... if we don't need the result anymore:
call.cancel();

This way, the call immediately dies and stops using up a connection.

Erez

Rahul

unread,
Dec 25, 2006, 12:01:01 PM12/25/06
to Google Web Toolkit
Try it out and let me know whether it worked for you.

Thanks,
Rahul

Erez

unread,
Dec 26, 2006, 5:10:34 PM12/26/06
to Google Web Toolkit
We're using 1.2, so I'm afraid to patch. However, it looks like this
would do exactly what we need: control in-flight RPC calls by getting a
handle to the RPC call itself immediately after the call.

I added my 2cents to the ticket. I hope they raise the priority on
this and release this with the next version. Maybe they can find a way
to add this in without breaking existing clients.

Erez

Jon

unread,
Dec 26, 2006, 10:46:50 PM12/26/06
to Google Web Toolkit
What does it mean to cancel the call on the server side? Short of your
server code frequently testing for whether it's been cancelled and
aborting on its own, or failing when trying to write back to the
client, or halting the thread(s) processing the request (not
recommended right?) is it really possible to cancel a long running
server-side call? of course, you can always ignore the result on the
client, but this won't prevent the call from completing on the server
and consuming resources (client and server side), etc.

is there some standard way to preempt server-side requests?

is just marking your AsyncCallback instance to ignore the onSuccess()
call enough? I'm assuming the answer is "no"

Erez

unread,
Dec 27, 2006, 8:16:00 AM12/27/06
to Google Web Toolkit
We're emulating server-push by initiating a request that waits on the
server-side until something changes and then responds to the client
with the change. The problem is that sometimes the client knows that a
request is already stale.

We can send a "cancel" message from client to server, asking the server
to stop waiting for a change. This prevents the server-side resource
use and eventually will kill the client connection. I guess it's
preferable to actually killing off the connection from the client side.
However, if too many such calls happen at once, then the client may
hang waiting for the "cancel" messages to take effect and kill off the
long-running calls. It would be nice to be able to simply kill the
long-running calls from the client side so we're not waiting for the
server to cancel and clean up.

Maybe there's a better way to achieve what we're trying to do.
We're basically calling the request and letting the server-side thread
wait until there's a change. Then, returning the value and handling on
the client side. Then, we run the request again. Requests wait up to
a minute on the server-side before returning "no change" and starting
again.

The alternative (what we were doing before) is brute-force calling the
server-side every second to check for changes. We assumed the
long-running request method is better since it causes fewer
connections/sec on our web server and app server.

I'm curious how Google applications (like Gmail chat) refresh in near
real-time.

Erez

Jon Wells

unread,
Dec 27, 2006, 1:50:33 PM12/27/06
to Google-We...@googlegroups.com
Not sure what the best solution is to your problem but here are a couple of thoughts:

1.  I've seen some discussion about a server-push library COMET.  You might check it out.
2.  Seems like you wouldn't want to tie up app server threads with waits unless you only need to support a tiny number of concurrent clients.
3.  Seems like there could be a need for a framework for clients to manage true long-running methods.   For instance, say i had a service call that is supposed to send 10000 emails and i want to see a progress bar on the client that shows something like "Sending 245 out of 10000" with a progress bar and maybe a cancel button.  It would be nice to have a simple way for service method impls to report progress, test for cancellation requests,  and a nice way for clients to receive updates about the progress and submit cancellation requests. 

Erez

unread,
Dec 27, 2006, 2:05:40 PM12/27/06
to Google Web Toolkit
1. Comet sounds neat. Does it work with GWT? Is there any support in
GWT for this (or is anyone at Google thinking about adding it?)

2. We're currently running about 200 concurrent users and will probably
reach 10,000 in a few years, so I guess we're pretty tiny. We could
spread the load onto multiple servers, but I would think 10,000
concurrent threads shouldn't be too much of an issue for a single JVM
with 4GB RAM. (I wonder if epoll-enabled JVMs be better able to handle
this level of dormant concurrency?)

3. That's sounds like a nice client-side management framework. I would
think part of it could be implemented in the return object from the RPC
call. What would be really neat would be for the CallBack object to be
able to receive multiple onSuccess() calls from the server as long as
the connection was active (like COMET?)

Possibly a more scalable solution would be able to pass off dormant
long-lived requests to a single (or pooled) thread that would handle
all of the sleepers. That thread(s) would then be responsible for
responding to the long-running requests instead of letting the
connection-handling threads deal with everything. I would think this
would have to be more tightly integrated into the servlet framework,
though.

Sascha Matzke

unread,
Dec 27, 2006, 5:48:02 PM12/27/06
to Google Web Toolkit
Hi,

On Dec 27, 4:46 am, "Jon" <jon.we...@gmail.com> wrote:
> What does it mean to cancel the call on the server side?

Pretty simple... When you close the connection on the client side, the
server side code will receive a SocketException (Broken pipe) and can
handle that, for instance rolling back a pending transaction.

Sascha

Jon

unread,
Dec 27, 2006, 6:55:09 PM12/27/06
to Google Web Toolkit
Right, but the distinction I was trying to make is that the
SocketException is not thrown until after the service method returns
which may be too late in many cases. For instance, say I have a
service method that takes 20 mins to complete and performs a bunch of
resource-consuming stuff. My pt was that "cancelling" the call from
the client could mean many different things depending upon who you ask.
it could mean:

1. like you said that the client can close the connection and the
server will fail when it tries to write back the method return value
(after 20 mins of sucking up server-side resources)
2. the server should rollback anything its done (not currently possible
to catch those SocketExceptions on the server since they're thrown in
the GWT base servlet),
3. the service method should abort its processing ASAP sparing you the
wasted server resources.
4. You could also mean that the client will simply ignore the onSuccess
callback

Rahul

unread,
Dec 28, 2006, 3:05:50 AM12/28/06
to Google Web Toolkit
Jon,

Even I am facing the same problem as you have mentioned in step 2.

>2. the server should rollback anything its done (not currently possible
>to catch those SocketExceptions on the server since they're thrown in
>the GWT base servlet),

There should be a cleaner way to handle such situation. Even my
application is refreshing the content of page in every 5 seconds. But
then few calls to server are running afoul and throwing
SocketTimeoutException on serverside.Whenever there is a
SocketTimeoutException on server side you can register it on client
side inside onFailure() method as,

public void onFailure(Throwable caught)
{
try {
throw caught;
}
catch (InvocationException ie) {
// Invocation failed on server side.
}
catch (Throwable th) {
// Exception for some other reason.
}
}

But then there is no way we can make sure that this InvocationException
has come because of a SocketTimeoutException on serverside and deal it
as a special case. InvocationException can come because of many
reasons.

Rahul

Randall R Schulz

unread,
Dec 28, 2006, 10:48:16 AM12/28/06
to Google-We...@googlegroups.com
On Tuesday 26 December 2006 19:46, Jon wrote:
> What does it mean to cancel the call on the server side? Short of
> your server code frequently testing for whether it's been cancelled
> and aborting on its own, or failing when trying to write back to the
> client, or halting the thread(s) processing the request (not
> recommended right?) is it really possible to cancel a long running
> server-side call? of course, you can always ignore the result on
> the client, but this won't prevent the call from completing on the
> server and consuming resources (client and server side), etc.
>
> is there some standard way to preempt server-side requests?

I recommend that anyone doing client-server programming read the
excellent book "Java Concurrency in Practice." Among its topics is
extensive treatment of how to handle the cancellation of long-running
tasks.


> ...


Randall Schulz

Reply all
Reply to author
Forward
0 new messages