HttpMessageNotReadableException: Required request body is missing (Occasional) - SpringMVC Default Controller Request Mapping HTTP Method? - ajax

I have the following code which represents an Ajax POST request:
#RequestMapping("/participant/insertEvent")
public boolean insertEvent(Principal principal, #RequestBody String json, HttpServletRequest request) throws Exception {
//...
//return true or false
}
JS:
$.ajax({
type : "post",
dataType : "json",
url : '/app/participant/insertEvent',
data : JSON.stringify({'p1': p1, 'p2' : p2})
});
The app is deployed in Production and everything has been working with many users the whole week.
This morning I got the following production issue at this method (insertEvent):
org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public boolean
app.controller.participant.AjaxOperationsController.insertEvent(java.security.Principal,java.lang.String,javax.servlet.http.HttpServletRequest) throws java.lang.Exception at
org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:161) at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:130) at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:124) at
org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161) at ...
I'm wondering, is it because I didn't explicitly specify this is a method={RequestMethod.POST} ?
But if I don't specify an HTTP method, what is the default?
However, if this is the issue, then why does the app work 99% of the time, and not for that one user?

FYI, the error was caused by including in the JSON an un-encoded % (percent) special char coming from a TextArea value.

Related

RestController PutMapping malformed url when using "[]"

