Reputation: 5524
Based on the answer for problem with x-www-form-urlencoded with Spring @Controller
I have written the below @Controller method
@RequestMapping(value = "/{email}/authenticate", method = RequestMethod.POST
, produces = {"application/json", "application/xml"}
, consumes = {"application/x-www-form-urlencoded"}
)
public
@ResponseBody
Representation authenticate(@PathVariable("email") String anEmailAddress,
@RequestBody MultiValueMap paramMap)
throws Exception {
if(paramMap == null || paramMap.get("password") == null) {
throw new IllegalArgumentException("Password not provided");
}
}
the request to which fails with the below error
{
"timestamp": 1447911866786,
"status": 415,
"error": "Unsupported Media Type",
"exception": "org.springframework.web.HttpMediaTypeNotSupportedException",
"message": "Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported",
"path": "/users/usermail%40gmail.com/authenticate"
}
[PS: Jersey was far more friendly, but couldn't use it now given the practical restrictions here]
Upvotes: 175
Views: 454871
Reputation: 51
@ModelAttribute
for URL Encoded Forms@ModelAttribute is used to map URL Encoded form data (application/x-www-form-urlencoded
) directly to a Java object. Unlike @RequestBody, which is for JSON or XML payloads, @ModelAttribute is ideal for data sent as key-value pairs.
@PostMapping(value = "/check-verification",
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public String checkVerification(@ModelAttribute CodeOTP codeOTP) {
return "Response: " + codeOTP.getCode();
}
This method allows you to receive form data in the CodeOTP
object automatically.
Upvotes: 1
Reputation: 559
@RequestBody MultiValueMap paramMap
in here Remove the @RequestBody Annotaion
@RequestMapping(value = "/signin",method = RequestMethod.POST)
public String createAccount(@RequestBody LogingData user){
logingService.save(user);
return "login";
}
@RequestMapping(value = "/signin",method = RequestMethod.POST)
public String createAccount( LogingData user){
logingService.save(user);
return "login";
}
like that
Upvotes: 17
Reputation: 127
I found simple way. Just add @FormProperty annotation for each field of your request domain. Of course, you should use consumes = APPLICATION_FORM_URLENCODED_VALUE in your controller or client. Example:
public class AccessTokenRequest {
@FormProperty("client_id")
private String clientId;
@FormProperty("username")
private String username;
@FormProperty("grant_type")
private String grantType;
}
Upvotes: 0
Reputation: 3005
The problem is that when we use application/x-www-form-urlencoded, Spring doesn't understand it as a RequestBody. So, if we want to use this we must remove the @RequestBody annotation.
Then try the following:
@RequestMapping(
path = "/{email}/authenticate",
method = RequestMethod.POST,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = {
MediaType.APPLICATION_ATOM_XML_VALUE,
MediaType.APPLICATION_JSON_VALUE
})
public @ResponseBody Representation authenticate(
@PathVariable("email") String anEmailAddress,
MultiValueMap paramMap) throws Exception {
if (paramMap == null &&
paramMap.get("password") == null) {
throw new IllegalArgumentException("Password not provided");
}
return null;
}
Note that removed the annotation @RequestBody
answer: Http Post request with content type application/x-www-form-urlencoded not working in Spring
Upvotes: 218
Reputation: 119
I met the same problem when I want to process my simple HTML form submission (without using thymeleaf or Spring's form tag) in Spring MVC.
The answer of Douglas Ribeiro will work very well. But just in case, for anyone, like me, who really want to use "@RequestBody" in Spring MVC.
Here is the cause of the problem:
Solution:
Steps:
By the way, the reason why we can access the value by using "@RequestParam" is:
According to Servlet Specification (Section 3.1.1):
The following are the conditions that must be met before post form data will be populated to the parameter set: The request is an HTTP or HTTPS request. 2. The HTTP method is POST. 3. The content type is application/x-www-form-urlencoded. 4. The servlet has made an initial call of any of the getParameter family of methods on the request object.
So, the value in request body will be populated to parameters. But in Spring, you can still access RequestBody, even you can use @RequstBody and @RequestParam at the same method's signature. Like:
@RequestMapping(method = RequestMethod.POST, consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
public String processForm(@RequestParam Map<String, String> inputValue, @RequestBody MultiValueMap<String, List<String>> formInfo) {
......
......
}
The inputValue and formInfo contains the same data, excpet for the type for "@RequestParam" is Map, while for "@RequestBody" is MultiValueMap.
Upvotes: 5
Reputation: 647
Just add an HTTP Header Manager if you are testing using JMeter :
Upvotes: 0
Reputation: 1616
You can try to turn support on in spring's converter
@EnableWebMvc
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
// add converter suport Content-Type: 'application/x-www-form-urlencoded'
converters.stream()
.filter(AllEncompassingFormHttpMessageConverter.class::isInstance)
.map(AllEncompassingFormHttpMessageConverter.class::cast)
.findFirst()
.ifPresent(converter -> converter.addSupportedMediaTypes(MediaType.APPLICATION_FORM_URLENCODED_VALUE));
}
}
Upvotes: 1
Reputation: 620
@PostMapping(path = "/my/endpoint", consumes = { MediaType.APPLICATION_FORM_URLENCODED_VALUE })
public ResponseEntity<Void> handleBrowserSubmissions(MyDTO dto) throws Exception {
...
}
That way works for me
Upvotes: 6
Reputation: 4275
Simply removing @RequestBody
annotation solves the problem (tested on Spring Boot 2):
@RestController
public class MyController {
@PostMapping
public void method(@Valid RequestDto dto) {
// method body ...
}
}
Upvotes: 9
Reputation: 663
In Spring 5
@PostMapping( "some/request/path" )
public void someControllerMethod( @RequestParam MultiValueMap body ) {
// import org.springframework.util.MultiValueMap;
String datax = (String) body .getFirst("datax");
}
Upvotes: 20
Reputation: 1046
I wrote about an alternative in this StackOverflow answer.
There I wrote step by step, explaining with code. The short way:
First: write an object
Second: create a converter to mapping the model extending the AbstractHttpMessageConverter
Third: tell to spring use this converter implementing a WebMvcConfigurer.class overriding the configureMessageConverters method
Fourth and final: using this implementation setting in the mapping inside your controller the consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE and @RequestBody in front of your object.
I'm using spring boot 2.
Upvotes: 3
Reputation: 9723
It seems that now you can just mark the method parameter with @RequestParam
and it will do the job for you.
@PostMapping( "some/request/path" )
public void someControllerMethod( @RequestParam Map<String, String> body ) {
//work with Map
}
Upvotes: 103
Reputation: 251
Add a header to your request to set content type to application/json
curl -H 'Content-Type: application/json' -s -XPOST http://your.domain.com/ -d YOUR_JSON_BODY
this way spring knows how to parse the content.
Upvotes: 21