I have a Spring MVC project and I have configured the jackson library to automatically transform the response (java object) to a json and it works in GET requests as following.
#RequestMapping(method = RequestMethod.GET)
public #ResponseBody Orders createOrder(Model model){
Orders orders = new Orders();
//Populate orders.....
return orders;
}
But when a I try to process the POST request and get the object from the json's request, I get the error "400 Bad Request" as Spring cannot create the object Orders from the json. I put the same json file that the GET method response, so I suppose that the file is well formatted.
#RequestMapping(method = RequestMethod.POST)
public #ResponseBody ResponseEntity<String> createOrder(#RequestBody Orders orders){
LOG.info(orders.toString());
return new ResponseEntity<String>("", HttpStatus.CREATED);
}
If I change the #RequestBody class to String (createOrder(#RequestBody String orders)), the POST request is well processed.
Do I have to create a mapper that maps the input json to the class Order?
UPDATE:
I have created the most simple example to try it and I receive the error 400. Exmaple:
Domain: Home.java
public class Home {
private String address = "Calle mármoles";
public Home(){
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
Controller:
#RequestMapping(method = RequestMethod.POST)
public #ResponseBody ResponseEntity<String> createOrder2(#RequestBody Home orders){
return new ResponseEntity<String>("{}", HttpStatus.CREATED);
}
JSON (POST):
{
address: "Prueba"
}
[SOLVED]
I missed to put "" in the name of the parameter name.
[SOLVED]
I missed to put "" in the name of the parameter name.
Besides, the class has to have a default blank constructor in order to allow the jackson library creating the object.
Related
In a Spring Boot application I have the following method signature in a Controller:
#PostMapping(value="/borrow")
public ResponseEntity<Void> postBorrowBook(#RequestBody String personId,
#RequestBody String bookId) {
LOG.info(RESTController.class.getName() + ".postBorrowBook() method called.");
...
return new ResponseEntity<Void>(HttpStatus.OK);
}
I want to get the values of the two parameters from the RequestBody.
Can anyone let me know how this be done if the request I am making is JSON as follows:
{"personId":"207","bookId":"5"}
I am currently receiving:
{
"timestamp": "2018-06-17T20:59:37.330+0000",
"status": 400,
"error": "Bad Request",
"message": "Required request body is missing: public org.springframework.http.ResponseEntity<java.lang.Void> com.city2018.webapps.code.controller.RESTController.postBorrowBook(java.lang.String,java.lang.String)",
"path": "/rest/borrow/"
}
I already have the following working in a similar scenario for simple non-REST requests:
#RequestMapping(value="/borrow", method=RequestMethod.POST)
public String postBorrowBook(#RequestParam("personId") String personId,
#RequestParam("bookId") String bookId,
Model model) {
LOG.info(PersonController.class.getName() + ".postBorrowBook() method called.");
You can declare a POJO with 2 fields (personId and bookId) and change your signature as follow:
#PostMapping(value="/borrow")
public ResponseEntity<Void> postBorrowBook(#RequestBody RequestDTO requestBody) {
requestBody.getPersonId();
requestBody.getBookId();
...
}
First you should define a POJO class as:
public class BorrowBookEntity{
public String personId;
public String bookId;
}
Then you rely on spring to get the value as:
#PostMapping("/request")
public ResponseEntity<Void> postController(
#RequestBody BorrowBookEntity borrowBookEntity) {
...
You can also try another .
e.g. #RequestBodyParam
#RequestMapping(value = "/saveData", headers="Content-Type=application/json", method = RequestMethod.POST)
#ResponseBody
public ResponseEntity<Boolean> saveData(#RequestBodyParam String source,#RequestBodyParam JsonDto json) throws MyException {
...
}
https://github.com/LambdaExpression/RequestBodyParam
I have created a Spring Boot with Spring REST application.
This is my controller code.
#RestController
public class SampleController {
#RequestMapping(value = "/sample/get", method = RequestMethod.GET, produces = "application/json")
#ResponseBody
public Response getResponse(SampleDTO dto) {
Response response = new Response();
response.setResponseMsg("Hello "+dto.getFirstName());
return response;
}
}
This is my SampleDTO
public class SampleDTO {
#JsonProperty("firstname")
private String firstName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
and this is my Response object
public class Response {
private String responseMsg;
public String getResponseMsg() {
return responseMsg;
}
public void setResponseMsg(String responseMsg) {
this.responseMsg = responseMsg;
}
}
When I try to access service this way
http://localhost:8080/sample/get?firstName=mvg
I am getting this expected output
{"responseMsg":"Hello mvg"}
When I try to access service this way
http://localhost:8080/sample/get?firstname=mvg
I am getting this output
{"responseMsg":"Hello null"}
My question is how do I map 'firstname' in request parameter with 'firstName' of DTO?
Thanks in advance
When you are setting #JsonProperty("firstname") make sure you are imported the this statement "import com.fasterxml.jackson.annotation.JsonProperty ;". One thing more if you are sending more properties and your bean class does not have that you can set the #JsonIgnoreProperties(ignoreUnknown=true) on the top of the bean name.
You are also missing the #RequestBody annotation. You should take this as (#RequestBody SampleDTO dto)in getResponse method.
Simply create a Pojo Java Bean with fields with names that match your request parameters.
Then use this class as an argument for your request handler method (without any additional annotations)
see this
First you need to choose which approach do you need (or want to use) param or model. When you use something like this http://localhost:8080/sample/get?firstName=mvg , you are passing data as request parameters. So you need to use the #RequestParam annotation.
Sample using #RequestParam annotation (use is explained in the docs)
#RequestMapping(method = RequestMethod.GET)
public Response foo(#RequestParam("firstName") String firstName) {
Response response = new Response();
response.setResponseMsg("Hello "+ firstName );
return response;
}
I need to represent JSON in table. I get JSON from my controller and i don`t know what next...How can i pass JSON to exact jsp or i should not do it?Sorry, I m new in JSON.
And what should i do after method add(...)? What should i return.
Here is my controller code
#Controller
public class MainController {
#Autowired
private ClientLogManager clientLogManager;
#ResponseBody
#RequestMapping(value = "/api/getlog/{appId}", method = RequestMethod.GET)
public List<ClientLog> getAll(#PathVariable Integer appId, Model model) {
List clientLogs = clientLogManager.get(appId);
return clientLogs;
}
#ResponseBody
#RequestMapping(value = "/api/log", method = RequestMethod.POST)
public ClientLog add(#RequestBody ClientLog clientLog) {
clientLogManager.add(clientLog);
return clientLog;
}
}
u can get your json data via a simple html file ...
in your jsp file you can get this list with jQuery
$.getJSON('localhost:8080/api/getlog/12', function (clientlogs) {
for(clientlog : clientlogs){
console.log(clientlog.id);
}
});
if u have a save operation you had better use PUT method
#ResponseBody
#RequestMapping(value = "/api/log", method = RequestMethod.PUT)
public ClientLog add(#RequestBody ClientLog clientLog) {
clientLogManager.add(clientLog);
return clientLog;
}
I have a spring web service method where i want to get a string as a parameter. The string is sent in body of the request. My web service class is:
#Controller
#RequestMapping(value = "/users/{uid}/openchart")
public class OpenChartWebService {
#RequestMapping(method = RequestMethod.POST)
#ResponseBody
public String saveABC(#PathVariable("uid") Long uid,
#RequestBody String myString) {
System.out.println("sent string is: "+myString);
return "something";
}
}
My request in body is :
{
"name":"Ramesh"
}
But this is not working. This shows "Bad Request" HTTP error(400). How to send a string in a body and how to get a string sent in a body inside webservice method?
As #Leon suggests, you should add the media type to your request mapping, but also make sure you have Jackson on your classpath. You'll also want to change your #RequestBody argument type to something that has a "name" property, rather than just a String so that you don't have to convert it after.
public class Person {
private name;
public getName() {
return name;
}
}
If your data object looked like the above, then you could set your #RequestBody argument to Person type.
If all you want is a String, then perhaps just pass the value of "name" in your request body rather than an object with a name property.
I would like to know how to read a flash attributes after redirection in Spring MVC 3.1.
I have the following code:
#Controller
#RequestMapping("/foo")
public class FooController {
#RequestMapping(value = "/bar", method = RequestMethod.GET)
public ModelAndView handleGet(...) {
// I want to see my flash attributes here!
}
#RequestMapping(value = "/bar", method = RequestMethod.POST)
public ModelAndView handlePost(RedirectAttributes redirectAttrs) {
redirectAttrs.addFlashAttributes("some", "thing");
return new ModelAndView().setViewName("redirect:/foo/bar");
}
}
What I am missing?
Use Model, it should have flash attributes prepopulated:
#RequestMapping(value = "/bar", method = RequestMethod.GET)
public ModelAndView handleGet(Model model) {
String some = (String) model.asMap().get("some");
// do the job
}
or, alternatively, you can use RequestContextUtils#getInputFlashMap:
#RequestMapping(value = "/bar", method = RequestMethod.GET)
public ModelAndView handleGet(HttpServletRequest request) {
Map<String, ?> inputFlashMap = RequestContextUtils.getInputFlashMap(request);
if (inputFlashMap != null) {
String some = (String) inputFlashMap.get("some");
// do the job
}
}
P.S. You can do return return new ModelAndView("redirect:/foo/bar"); in handlePost.
EDIT:
JavaDoc says:
A RedirectAttributes model is empty when the method is called and is
never used unless the method returns a redirect view name or a
RedirectView.
It doesn't mention ModelAndView, so maybe change handlePost to return "redirect:/foo/bar" string or RedirectView:
#RequestMapping(value = "/bar", method = RequestMethod.POST)
public RedirectView handlePost(RedirectAttributes redirectAttrs) {
redirectAttrs.addFlashAttributes("some", "thing");
return new RedirectView("/foo/bar", true);
}
I use RedirectAttributes in my code with RedirectView and model.asMap() method and it works OK.
Try this:
#Controller
public class FooController
{
#RequestMapping(value = "/foo")
public String handleFoo(RedirectAttributes redirectAttrs)
{
redirectAttrs.addFlashAttribute("some", "thing");
return "redirect:/bar";
}
#RequestMapping(value = "/bar")
public void handleBar(#ModelAttribute("some") String some)
{
System.out.println("some=" + some);
}
}
works in Spring MVC 3.2.2
For all those like me who were having problems with seeing the POST url in the browser when a validation would fail.
The POST url is a private url that should not be exposed to users but it was automatically rendered when a validation failed. i.e. if a field was below a minimum length. I was using #Valid. I wanted the original GET url of the form to show at all times even when validation bounced back to the form, so I did the following:
if (validation.hasErrors()) {
redirectAttributes.addFlashAttribute("org.springframework.validation.BindingResult.story", validation);
redirectAttributes.addFlashAttribute("story", story);
return new ModelAndView("redirect:/january/2015");
where story is the form object representation, redirectAttributes are RedirectAttributes you put in the method signature and validation is the BindingResult. /january/2015 is the mapping to the GET controller where the form lives.
After this implementation, in the mapping for /january/2015, story comes in intact as follows:
Story story= (Story) model.asMap().get("story");
//story from the POST method
I had to augment my GET method and check if this was not null. If not null, then send this to the form else I would send a newly initialized Story type to the form as default behaviour before.
In this manner, I am able to return to the form with the bindingresults intact (errors show on form) but have my GET url in place of the post url.