In GWT, when is the AsyncCallback:onFailure method called in a json-p request using JsonpRequestBuilder - gwt

I've been implementing a GWT application that calls a REST-service (which we're also developing). When the REST-service returns anything with a HTTP-status other than 200 I would expect the onFailure method of AsyncCallback to be called. However I can't get this to happen.
To test it further I created a test GWT app and a test servlet. The part of the GWT app that calls the service looks like this:
JsonpRequestBuilder jsonp = new JsonpRequestBuilder();
jsonp.setCallbackParam("_jsonp");
jsonp.setFailureCallbackParam("_jsonp_failure");
jsonp.requestObject(url, new AsyncCallback<JavaScriptObject>()
{
#Override
public void onFailure(Throwable caught)
{
Window.alert("Failure: " + caught.getMessage());
}
#Override
public void onSuccess(JavaScriptObject result)
{
Window.alert("Success");
}
});
The servlet-code looks like this:
public class MyRestServlet extends HttpServlet
{
protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException
{
String padding = httpServletRequest.getParameter("_jsonp_failure");
httpServletResponse.setContentType("application/x+javascript");
httpServletResponse.setStatus(500);
PrintWriter out = httpServletResponse.getWriter();
out.println(padding + "({\"some\":\"json\"});");
out.close();
}
}
OnFailure eventually gets called when the request times out, but I would expect it to be called as soon as the http response arrives(if it's a failure). I guess there is something I haven't understood and I would really appreciate to get some help with this.
Thanks

According to HTML5, if there's an error loading the script, an error event should be dispatched, and GWT doesn't listen for it (because almost no browser actually fires it AFAICT).
For best browser compatibility, you'd better always send a 200 status, but then call the failure callback (or in other words, return an error state/condition, rather than throw an exception).
Also, the argument to the failure callback is expected to be a string (will be the message of the exception).

From the server code where you call the REST service, throw an exception yourself if the response is something other than 200 (by writing code to check the response yourself). This way it will persist to the client side as an error and onFailure will be called in client side.
In GWT's mind currently nothing went wrong. It sent a request, got some result did not matter what, the call was successful. It does call the onFailure on a timeout because something did go wrong with the request "physically", and GWT persisted the exception to the client side as a failure.

Related

Why is sendRedirect(String path) not throwing IllegalStateException?

I've following code in my servlet
public class RedirectingExceptionServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.println("Hello, response is being committed");
out.flush();
response.sendRedirect("redirectedExceptionServlet");
System.out.println("Tried redirecting after committing response");
}
}
Here, I'm trying to redirect after the response has been committed.
As per the specification Send Redirect java doc sendRedirect(String) should throw IllegalStateException if you try to call sendRedirect(path) after response is committed
Rather i see a page with message : Hello, response is being committed
Another interesting thing is, i'm unable to see statement "Tried redirecting after committing response" in server console
Can someone pls explain me this behavior?
Env details : Windows 7, Tomcat 7.0.47, J2EE-6
Once the container encounters out.flush(); it returns from there and doesn't execute remaining lines of code or simply ignores them and this is true only in case there is no redirection before out.flush();
I have tried a lot of combinations. If someone is interested to have a look at these combinations, I can share them

GWT: What to expect when an HTTP request fails

I'm sending an HTTP request with RequestBuilder.send(). I would expect to see successful responses come back in onResponseReceived(), and errors come back in onError(). But that's not what I'm seeing. GWT calls onResponseReceived() regardless of success or failure.
Does anyone know what I should really expect? Do you have any information that would help me detect and report errors better?
Here's some sample code:
builder.sendRequest(null, new RequestCallback() {
#Override
public void onResponseReceived(Request request, Response response) {
Header[] debugHeaders = response.getHeaders();
String debugHeaders1 = response.getHeadersAsString();
int debugStatusCode = response.getStatusCode();
String debugStatusText = response.getStatusText();
String debugText = response.getText();
handleResponse(response);
}
#Override
public void onError(Request request, Throwable exception) {
reportError();
}
});
I can force an error on my computer by disabling the Wi-Fi. In that case onResponse() is called. getHeaders() returns an array of length 1, with the only entry set to null. getHeadersAsString returns "". getStatusCode returns 0. getStatusText() returns "". getText() returns "".
If this is always the case, I can look for that in my code. However, I expect that different browsers, different errors, etc, will cause a different result. Is there any good way to always detect an error?
(As long as there are no HTTP problems, my code works fine.)
This the expected behavior; see comments in: https://code.google.com/p/google-web-toolkit/issues/detail?id=2858
According to documentation onResponseReceived is called in both cases (success or not).
I got the same on old browsers when my browser tried to go to download something and the prev. http request was not completed. So maybe try to wait untill the response is completed, maybe try to add some 200 msec. delay somewhere.
In my application i ignore when status code is 0.

What is best apprach to attempt multiple times same RPC call

