Cancel RPC under way?

395 views
Skip to first unread message

georgeuoa

unread,
Aug 8, 2006, 5:08:54 AM8/8/06
to Google Web Toolkit
Dear All

I was wondering if it's possible to cancel an undergoing RPC, even to
make it fail on purpose so as to definately _not_ receive a
success/fail after the cancellation.

G.

Slava

unread,
Aug 8, 2006, 9:23:50 AM8/8/06
to Google Web Toolkit
private boolean cancelled = false;

...........................
asyncInterface.method(new AsyncCallback() {
public void onSuccess(Object result) {
if(!cancelled){
........................
}
}
public void onFailure(){
if(!cancelled) {
....................
}
}
});

cancelled = true;

tweitzel

unread,
Aug 8, 2006, 10:26:52 AM8/8/06
to Google Web Toolkit
Once the request has reached the server, it is not a trivial task to
cancel a RPC. Slava is only ignoring the result on the client side, but
all the changes of the RPC on the server side are still in place (if
there are any).

The only way I can think of to avoid reception of a result (success or
fail) on the client side is to close the page ;-). The server side
logic will still be executed. But if you're only concerned about the
client side, Slava's solution will work.

georgeuoa

unread,
Aug 8, 2006, 4:24:52 PM8/8/06
to Google Web Toolkit
Slava, tweitzel, thank you for your replies

Of course, the network communication is far from participating in a
transaction thus I wouldn't even attempt on 'rolling back' server
actions. I am more interested in the client side here and yes, though
Slava's solution works... it's cumbersome, although the only possible I
see in the absence of something like Window.cancelPendingRPC()... or
even nicer, if the RPC invocation returned a handle which one then can
cancel.

I try to see this similar to canceling timer events with the
window.setTimeout() in javascript: I can call window.clearTimeout() and
never receive the (now cancelled) call, while in the solution provided
in the previous post, I still receive the call - but I must know now
that I have to discard it.

This is in general not easy at all, because the asynchronous response
can be in the very distant future - from a temporal and eventual
perspective, so I must do a lot of housekeeping in my application and
remember which RPCs will lead to a response I must process and which I
have to ignore.

Imagine this example: a user clicks an action button 10 times and then
on the 'cancel' button 9 times. Due to network latencies or server
load, these RPCs can get out of the regular order - so which response
goes now with which request? Well, one could keep some running serial
numbers to pass from and forth - but that's just working around it, no?

Jason Essington

unread,
Aug 8, 2006, 5:16:27 PM8/8/06
to Google-We...@googlegroups.com

On Aug 8, 2006, at 2:24 PM, georgeuoa wrote:

> or even nicer, if the RPC invocation returned a handle which one
> then can cancel.

Well, I suppose if you created a cancelable AsyncCallback that your
application extended, then you would have your "handle"

something like

public abstract class CancelableCallback extends AsyncCallback {

private boolean canceled = false;
private List stack; // see text below

public CancelableCallback(List stack) {
stack.add(this);
this.stack = stack;
}
public void cancel() {
canceled = true;
this.stack.remove(this);
this.stack = null; // we're done with this
}
public void onSuccess(Object result) {
if (!canceled){
this.stack.remove(this);
this.stack = null; // we're done with this
onSuccessImpl(Object result);
}
}
public void onFailure(Throwable caught) {
if (!canceled){
this.stack.remove(this);
this.stack = null; // we're done with this
onFailureImpl(Throwable caught);
}
}
// for your subclasses to implement rather than the originals
public abstract void onSuccessImpl(Object result);
public abstract void onFailureImpl(Throwable caught);
}


> This is in general not easy at all, because the asynchronous response
> can be in the very distant future - from a temporal and eventual
> perspective, so I must do a lot of housekeeping in my application and
> remember which RPCs will lead to a response I must process and which I
> have to ignore.

not really ...

> Imagine this example: a user clicks an action button 10 times

your application adds each RPC's callback into a List when the rpc is
invoked ...

myService.invoke(some, params, new CancelableCallbackImpl(callStack));

> and then
> on the 'cancel' button 9 times.

The first element (callback) in the List is cancelled and removed
from the list each time the cancel button is pressed.

cancelButton.addClickListener(new ClickListener(){
public void onClick(Widget sender){
((CancelableCallback) callStack.get(0)).cancel();
}
}

I omitted some error checking and such for brevity, but you get the
idea.

> Due to network latencies or server load, these RPCs can get out of
> the regular order - so which response
> goes now with which request?

In this scenario, each request has its own callback (or handle), and
completed requests are removed from the call stack (List), so
the oldest outstanding RPC gets cancelled each time the cancel button
is pressed.

> Well, one could keep some running serial
> numbers to pass from and forth - but that's just working around it,
> no?

Aside from holding on to your call stack (java.util.List) there's not
much to keep track of here.

It is all pretty self maintaining and you don't have to worry about
serials and such.

-jason

georgeuoa

unread,
Aug 9, 2006, 1:58:23 AM8/9/06
to Google Web Toolkit
Marvelous!

ash

unread,
Aug 9, 2006, 9:13:14 PM8/9/06
to Google Web Toolkit
gday jason,


> public abstract class CancelableCallback extends AsyncCallback {
>
> private boolean canceled = false;
> private List stack; // see text below
>
> public CancelableCallback(List stack) {
> stack.add(this);
> this.stack = stack;
> }


nice design.

i went down the same approach for other things that i have needed. in
fact i created a filter and built it into the framework because it
needed to be done repeatedly.

1.
http://javaongems.googlecode.com/svn/trunk/src/org/javaongems/client/rt/io/AsyncCallbackFilter.java
2.
http://javaongems.googlecode.com/svn/trunk/src/org/javaongems/client/AbstractGemlet.java

see snippet:
public AsyncCallbackFilter decorateCallback(AsyncCallback toDecorate,
Object[] args) {
HandleFailuresCallback failuresWrapper = new
HandleFailuresCallback(toDecorate);
FormLoadStatusCallback formWrapper = new FormLoadStatusCallback(null,
failuresWrapper);
if (args != null && args.length > 0 ) {
if (args[0] instanceof Form)
formWrapper.setForm((Form)args[0]);
}
return formWrapper;
}

above are the common decorations that i have needed to add. your
cancelation rpc response handling callback is good addition.

you can contribute it to the gems distributions if you care to.

rgds ash
http://www.gworks.com.au/

self help sources:
1. http://javaongems.org/ -> http://code.google.com/p/javaongems/
2. http://code.google.com/p/gems-gwt-user/
3. http://code.google.com/p/juls/

Reply all
Reply to author
Forward
0 new messages