3

I have a method in GWT which retrieves the DATA from the DB using the fire method of the requests as you all know its asynchronous I am calling this method from JS so I need to make synchronous is it possible

private static String retriveLocation(String part)
{
    ClientFactory clientFactory = GWT.create(ClientFactory.class);
    MyRequestFactory requestFactory = clientFactory.getRequestFactory();
    YadgetRequest request = requestFactory.yadgetRequest();
    String criteria = "!" + part;
    final ArrayList<String> tags = new ArrayList<String>();

    request.getTagsStartingWith(criteria, 10, 0).fire(
            new Receiver<List<TagProxy>>() {
                @Override
                public void onSuccess(List<TagProxy> tagList) {
                    String output = "[";

                    for (TagProxy pt : tagList) {
                        output += "{";
                        output += "\"id\":" + "\"" + pt.getId() + "\",";
                        output += "\"value\":"
                                + "\""
                                + pt.getName().replaceAll("\"", "")
                                        .replaceAll("!", "") + "\"";
                        output += "},";

                    }
                    if (output.length() > 2)
                        output = output.substring(0, output.length() - 1);
                    output += "]";
                    tags.add(output);

                }

                @Override
                public void onFailure(ServerFailure error) {

                }

            });

    return tags.size() + "";

}

and calling this function from JS like this:

public static native void exportStaticMethod() /*-{
    $wnd.computeLoanInterest =
    $wnd.getAutocomplete =@com.yadget.client.Yadget::retriveLocation(Ljava/lang/String;);
}-*/;

and inside onModuleLoad() I call exportStaticMethod().

and in html I have a button I call onclick getAutocomplete() like this:

<input type="button" onclick="alert(getAutocomplete('j'))" value="momo" /> 

The problem is that the size always returns 0 because the method is asynchronous but if I could return the value onSuccess that would solve my problem. Any ideas please? I have been googling it for 2 days and got no answer.

In other words:

I have JS method I need it to call java method to retrieve data from DB but synchronously!

Example

If I have an HTML button and on click I will pass ID to a function and I need to retrive the name from the DB via GWT and alert it; simply because GWT is asyncronous, I wont be able to do so everytime and when I alert the result, it will be an empty because it's not filled yet.

Evan Mulawski
  • 54,662
  • 15
  • 117
  • 144
John Donvan
  • 554
  • 8
  • 22
  • RPC call is asynchronous call so it will try to return tags.size before even though rpc call is not completed. so it is not correct logically. put sysout for tags.size in success and remove return statement. Do code inside success if you must required tags list detail. – bNd Jun 23 '12 at 06:33
  • @Bhumika I c but as you see in my [ost I call this from javascript function and the value to be exisit when I call it from javascript so I have to put in the return value is there any work around ? – John Donvan Jun 23 '12 at 06:50
  • This way you are not able to get correct tag list in return statement.but refer jsni. create another method which will call java to javascript. call it on success after setting tag list. this will works. – bNd Jun 23 '12 at 07:07
  • @Bhumika really thx for youe suggestions but still it wont help me out to achieve my work ! my business need is to make a JS function retrieve data from DB but IT MUST BE SYNCHRONOUS – John Donvan Jun 23 '12 at 09:52

4 Answers4

6

You cannot use the native GWT RPC synchronously. I am not sure that this is what you are asking, but here is how to make a call to the server synchronously:

private native String makeSyncAjaxCall(String url, String msgText, String conType)/*-{
    var xhReq = new XMLHttpRequest();
    xhReq.open(conType, url, false);
    if(conType == "POST") xhReq.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
    xhReq.send(msgText);
    var serverResponse = xhReq.status + xhReq.responseText;
    return serverResponse;
}-*/; 

Please note that I am not discussing whether that is good idea or not. You should probably stick with Async and put the alert on the success event.

Eliran Malka
  • 15,821
  • 6
  • 77
  • 100
AhHatem
  • 1,415
  • 3
  • 14
  • 23
  • thank you for your help ! but I need to get GWT RPC work synchronous any work-around may be if there is any delay or wait function that may help ? – John Donvan Jun 23 '12 at 10:37
  • AFAIK, you can't. A lot of people tried to emulate sync using ideas like that... but Javascript is really single threaded, so the callback won't even be done until the delay is over. – AhHatem Jun 23 '12 at 10:39
  • GWT RPC is explicitly designed to prevent this :) so you cannot use it unless you modify the source of course. – AhHatem Jun 23 '12 at 10:41
3

GWT doesn't allow to make synchronous calls to the server, as they can make your browser hang until it gets the response, so for obvious reasons it's best if you can change the flow such that the result from the server will be processed inside the onSuccess event handler.

my business need is to make a JS function retrieve data from DB but IT MUST BE SYNCHRONOUS

You can get data from a database only through java (or using any other server-side language), but not using JavaScript. Just make an asynchronous call from GWT using either RequestBuilder or the GWT RPC mechanism. The returned data can than be process inside the appropriate handlers, as mentioned.

Eliran Malka
  • 15,821
  • 6
  • 77
  • 100
Manikandaraj Srinivasan
  • 3,557
  • 5
  • 35
  • 62
  • I Know manika thats why I use JSNI to retrive the data but I need it synchronous not asynchronous ! – John Donvan Jun 23 '12 at 10:33
  • Use a script tag, and embed it during a javascript call... That should freeze the window for you ;) – Ajax Mar 25 '13 at 00:24
3

Ahmad, referring the example you have quoted :

Call a function on Click , say 'getNamefromID()' in GWT , which makes an asynchronous call to the DB and in the onSuccess() function , call a function that will alert the Name.

public void getNamefromID(int ID) {
    String postUrl = "http://mani/getName";
    String requestData = "q=ID";
    RequestBuilder builder = new RequestBuilder(RequestBuilder.POST,
            postUrl);
    builder.setHeader("Access-Control-Allow-Origin", "*");
    try {
        builder.sendRequest(requestData.toString(), new RequestCallback() {
            public void onError(Request request, Throwable e) {
                Window.alert(e.getMessage());
            }

            public void onResponseReceived(Request request,
                    Response response) {
                if (200 == response.getStatusCode()) {
                    Window.alert("Name :" + response.getText());
                } else {
                    Window.alert("Received HTTP status code other than 200 : "
                            + response.getStatusText()
                            + "Status Code :"
                            + response.getStatusCode());
                }
            }
        });
    } catch (RequestException e) {
        // Couldn't connect to server
        Window.alert(e.getMessage());
    }
}
Eliran Malka
  • 15,821
  • 6
  • 77
  • 100
Manikandaraj Srinivasan
  • 3,557
  • 5
  • 35
  • 62
1

From https://stackoverflow.com/a/40610733/6017801:

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.

Community
  • 1
  • 1