Resty-GWT custom callback on async start and end

♀尐吖头ヾ 提交于 2019-12-04 14:32:51

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)

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

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))));

    //...
}

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"));
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!