tags:

views:

1320

answers:

3

Hello there,

I am looking for a way to automate showing and hiding a 'loading' message when calling an async service, so instead of doing this:

showLoadingWidget();

service.getShapes(dbName, new AsyncCallback() {
  public void onSuccess(Shape[] result) {
    hideLoadingWidget();
    // more here...
  }

  public void onFailure(Throwable caught) {
    hideLoadingWidget();
  //more here
  }
});

I'd like to do just this, but still show and hide the message at completion.

// this should be gone: showLoadingWidget();
service.getShapes(dbName, new AsyncCallback() {
    public void onSuccess(Shape[] result) {
        // this should be gone: hideLoadingWidget();
        // more here...
    }
    public void onFailure(Throwable caught) {
        //this should be gone:  hideLoadingWidget();
        //more here
    }
});

In short I would like to change the behavior of the async calls. Thank you for all the possible suggestions.

Daniel

+1  A: 

You could create a default callback superclass which takes a LoadingMessage object argument in its constructor, and provides hook methods for subclasses, e.g. onSuccess0 and onFailure0.

The implementation would be similar to:

public final void onFailure(Throwable caught) {
    loadingMessage.hide();
    onFailure0(caught);
}

protected abstract void onFailure0(Throwable caught);
Robert Munteanu
Thanks for your suggestion Robert. I am not that would work because GWT Async interface requires to have OnSucess() and OnFailure() functions implemented.
supercobra
My code was just a skeleton. Implement in a similar manner onSuccess(T result) onSuccess0(T result). I don't see why this would not work.
Robert Munteanu
+5  A: 

You could wrap the call itself in an object that handles displaying the loading message, maybe retrying a few times on errors or whatever. Something like this:

public abstract class AsyncCall<T> implements AsyncCallback<T> {

    /** Call the service method using cb as the callback. */
    protected abstract void callService(AsyncCallback<T> cb);

    public void go(int retryCount) {
        showLoadingMessage();
        execute(retryCount);
    }

    private void execute(final int retriesLeft) {
        callService(new AsyncCallback<T>() {
            public void onFailure(Throwable t) {
                GWT.log(t.toString(), t);
                if (retriesLeft <= 0) {
                    hideLoadingMessage();
                    AsyncCall.this.onFailure(t);
                } else {
                    execute(retriesLeft - 1);
                }
            }
            public void onSuccess(T result) {
                hideLoadingMessage();
                AsyncCall.this.onSuccess(result);
            }
        });
    }

    public void onFailure(Throwable t) {
        // standard error handling
    }
    ...
}

To make the call do something like this:

new AsyncCall<DTO>() {
    protected void callService(AsyncCallback<DTO> cb) {
        DemoService.App.get().someService("bla", cb);
    }
    public void onSuccess(DTO result) {
        // do something with result
    }
}.go(3); // 3 retries

You could extend this with code to detect calls that are taking a long time and display a busy indicator of some kind etc.

David Tinker
Perfect. That works well.
supercobra
A: 

Full example (Robert)

public abstract class AsyncCall<T> implements AsyncCallback<T> 
{
    public AsyncCall()
    {
        loadingMessage.show();
    }

    public final void onFailure(Throwable caught) 
    {    
        loadingMessage.hide();    
        onCustomFailure(caught); 
    } 

    public final void onSuccess(T result) 
    {       
        hideLoadingMessage();       
        onCustomSuccess(result);     
    }
    /** the failure method needed to be overwritte */   
    protected abstract void onCustomFailure(Throwable caught);  
    /** overwritte to do something with result */
    protected abstract void onCustomSuccess(T result); 
}
Javier Arnáiz