MissingServletRequestParameterException with PostMapping in Spring MVC - java

I'm getting this error when I try to create an instance of an Object and store it into a database:
org.springframework.web.bind.MissingServletRequestParameterException
The code for the method:
#PostMapping(path="accounts/add", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
public
#ResponseBody
String addAccount(#RequestParam String accountNumber, #RequestParam String accountName ) {
Account account = new Account();
account.setAccountName(accountName);
account.setAccountNumber(accountNumber);
accountRepository.save(account);
return "Saved";
}
When I use PostMan and try to enter the JSON in, it gives me this message. What am I doing wrong?

Since your POSTing (or PUTing?) JSON as the content body, you cannot use #RequestParam to deconstruct it. That is used for query or form parameters. You need to specify a single method parameter with #RequestBody, which is a class that looks something like the following.
public class Account {
public String accountNumber;
public String accountName;
// setters and getters removed for brevity
}
See this answer for more info: #RequestBody and #ResponseBody annotations in Spring

Related

For multipart request, how to use using #ModelAttribute and Hashmap together?

First of all, thank you in advance for your support.
My problem;
First I am successfully getting my specific parameters in Employer. However, I also have a constantly changing parameter list in request. I want to get them with Map too.
My dto:
public class Employee {
private String name;
private MultipartFile document;
}
#RequestMapping(path = "/employee", method = POST, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
public Mono<Employee> saveEmployee(#ModelAttribute Employee employee, Map<String,Object> otherValues) {
System.out.println(otherValues.get("key1").toString());
return employeeService.save(employee);
}
I attached a request example aslo.
NOTE:
I used #RequestParam, #RequestPart before Map<String,Object> otherValues like this;
#RequestParam Map<String,Object> otherValues
#RequestPart Map<String,Object> otherValues
But I still couldn't get the rest of the data.
When you want to get values from form data, you can create a model like a DTO, with field of both entity (employee) and additional data (otherValues). Because #ModelAttribute can bind data to only one named model attribute
This is working for Spring MVC. But When you work with Spring WebFlux for reactive applications, it doesn't work.
#RequestMapping(path = "/employee", method = POST, consumes ={MediaType.MULTIPART_FORM_DATA_VALUE })
public Employee saveEmployee(
#ModelAttribute Employee employee,
#RequestParam Map<Object,Object> otherValues,
#RequestParam("file") MultipartFile file) {
System.out.println(otherValues.get("key1").toString());
return employeeService.save(employee);
}
Main trick is to use Object for key and value;
#RequestParam Map<Object,Object> otherValues

Spring boot rest controller not converting request body to custom object

