Fake a GWT Synchronous RPC call
Asked Answered
U

3

5

First of all, I know that doing a synchronous call is "wrong", and know that "is not possible".

But, in a situation a lot complex (i dont know how to explain), i need to wait the response from server, I'am using the GWT-Platform command implementation for the GWT RPC calls.

I was looking for some kind of "hack" for doing this.

Thanks in advance.

Underdone answered 4/1, 2012 at 16:10 Comment(6)
Dont do it. Find a asynchronous solution for your problemn is better.Stichous
"First of all, I know that doing a synchronous call is "wrong", and know that "is not possible"."Underdone
It is possible, but it is not easy, do you really want to do it?Phosphocreatine
Hard to give an answer with that information, but couldn't you just detach all widgets from the dom before the rpc call and attach them to the dom in your onSuccess()? The user couldn't do anything while the call is made if that is what you want.Nonpartisan
the basics is that I need an object from server. The presenter will know what widgets and nested presenters show from this object. Without the "synchronous" call, I need to "build" the widgets and presenters for null object, and, when the data comes, do all again for the object that server given to me. I just want to evict this "redraw".Underdone
Then design your code differently, so that you don't "have to build the widgets and presenters for null object". such as, simply wait for the onSuccess to start "building" anything.Scribbler
P
5

There is a solution but it is not easy (e.g. you cannot flip a single parameter to make it work). GWT is using normal JS XMLHttpRequest under the hood. In GWT there is an overlay type for it called com.google.gwt.xhr.client.XMLHttpRequest. This class is used to send requests to the server over HTTP. Each JS XMLHttpRequest is first initialized by calling method open. This method has few parameters, but the third parameter specifies if the request should be asynchronous. If you change it to false, request will be synchronous.

But GWT-RPC doesn't use this class directly, it using it via RpcRequestBuilder, and this class is not using XMLHttpRequest directly as well, it is using RequestBuilder.

So what you'll need to do is to create customized version of RpcRequestBuilder and RequestBuilder (which will use XMLHttpRequest initialized to be synchronous).

The you can set RPCRequest builder to your GWT-RPC service instance, by casting it to the ServiceDefTarget.

Do you still want to have synchronous GWT-RPC requests?

Phosphocreatine answered 4/1, 2012 at 17:23 Comment(1)
Mother of God, hard work. I give up trying to do this. I will put your answer as right for now. Thanks, anyway.Underdone
S
8

Usually, by handling stuff in the onSuccess() function of your RPC request, you'll automatically "wait the response from server". So I assume you want to block all the code currently running? Since JavaScript is single-threaded that won't be easy, there is no sleep function that just halts the program.

But it might be that a hack using a timer does what you want:

    Timer checkRPCResponse = new Timer() {
        @Override
        public void run() {
            if (!serverResponseReceived) {
                this.schedule(100);
            } else {
                proceedWithProgram();
            }
        }
    };
    checkRPCResponse.schedule(100);

I haven't tried out if the this.schedule(100) works in the above example, but you get the idea, which is a check if the server has responded every 100 ms. Of course you have to set serverResponseReceived = true yourself in the onSuccess() function. Call the timer right after the RPC.

Schistosomiasis answered 4/1, 2012 at 16:53 Comment(1)
i've already tried do something like this, but it dont work, because I need this in a getter. Anyway, I done a little workaround, calling an event before the response comes from server, and, in presenter i was needing the information, I update again all the widgets. That isnt the best solution for my problem, but, is the only way I found...Underdone
P
5

There is a solution but it is not easy (e.g. you cannot flip a single parameter to make it work). GWT is using normal JS XMLHttpRequest under the hood. In GWT there is an overlay type for it called com.google.gwt.xhr.client.XMLHttpRequest. This class is used to send requests to the server over HTTP. Each JS XMLHttpRequest is first initialized by calling method open. This method has few parameters, but the third parameter specifies if the request should be asynchronous. If you change it to false, request will be synchronous.

But GWT-RPC doesn't use this class directly, it using it via RpcRequestBuilder, and this class is not using XMLHttpRequest directly as well, it is using RequestBuilder.

So what you'll need to do is to create customized version of RpcRequestBuilder and RequestBuilder (which will use XMLHttpRequest initialized to be synchronous).

The you can set RPCRequest builder to your GWT-RPC service instance, by casting it to the ServiceDefTarget.

Do you still want to have synchronous GWT-RPC requests?

Phosphocreatine answered 4/1, 2012 at 17:23 Comment(1)
Mother of God, hard work. I give up trying to do this. I will put your answer as right for now. Thanks, anyway.Underdone
D
0

GWT calls XMLHttpRequest.open() whith true as its third parameter which means the call will be asynchronous. I solved a similar need for testing purposes just forcing this third parameter to be always false:

private static native void fakeXMLHttpRequestOpen() /*-{
   var proxied = $wnd.XMLHttpRequest.prototype.open;

   (function() {
       $wnd.XMLHttpRequest.prototype.open =
           function() {
                arguments[2] = false;
                return proxied.apply(this, [].slice.call(arguments));
            };
        })();
}-*/;

After invoking fakeXMLHttpRequestOpen(), any further use of XMLHttpRequest will act synchronously. For instance:

remoteSvc.getResult(new AsyncCallback<String>() {
    @Override
    public void onSuccess(String result) {
        GWT.log("Service called!");
    }

    @Override
    public void onFailure(Throwable caught) {
        GWT.log("Service failed...");
    }
}

GWT.log("Last message");

will allways render:

Service called!
Last message

See https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/open for XMLHttpRequest.open() specification.

Doubleganger answered 15/11, 2016 at 13:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.