How to send JSON in Spring? - json

I tried to find how I can write in Spring to POST JSON from REST client. For example, I wrote:
#RequestMapping(value = "/{userId}/add", method = RequestMethod.POST, headers = {"content-type=application/json"})
#ResponseBody
public Map<String, String> saveUser(#RequestBody User user, BindingResult result) {
Map<String, String> jsonResponse = new HashMap<String, String>();
if (result.hasErrors()) {
jsonResponse.put("Message", "Can't add the user");
jsonResponse.put("Code", "401");
return jsonResponse;
}
userService.addUser(user);
jsonResponse.put("Message", "Success add User");
jsonResponse.put("Code", "200");
return jsonResponse;
}
End tested it from Firefox REST client. But I saw 404 error. What am I doing wrong? Thanx for help.

First, if the URI of your request ended with "/user/2/add", it won't map to your method, which is mapped as "/{userId}/add". This will cause the HTTP 404 error you receive. Instead, your URI should end with "/2/add", if the "userId" is 2.
Second, annotating the User parameter with #RequestBody is not enough for the complex User type. You will need to convert your JSON request body into a User object. You can accomplish this with the MappingJacksonHttpMessageConverter. By declaring a bean of this type, you can use Jackson's annotations to control how the JSON is parsed into the User properties.

Related

how to map json object having unlimited property to pojo or in #RequestBody variable in controller

I have json object as below
{'key_1':'value_1','key_2':'value_2','key_3':'value_3',.....'key_N':'value_N',}
i tried to map this json with HashMap<String,String>, but it does not worked for me.
if any one have solution to map above json with proper datatype in #RequestBody in spirng controller would be appreciated.
Thanks
As per question, you can not hold many number of json values in the Map object or any other object because it will become heavy object and may cause memory leaks.
You can add required values to Map or any other object and send response to the client.
Note: it should not be a heavy object because it will impact in the real time environment while concurrency.
However you can use below snippet:
#RequestMapping(value = "/someUrl", method = RequestMethod.POST)
public #ResponseBody ResponseEntity<Object> someMethod(final HttpServletRequest req, final HttpSession session) {
ResponseEntity<Object> responseEntity;
Map<String,String> map = new HashMap<>();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
map.put("key4", "value4");
map.put("key5", "value5");
map.put("key6", "value6");
map.put("key7", "value7");
map.put("key8", "value8");
map.put("key9", "value9");
responseEntity = new ResponseEntity<Object>(map, HttpStatus.OK);
return responseEntity;
}

How to get response in JSON format using #ExceptionHandler in Spring MVC

I am new to this #ExceptionHandler. I need to return response in JSON format if there is any exception. My code is returning response in JSON format if the operation is successful. But when any exception is thrown it is return HTML response as I have used #ExceptionHandler.
Value and reason in #ResponseStatus is coming properly but in HTML. How can I can change it to a JSON response? Please help.
In my controller class i have this methods:
#RequestMapping(value = "/savePoints", method = RequestMethod.POST, consumes = "application/json", produces = "application/json;charset=UTF-8")
public #ResponseBody
GenericResponseVO<TestResponseVO> saveScore(
#RequestBody(required = true) GenericRequestVO<TestVO> testVO) {
UserContext userCtx = new UserContext();
userCtx.setAppId("appId");
return gameHandler.handle(userCtx, testVO);
}
Exception handling method:
#ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "Error in the process")
#ExceptionHandler(Exception.class)
public void handleAllOtherException() {
}
You can annotate the handler method with #ResponseBody and return any object you want and it should be serialized to JSON (depending on your configuration of course). For instance:
public class Error {
private String message;
// Constructors, getters, setters, other properties ...
}
#ResponseBody
#ResponseStatus(HttpStatus.BAD_REQUEST)
#ExceptionHandler(MethodArgumentNotValidException.class)
public Error handleValidationException(MethodArgumentNotValidException e) {
// Optionally do additional things with the exception, for example map
// individual field errors (from e.getBindingResult()) to the Error object
return new Error("Invalid data");
}
which should produce response with HTTP 400 code and following body:
{
"message": "Invalid data"
}
Also see Spring JavaDoc for #ExceptionHandler which lists possible return types, one of which is:
#ResponseBody annotated methods (Servlet-only) to set the response content. The return value will be converted to the response stream using message converters.
Replace
#ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "Error in the process")
by
#ResponseStatus(value = HttpStatus.NOT_FOUND)
the 'reason' attribute force html render!
I've waste 1 day on that.....

make mvc controller return text instead of json

I am trying to make method Spring MVC method in controller to return text instead of json.
My current method looks like this
#RequestMapping(value = "/upload", method = RequestMethod.POST, produces = "text/html")
public ModelAndView uploadFile(#RequestParam("file") MultipartFile file) {
LOGGER.debug("Attempt to upload file with template.");
try {
String fileContent = FileProcessUtils.processFileUploading(file);
return createSuccessResponse(fileContent);
} catch (UtilityException e) {
LOGGER.error("Failed to process file.", e.getWrappedException());
return createResponse(INTERNAL_ERROR_CODE, e.getMessage());
}
}
But the response header content-type: application/json.
I was trying to pass HttpServletResponse to controller and set content type but it still continued to return json.
What's the problem?
What's FileProcessUtils? Google doesn't bring up anything. Is it a class created by you or your organization? It would appear that the method is returning a response with a content-type of application/json. What were you expecting it to return and why? You would have to somehow parse the json to extract the data necessary for constructing a ModelAndView or find another method that returns what you want.
But without more information on FileProcessUtils, it isn't possible to provide more of an answer.
You can either do this:
#RequestMapping(value = "/foo", method = RequestMethod.GET)
public ResponseEntity foo() throws Exception {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.TEXT_HTML);
return ResponseEntity.ok().headers(headers).body("response");
}
or do this:
#RequestMapping(value = "/foo", method = RequestMethod.GET, produces = MediaType.TEXT_HTML_VALUE)
Both works fine.

