Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to resend a GWT RPC request if it fails (or how to create persistent RPC request)?

Tags:

gwt

I require retrying to send a GWT RPC request if it fails (any response code other then HTTP 200). Reasons are complex so I won't elaborate on that. What I have so far is I treat all request responses in the same place like this:

    // We override the RpcRequestBuilder.doSetCallback method and force your service to use it
    // With this we can read the response headers if we need to.
    ((ServiceDefTarget)serviceRPC).setRpcRequestBuilder(new RpcRequestBuilder() {

        @Override
        protected void doSetCallback(RequestBuilder rb, final RequestCallback callback) {
            super.doSetCallback(rb, new RequestCallback() {

                @Override
                public void onResponseReceived(Request request,
                        Response response) {
                    httpResponseOkHandler(callback, request, response);
                }

                @Override
                public void onError(Request request, Throwable exception) {
                    httpResponseErrorHandler(callback, request, exception);
                }
            });
        }
    });

So, using httpResponseOkHandler method, I can catch HTTP failures. But, is there a way to "rethrow" the Request, i.e. try again? I don't want to store the high level parameters of the RPC request, I would prefer to use the request content that was already streamed and ready to resend.

Any ideas?

like image 254
code-gijoe Avatar asked Oct 07 '22 12:10

code-gijoe


1 Answers

Well, found the answer myself. So it's pretty neat after all. Working in heavily loaded hospital environments, network tend to be unreliable. So that is why I needed to resend rpc requests a few times before giving up. Here is the solution :

1- Set you special request builder to catch all requests responses but keep the request builder.

    ((ServiceDefTarget)serviceRPC).setRpcRequestBuilder(new RpcRequestBuilder() {

        @Override
        protected void doSetCallback(RequestBuilder rb, final RequestCallback callback) {
            final RequestBuilder requestBuilder = rb;
            super.doSetCallback(rb, new RequestCallback() {

                @Override
                public void onResponseReceived(Request request,
                        Response response) {
                    httpResponseOkHandler(requestBuilder, callback, request, response);
                }

                @Override
                public void onError(Request request, Throwable exception) {
                    httpResponseErrorHandler(requestBuilder, callback, request, exception);
                }
            });
        }
    });

2- Now use the request builder to send the request as many times as you want. One great thing is the request builder was already set and data was serialized which avoids having to store POJO unserialized data.

    // We had some server HTTP error response (we only expect code 200 from server when using RPC)
    if (response.getStatusCode() != Response.SC_OK) {
        Integer requestTry = requestValidation.get(requestBuilder.getRequestData());
        if (requestTry == null) {
            requestValidation.put(requestBuilder.getRequestData(), 1);
            sendRequest(requestBuilder, callback, request);
        }
        else if (requestTry < MAX_RESEND_RETRY) {
            requestTry += 1;
            requestValidation.put(requestBuilder.getRequestData(), requestTry);
            sendRequest(requestBuilder, callback, request);
        } else {
            InvocationException iex = new InvocationException("Unable to initiate the asynchronous service invocation -- check the network connection", null);
            callback.onError(request, iex);
        }
    } else {
        callback.onResponseReceived(request, response);         
    }

This is working fine for me, use it at your own risK!

like image 131
code-gijoe Avatar answered Oct 13 '22 11:10

code-gijoe