I am posting a POJO where I get an error saying the field is not included.
Asset POJO
public class Asset {
private MultipartFile[] files;
private String name;
private String meta;
//Constructor/Getters n Setters
}
Resource Method
#PostMapping("asset")
public ResponseEntity uploadAsset(#RequestParam("asset") Asset asset) {
System.out.println(asset);
return new ResponseEntity(HttpStatus.ACCEPTED);
}
PostMan JSON Body
{
"asset" : {
"files": [
"#/home/Downloads/1.jpeg",
"#/home/Downloads/2.jpeg"
],
"name": "assetName",
"meta": "assetMeta"
}
}
PostMan JSON Response
{
"timestamp": "2019-10-29T20:46:19.536+0000",
"status": 400,
"error": "Bad Request",
"message": "Required Asset parameter 'asset' is not present",
"path": "/asset"
}
I don't understand why I get the Required Asset parameter 'asset' is not present message when I have it in the JSON body. Any ideas on this?
Use #RequestBody rather than #RequestParam
public ResponseEntity uploadAsset(#RequestBody Asset asset) {
Based on your payload, Spring is expecting an object that looks like this:
public class SomeClass {
private Asset asset;
}
Change your payload to look like this:
{
"files": [
"#/home/Downloads/1.jpeg",
"#/home/Downloads/2.jpeg"
],
"name": "assetName",
"meta": "assetMeta"
}
RequestParam
Annotation which indicates that a method parameter should be bound to a web request parameter.
RequestBody
Annotation indicating a method parameter should be bound to the body of the web request. The body of the request is passed through an HttpMessageConverter to resolve the method argument depending on the content type of the request. Optionally, automatic validation can be applied by annotating the argument with #Valid.
HttpMessageConverter
Strategy interface that specifies a converter that can convert from and to HTTP requests and responses.
You need to check converter dependency. because you using application/json.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
Q : Missing request param when it is included in body
A : Use #RequestBody annotation.
I tried #Jordans answer and the endpoint was called with all values set to null :(
Doing more research I came across this statement https://stackoverflow.com/a/51982230/2199102 and tried it out.
Combining #Jordans answer and then the annotation change, I was able to get the answer I wanted
Related
I would like to throw different exceptions with different Strings (giving details of the error via message) with a very specific JSON structure, something like:
[
{
"error": [
{
"statusCode": 400,
"customMessage": "xxx",
"timestamp": "time"
}
]
}
]
Is this possible to achieve with Spring Boot? I haven't found how to do it.
Create an ErrorHandler(as per your naming convention) class and extend spring class ResponseEntityExceptionHandler which receives all method exceptions. Check spring documentation for more details on this class.
In your class add handleTechincalException method as below for required exceptions.
#ExceptionHandler({ Exception.class, AbcException.class, XyzException.class })
public ResponseEntity<Object> handleTechnicalException(Exception e, WebRequest webRequest) {
// prepare response entity object as required based on type of exception
// return ResponseEntity<Object>
}
I am trying to create a REST API in the format which will accept request data with both JSON and MultipartFile type.
THis is my request which will be in following format in POSTMAN:
My POJO classes are as follows:
Class:Organisation
public class Organisation
{
priavet int org_id;
private MultipartFile organisationRegistrationDocument;
private Teachers[]
// getters and setters
}
Class: Teachers
class Teachers{
private String teacherId;
private MultipartFile teacherPhoto;
// getters and setters
}
My controller Class is as follows:
#RequestMapping(value="/test",method=RequestMethod.POST,headers = {"content-type=multipart/mixed","content-type=multipart/form-data"})
private ResponseEntity<Object> testUpload(#RequestBody Organisation org) {
return null;
}
Error Thrown from POSTMAN:
{
"timestamp": "2018-10-03T07:38:30.439+0000",
"status": 400,
"error": "Bad Request",
"message": "Required request part 'org' is not present",
"path": "/test"
}
So anyone can kindly guide me what can I am doing wrong due to which I am not able to achieve the desired result to process request of the above form?
I try to insert an event to Google Calendar.
If I create my event with Java Object directly, using the Java client, I have no problem.
My problem is when I send my event in JSON to my controller: (The Content-type is application/json, and I use postman or command line to send it)
My JSON:
{
"summary": "Google I/O 2015",
"location": "800 Howard St., San Francisco, CA 94103",
"description": "A chance to hear more about Google\"s developer products.",
"start":{
"dateTime":"2018-04-07T17:00:00.000-04:00"
},
"end":{
"dateTime":"2018-04-07T18:00:00.000-04:00"
},
"attendees": [
{"email": "lpage#example.com"},
{"email": "sbrin#example.com"}
]
}
My controller:
#PostMapping(path = "/new/event/{calendarId}/{sendNotification}")
public ResponseEntity<?> newEvent(#NonNull #PathVariable String calendarId,
#NonNull #PathVariable boolean sendNotification,
#NonNull #RequestBody Event event) {
Event eventCreated = postEventService.postNewEvent(calendarId, sendNotification, event);
return new ResponseEntity<>(eventCreated, HttpStatus.CREATED);
}
And here is my error:
{
"status": 400,
"error": "Bad Request",
"message": "JSON parse error: Can not set com.google.api.services.calendar.model.EventDateTime field com.google.api.services.calendar.model.Event.start to java.util.LinkedHashMap; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not set com.google.api.services.calendar.model.EventDateTime field com.google.api.services.calendar.model.Event.start to java.util.LinkedHashMap (through reference chain: com.google.api.services.calendar.model.Event[\"start\"])",
"path": "/new/event/primary/true"
}
My problem is that the exact same JSON works perfectly on the Try this API in the documentation.
Thanks in advance for your help!
You can resolve this error by creating a custom JSON deserializer. In Spring Boot you can do that using #JsonComponent annotation.
Here is the Rest Controller Service signature
#RequestMapping(value = "/getFilteredReport", method = RequestMethod.POST)
public void getFilteredReport(#RequestBody FilteredReportVO filteredReportVO,HttpServletRequest request,HttpServletResponse response) {
Now below is the JSON structure I am sending
{
"filterAttributesFactory":{
"930000":{
"metaDataId":930000,
"displayText":"Select Category",
"attributeType":211009,
"userInputValue":null,
"dropDownoptions":null,
"isMandatory":false,
"isDropDown":false,
"defaultValue":null,
"isdefaultValue":false,
"constraintId":null
},
"930001":{
"metaDataId":930001,
"displayText":"Item Status",
"attributeType":211005,
"userInputValue":null,
"dropDownoptions":{
"157005":"FC - fake scrap",
"157006":"FH - firearm hold",
"157008":"IN - inventory"
},
"isMandatory":false,
"isDropDown":true,
"defaultValue":null,
"isdefaultValue":false,
"constraintId":213007
}
},
"reportId":132030,
"location":1202
}
Here is the FilteredReportVO POJO
public class FilteredReportVO {
private HashMap<Integer,FilterAttributeVO> filterAttributesFactory=new HashMap<Integer,FilterAttributeVO>();
private Integer reportId;
private Long location; .....GETTERS and setters below
FilterAttributeVO pojo structure is below..
public class FilterAttributeVO {
Integer metaDataId;
//String elementName;
String displayText;
Integer attributeType;
Object userInputValue;
Map<Integer,String> dropDownoptions;
Boolean isMandatory=false;;
Boolean isDropDown=false;
Object defaultValue;
Boolean isdefaultValue=false;
Integer constraintId=null;...Getters n setters..
I am hitting the service through POSTMAN plugin.
Getting error:
"The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications".
FYI in POSTMAN I am putting the JSON structure inside "Body", selected "raw", type as "JSON(application/json)".
Notice I am using 2 object type attributes userInputValue and defaultValue inside FilteredAttributeVO. R we allowed to keep object type?
Where is the problem here?
If you see the screen shot of your input JSON with JSONlint your json is not valid.Please fix your json object and validate it using jsonlint
you can try following code in your Test to Resolve this issue coz Spring internally uses Jackson library
ObjectMapper mapper = new ObjectMapper();
Staff obj = mapper.readValue(jsonInString, FilteredReportVO.class);
If this works fine then their should be issue with your Postman RequestBody preparation otherwise you will get detailed stacktrace :)
The problem was with FilteredReportVO POJO. I was setting values of the attributes "location" and "reportId" through a constructor. No setter methods were defined for these 2 attributes.
It was my bad, if I would have posted the complete POJO class u guys must have figured it out. Anyway thanks everyone for ur help
I am trying to send a JSON string as a request to my application. This is my code:
#RequestMapping(
value = "/mylink/upload",
method = RequestMethod.POST,
consumes ="application/json",
produces = "application/json")
public
#ResponseBody
List<Upload> upload(
#RequestParam(value = "hdfsLocation") String hdfsLocation
) throws Exception {
return S3HdfsTransfer.uploadFromHDFS(hdfsLocation);
}
I am trying to send a request with Postman. The method I use is POST, the header contains: Accept "application/json",Content-Type "application/json", the request body is the following:
{
"hdfsLocation" : "hdfs://145.160.10.10:8020"
}
This is the response I get. If I put the parameter in the URL, it works.
{
"httpStatus": 500,
"appErrorId": 0,
"message": "Required String parameter 'hdfsLocation' is not present",
"trackingId": "8c6d45fd-2da5-47ea-a213-3d4ea5764681"
}
Any idea what I am doing wrong?
Thanks,
Serban
Looks like you have confused #RequestBody with #RequestParam. Do either of following :
Pass the request param as a request param(not as a body). Like, (encoded)
http://example.com?hdfsLocation=http%3A%2F%2Fexample.com%3FhdfsLocation%3Dhdfs%3A%2F%2F145.160.10.10%3A8020
Replace the #RequestParam with #RequestBody. If you are sending a body, don't send it along with request param. Those are two different things.
I guess you over looked :)
Shouldn't it be #RequestBody instead of #RequestParam?
Also, even after using #RequestBody, the whole of the JSON string:
{
"hdfsLocation" : "hdfs://145.160.10.10:8020"
}
will be the value of String hdfsLocation and not just the hdfs url. Hence, you'll have to JSON parse that JSON by yourself to get just the hdfs url.