122
votes

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]

10
Did you add consumes = {"application/x-www-form-urlencoded"} in @RequestBody? - shiladitya
How did you execute the request? add the code of (js,jquery, curl or whatever you use ) . - Nikolay Rusev
I have the same problem. In my case I use jquery ajax to post the data and the data is JSON.stringify({"ordersToDownload":"00417002"} - Arashsoft
This is the code I use: $.ajax({url:"/myurl", type:"POST", data: JSON.stringify({"someAttribute":"someData"}) }) - Arashsoft

10 Answers

155
votes

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(value = "/{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

73
votes

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
}
19
votes

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.

12
votes

In Spring 5

@PostMapping( "some/request/path" )
public void someControllerMethod( @RequestParam MultiValueMap body ) {

    // import org.springframework.util.MultiValueMap;

    String datax = (String) body .getFirst("datax");
}
6
votes

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 ...
    }
}
5
votes

@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

2
votes

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.

0
votes
@PostMapping(path = "/my/endpoint", consumes = { MediaType.APPLICATION_FORM_URLENCODED_VALUE })
public ResponseEntity<Void> handleBrowserSubmissions(MyDTO dto) throws Exception {
    ...
}

That way works for me

0
votes

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));
    }

}

0
votes

Just add an HTTP Header Manager if you are testing using JMeter : enter image description here