I have spring boot application which used spring rest controller .
This is the controller , below is the response an getting. Am using postman tool for sending request to this controller. And am sending content type as application/json
#RequestMapping(value = "/test", method = RequestMethod.POST)
public String test(#RequestBody WebApp webapp, #RequestBody String propertyFiles, #RequestBody String) {
System.out.println("webapp :"+webapp);
System.out.println("propertyFiles :"+propertyFiles);
System.out.println("propertyText :"+propertyText);
return "ok good";
}
2018-03-21 12:18:47.732  WARN 8520 --- [nio-8099-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved exception caused by Handler execution: org.springframework.http.converter.HttpMessageNotReadableException: I/O error while reading input message; nested exception is java.io.IOException: Stream closed
This is my postman request
{
"webapp":{"webappName":"cavion17","path":"ud1","isQA":true},
"propertyFiles":"vchannel",
"propertytText":"demo property"}
I tried by removing the RequestBody annotation, then able to hit the service , but param objects are received as null.
So please suggest how to retrieve objects in the restcontroller?
You cannot use multiple #RequestBody annotations in Spring. You need to wrap all these in an object.
Some like this
// some imports here
public class IncomingRequestBody {
private Webapp webapp;
private String propertryFiles;
private String propertyText;
// add getters and setters here
}
And in your controller
#RequestMapping(value = "/test", method = RequestMethod.POST)
public String test(#RequestBody IncomingRequestBody requestBody) {
System.out.println(requestBody.getPropertyFiles());
// other statement
return "ok good";
}
Read more here
Passing multiple variables in #RequestBody to a Spring MVC controller using Ajax
Based on the sample postman payload you gave, you will need:
public class MyObject {
private MyWebapp webapp;
private String propertyFiles;
private String propertytText;
// your getters /setters here as needed
}
and
public class MyWebapp {
private String webappName;
private String path;
private boolean isQA;
// getters setters here
}
Then on your controller change it to:
#RequestMapping(value = "/test", method = RequestMethod.POST)
public String test(#RequestBody MyObject payload) {
// then access the fields from the payload like
payload.getPropertyFiles();
return "ok good";
}

Spring Boot REST: #DeleteMapping that consuming form_urlencoded not work as expect

I'm using Spring boot 1.4.0, Consider below code in a #RestController, what I expect is, the server side will receive a http body with form_urlencoded content type, but unfortunately it demands me a query parameter type with email and token. What's the problem here and how to fix?
#DeleteMapping(consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
#ResponseStatus(HttpStatus.NO_CONTENT)
public void removeAdmin(#RequestParam(value = "email") String email, #RequestParam(value = "token") String token) {
//...
}
#DeleteMapping is only a convenience extension the provides #RequestMapping(method=DELETE) It will not handle request paramters. You will still have to map those in the controllers method signature if you need the data to perform the work.
Since you want a body, You could create an object and mark it as #RequestBody:
public class DeleteBody {
public String email;
public String token;
}
public void removeAdmin(#RequestBody DeleteBody deleteBody) {
...
}

Spring Boot: Is it possible to consume #RequestParam's as json?

I have following rest endpoint in spring boot application:
#RequestMapping(method = RequestMethod.POST, value = "/sign-in")
public Client signIn(#RequestParam String username, #RequestParam String password, HttpServletRequest request) {
Client client = authService.signIn(username, password);
return client;
}
I want accept data as application/json.
Is it possible to do this WITHOUT creating class for this like this?:
public class LoginModel {
private String username;
private String password;
...
}
Also, without argument of type Map in signIn method
I need to accept application/json with this signature:
public Client signIn(#RequestParam String username, #RequestParam String password)
Is it possible?
No. I don't think it's possible.
You need to create the intermediary Login object.
#RequestParam mandates you have a request param.

How to take the #PathVariableValue and add it to the #ModelAttribute String value?

I have:
#RequestMapping
public String someMethod(final RedirectAttributes redirectAttributes) {
redirectAttributes.addFlashAttribute("customer_id" + someId, customerWithThatId);
return "redirect:showcustomer.html";
}
How can I query a customer_id_{certain_id_value}, by taking the certain_id_value from the #PathVariable:
#RequestMapping
public String showCustomer(#ModelAttribute("customer_id_{howToTakeTheIdFromPathVariable?}") Customer customer, #PathVariable("customerId") String customerId) {
// ...
}
Typically you don't need to fill #ModelAttribute from #PathVariable. You need to get id from there, and then get model from the database. Something like the following:
#Autowired
private CustomerRepository customerRepository;
#RequestMapping("/show/customer/customer_id_{customerId}")
public String showCustomer(#PathVariable("customerId") long customerId) {
Customer customer = customerRepository.get(customerId);
......
}
As of Spring 3.1 parameters annotated with #PathVariable are exposed to the model automatically so there is no need for special treatment.
https://jira.spring.io/browse/SPR-7543
Same goes for RedirectAttributes flash scoped attributes.
http://docs.spring.io/spring/docs/3.1.x/javadoc-api/org/springframework/web/servlet/mvc/support/RedirectAttributes.html
After the redirect, flash attributes are automatically added to the model of the controller that serves the target URL.

Categories