diff --git a/spring-mvc-basics/README.md b/spring-mvc-basics/README.md
index 997e6a88df..9593fd6222 100644
--- a/spring-mvc-basics/README.md
+++ b/spring-mvc-basics/README.md
@@ -10,4 +10,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [The Spring @Controller and @RestController Annotations](http://www.baeldung.com/spring-controller-vs-restcontroller)
- [Using Spring ResponseEntity to Manipulate the HTTP Response](http://www.baeldung.com/spring-response-entity)
- [A Guide to the ViewResolver in Spring MVC](http://www.baeldung.com/spring-mvc-view-resolver-tutorial)
-- [Guide to Spring Handler Mappings](http://www.baeldung.com/spring-handler-mappings)
\ No newline at end of file
+- [Guide to Spring Handler Mappings](http://www.baeldung.com/spring-handler-mappings)
+- [Spring MVC Content Negotiation](http://www.baeldung.com/spring-mvc-content-negotiation-json-xml)
\ No newline at end of file
diff --git a/spring-mvc-basics/pom.xml b/spring-mvc-basics/pom.xml
index d04bdda8f6..8c52c60b65 100644
--- a/spring-mvc-basics/pom.xml
+++ b/spring-mvc-basics/pom.xml
@@ -30,7 +30,6 @@
javax.servlet
jstl
- ${jstl.version}
org.springframework.boot
diff --git a/spring-mvc-basics/src/main/java/com/baeldung/model/Employee.java b/spring-mvc-basics/src/main/java/com/baeldung/model/Employee.java
new file mode 100644
index 0000000000..fb0a452219
--- /dev/null
+++ b/spring-mvc-basics/src/main/java/com/baeldung/model/Employee.java
@@ -0,0 +1,61 @@
+package com.baeldung.model;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+public class Employee {
+
+ private long id;
+ private String name;
+ private String contactNumber;
+ private String workingArea;
+
+ public Employee() {
+ super();
+ }
+
+ public Employee(final long id, final String name, final String contactNumber, final String workingArea) {
+ this.id = id;
+ this.name = name;
+ this.contactNumber = contactNumber;
+ this.workingArea = workingArea;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(final long id) {
+ this.id = id;
+ }
+
+ public String getContactNumber() {
+ return contactNumber;
+ }
+
+ public void setContactNumber(final String contactNumber) {
+ this.contactNumber = contactNumber;
+ }
+
+ public String getWorkingArea() {
+ return workingArea;
+ }
+
+ public void setWorkingArea(final String workingArea) {
+ this.workingArea = workingArea;
+ }
+
+ @Override
+ public String toString() {
+ return "Employee [id=" + id + ", name=" + name + ", contactNumber=" + contactNumber + ", workingArea=" + workingArea + "]";
+ }
+
+}
diff --git a/spring-mvc-basics/src/main/java/com/baeldung/spring/web/config/WebConfig.java b/spring-mvc-basics/src/main/java/com/baeldung/spring/web/config/WebConfig.java
index a56dfe550f..9a321f65a2 100644
--- a/spring-mvc-basics/src/main/java/com/baeldung/spring/web/config/WebConfig.java
+++ b/spring-mvc-basics/src/main/java/com/baeldung/spring/web/config/WebConfig.java
@@ -3,7 +3,9 @@ package com.baeldung.spring.web.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
+import org.springframework.http.MediaType;
import org.springframework.web.servlet.ViewResolver;
+import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@@ -47,4 +49,19 @@ public class WebConfig implements WebMvcConfigurer {
bean.setOrder(1);
return bean;
}
+
+ /**
+ * Spring Boot allows configuring Content Negotiation using properties
+ */
+ @Override
+ public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) {
+ configurer.favorPathExtension(true)
+ .favorParameter(true)
+ .parameterName("mediaType")
+ .ignoreAcceptHeader(false)
+ .useRegisteredExtensionsOnly(false)
+ .defaultContentType(MediaType.APPLICATION_JSON)
+ .mediaType("xml", MediaType.APPLICATION_XML)
+ .mediaType("json", MediaType.APPLICATION_JSON);
+ }
}
\ No newline at end of file
diff --git a/spring-mvc-basics/src/main/java/com/baeldung/web/controller/EmployeeController.java b/spring-mvc-basics/src/main/java/com/baeldung/web/controller/EmployeeController.java
new file mode 100644
index 0000000000..00bbbfbe41
--- /dev/null
+++ b/spring-mvc-basics/src/main/java/com/baeldung/web/controller/EmployeeController.java
@@ -0,0 +1,31 @@
+package com.baeldung.web.controller;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.baeldung.model.Employee;
+
+@Controller
+public class EmployeeController {
+
+ Map employeeMap = new HashMap<>();
+
+ @ModelAttribute("employees")
+ public void initEmployees() {
+ employeeMap.put(1L, new Employee(1L, "John", "223334411", "rh"));
+ employeeMap.put(2L, new Employee(2L, "Peter", "22001543", "informatics"));
+ employeeMap.put(3L, new Employee(3L, "Mike", "223334411", "admin"));
+ }
+
+ @RequestMapping(value = "/employee/{Id}",produces = { "application/json", "application/xml" }, method = RequestMethod.GET)
+ public @ResponseBody Employee getEmployeeById(@PathVariable final Long Id) {
+ return employeeMap.get(Id);
+ }
+}
diff --git a/spring-mvc-basics/src/main/resources/application.properties b/spring-mvc-basics/src/main/resources/application.properties
index 4de974142e..b8a9be0b40 100644
--- a/spring-mvc-basics/src/main/resources/application.properties
+++ b/spring-mvc-basics/src/main/resources/application.properties
@@ -1 +1,7 @@
-server.servlet.context-path=/spring-mvc-basics
\ No newline at end of file
+server.servlet.context-path=/spring-mvc-basics
+
+### Content Negotiation (already defined programatically)
+spring.mvc.pathmatch.use-suffix-pattern=true
+#spring.mvc.contentnegotiation.favor-path-extension=true
+#spring.mvc.contentnegotiation.favor-parameter=true
+#spring.mvc.contentnegotiation.parameter-name=mediaType
diff --git a/spring-mvc-basics/src/test/java/com/baeldung/web/controller/EmployeeControllerContentNegotiationIntegrationTest.java b/spring-mvc-basics/src/test/java/com/baeldung/web/controller/EmployeeControllerContentNegotiationIntegrationTest.java
new file mode 100644
index 0000000000..6500955d23
--- /dev/null
+++ b/spring-mvc-basics/src/test/java/com/baeldung/web/controller/EmployeeControllerContentNegotiationIntegrationTest.java
@@ -0,0 +1,63 @@
+package com.baeldung.web.controller;
+
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.test.web.servlet.MockMvc;
+
+@SpringBootTest
+@AutoConfigureMockMvc
+public class EmployeeControllerContentNegotiationIntegrationTest {
+
+ @Autowired
+ private MockMvc mockMvc;
+
+ @Test
+ public void whenEndpointUsingJsonSuffixCalled_thenJsonResponseObtained() throws Exception {
+ this.mockMvc.perform(get("/employee/1.json"))
+ .andExpect(status().isOk())
+ .andExpect(header().string(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE));
+ }
+
+ @Test
+ public void whenEndpointUsingXmlSuffixCalled_thenXmlResponseObtained() throws Exception {
+ this.mockMvc.perform(get("/employee/1.xml"))
+ .andExpect(status().isOk())
+ .andExpect(header().string(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE));
+ }
+
+ @Test
+ public void whenEndpointUsingJsonParameterCalled_thenJsonResponseObtained() throws Exception {
+ this.mockMvc.perform(get("/employee/1?mediaType=json"))
+ .andExpect(status().isOk())
+ .andExpect(header().string(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE));
+ }
+
+ @Test
+ public void whenEndpointUsingXmlParameterCalled_thenXmlResponseObtained() throws Exception {
+ this.mockMvc.perform(get("/employee/1?mediaType=xml"))
+ .andExpect(status().isOk())
+ .andExpect(header().string(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE));
+ }
+
+ @Test
+ public void whenEndpointUsingJsonAcceptHeaderCalled_thenJsonResponseObtained() throws Exception {
+ this.mockMvc.perform(get("/employee/1").header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE))
+ .andExpect(status().isOk())
+ .andExpect(header().string(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE));
+ }
+
+ @Test
+ public void whenEndpointUsingXmlAcceptHeaderCalled_thenXmlResponseObtained() throws Exception {
+ this.mockMvc.perform(get("/employee/1").header(HttpHeaders.ACCEPT, MediaType.APPLICATION_XML_VALUE))
+ .andExpect(status().isOk())
+ .andExpect(header().string(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE));
+ }
+}
diff --git a/spring-mvc-java/README.md b/spring-mvc-java/README.md
index 8ba9b5fd1e..8a302e6fa3 100644
--- a/spring-mvc-java/README.md
+++ b/spring-mvc-java/README.md
@@ -13,7 +13,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [A Quick Guide to Spring MVC Matrix Variables](http://www.baeldung.com/spring-mvc-matrix-variables)
- [Intro to WebSockets with Spring](http://www.baeldung.com/websockets-spring)
- [File Upload with Spring MVC](http://www.baeldung.com/spring-file-upload)
-- [Spring MVC Content Negotiation](http://www.baeldung.com/spring-mvc-content-negotiation-json-xml)
- [Circular Dependencies in Spring](http://www.baeldung.com/circular-dependencies-in-spring)
- [Introduction to HtmlUnit](http://www.baeldung.com/htmlunit)
- [Spring @RequestMapping New Shortcut Annotations](http://www.baeldung.com/spring-new-requestmapping-shortcuts)
diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java
index 96b50f2c37..44fef92917 100644
--- a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java
+++ b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java
@@ -17,7 +17,6 @@ import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.ViewResolver;
-import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
@@ -94,11 +93,6 @@ public class WebConfig implements WebMvcConfigurer {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
- @Override
- public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) {
- configurer.favorPathExtension(false).favorParameter(true).parameterName("mediaType").ignoreAcceptHeader(true).useRegisteredExtensionsOnly(false).defaultContentType(MediaType.APPLICATION_JSON).mediaType("xml", MediaType.APPLICATION_XML).mediaType("json",
- MediaType.APPLICATION_JSON);
- }
@Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver() {
diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/EmployeeIntegrationTest.java b/spring-mvc-java/src/test/java/com/baeldung/web/controller/EmployeeIntegrationTest.java
deleted file mode 100644
index 0c2aa3de1b..0000000000
--- a/spring-mvc-java/src/test/java/com/baeldung/web/controller/EmployeeIntegrationTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.baeldung.web.controller;
-
-import org.junit.Before;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.context.web.WebAppConfiguration;
-
-import com.baeldung.model.Employee;
-import com.baeldung.spring.web.config.WebConfig;
-
-@RunWith(SpringJUnit4ClassRunner.class)
-@WebAppConfiguration
-@ContextConfiguration(classes = WebConfig.class)
-public class EmployeeIntegrationTest {
-
- @Autowired
- private EmployeeController employeeController;
-
- @Before
- public void setup() {
- employeeController.initEmployees();
- }
-
- @Test
- public void whenInitEmployees_thenVerifyValuesInitiation() {
-
- Employee employee1 = employeeController.employeeMap.get(1L);
- Employee employee2 = employeeController.employeeMap.get(2L);
- Employee employee3 = employeeController.employeeMap.get(3L);
-
- Assert.assertTrue(employee1.getId() == 1L);
- Assert.assertTrue(employee1.getName().equals("John"));
- Assert.assertTrue(employee1.getContactNumber().equals("223334411"));
- Assert.assertTrue(employee1.getWorkingArea().equals("rh"));
-
- Assert.assertTrue(employee2.getId() == 2L);
- Assert.assertTrue(employee2.getName().equals("Peter"));
- Assert.assertTrue(employee2.getContactNumber().equals("22001543"));
- Assert.assertTrue(employee2.getWorkingArea().equals("informatics"));
-
- Assert.assertTrue(employee3.getId() == 3L);
- Assert.assertTrue(employee3.getName().equals("Mike"));
- Assert.assertTrue(employee3.getContactNumber().equals("223334411"));
- Assert.assertTrue(employee3.getWorkingArea().equals("admin"));
- }
-
-}