I have a Spring App witch use a controller like this:
#PutMapping("/block/{blockid}/service/{serviceid}")
public ResponseEntity<String> config(#PathVariable blockid, #PathVariable serviceid, #RequestBody String body) {
{
And I using Postman to test the request, if i send this request to this url:
url: localhost:7000/block/myBlockTest/service/externalServiceTest[0]
Response this error:
Description The server cannot or will not process the
request due to something that is perceived to be a client error
(e.g., malformed request syntax, invalid request message framing, or
deceptive request routing).
I know the problem is "[0]" in the url.
Is there any way I can send this in the URL ?
Thanks.
OK, I just need modify the request to be localhost:7000/block/myBlockTest/service/externalServiceTest%5B0%5D
Special parameters.
https://cachefly.zendesk.com/hc/en-us/articles/215068626-How-to-format-URLs-that-have-special-characters-in-the-filename-

Spring post method "Required request body is missing"

#PostMapping(path="/login")
public ResponseEntity<User> loginUser(#RequestBody Map<String, String> userData) throws Exception {
return ResponseEntity.ok(userService.login(userData));
}
I have this method for the login in the UserController. The problem is when i try to make the post request for the login i get this error:
{
"timestamp": "2018-10-24T16:47:04.691+0000",
"status": 400,
"error": "Bad Request",
"message": "Required request body is missing: public org.springframework.http.ResponseEntity<org.scd.model.User> org.scd.controller.UserController.loginUser(java.util.Map<java.lang.String, java.lang.String>) throws java.lang.Exception",
"path": "/users/login"
}
You have to pass that as JSON in your body, if it's a POST request.
I had a similar issue, was getting this error in my Spring Boot service
HttpMessageNotReadableException: Required request body is missing:...
My issue was that, when I was making requests from Postman, the "Content-Length" header was unchecked, so service was not considering the request body.
This is happening because you are not passing a body to you server.
As can I see in your screenshot you are passing email and password as a ResquestParam.
To handle this values, you can do the following:
#PostMapping(path="/login")
public ResponseEntity<User> loginUser(#RequestParam("email") String email, #RequestParam("password") String password) {
//your imp
}
In order to accept an empty body you can use the required param in the RequestBody annotation:
#RequestBody(required = false)
But this will not solve your problem. Receiving as RequestParam will.
If you want to use RequestBody you should pass the email and password in the body.
You need to send data in Body as JSON
{ "email":"email#email.com", "password":"tuffCookie"}
If it's still not working, try adding additional information UTF-8 in Headers.
key : Content-Type
value : application/json; charset=utf-8
For my case, I must adding UTF-8 in Headers.
In my case it was poorly defined JSON that I sent to my REST service.
Attribute that was suppose to be an object, was in my case just string:
Changed from:
"client" = "",
to:
"client" = { ... },
In my case String did not add additional information about value in different format.

Spring + Angular: How to parse ResponseEntity in angular?

I'm using Spring Boot to create an API that needs to be consumed in Angular 4. Spring and Angular are on different ports.
The problem is that Spring's ResponseEntity raises an error in Angular.
#RequestMapping(value = "/{id}", method = RequestMethod.GET)
public ResponseEntity getFlow(#PathVariable int id) {
Flow flow = flowService.findById(id);
return new ResponseEntity(flow, HttpStatus.FOUND);
}
Now, I can perfectly use Postman to test the API and it works.
But when I make a request from Angular, it returns an error:
Strangely, it returns an error alongside the requested object.
Now, the cause of the problem is that the Spring Boot application returns a ResponseEntity and not a normal object (like String), and Angular doesn't know how to interpret it. If the controller returns just a Flow object, it works.
How can it be solved using ResponseEntity? Or, how else can I send the object alongside the HTTP status code?
Also, in #RequestMapping put produces = "application/json", and in get request in angular, add http options :
const httpOptions = {
headers: new HttpHeaders({
'Accept': 'application/json',
'Content-Type': 'application/json'
})
};
So your get request looks like this:
this.http.get(url, httpOptions)
As per the document mentioned here
https://docs.angularjs.org/api/ng/service/$http
A response status code between 200 and 299 is considered a success status and will result in the success callback being called. Any response status code outside of that range is considered an error status and will result in the error callback being called. Also, status codes less than -1 are normalized to zero. -1 usually means the request was aborted, e.g. using a config.timeout. Note that if the response is a redirect, XMLHttpRequest will transparently follow it, meaning that the outcome (success or error) will be determined by the final response status code.
As you are sending an instance of ResponseEntity(HttpStatus.Found) whose Http status code is 302 which doesnt fall under the success range thats why error callback is called.
Try returning the content like this
return new ResponseEntity(flow, HttpStatus.OK);

Ajax POST to WCF Rest CORS-compliant WebService throws error 405

I'm doing some test over WCF REST WebServices and i'm stuck with the POST call.
I've created a webservice that exposes some test data about the good ol' Northwind DB and since i wish to consume it locally from a test HTML page and since i'd like to test CORS capabilities, i made it CORS compliant by following these instruction http://enable-cors.org/server_wcf.html.
Unfortunately problems comes out when i make POST calls.
Unlike GET calls (works very well), POST call throws this error:
What the hell is it? it seems that "Access-Control-Allow-Origin" header is not correctly managed client-side, beacuse in my EnableCrossOriginResourceSharingBehavior WCF class, the method "ApplyDispatchBehavior" (it filter "Access-Control-Allow-Origin" headers of the arrival requests) is hit when i make a POST call, but then Ajax call fails.
This is my jQuery Ajax post command:
//Create new object
var item = {
"CustomerId": "0",
"CompanyName": "prova"
};
//Push object
$.ajax({
type: "POST",
url: 'http://localhost:3434/NorthwindService.svc/Customer/Create',
crossDomain: true,
headers: {'Access-Control-Allow-Origin' : '*'},
data: JSON.stringify(item),
success: function (data) {
alert('ok!');
},
contentType: 'application/json; charset=utf-8',
dataType: 'json'
});
This is my WCF service Visual Studio 2013 project.
To test it, you only have to set "NorthwindConnectionString" in web.config to an existing one. The webservice method that i've problem with, is the POST to the "http://localhost:3434/NorthwindService.svc/Customer/Create" method, all the others works fine.
This is a preview of my method contract:
[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, UriTemplate = "Customer/Create", BodyStyle=WebMessageBodyStyle.WrappedRequest)]
void NewCustomer(CustomerDTO customer);
Thanks in advance.
I don't know what's going on, but thanks to supertopi and his link, i did the right steps to make it works. Unfortunately implementing all things discussed in here How to handle Ajax JQUERY POST request with WCF self-host did't works. I continued to get "405 Method not allowed" even by creating a new project.
The only thing that works in my case is the following:
1) Implement CustomHeaderMessageInspector and EnableCrossOriginResourceSharingBehavior classes and edit web.config as exposed in http://enable-cors.org/server_wcf.html.
2) Create in the service contract the following method:
[OperationContract]
[WebInvoke(Method = "OPTIONS", UriTemplate = "*")]
void GetOptions();
3) Implementing it empty.
public void GetOptions()
{
}
It sounds crazy, but it actually works.
If i remove GetOptions() operation contract, i continue to get 405 error on my client. If i implement it like indicated by supertopi's link (obviously after remove all stuff created in the step 1), it doesn't work either.
Hope it helps.
Your HTTP Request Method is defined OPTIONS instead of POST.
That is why you get HTTP Response 405 Method not Allowed (no handler for OPTIONS request)
Change the type parameter in jQuery ajax constructor to "POST" and the request is routed to correct handler.

Error 404 RESTFul Service with Ajax

I got a RESTful service call with ajax :
var request = $.ajax({type: "GET",
type : "GET",
url : "/services/equipment/searchEquipments?pId="+id,
cache : false
});
The java method in the service is declared as :
#GET
#Path("/searchEquipments/{pId}")
#Produces("application/json; charset=UTF-8")
public List<EquipmentVO> searchEquipments(#PathParam("pId") String pId){
I got a 404 return code.
I can't understand because after the call, the 404 code is on a weird URL :
http://localhost:7001/services/equipement/searchEquipments?pId=00192772&_=1408446932784
I can't figure why there's &_=1408446932784 at the end ??? It's not a part of the made URL during the call.
Any idea ?
RESTfull service does not accept argument in this way.
the argumant should be a part of the path (as it is defined)
so you should send a get request to "/services/equipment/searchEquipment/"+id
(without the ?pId=)
for example, if the Pid is 123, the path should be
/services/equipment/searchEquipment/123

Resources