I am using play 2.2.0
I have a Global object settings defined with methods onError and onHandlerNotFound overridden. From view I am making ajax call which throws 500 internal server due to sql syntax issue, but I am not able to see 500 internal page that I have setup in onError method, but I can see NotFound page if handler is not found. Is it something expected because I am using ajax request.
object Global extends WithFilters(LogFilter) with GlobalSettings {
override def onError(request: RequestHeader, ex: Throwable) = {
Future.successful(InternalServerError(
views.html.error(ex)
))
}
...
}
I suppose that is expected, as your two ajax requests are most likely different (as Ashalynd mentioned, post your frontend code). Where you do your ajax request capture the response and redirect accordingly. E.g. with jQuery:
$.ajax({
url: "http://wherever.com",
type: 'GET',
success: function(msg) {
// Do successful things
},
error: function (xhr, ajaxOptions, thrownError) {
// Redirect
window.location.href = "/errorpage.html";
// Or some weird form of "redirect" (don't use this, just
// for demonstration purpose, showing how you can capture
// whatever you sent along with your error)
var responseText = $.httpData(xhr);
document.body.innerHtml = responseText;
}
});
It's a feature of Play! 2.2. I have the same problem with Play! 2.2.1, Java API and using curl from command line. It's just that onHandlerNotFound works as specified, but onError just leaves the HTTP connection hanging and never returns a response.
Downgrading to 2.1.5 fixes the problem.
Related
xhrPost seems to be modifying the URL resulting in either 404 or 405.
This is from a custom widget and attempting to go to a REST service on a WebSphere Liberty server.
The rest service responds correctly when using RESTClient and building the request manually.
I am using var jsonData = JSON.stringify(domForm.toObject("TaskTemplate")); so I can verify the data is correct and sending the data as that string:
data: jsonData,
the URL is hardcoded in the form and no substitution is currently being used:
<form id="TaskTemplate" name="TaskTemplate"
data-dojo-attach-point="taskTemplateNode"
method="POST"
action="http://localhost:9080/test2/rm/tasks/64/update">
I also have a GET with a URL of "http://localhost:9080/test2/rm/tasks/64/" that is working fine.
Seems to be associated with PUT or POST...
When I do the xhrPost, I am getting the following error:
"NetworkError: 404 Not Found - http://localhost:9080/test2/undefined"
since "undefined" is seen, it is like xhrPost is doing some substitution in the hardcode URL...
I am using 1.9.2-20140219-IBM version of dojo which comes with Rational Application Developer.
I have tried both xhrPost and xhrPut with the same results.
Here is the method that is invoked when the button is pushed:
applySubmit: function() {
console.log("inside applySubmit");
var jsonData = JSON.stringify(domForm.toObject("TaskTemplate"));
console.log(jsonData);
var xhrArgs = {
// url: "http://localhost:9080/test2/rm/tasks/64/update",
data: jsonData,
preventCache: true,
timeout: 10000,
handleAs: "text",
contentType: "application/json",
load: function(data) {
console.debug("applySubmit success:" + data);
},
error: function(data) {
console.debug("applySubmit error:");
}
};
console.log("doing dojo.xhrPxxx(xhrArgs);");
var deferred = dojo.xhrPost(xhrArgs); // any need to save local var and exit?
}
In the server logs, I am seeing [WARNING ] SRVE0190E: File not found: /undefined
and that is coming from the webcontainer (makes sense given the error msg above)
So, this means it is not related to my rest service, never gets to it.
This is really starting to delay our project, so any ideas about why this might be occurring would be greatly appreciated!
I started using Restangular to send RESTful requests from my AngularJS app. I have a REST service deployed on http://localhost:20080/v1/customer which produces JSON with customer information.
When I debug AngularJS app it hits a breakpoint in the back-end REST service, however in the browser console it always logs "Failed to find customers with status code 0". Moreover, I never hit the breakpoint in the function that I register as setResponseExtractor.
I also don't see any errors in the console.
When I open http://localhost:20080/v1/customer in the browser I get the following response:
[{"customerInfo":{"name":"My Name","email":"My Email"},"id":"6ca43d0f-94a8-36e8-af3d-963584573d6d"}]
My Restangular code is as follows:
var customerModule = angular.module('customer-module',
['restangular' ]).config(
['RestangularProvider', '$httpProvider',
function (RestangularProvider, $httpProvider)
{
RestangularProvider.setBaseUrl('http://localhost\\:20080/v1');
RestangularProvider.setResponseExtractor(function (response, operation, what) {
return response;
});
...
customerModule.controller('CustomerCtrl',
[ '$scope', 'Restangular', function ($scope, Restangular)
{
var baseCustomers = Restangular.all("customer");
$scope.customers = baseCustomers.getList().then(function (result) {
console.log("Got customers", response.status);
}, function (response) {
console.log("Failed to find customers with status code", response.status);
});
Thoughts?
I'm the creator of Restangular.
You also don't have to add the responseExtractor to the config if you're just returning the response. That's what it does by default.
If you have any other problem, please contact me!
The problem turned out to be with accessing REST services running on a different port than my AngularJS app.
I am moving this thread to AngularJS mailing list - "Problems with a basic $resource.get() call"
Alec
I'm trying to learn how to use web sockets in Play 2.1, and I'm having trouble getting the web socket URL to work with my app's routing configuration. I started with a new Play application and the Play framework documentation on websockets.
Here is my conf/routes:
# Home page
GET / controllers.Application.index
# Websocket test site
GET /wstest controllers.Application.wstest
Then I added the wstest function to my controller class:
object Application extends Controller {
def index = Action {
Ok(views.html.index("Websocket Test"))
}
def wstest = WebSocket.using[String] { request =>
// Log events to the console
val in = Iteratee.foreach[String](println).mapDone { _ =>
Logger.info("Disconnected")
}
// Send a single 'Hello!' message
val out = Enumerator("Hello!")
(in, out)
}
}
However, so far, I can only access the websocket with the URL ws://localhost:9000/wstest (using the sample code at websocket.org/echo.html). I was looking at the sample/scala/websocket-chat app that comes with the Play framework, and it uses the routing configuration file to reference the websocket, like this:
var WS = window['MozWebSocket'] ? MozWebSocket : WebSocket
var chatSocket = new WS("#routes.Application.chat(username).webSocketURL()")
I tried replacing my websocket URL with #routes.Application.wstest.webSocketURL() and #routes.Application.wstest. The first one doesn't compile. The second one compiles, but the client and server don't exchange any messages.
How can I use my Play routing configuration to access this websocket? What am I doing wrong here?
Edit
Here is a screenshot of my compilation error, "Cannot find any HTTP Request Header here":
Without the compiler error it's hard to guess what might be the problem.
Either you have to use parens because of the implicit request, i.e. #routes.Application.wstest().webSocketURL(), or you have no implicit request in scope which is needed for the webSocketURL call.
Marius is right that there was no implicit request in scope. Here's how to get it in scope:
Update the index function in the controller:
def index = Action { implicit request =>
Ok(views.html.index("Websocket Test"))
}
Add the request as a curried parameter to index.scala.html:
#(message: String)(implicit request: RequestHeader)
#main(message) {
<script>
var output;
function init() {
output = document.getElementById("output");
testWebSocket();
}
function testWebSocket() {
websocket = new WebSocket("#routes.Application.wstest.webSocketURL()");
.
.
.
And now the RequestHeader is in scope.
I'm making a REST DELETE call, which returns a 204. In jQuery 1.8.3 this works, and hits the request.done callback. But if I use 1.9 it goes to request.fail with a parsererror in the textStatus and a 'SyntaxError: Unexpected end of input' in the errorThrown.
remove = function (complete) {
var self = this;
var request = $.ajax({
context: self,
url: "/v1/item/" + itemId,
dataType: "json",
type: "DELETE"
});
request.done(removeCallback);
request.fail(function (xhr, textStatus, errorThrown) {
alert(errorThrown);
});
},
Anyone know what has changed in 1.9 that would cause this to fail, and what needs to change in order to fix it?
So, answering my own question it looks like this is in fact the problem:
From the jQuery upgrade guide
jQuery.ajax returning a JSON result of an empty string
Prior to 1.9, an ajax call that expected a return data type of JSON or JSONP would consider a return value of an empty string to be a success case, but return a null to the success handler or promise. As of 1.9, an empty string returned for JSON data is considered to be malformed JSON (because it is); this will now throw an error. Use the error handler to catch such cases.
So, if remove the dataType
dataType: "json",
It works in jQuery 1.8.3 and 1.9.
An HTTP 204 response is not an empty string: it means there is no data. This is a valid response for delete and update operations.
This looks like a bug introduced in JQuery 1.9.
The reason removing the dataType property fixes this is because when it's set to "json" JQuery attempts to parse the content using JSON.parse and failing as a result. From the ticket:
This won't fail with any other dataType than "json" because the
regression is due to the re-alignment of parseJSON with native
JSON.parse (throwing an exception for null/undefined values).
Don't try the workaround suggested in the ticket of adding a handler for the 204 via the statusCode property, because both that handler and the error handler will be triggered. A possible solution is the following:
$.ajax(url, {
type: "DELETE",
dataType: "json",
error: function (error) {
if (error.status === 204) {
// Success stuff
}
else {
// fail
}
}});
I was having a very similar problem, and you helped my find my answer - so thank you. My solution, however is slightly different, so I figured I would share it.
As stated in the question, on the JQuery website it says:
Prior to 1.9, an ajax call that expected a return data type of JSON or JSONP would consider a return value of an empty string to be a success case, but return a null to the success handler or promise. As of 1.9, an empty string returned for JSON data is considered to be malformed JSON (because it is); this will now throw an error. Use the error handler to catch such cases.
I was passing JSON data to a method on my server with "void" as a return type because I did not need to do anything with returned data in the success function. You can no longer return null when passing JSON in an AJAX request in JQuery 1.9 +. This was possible in previous versions of JQuery however.
To stop getting an error and get the success function to fire instead, you must simply return valid JSON in your AJAX request. It doesn't matter what you pass, as long as it's valid, because (in my case anyways) you are not using the returned data.
The problem seems to be that jQuery treats the empty body (where Content-Length is 0) of a 204 response as "". Which is one interpretation, but the downside is that "" gets treated like any other response string. So if you have called jQuery.ajax() with the dataType:json option, jQuery tries to convert "" to an object and throws an exception ("" is invalid JSON).
jQuery catches the exception and recovers, but if you prefer to avoid the exception altogether (in your development environment) you might do something like the following. Add in the "converters" option to jQuery.ajax() and use it to change "" responses to nulls (I do this when dataType is json). Something like :
var ajax_options =
{
/* ... other options here */
"converters" :
{
"text json" :
function( result )
{
if ( result === "" ) result = null;
return jQuery.parseJSON( result );
}
}
};
var dfd = jQuery.ajax( ajax_options );
I'm building upon RESTFul Store example of ExtJs 4. I'd like my script to display errors provided by the REST server, when either Add or Delete request fails. I've managed to obtain the success status of a request (see the code below), but how do I reach the message provided with the response?
Store:
var store = Ext.create('Ext.data.Store', {
model: 'Users',
autoLoad: true,
autoSync: true,
proxy: {
type: 'rest',
url: 'test.php',
reader: {
type: 'json',
root: 'data',
model: 'Users'
},
writer: {
type: 'json'
},
afterRequest: function(request, success) {
console.log(success); // either true or false
},
listeners: {
exception: function(proxy, response, options) {
// response contains responseText, which has the message
// but in unparsed Json (see below) - so I think
// there should be a better way to reach it than
// parse it myself
console.log(proxy, response, options);
}
}
}
});
Typical REST response:
"{"success":false,"data":"","message":"VERBOSE ERROR"}"
Perhaps I'm doing it all wrong, so any advice is appreciated.
I assume that your service follows the REST principle and uses HTTP status codes other than 2xx for unsuccessful operations.
However, Ext will not parse the response body for responses that do not return status OK 2xx.
What the exception/response object (that is passed to 'exception' event listeners) does provide in such cases is only the HTTP status message in response.statusText.
Therefore you will have to parse the responseText to JSON yourself. Which is not really a problem since it can be accomplished with a single line.
var data = Ext.decode(response.responseText);
Depending on your coding style you might also want to add some error handling and/or distinguish between 'expected' and 'unexpected' HTTP error status codes. (This is from Ext.data.reader.Json)
getResponseData: function(response) {
try {
var data = Ext.decode(response.responseText);
}
catch (ex) {
Ext.Error.raise({
response: response,
json: response.responseText,
parseError: ex,
msg: 'Unable to parse the JSON returned by the server: ' + ex.toString()
});
}
return data;
},
The reason for this behavior is probably because of the REST proxy class not being a first class member in the data package. It is derived from a common base class that also defines the behavior for the standard AJAX (or JsonP) proxy which use HTTP status codes only for communication channel errors. Hence they don't expect any parsable message from the server in such cases.
Server responses indicating application errors are instead expected to be returned with HTTP status OK, and a JSON response as posted in your question (with success:"false" and message:"[your error message]").
Interestingly, a REST server could return a response with a non-2xx status and a response body with a valid JSON response (in Ext terms) and the success property set to 'true'. The exception event would still be fired and the response body not parsed.
This setup doesn't make a lot of sense - I just want to point out the difference between 'success' in terms of HTTP status code compared to the success property in the body (with the first having precedence over the latter).
Update
For a more transparent solution you could extend (or override) Ext.data.proxy.Rest: this will change the success value from false to true and then call the standard processResponse implementation. This will emulate 'standard' Ext behavior and parse the responseText. Of course this will expect a standard JSON response as outlined in your original post with success:"false" (or otherwise fail).
This is untested though, and the if expression should probably be smarter.
Ext.define('Ext.ux.data.proxy.Rest', {
extend: 'Ext.data.proxy.Rest',
processResponse: function(success, operation, request, response, callback, scope){
if(!success && typeof response.responseText === 'string') { // we could do a regex match here
var args = Array.prototype.slice.call(arguments);
args[0] = true;
this.callParent(args);
} else {
this.callParent(arguments);
}
}
})