I have created a statuscallback url for Twilio SMS.
But am getting this exception
org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: It is invalid to call isReady() when the response has not been put into non-blocking mode (through reference chain: org.apache.catalina.connector.ResponseFacade["outputStream"]->org.apache.catalina.connector.CoyoteOutputStream["ready"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: It is invalid to call isReady() when the response has not been put into non-blocking mode (through reference chain: org.apache.catalina.connector.ResponseFacade["outputStream"]->org.apache.catalina.connector.CoyoteOutputStream["ready"])
org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:292)
org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:100)
org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:231)
org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:174)
org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:81)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:132)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
org.springframework.web.servlet.mvc.method
My code is as below
#RequestMapping(value = "/getstatus", method = RequestMethod.POST)
public Object getTwilioStatusCallback( HttpServletRequest httpRequest, final HttpServletResponse httpServletResponse){
// System.out.println(httpRequest.getParameter("MessageSid"));
httpServletResponse.setStatus(httpServletResponse.SC_NO_CONTENT);
return httpServletResponse;
}
Two things. First it looks like you are doing a synchronous call, which is a nono in web development. Second, your parameter as MessageSid.. Twilio is notorious for not having the correct reference in their documents. Try messageSid as a parameter. I had the same problem in Node.
You can also look at the entire request body and see how it shows up and get the correct parameter from there, which is what I had to do.
Hopefully this helps.
Related
I am using Jersey Rest implementation. There are one Rest Services Called HelloWorld. See the below code.
Please consider this code as reference not as compiled code.
#Path("helloWorld")
public class HelloWorld{
#Path("test")
#Produces(...)
#Consum(...)
#GET
public Response test(Person person){
System.out.println(person);
}
}
I am using Jersey client to sent the request.
Here My question is apart from POST method is there any way to send the object to GET method directly. Instead of QueryString.
Please let me if there is any way to do so.
Thanks
So the problem shouldn't be with the server. I did a few tests on different servers (not weblogic as I don't use it) and all of them seem to have no problems accepting a body in the GET request. The problem seem to be with the client. To test I used the following code
ClientBuilder.newClient()
.target("http://localhost:8080/api/get-body")
.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true)
.request()
.method(HttpMethod.GET, Entity.text("Hello World"));
The SUPPRESS_HTTP_COMPLIANCE_VALIDATION allows us to pass a body to the request. If we didn't use this, then we would get an error.
The problem with this code, is that even though we set this override property, the client completely overrides the GET method and automatically makes it a POST method, so I would get back a 405 Method Not Allowed.
The solution I came up with is to just allow the client to set a header, e.g. X-GET-BODY-OVERRIDE, and then use a #PreMatching filter on the server side to check for this header. If the header is present, then just change the method to a GET
#Provider
#PreMatching
public class GetWithBodyFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext request) throws IOException {
String getOverride = request.getHeaderString("X-GET-BODY-OVERRIDE");
if (getOverride != null && "true".equalsIgnoreCase(getOverride)) {
request.setMethod(HttpMethod.GET);
}
}
}
Then just register the filter with the server side. On the client, you would simply need to add the header
ClientBuilder.newClient()
.target("http://localhost:8080/api/get-body")
.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true)
.request()
.header("X-GET-BODY-OVERRIDE", "True")
.method(HttpMethod.GET, Entity.text("Hello World"));
This solution is good because it takes into account more than just the Jersey client, in regards with being able to send a body in the GET request.
I've created a REST controller the can handle, as usual, GET, POST, PUT and DELETE HTTP requests using Spring MVC. The web server is Tomcat 8.
If a send request, for instance, with HEAD method, the response is an error page from Tomcat with message
HTTP Status 501 - Method LINK is not is not implemented by this servlet for this URI
I have such exception handler:
#ResponseBody
#ExceptionHandler(Throwable.class)
public ResponseEntity<?> exceptionHandler() {
Error error = createError("error_message.unforeseen_error");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
}
But it doesn't catch any error in this case.
Is there a way to send back a message wrapped in JSON object as a response instead of this Tomcat page?
The problem is that SpringMVC does not find any method for HEAD in your controller, so it does not use it and your #ExceptionHandler is not used. It would be used for exception arising inside the controller. Extract from Spring Frameword Reference : You use the #ExceptionHandler method annotation within a controller to specify which method is invoked when an exception of a specific type is thrown during the execution of controller methods (emphasis mine).
To process exception outside of any controller, you must register a HandlerExceptionResolver bean that will replace the DefaultHandlerExceptionResolver provided by default by Spring MVC. You could either directly put the Json String in the response and return null from resolve method (my prefered way), or put the elements in a model and use a view to format the Json.
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 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.
I'm building a very simple REST API using Jersey, and I've got a warning in my log files that I'm not sure about.
WARNING: A servlet POST request, to
the URI
http://myserver/mycontext/myapi/users/12345?action=delete,
contains form parameters in the
request body but the request body has
been consumed by the servlet or a
servlet filter accessing the request
parameters. Only resource methods
using #FormParam will work as
expected. Resource methods consuming
the request body by other means will
not work as expected.
My webapp only has the Jersey servlet defined, mapped to /myapi/*
How can I stop these warnings?
For me the warning was showing for POST application/x-www-form-urlencoded. And I am using Spring Boot which has an HiddenHttpMethodFilter that does a getParameter before anything else... So I ended up doing this nasty override:
#Bean
public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
return new HiddenHttpMethodFilter() {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
if ("POST".equals(request.getMethod())
&& request.getContentType().equals(MediaType.APPLICATION_FORM_URLENCODED_VALUE)) {
filterChain.doFilter(request, response);
} else {
super.doFilterInternal(request, response, filterChain);
}
}
};
}
This message is meant to warn developers about the fact that the request entity body has been consumed, thus any other attempts to read the message body will fail.
It is safe to ignore the message or filter it out from the logs:
java.util.logging.Logger jerseyLogger =
java.util.logging.Logger.getLogger(WebComponent.class.getName());
jerseyLogger.setFilter(new Filter() {
#Override
public boolean isLoggable(LogRecord record) {
boolean isLoggable = true;
if (record.getMessage().contains("Only resource methods using #FormParam")) {
isLoggable = false;
}
return isLoggable;
}
});
The following thread describes the warning you are receiving. It sounds as though you might have a filter defined in your web.xml that is processing the request before Jersey does.
Finally got rid of this by making sure I had Content-Type: application/json in my request headers (obviously, on the client side)
I just had my ajax-function in JQuery set to contentType: "application/x-www-form-urlencoded; charset=UTF-8" because with a prior solution (without Jersey) I had some encoding problems. When I removed that the message was gone and everything worked fine.
This warning is the only thing the WebComponent logs, so just turn logging up to ERROR level or turn off logging for this component in your logback.xml or wherever you have logging configured. You don't need to write a custom filter to ignore this specific message since there are no other messages logged from this component.
Source code snippet from org.glassfish.jersey.servlet.WebComponent version 2.14:
if(!form.asMap().isEmpty()) {
containerRequest.setProperty("jersey.config.server.representation.decoded.form", form);
if(LOGGER.isLoggable(Level.WARNING)) {
LOGGER.log(Level.WARNING, LocalizationMessages.FORM_PARAM_CONSUMED(containerRequest.getRequestUri()));
}
}
The localized message that is used for this warning message is:
form.param.consumed=A servlet request to the URI {0} contains form parameters in the request body but the request body has been consumed by the servlet or a servlet filter accessing the request parameters. Only resource methods using #FormParam will work as expected. Resource methods consuming the request body by other means will not work as expected.
Turn logging off for the WebComponent in your logback.xml like so:
<logger name="org.glassfish.jersey.servlet.WebComponent" level="OFF" additivity="false"/>
Right.
So I've been suffering this issue, and I've been trying to solve it on different ways, but I did't want to change my web.xml settings, just because if I was testing my application with Postman it worked perfect, but when it was being integrated with the webapp it fails with the mentioned issue (A servlet request to the URI {MY_URI} contains form parameters in the request body but the request body has been consumed by the servlet or a servlet filter accessing the request parameters. Only resource methods using #FormParam will work as expected. Resource methods consuming the request body by other means will not work as expected.)
So as #clijk mentioned, you only have to set your headers as:
"Content-Type":"application/json"
"charset":"UTF-8"
and voilá, the warning it's gone.
Thanks
In my case I've fixed this error when I've changed the Object Date to String in the method.
Error:
#POST
#Path("/myPath")
#Produces(MediaType.APPLICATION_JSON)
public List<MyObject> myMethod(#FormParam("StartDate") Date date) throws Exception {
Fixed
#POST
#Path("/myPath")
#Produces(MediaType.APPLICATION_JSON)
public List<MyObject> myMethod(#FormParam("StartDate") String date) throws Exception {
Put this to your resource signature. Or find this string in your project someone already use this if #PUT or #POST is used. This should help
import javax.ws.rs.Consumes;
#Consumes(MediaType.APPLICATION_JSON)