Need help on RestTemplate postForObject() method

I have to send JSON data from one service method to the other using postForObject() method.
I saw one example on RestTemplate on this link.
postForObject() method has the following format:
User returns = rt.postForObject(uri, u, User.class, vars);
Or
User returns = rt.postForObject(uri, u, User.class);
I want to know that, after using postForObject() method, if we implement the service method to accept the User object, how it will look like?
In my project, I have code like
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJacksonHttpMessageConverter());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
String uri = "http://testcode.com/myapp/api/launchservices";
ServiceRequest request = new ServiceRequest();
request.setId(UUID.randomUUID().toString());
....
I am getting error at this line:
ServiceRequest req = restTemplate.postForObject(uri, request, ServiceRequest.class);
while executing this, I am getting this error mesage:
org.springframework.web.client.HttpClientErrorException: 400 Bad Request
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:88)
at org.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.java:537)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:493)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:452)
at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:302)
my implementation method is:
#RequestMapping(value = "/launchservices", method = RequestMethod.POST)
#ResponseBody
public boolean launchServices(#PathVariable ServiceRequest request) {
System.out.println("Request: "+request.toString());
return true;
}
How to get rid of this? What will be the URI?
I got solution to this problem.
In this example,method postForObject returns an object of class "ServiceRequest"
ServiceRequest req = restTemplate.postForObject(uri, request, ServiceRequest.class);
So, the method that implements this service with the above 'uri' should return an object of class ServiceRequest
All it needs is, slight modification in implementation method as below
#RequestMapping(value = "/launchservices", method = RequestMethod.POST, headers = "Accept=application/json")
#ResponseBody
public ServiceRequest launchServices(#RequestBody ServiceRequest request) {
System.out.println("Request: "+request.toString());
return request;
}

The request sent by the client was syntactically incorrect ().+Spring , RESTClient

I am working with Spring MVC using JSON objects. while I am tring to send JSON Object from RESTClient, I am getting
HTTP Status 400 - The request sent by the client was syntactically incorrect ().
This is my controller
ObjectMapper mapper=new ObjectMapper();
#RequestMapping(value = "/addTask", method = RequestMethod.GET)
public ModelAndView addTask(#RequestParam("json") String json) throws JsonParseException, JsonMappingException, IOException
{
System.out.println("Json object from REST : "+json);
Task task=(Task) mapper.readValue(json, Task);
service.addService(task);
return new ModelAndView("Result");
}
My request URL : http://localhost:8080/Prime/addTask
My Json Object :
{"taskName":"nothing","taskId":1234,"taskDesc":"nothing doing"}
Also i tried specifying "Content-Type: application/json" in RESTClient but still am getting the same error
I ran into a similar situation using a JSON string in the request body recently, and using a very similar Spring setup as yours. In my case I wasn't specifying a String parameter and deserialising it myself though, I was letting Spring do that:
#RequestMapping(value = "/myService/{id}", method = RequestMethod.POST)
#ResponseBody
public void myService(#PathVariable(value = "id") Long id, #RequestBody MyJsonValueObject request) {
..
}
I was getting an HTTP error 400 "The request sent by the client was syntactically incorrect" response. Until I realised that there wasn't a default constructor on the #RequestBody MyJsonValueObject so there were problems deserialising it. That problem presented in this way though.
So if you are using POST and objects, and getting errors like this, make sure you have a default constructor! Add some JUnit to be sure you can deserialise that object.
Note: I'm not saying this is the only reason you get this error. The original case used just String (which does have a default constructor !) so it's a little different. But in both cases it appears the request URI appears to have been mapped to the right method, and something has gone wrong trying to extract parameters from the HTTP request.
Try this
Change
#RequestParam("json") String json
To
#RequestBody Task task
If you are not interested in POST method you can try this
change your Controller method from
#RequestMapping(value = "/addTask", method = RequestMethod.GET)
public ModelAndView addTask(#RequestParam("json") String json)
to
#RequestMapping(value = "/addTask/{taskName}/{taskId}/{taskDesc}", method = RequestMethod.GET)
public ModelAndView addTask(#RequestParam("taskName") String taskName,
#RequestParam("taskId") String taskId,#RequestParam("taskDesc") String taskDesc)
and change your URL to
http://localhost:8080/Prime/addTask/mytask/233/testDesc
My problem was due to the incorrect mapping of the #RequestBody object.
My Request Body looks like this
{data: ["1","2","3"]}
I had the following code in my controller
#RequestMapping(value = "/mentee", method = RequestMethod.POST)
public #ResponseBody boolean updateData(#RequestBody List<Integer> objDTO, HttpSession session) {
...
}
This give me HTTP 400 because Spring doesn't know how to bind my Json data to a List.
I changed the RequestBody object to the following
#RequestMapping(value = "/mentee", method = RequestMethod.POST)
public #ResponseBody boolean updateData(#RequestBody ObjectiveDto objDTO, HttpSession session) {
...
}
and defined ObjectiveDto as followed
#ToString
public class ObjectiveDto {
#Getter #Setter
private List<Integer> data;
}
This resolved the HTTP 400 error.