What is best way to attempt multiple time same RPC call while failing RPC call?
just example: Here one case like if RPC get failed due to network connection, it will catch in onFailure(Throwable caught).
Now here it should recall same RPC again for check network connection. The maximum attempt should be 3 times only then show message to user like "Network is not established"
How can I achieve it?
Some couple of thoughts like call same rpc call in onFailure but here request become different.but I want same request have a three request and it is not good approach and I don't know if any good solution for it.
Thanks In Advance.
Use a counter in your AsynCallBack implementation. I recommend as well to use a timer before requesting the server again.
This code should work:
final GreetingServiceAsync greetingService = GWT.create(GreetingService.class);
final String textToServer = "foo";
greetingService.greetServer(textToServer, new AsyncCallback<String>() {
int tries = 0;
public void onSuccess(String result) {
// Do something
}
public void onFailure(Throwable caught) {
if (tries ++ < 3) {
// Optional Enclose the new call in a timer to wait sometime before requesting the server again
new Timer() {
public void run() {
greetingService.greetServer(textToServer, this);
}
}.schedule(4000);
}
}
});
#Jens given this answer from Google Groups.
You could transparently handle this for all your requests of a given GWT-RPC interface by using a custom RpcRequestBuilder. This custom RpcRequestBuilder would make 3 request attempts and if all 3 fail, calls the onFailure() method.
MyRemoteServiceAsync service = GWT.create(MyRemoteService.class);
((ServiceDefTarget) service).setRpcRequestBuilder(new RetryThreeTimesRequestBuilder());
The custom RequestBuilder could also fire a "NetworkFailureEvent" on the eventBus if multiple application components may be interested in that information. For example you could overlay the whole app with a dark screen and periodically try sending Ping requests to your server until network comes back online. There is also the onLine HTML 5 property you can check, but its not 100% reliable (https://developer.mozilla.org/en-US/docs/Web/API/window.navigator.onLine)

How can I determine why onFailure is triggered in GWT-RPC?

I have a project that does 2 RPC calls and then saves the data that the user provided in tha datastore. The first RPC call works ok, but from the second I always recieve the onFailure() message. How can I determine why the onFailure() is triggered? I tried caught.getCause() but it doesn't return anything.
feedbackService.saveFeedback(email,studentName,usedTemplates,
new AsyncCallback<String>() {
public void onFailure(Throwable caught) {
// Show the RPC error message to the user
caught.getCause();
Window.alert("Failure!");
}
public void onSuccess(String result) {
Window.alert("Saved!");
}
});
Throwable instance is instance of an Exception. You can check if it is a custom Exception like this:
if (caught instanceOf CustomException){
or if you want to show the message of exception you can use the getMessage():
Window.alert("Failure: " + caught.getMessage());
GWT-rpc is not not easy to ebug if an error occurs.
The easiest part is th check if the Exception is part of StatusCodeException.
A Statuscode of 404 means, you are pointing to a wrong endpoint
0 means, that
The searver is unreachable
You don't have permissions to check, if the server is available (X-domain-request)
You can use the Chrome-Web-Inspector to bedug GWT-RPC
You should be able to see all calls from the browser to you backend.
The most common failures are because of serialization of object. You have to ensure, that all dtransferred object implement java.io.Serializable
Most of the time it will just be a server side exception being raised which fires the onFailure() method.
Try putting breakpoints on your server side. That should help you pinpoint what's going wrong.

GWT JSONPRequestBuilder - "Unknown Token :" error in browser console with Timeout exception at the end

I am trying to call a Restful WS from GWT using JSOPRequestBuilder. I have a similar issue which was reported in the link
http://groups.google.com/group/google-web-toolkit/browse_thread/thread/ef93383aca7a3dfc/d4dc5bad1a9110ea
But, I could not figure out the solution. Kindly help me at the earliest.
My JAX-WS resource code snippet from server
#GET
#Produces(MediaType.APPLICATION_JSON)
public DealerAddress getDealerAddress(#QueryParam("dealerId") String sDealerId) {
DealerAddress dlrAd = new DealerAddress("test", "test", "test", "test", 10, new Date(), new Date());
return dlrAd;
}
Jersey returns a JSON object of DealerAddress.
Now rest URL "https://127.0.0.1:8181/application/rest/OrderManagementResource?alt=json-in-script&dealerId=DLR1"
works absolutely fine when i tried request in browser.
It even works with RequestBuilder approach from GWT but not with JSONPRequestBuilder approach.
Code snippet to invoke WS from GWT using JSONPRequestBuilder
JsonpRequestBuilder jsonPReqBuilder = new JsonpRequestBuilder();
jsonPReqBuilder.setTimeout(100000);
jsonPReqBuilder.setCallbackParam("callback");
jsonPReqBuilder.requestObject("https://127.0.0.1:8181/application/rest/OrderManagementResource?alt=json-in-script&dealerId=DLR1" , new AsyncCallback<DealerAddressJSON>() {
#Override
public void onFailure(Throwable caught) {
// TODO Auto-generated method stub
caught.printStackTrace();
Window.alert("Inside error"+caught.getLocalizedMessage());
}
#Override
public void onSuccess(DealerAddressJSON result) {
// TODO Auto-generated method stub
Window.alert("Inside success"+result);
}
});
where as DealerAddressJSON is a JavaScriptObject type class.
I could see that my JAX Rest resource getting called and saying returning from server.
Also, I could see that in Firebug that the response comes in browser but fails with an exception "Unknown token :"
At the end I always get a Timeout exception.
Now I am in big question whether the way we return JSON from JAX-RS resource is a problem in server
or
JSONPRequestBuilder calling procedure is a problem? I could not understand the callback changes which some of the links explained on this issue.
Kindly help me.
You are probably sending back JSON, while the JSONPRequestBuilder expects JSONP. These are not the same thing.
JSON is just the data, as is - make the request using AJAX (i.e. the RequestBuilder), and the contents can be read directly. These requests can only be made to the same server. Example JSON data:
{"response":"success", "items":[{"id":1}, {"id":2}]}
In contrast, JSONP is designed for cross-origin requests, so instead of just containing the data, the data is wrapped up in a JavaScript. Since your JSON service isn't wrapping the a response in a js function call, this isn't working. Example JSONP data:
callback_1({"response":"success", "items":[{"id":1}, {"id":2}]})
The callback changes with each request, so the server is supposed to change that callback function based on what the client requested each time.