Deserializing json array in Spring MVC controller - java

I am sending a list of json object and trying to deserialize it in my Spring controller. But all the time I am getting error of 'Bad request' and results into a status code of 415. However, my json array is a valid one.
json is -
{
"users": [
{
"userName": "john",
"email": "john#gmail.com",
"user_id": "u223344"
},
{
"userName": "Smith",
"email": "smith#gmail.com",
"user_id": "u223345"
}
]
}
Ajax call is as follows -
$.ajax({
url: $("#addNewUser").attr("action"),
data: JSON.stringify({users : dataToSend}),
dataType: 'json',
type: "POST",
beforeSend: function(xhr) {
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("Content-Type", "application/json");
},
success: function(data){
alert('success= ' + data);
},
error:function(data,status,er) {
alert("error: "+ data.responseText +" status: "+status+" er:"+er);
}
});
Wrapper classes are as follows. User and UserWrapper class -
public class User {
private String email;
private String userName;
private String user_id;
//getters and setters
}
public class UserWrapper {
private List<User> userList;
//getter and setter
}
And finally the spring MVC controller is -
#RequestMapping(value="/user/add", method=RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public void createTeamMember(#RequestBody UserWrapper userWrapper) {
try{
for(User user : userWrapper.getUserList()){
System.out.println(user.getEmail());
}
}catch(Exception ex){
ex.printStackTrace();
}
}
I've added dependency for jackson-core and jackson-mapper in pom.xml. And I am using Spring 4.0.3. Any help is appreciated.

As #shazin is saying, you've most likely posted a wrong method to your question, or if not, simply make a change that he suggested.
You'll need another fix, and that is renaming the usersList property from UserWrapper to users so that it matches the JSON property being sent.
We these fixes, you should not have further problems, since your request is OK.

I think you need to change your #RequestBody POJO to UserWrapper
#RequestMapping(value="/task/add", method=RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public void createTeamMember(#RequestBody UserWrapper userWrapper) {
// Code to create members
}

I will not suspect server side binding error yet because you are getting 415 - Unsupported Media Type error. You are setting correct media type on controller and hence server side is looking good.
At client side, Please make sure you are using jquery 1.5+ to make sure beforeSend() method is getting invoked.
Easier way to content type will be,
$.ajax({
url:api,
....
contentType: "application/json"
});
Please inspect network request from browser and make sure content type is set in header.
If you receive 400-Bad Request, then you can start looking deserializing issues.

Related

Request method 'POST' not supported error spring boot and ajax. But GET does not have the same error

