In Spring MVC, if none of the enabled ContentNegotiationStrategies can determine the requested content type then 406 code (Not Acceptable) is returned. One way to avoid that; we can set a default content type to be used. In the following example, we are going to set json as default media type by using ContentNegotiationConfigurer#defaultContentType() method.
Example
Setting default content type
@EnableWebMvc
@Configuration
@ComponentScan
public class MyWebConfig extends WebMvcConfigurerAdapter {
@Override
public void configureContentNegotiation (ContentNegotiationConfigurer configurer) {
configurer.defaultContentType(MediaType.APPLICATION_JSON);
}
}
Writing Controller
@Controller
@RequestMapping("user")
public class UserController {
@RequestMapping
@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;
}
}
@XmlRootElement
public class User implements Serializable {
private Long id;
private String name;
private String password;
private String emailAddress;
.............
}
Adding Jackson dependency
We also need to include Jackson dependency so that MappingJackson2HttpMessageConverter can be used to produce JSON response.
pom.xml<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.9</version>
</dependency>
Writing JUnit tests
In this test, we are not going to use 'Accept' header, or path extension or request parameter ('format') so that our default JSON media type can be used to returned the response:
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = MyWebConfig.class)
public class UserTests {
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setup () {
DefaultMockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(this.wac);
this.mockMvc = builder.build();
}
@Test
public void testUserRequest () throws Exception {
MockHttpServletRequestBuilder builder =
MockMvcRequestBuilders.get("/user")
.param("id", "100");
this.mockMvc.perform(builder)
.andExpect(MockMvcResultMatchers.status()
.isOk())
.andDo(MockMvcResultHandlers.print());
}
} Outputmvn -q test -Dtest=UserTests#testUserRequest
MockHttpServletRequest: HTTP Method = GET Request URI = /user Parameters = {id=[100]} 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/json;charset=UTF-8]} Content type = application/json;charset=UTF-8 Body = {"id":100,"name":"joe","password":null,"emailAddress":"joe@example.com"} Forwarded URL = null Redirected URL = null Cookies = []
As seen in the output, we got JSON output in the body.
Note that, the browser (like Chrome) will always have XML response, that's because the browser implicitly sends multiple 'Accept' headers in the request which includes XML media type as well. That means HeaderContentNegotiationStrategy will be utilized before our default content types will be used.
Example ProjectDependencies and Technologies Used: - spring-webmvc 4.3.10.RELEASE: Spring Web MVC.
- spring-test 4.3.10.RELEASE: Spring TestContext Framework.
- javax.servlet-api 3.1.0 Java Servlet API
- jackson-databind 2.8.9: General data-binding functionality for Jackson: works on core streaming 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
|