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.
Related
I have a scalatra servlet with multiple REST APIs. For logging purposes, I use the after() method to print out the return status code after each API is called.
after() {
logger.info("request {} {} returned with status code {}", request.getMethod, request.getRequestURL, response.getStatus.toString)
}
I have noticed that when a method returns with halt, the status code is printed correctly, but when the method return a status code in the last line (without halt), the status code which will be printed will always be 200, regardless of real status returned.
For example:
post("/users/:user") {
try {
//some logic here...
if(condition)
halt(InternalServerError("DB error")) //this will cause status 500 to be printed in the 'after' method
} catch {
case e: Exception =>
InternalServerError("an unknown error occurred") //this will cause status 200 to be printed in the 'after' method
}
}
The user gets back the real status code (500) in both cases.
Any idea why this happens? Is this a bug?
I posted this question on the scalatra-user mailing list, but the list seems to be quite inactive.
Aliza
(disclaimer: I'm not a Scalatra developer but I have been using it for a project. This is based on me reading the code some time ago.)
This has to do with the way Scalatra is handling thrown exceptions (the relevant code seems to be start from this one). If the somewhere in runActions an exception is thrown (halt throws a HaltException), the catch block of cradleHalt will be called and we go to renderHaltException which will set the response status code.
It's not exactly the same when you're not calling halt but returns an ActionResult directly. In that case, executeRoutes seems to produce a value which is then passed on to renderResponse, which will then call renderResponseBody and finally the renderPipeline. This block seems to be the place where the actual status code from an ActionResult is actually set. However, the after function is already called (it was called in actionResult, before executeRoutes returns). So what you get is exactly your behavior: when you don't use halt, the correct response status is only set in the actual response but not your logging call.
You've probably tried this, but the quick fix to your InternalServerError not generating the correct HTTP status code when logged is to simply wrap it in another halt call.
As to whether this is a bug, I can't say. I'm guessing probably not, because they did say in the executeRoutes documentation that after is called before the actionResult is passed to renderResponse. What was not clear was that the act of rendering actionResult also sets the HTTP error code, which you wanted to log before.
You'll have to confirm with them on that :).
I have created a REST service and I was wondering what the best practice was for sending meaningful messages to a GET request. Basically my GET request returns a specific object, something like this;
#GET
#Path("/examsple")
#Produces(MediaType.APPLICATION_JSON)
public List<SomeObject> retrieveSomeObjs() {
List<SomeObject> result = new ArrayList<>();
try {
result = ... Get SomeObjects ...;
} catch (Exception e) {
... Deal with exception ...
}
return result;
}
That works great except when there is an error the response just sends back an empty List! What would be more useful would be a message that explains what the problem is. However I cant send back a String message because the return type is List!
My current solution is to change the return type to a Map and then I can return the object wrapped in the Map along with any messages. However its a little messy on the client side and I was wondering if there was either an inbuilt solution or an 'accepted' solution for this.
If the client has made an error then use HTTP Response codes. If an item is not found then your response would be a 404 Not Found. If the user does not have permissions to access an object then return a 403 Forbidden. Currently you are responding with a 200 OK saying everything is OK when it's not.
If it's an error at the server side you don't really want to be sending that information to your clients. Catch the error on the server and do something meaningful with it (like log it) so you can change the code so it doesn't happen again.
You could return an HTTP error status code in the header and a JSON response body with an object describing the exception.
As already mentioned some common error codes for GET requests include:
301 Moved Permanently - If the resource has been moved
400 Bad Request - If the client request is unaccaptable, i.e. if the client sends none-sense parameters in the request
401 Unauthorized - If the client did not provide any valid credentials
403 Forbidden - If the client is authorized but not allowed to perform the request (you can also return a 404 in this case to conceal that this resource exists at all)
404 Not Found - If the requested resource could not be found
I usually create a POJO to represent these error messages and then return it using a Jersey Response object.
For example the error object could look like this:
public class ApiError {
private String status;
private String code;
private String message;
private String developerMessage;
// Getters and Setters here
}
To return it you can do the following (i.e. in your catch block or your custom ExceptionMapper):
ApiError error = new ApiError("409", "409-1", message, developerMessage);
return Response.status(Response.Status.CONFLICT).entity(error).build();
This way you can provide nicely formatted JSON/XML error messages containing custom error codes and further information for the developer. The error entities will get serialized according to your #Produces annotation.
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.
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.
I am writing some interface for users to collect data and send to a server. I went for GWT for various reasons.
Now, when I try to call my server:
String url = "http://127.0.0.1:3000/data/collection.xml";
RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, URL.encode(url));
Request request = builder.sendRequest(data, new RequestCallback() {
public void onResponseReceived(Request request, Response response) {
if (200 == response.getStatusCode()) {
result.setText("SUCCESS!");
} else {
result.setText("ERROR with code: " + response.getStatusCode());
My server gets the request (a POST with some data) but I get ERROR with code: 0 (!) all the time. I guess this has to do with SOP. I read lots about this SOP but I am even more confused now. I tried to follow this tutorial but that's using a different approach (I managed to adapt it to issue GET calls only, but return objects are always null).
Can anyone point me into the right direction? thanks
You can not call any service from another server because of SOP. What you can do, you can use your original server as proxy to other servers.. I would recommend you to read this tutorial.