Spring MVC - Parameter Content Negotiation Strategy

[Updated: Jul 18, 2017, Created: Jul 18, 2017]

We have seen how content-negotiation works in spring. In this example, we will utilize ParameterContentNegotiationStrategy by turning it on. We will, then, specify a media type in query parameter with the name 'format' e.g. we will send an extra parameter similar to "http:/www.example.com/app?format=xml".

Example

Turning on ParameterContentNegotiationStrategy

@EnableWebMvc
@Configuration
@ComponentScan
public class MyWebConfig extends WebMvcConfigurerAdapter {
  
  @Override
  public void configureContentNegotiation (ContentNegotiationConfigurer configurer) {
      configurer.favorParameter(true);
  }
}

Writing Controller

@Controller
@RequestMapping("user")
public class UserController {
  
  @RequestMapping(produces = MediaType.APPLICATION_XML_VALUE)
  @ResponseBody
  public User getUserById (@RequestParam("id") long userId) {
      //creating dummy user
      User user = new User();
      user.setId(userId);
      user.setName("joe");
      user.setEmailAddress("joe@example.com");
      return user;
  }
  
  @RequestMapping
  @ResponseBody
  public String getUserStringById (@RequestParam("id") long userId) {
      return "joe, id: "+userId;
  }
}
@XmlRootElement
public class User implements Serializable {
  private Long id;
  private String name;
  private String password;
  private String emailAddress;
    .............
}

Writing JUnit tests

In this test, we will make request without 'format' param:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = MyWebConfig.class)
public class UserTests {
  @Autowired
  private WebApplicationContext wac;
  private MockMvc mockMvc;
    .............
  @Test
  public void testUserRequestWithoutFormatParam () throws Exception {
      MockHttpServletRequestBuilder builder =
                MockMvcRequestBuilders.get("/user")
                                      .param("id", "10");
      
      this.mockMvc.perform(builder)
                  .andExpect(MockMvcResultMatchers.status()
                                                  .isOk())
                  .andDo(MockMvcResultHandlers.print());
  }
    .............
}

Output

mvn -q test -Dtest=UserTests#testUserRequestWithoutFormatParam


MockHttpServletRequest:
HTTP Method = GET
Request URI = /user
Parameters = {id=[10]}
Headers = {}

Handler:
Type = com.logicbig.example.UserController
Method = public java.lang.String com.logicbig.example.UserController.getUserStringById(long)

Async:
Async started = false
Async result = null

Resolved Exception:
Type = null

ModelAndView:
View name = null
View = null
Model = null

FlashMap:
Attributes = null

MockHttpServletResponse:
Status = 200
Error message = null
Headers = {Content-Type=[text/plain;charset=ISO-8859-1], Content-Length=[11]}
Content type = text/plain;charset=ISO-8859-1
Body = joe, id: 10
Forwarded URL = null
Redirected URL = null
Cookies = []

In above output, the test request maps to the handler method which returns String. Now let's use format=xml param with the request:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = MyWebConfig.class)
public class UserTests {
  @Autowired
  private WebApplicationContext wac;
  private MockMvc mockMvc;
    .............
  @Test
  public void testUserRequestWithFormatParam () throws Exception {
      MockHttpServletRequestBuilder builder =
                MockMvcRequestBuilders.get("/user")
                                      .param("format", "xml")
                                      .param("id", "10");
      
      this.mockMvc.perform(builder)
                  .andExpect(MockMvcResultMatchers.status()
                                                  .isOk())
                  .andDo(MockMvcResultHandlers.print());
  }
}

Output

mvn -q test -Dtest=UserTests#testUserRequestWithFormatParam


MockHttpServletRequest:
HTTP Method = GET
Request URI = /user
Parameters = {format=[xml], id=[10]}
Headers = {}

Handler:
Type = com.logicbig.example.UserController
Method = public com.logicbig.example.User com.logicbig.example.UserController.getUserById(long)

Async:
Async started = false
Async result = null

Resolved Exception:
Type = null

ModelAndView:
View name = null
View = null
Model = null

FlashMap:
Attributes = null

MockHttpServletResponse:
Status = 200
Error message = null
Headers = {Content-Type=[application/xml]}
Content type = application/xml
Body = <?xml version="1.0" encoding="UTF-8" standalone="yes"?><user><emailAddress>joe@example.com</emailAddress><id>10</id><name>joe</name></user>
Forwarded URL = null
Redirected URL = null
Cookies = []

As seen in the output, we got xml output in the body.

Output on the browser

For our example, the chrome (Version 59.0.3071.115) will always get xml response that's because by default it sends following 'Accept' headers with GET requests:

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8

That means HeaderContentNegotiationStrategy will match the more specific media type (xml). One way to test our code is to turn off HeaderContentNegotiationStrategy on the application side:

@EnableWebMvc
@Configuration
@ComponentScan
public class MyWebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configureContentNegotiation (ContentNegotiationConfigurer configurer) {
        configurer.favorParameter(true);
        configurer.ignoreAcceptHeader(true);
    }
}

Now we can have expected results in the browser:

URL: http://localhost:8080/user?id=2

URL: http://localhost:8080/user?id=2&format=xml

Example Project

Dependencies and Technologies Used :

  • spring-webmvc 4.3.9.RELEASE: Spring Web MVC.
  • spring-test 4.3.9.RELEASE: Spring TestContext Framework.
  • javax.servlet-api 3.1.0 Java Servlet API
  • junit 4.12: JUnit is a unit testing framework for Java, created by Erich Gamma and Kent Beck.
  • JDK 1.8
  • Maven 3.3.9

Query Parameter Content-Negotiation Strategy Example Select All Download
  • param-content-negotiation-strategy
    • src
      • main
        • java
          • com
            • logicbig
              • example
      • test
        • java
          • com
            • logicbig
              • example

See Also