Friday, August 23, 2013

Spring Framework: Working with x-www-form-urlencoded HTTP requests

I spent a few minutes today figuring out how to send and receive an HTTP request with a content type of application/x-www-form-urlencoded using Spring Framework and Java. Although the solution was somewhat trivial (with Spring's help of course!), I thought posting my findings here would make a good first blog post.

A little background: this content type is typically associated with form submissions sent from a browser. However, I'm trying to make a REST call server to server.

Required changes on the producer side (the server that's generating the request):
  • Register a new Spring FormHttpMessageConverter with the desired REST template
  • Create a MultiValueMap representing the form variables to send in the request
The Spring FormHttpMessageConverter is automatically invoked when the MultiValueMap type is detected in the body of the request, upon making the REST call via Spring's RestTemplate. The converter also takes care of setting the content type header to application/x-www-form-urlencoded. Here is a quick example (ugly I know, getting code to look nice is on my TODO list):

// register form message converter
final RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add( new FormHttpMessageConverter() );

// create form parameters as a MultiValueMap
final MultiValueMap<String, String> formVars = new LinkedMultiValueMap<>();
formVars.add( "name", "matt" );
formVars.add( "status", "awesome" );

// send the request -- our service returns a String in the body
final String result = restOperations.postForObject( uri.toString(), formVars, String.class )

Required changes on the consumer side:
  • Set the consumes field of the RequestMapping to application/x-www-form-urlencoded, to let Spring know that this is the only supported media type we expect
  • Create a parameter representing the form variables sent in the request, and annotate them with @RequestBody. I had found that this annotation was required on both the interface and implementation. 
// interface
@RequestMapping( method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE )
@ResponseBody
ResponseEntity<String> processFormStuff( @RequestBody final MultiValueMap<String, String > formVars );

// implementation
@Override
public ResponseEntity<String> processFormStuff( @RequestBody final MultiValueMap<String, String> formVars )
{
    // do something with form variables, then return
}

3 comments:

  1. Thank you for this! Saved me a bunch of time!

    ReplyDelete
  2. Thank you, very helpful. Could not find anywhere else exactly what I was looking for -- how to make a REST call with x-www-form-urlencoded

    ReplyDelete