Sorry for asking repeated question but I have tried many solutions but none works,
So I have this class and table Draft, in the index.html I have a table containing many data, I want to use ajax to pass all of that data to Controller class in back-end to save that data in the draft table in the database which equivalent to class Draft.
But this error happened Request method 'POST' not supported.
The problem is GET does not return this error and I want to use POST to pass data.
This is my Draft controller class
#Controller
#Secured({"ADMIN","SUPER_ADMIN"})
public class DraftController {
#Autowired
private DraftService draftService;
#PostMapping("/newdraft")
public #ResponseBody Draft AddDraft(#RequestBody Draft draft, BindingResult result) {
draftService.save(draft); // save the draft to database
return draft;
}
}
This is my ajax function
$("#draftFormSubmit").on('click',function(e) {
e.preventDefault();
call_draft();
});
function call_draft() {
var draft = {
"id": 1,
"user_id":5,
"lowest_cost_found":3,
"paper_used":3,
"print_type":3,
"actual_ups_per_paper":3,
"quantity":3,
"color":3,
"size":3,
"gloss_lam":3,
"matt_lam":3,
"water_based":3,
"uv":3,
"varnish":3,
"spot_uv":3,
"emboss_deboss":3,
"hot_stamping":3,
"diecut":3,
"creasing_line":3,
"total_price":3,
"markup":3,
"final_price":3
}
$.ajax({
type: "POST",
contentType: "application/json",
url: "/newdraft",
data: JSON.stringify(draft),
dataType: 'json',
success: function(data) {
alert("success");
console.log(data)
},
error: function() {
alert("failed");
}
});
}
Only in this project the error occurs, when I write a simple POST on another project it does not have this error.
Thank you in advance!
Try to add the following
#Controller
#RequestMapping("/") // <------------
#Secured({"ADMIN","SUPER_ADMIN"})
public class DraftController {
and check again

Webhook to collect a JSON: Request method POST not supported

I'm writing a controller with Java for a webhook URL that receives a POST method call, with a JSON body, that I need to collect.
This is a simplified version of the controller, with Spring annotations:
#RestController
public class MyWebhoook {
#PostMapping("/my-webhook")
public void getMyJson(#RequestBody Map<String, Object> json) {
System.out.println("WebHook collected JSON: " + json);
}
}
I test it with Postman sending this JSON:
Header: Content-Type / application/json
{
"webhookKey" : "tranviaVermellCostaAvall",
"token" : "xx",
"channelId": 1,
"propertyId": "999999",
"status": "new",
"reservationId": "111211221",
"reservationStatus" : 1
}
And I get this answer:
{
"timestamp": "2019-04-09T07:23:38.093+0000",
"status": 405,
"error": "Method Not Allowed",
"message": "Request method 'POST' not supported",
"path": "/my-webhook"
}
The server log, gives some more information:
Request method 'POST' not supported, path=/my-webhook}] as "application/json" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter#7756c3cd
I've tried those different approaches, with the same result:
#RequestMapping(value = "/my-webhook", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.POST) instead of the #PostMapping("/my-webhook") annotation.
Modelling the received JSON as a java object instead of the Map<String, Object> json.
Using HttpServletRequest instead of the #RequestBody annotation, trying to read the request as a String.
I do not understand the reason why the POST method is not allowed. Any help, would be very much appreciated.
I added {} between your method and got a 200 as return. I added the pictures below on what code, request and console output i got.
I copied your code to my spring boot app, worked perfectly via postman...
API:
#PostMapping("/my-webhook")
public void getMyJson(#RequestBody Map<String, Object> json) {
System.out.println("WebHook collected JSON: " + json);
}
RequestBody:
{
"webhookKey" : "tranviaVermellCostaAvall",
"token" : "xx",
"channelId": 1,
"propertyId": "999999",
"status": "new",
"reservationId": "111211221",
"reservationStatus" : 1
}
URL: http://localhost:8080/my-webhook
Try to:
Update and Clean your project.
Invalidate IDE cache and restart it, and try again.
The problem was with the CSRF (Cross-site request forgery) security configuration. The path of the webhook, has to be taken out of the CSRF control. Otherwise, the POST request doesn't pass the CSRF control.
This is a simplified extract of the security settings:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http)throws Exception{
http
.csrf()
.ignoringAntMatchers("/my/webhook")

spring mvc transport json to object

I am trying to post a json using ajax to my spring mvc controller I am using code like this in my js file:
$('#regist').click(function () {
$.ajax({
url: 'user/regist',
contentType: "application/json; charset=utf-8",
type: 'post',
dataType: 'json',
success: function (data) {
var json = JSON.stringify(data);
alert(json);
},
fail: function (errMsg) {
alert(errMsg);
},
data: JSON.stringify({
'IDCard': '1234567890'
})
})
});
the signature of my controller function is like this:
#RequestMapping(value = "/regist", method = RequestMethod.POST)
#ResponseBody
public ResultJson regist(HttpSession session, #RequestBody RegistFormJson json)
the RegistFormJson goes like this:
public class RegistFormJson {
private String IDCard;
public String getIDCard() {
return IDCard;
}
public void setiDCard(String IDCard) {
this.IDCard = IDCard;
}
}
now when I send my request, and what I get from my controller using
logger.info(json.getIDCard);
is null.When I change my bean propertity to idCard and change my other code as well ,I can get the result successfully. Who can tell me why ? And If I want to use IDCard in my code, how can I get the result .Thanks
Spring comes with Jackson API which uses Standard Java Code Convention to map JSON properties to Java models.
Since IDCard is not in lower camel case, Jackson API is not able to map the JSON property.
To overcome this you need to specify a #JsonProperty("IDCard") annotation on a Java attribute in order to use IDCard for your JSON property.
Likewise, you can set the PropertyNamingStrategy on the ObjectMapper to overcome this issue.

Why does Spring MVC respond with 415 for an Ajax query requesting JSON?

I've read 3/4 posts on Stack plus many other examples to try figure this out but I've no clue ! Need some pointers please !!
Creating my first Ajax update through Spring-MVC and I keep getting a Status 415 being returned by my submission with The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request accept
JQuery... Version 3.1.1
function updateScore () {
$("div#results").append("<p>Posting User/Game ID " + this.id + " Value " + this.value + "</p>");
var prediction = {}
prediction["id"] = this.id;
prediction["value"] = this.value;
$.ajax({
type : "POST",
contentType : "application/json",
url : "/tournament/setPrediction.html",
data : JSON.stringify(prediction),
dataType : 'json',
timeout : 100000,
success : function(data) {
console.log("SUCCESS: ", data);
displayResult(data, "success");
},
error : function(e) {
console.log("ERROR: ", e);
displayResult(e, "error");
},
done : function(e) {
console.log("DONE");
displayResult(true, "done");
}
});
}
Controller... Spring version 4.3.5
#RestController
public class PredictionAjaxController {
#ResponseBody
#RequestMapping(value = "/setPrediction.html", consumes = MediaType.APPLICATION_JSON_VALUE,
method = RequestMethod.POST, headers="Accept=application/json")
public Prediction setUserPrediction(#RequestBody PredictionPojo prediction) {
Prediction result = new Prediction();
System.out.println("AJAX call made in controller");
return result;
}
}
Finally a very simple POJO for the JSon to map to
public class PredictionPojo {
private String id;
private String value;
Getters & Setters... ()
}
I've added different things onto the controller now to try and resolve, didn't start with it all ! I'm completely confuddled !
Should be so simple...
DH
You have an error in your ajax call, you are sending a string instead of a JSON object. Also I don't think is necessary to specify the consumes and headers attributes in you #RequestMapping annotation in your setUserPrediction method, The PredictionAjaxController is already defined as a RestController. Your ajax should be:
$.ajax({
// .......
data : prediction,
// .......
});

I got 404 error after sending POST method from ajax (#ResponseStatus & ResponseEntity)

I ma using Spring MVC and trying to use jQuery. I have this on my web page:
$(document).ready(function () {
var entity = {mag: "status_key", paper: "View10"};
$("#btn").click(function () {
$.ajax({
url: "ajaxJsonPost",
type: 'post',
dataType: 'json',
data: JSON.stringify(entity),
contentType: 'application/json',
});
});
});
Spring server has this:
#RequestMapping(value = "ajaxJsonPost", method = RequestMethod.POST)
public void postJson(#RequestBody Entity en) throws IOException {
System.out.println("writing entity: " + en.toString());
}
OK, Entity cames to server. BUT browser console prints 404 not found. I know that my POST request needs any response. In the Internet I've found solution which recommends me to return ResponseEntity object, OR use annotation #ResponseStatus. They both return HttpStatus well, but I don't know in which cases I should use them. What is the best way?
#Controller
#RequestMapping("/apipath")
public class SomeController {
#RequestMapping(value = "/ajaxJsonPost", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public String postJson(#RequestBody final Entity en) {
System.out.println(en.toString());
//assuming you have a class "EntityService" and
//it has a method postData
//which takes Entity object as parameter and pushes into database.
EntityService.postData(en);
System.out.println("added");
return "success";
}
}
Entity object on the Server side
#JsonAutoDetect
public class Entity {
private String mag;
private String paper;
public String getMag() {
return mag;
}
public void setMag(final String mag) {
this.mag = mag;
}
public String getPaper() {
return paper;
}
public void setPaper(final String paper)
this.paper = paper;
}
}
ajax
$(document).ready(function () {
var entity = {mag: "status_key", paper: "View10"};
$("#btn").click(function () {
$.ajax({
url: "/apipath/ajaxJsonPost",
type: 'post',
dataType: 'json',
data: JSON.stringify(entity),
contentType: 'application/json',
success : function(response) {
alert(response);
},
error : function() {
alert('error');
}
});
});
});
And as far as why and when to use #ResponseStatus and #ResponseEntity, there is already a short and simple answer here by #Sotirios Delimanolis. When use #ResponseEntity .
It says :
ResponseEntity is meant to represent the entire HTTP response. You can
control anything that goes into it: status code, headers, and body.
#ResponseBody is a marker for the HTTP response body and
#ResponseStatus declares the status code of the HTTP response.
#ResponseStatus isn't very flexible. It marks the entire method so you
have to be sure that your handler method will always behave the same
way. And you still can't set the headers. You'd need the
HttpServletResponse or a HttpHeaders parameter.
Basically, ResponseEntity lets you do more.

Categories