Resty-GWT custom callback on async start and end

2020-07-22 16:42发布

I use resty gwt for all server communication. I would like some indicator that would show the operation is in progress.

I consider 2 aproaches:

  • progressbar, which will show in progress percentage;
  • animation, that will be showed while operation is in progress, but without any percantage.

I've assumed that I need to add custom filter with callback. I would like to fire events like: RestyGwtComunicationStart and RestyGwtComunicationEnd, or callback to fire onComunicationStarted and onComunicationEnded. I would like to have this declared in one place, RestyGWT Dispatcher configuration. Also if there was an error I would like to fetch the error.

But I don't know where to start. There is no word about it in documentations.

Can I ask You for help? How can I do this?

4条回答
Lonely孤独者°
2楼-- · 2020-07-22 16:53

Unfortunately "Dispatcher/Callback filters" feature does not described in the official documentation. But I can suggest next solution (this code should be placed in EntryPoint implementation of your module):

public void onModuleLoad() {
    //...

    //used to show busy indicator before send HTTP request        
    DispatcherFilter busyIndicatorDispatcherFilter = new DispatcherFilter() {
        @Override
        public boolean filter(Method method, RequestBuilder builder) {
            BusyIndicator.show();
            return true;
        }
    };
    //used to show busy indicator after HTTP response recieved
    CallbackFilter busyIndicatorCallbackFilter = new CallbackFilter() {
        @Override
        public RequestCallback filter(Method method, Response response, RequestCallback callback) {
            BusyIndicator.hide();
            return callback;
        }
    };
    //registering FilterawareDispatcher (and busy indicator filters) as default Dispatcher
    Defaults.setDispatcher(new DefaultFilterawareDispatcher(
            busyIndicatorDispatcherFilter,
            new DefaultDispatcherFilter(new DefaultCallbackFactory(busyIndicatorCallbackFilter))));

    //...
}
查看更多
来,给爷笑一个
3楼-- · 2020-07-22 17:01

Someone already did it as a pull-request to resty. Guess you can give it a try:

https://github.com/resty-gwt/resty-gwt/pull/151

查看更多
兄弟一词,经得起流年.
4楼-- · 2020-07-22 17:05

So if you want to know that a request has been sent it is up to you in your GWT app to treat that. You can send an event when you trigger your request. You have multiple way of doing this.

Have a look at Request Dispatcher inside the doc https://resty-gwt.github.io/documentation/restygwt-user-guide.html

Then if you want to get progress info, as HTTP calls are synchronous. So there is no way to do this easily.

The way I have been doing it is the following:

1) Create a first call to initiate a processing on the backend with a POST, this will return the ID of your processing

2) Then do a GET on your processing ID that will return the progress. Once the progress is 100% it will return the ID of the result

3) GET the result with the result ID

(You can mix 2 and 3 together eventually and return result when progress is 100% in the same DTO)

Another option is to replace 2) by pushing info from backend to front end (html5 websocket)

查看更多
迷人小祖宗
5楼-- · 2020-07-22 17:05

Unfortunately I did not get adequate answer, So I developed my own solution.

At first I've added Resty configuration RestyGwtConfig to my Module configuration

public class ClientModule extends AbstractPresenterModule {
    @Override
    protected void configure() {
        bind(RestyGwtConfig.class).asEagerSingleton();
        install(new DefaultModule.Builder()
        .defaultPlace(Routing.HOME.url)
        .errorPlace(Routing.ERROR.url)
        .unauthorizedPlace(Routing.LOGIN.url)
        .tokenFormatter(RouteTokenFormatter.class).build());
        install(new AppModule());
        install(new GinFactoryModuleBuilder().build(AssistedInjectionFactory.class));
        bind(ResourceLoader.class).asEagerSingleton();
    }
}

then I've set Custom distpatcher for all my comunication requests of resty gwt.

import org.fusesource.restygwt.client.Defaults;
import org.fusesource.restygwt.client.Resource;
import pl.korbeldaniel.cms.shared.ServiceRouting;
import com.google.gwt.core.client.GWT;
import com.google.inject.Inject;

public class RestyGwtConfig {
    @Inject
    public RestyGwtConfig(RestyDispatcher dispatcher) {
        Defaults.setDispatcher(dispatcher);
    }
}

Then I've added custom filter (ProgressIndicatorFilter) to handle communication's start and end callbacks:

import org.fusesource.restygwt.client.Method;
import org.fusesource.restygwt.client.dispatcher.DefaultFilterawareDispatcher;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestException;
import com.google.inject.Inject;

public class RestyDispatcher extends DefaultFilterawareDispatcher {
    @Inject
    public RestyDispatcher(ProgressIndicatorFilter progressIndicatorFilter) {
        addFilter(progressIndicatorFilter);
    }
}

in filter class method overriden filter I've added an event trigger (eventBus.fireEvent(new IndicatorEvent("Rest-Gwt Comunication started"));) and registered callback, here is whole code:

import org.fusesource.restygwt.client.Method;
import org.fusesource.restygwt.client.dispatcher.DispatcherFilter;
import pl.korbeldaniel.cms.client.template.progressIndicator.IndicatorEvent;
import com.google.gwt.http.client.RequestBuilder;
import com.google.inject.Inject;
import com.google.web.bindery.event.shared.EventBus;

class ProgressIndicatorFilter implements DispatcherFilter {
    private AssistedInjectionFactory factory;
    private EventBus eventBus;

    @Inject
    public ProgressIndicatorFilter(AssistedInjectionFactory factory, EventBus eventBus) {
        this.factory = factory;
        this.eventBus = eventBus;
    }
    @Override
    public boolean filter(Method method, RequestBuilder builder) {
        builder.setCallback(factory.createProgressIndicatorCallback(method));
        eventBus.fireEvent(new IndicatorEvent("Resty-Gwt Comunication started"));
        return true;
    }
}

Registering a callback couldn't be done straight forward, like

new ProgressIndicatorDispatcherCallback()

cause I use dependency injection. So I've created a factory to assist injection as follow:

public interface AssistedInjectionFactory {
    ProgressIndicatorDispatcherCallback createProgressIndicatorCallback(Method method);
}

Here and here You can find more Assisted Injection info.

Here is the callback code:

class ProgressIndicatorDispatcherCallback implements RequestCallback {
    private RequestCallback requestCallback;
    private EventBus eventBus;

    @Inject
    public ProgressIndicatorDispatcherCallback(@Assisted Method method, EventBus eventBus) {
        this.requestCallback = method.builder.getCallback();
        this.eventBus = eventBus;
    }
    @Override
    public void onResponseReceived(Request request, Response response) {
        endComunicationFireIvent();
        requestCallback.onResponseReceived(request, response);
    }
    @Override
    public void onError(Request request, Throwable exception) {
        endComunicationFireIvent();
        requestCallback.onError(request, exception);
    }
    private void endComunicationFireIvent() {
        eventBus.fireEvent(new IndicatorEvent("Rest-Gwt Comunication ended"));
    }
}
查看更多
登录 后发表回答