diff --git a/spring-mvc-simple-2/pom.xml b/spring-mvc-simple-2/pom.xml
new file mode 100644
index 0000000000..74302cff78
--- /dev/null
+++ b/spring-mvc-simple-2/pom.xml
@@ -0,0 +1,37 @@
+
+
+ 4.0.0
+ spring-mvc-simple-2
+ war
+ spring-mvc-simple-2
+
+
+ com.baeldung
+ parent-boot-2
+ 0.0.1-SNAPSHOT
+ ../parent-boot-2
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ 1.8
+ 1.8
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+
+
+ spring-mvc-simple2
+
+
diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/spring/Application.java b/spring-mvc-simple-2/src/main/java/com/baeldung/spring/Application.java
new file mode 100644
index 0000000000..40a0a55761
--- /dev/null
+++ b/spring-mvc-simple-2/src/main/java/com/baeldung/spring/Application.java
@@ -0,0 +1,11 @@
+package com.baeldung.spring;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+}
diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/spring/headers/controller/ReadHeaderRestController.java b/spring-mvc-simple-2/src/main/java/com/baeldung/spring/headers/controller/ReadHeaderRestController.java
new file mode 100644
index 0000000000..6a0f3b6a0d
--- /dev/null
+++ b/spring-mvc-simple-2/src/main/java/com/baeldung/spring/headers/controller/ReadHeaderRestController.java
@@ -0,0 +1,97 @@
+package com.baeldung.spring.headers.controller;
+
+import java.net.InetSocketAddress;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class ReadHeaderRestController {
+ private static final Log LOG = LogFactory.getLog(ReadHeaderRestController.class);
+
+ @GetMapping("/")
+ public ResponseEntity index() {
+ return new ResponseEntity("Index", HttpStatus.OK);
+ }
+
+ @GetMapping("/greeting")
+ public ResponseEntity greeting(@RequestHeader(value = "accept-language") String language) {
+ String greeting = "";
+ String firstLanguage = (language.length() > 1 ? language.substring(0, 2) : language);
+ switch (firstLanguage) {
+ case "es":
+ greeting = "Hola!";
+ break;
+ case "de":
+ greeting = "Hallo!";
+ break;
+ case "fr":
+ greeting = "Bonjour!";
+ break;
+ case "en":
+ default:
+ greeting = "Hello!";
+ break;
+ }
+
+ return new ResponseEntity(greeting, HttpStatus.OK);
+ }
+
+ @GetMapping("/double")
+ public ResponseEntity doubleNumber(@RequestHeader("my-number") int myNumber) {
+ return new ResponseEntity(
+ String.format("%d * 2 = %d", myNumber, (myNumber * 2)),
+ HttpStatus.OK);
+ }
+
+ @GetMapping("/listHeaders")
+ public ResponseEntity listAllHeaders(@RequestHeader Map headers) {
+
+ headers.forEach((key, value) -> {
+ LOG.info(String.format("Header '%s' = %s", key, value));
+ });
+
+ return new ResponseEntity(String.format("Listed %d headers", headers.size()), HttpStatus.OK);
+ }
+
+ @GetMapping("/multiValue")
+ public ResponseEntity multiValue(@RequestHeader MultiValueMap headers) {
+ headers.forEach((key, value) -> {
+ LOG.info(String.format("Header '%s' = %s", key, value.stream().collect(Collectors.joining("|"))));
+ });
+
+ return new ResponseEntity(String.format("Listed %d headers", headers.size()), HttpStatus.OK);
+ }
+
+ @GetMapping("/getBaseUrl")
+ public ResponseEntity getBaseUrl(@RequestHeader HttpHeaders headers) {
+ InetSocketAddress host = headers.getHost();
+ String url = "http://" + host.getHostName() + ":" + host.getPort();
+ return new ResponseEntity(String.format("Base URL = %s", url), HttpStatus.OK);
+ }
+
+ @GetMapping("/nonRequiredHeader")
+ public ResponseEntity evaluateNonRequiredHeader(
+ @RequestHeader(value = "optional-header", required = false) String optionalHeader) {
+
+ return new ResponseEntity(
+ String.format("Was the optional header present? %s!", (optionalHeader == null ? "No" : "Yes")),
+ HttpStatus.OK);
+ }
+
+ @GetMapping("/default")
+ public ResponseEntity evaluateDefaultHeaderValue(
+ @RequestHeader(value = "optional-header", defaultValue = "3600") int optionalHeader) {
+
+ return new ResponseEntity(String.format("Optional Header is %d", optionalHeader), HttpStatus.OK);
+ }
+}
diff --git a/spring-mvc-simple-2/src/test/java/com/baeldung/AppContextIntegrationTest.java b/spring-mvc-simple-2/src/test/java/com/baeldung/AppContextIntegrationTest.java
new file mode 100644
index 0000000000..27207688e6
--- /dev/null
+++ b/spring-mvc-simple-2/src/test/java/com/baeldung/AppContextIntegrationTest.java
@@ -0,0 +1,13 @@
+package com.baeldung;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import com.baeldung.spring.Application;
+
+@SpringBootTest(classes = Application.class)
+public class AppContextIntegrationTest {
+ @Test
+ public void contextLoads() {
+ }
+}
diff --git a/spring-mvc-simple-2/src/test/java/com/baeldung/headers/controller/ReadHeaderRestControllerIntegrationTest.java b/spring-mvc-simple-2/src/test/java/com/baeldung/headers/controller/ReadHeaderRestControllerIntegrationTest.java
new file mode 100644
index 0000000000..6f94004cc7
--- /dev/null
+++ b/spring-mvc-simple-2/src/test/java/com/baeldung/headers/controller/ReadHeaderRestControllerIntegrationTest.java
@@ -0,0 +1,86 @@
+package com.baeldung.headers.controller;
+
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+
+import com.baeldung.spring.headers.controller.ReadHeaderRestController;
+
+@SpringJUnitWebConfig(ReadHeaderRestControllerIntegrationTest.Config.class)
+@ExtendWith(SpringExtension.class)
+public class ReadHeaderRestControllerIntegrationTest {
+ private static final Log LOG = LogFactory.getLog(ReadHeaderRestControllerIntegrationTest.class);
+
+ @Configuration
+ static class Config {
+
+ }
+
+ private MockMvc mockMvc;
+
+ @BeforeEach
+ public void setUp() {
+ mockMvc = MockMvcBuilders.standaloneSetup(new ReadHeaderRestController())
+ .build();
+ }
+
+ @Test
+ public void whenGetRequestSentToAllHeaders_thenStatusOkAndTextReturned() throws Exception {
+ mockMvc.perform(get("/listHeaders").header("my-header", "Test"))
+ .andExpect(status().isOk())
+ .andExpect(content().string("Listed 1 headers"));
+ }
+
+ @Test
+ public void whenGetRequestSentToMultiValue_thenStatusOkAndTextReturned() throws Exception {
+ mockMvc.perform(get("/multiValue").header("my-header", "ABC", "DEF", "GHI"))
+ .andExpect(status().isOk())
+ .andExpect(content().string("Listed 1 headers"));
+ }
+
+ @Test
+ public void whenGetRequestSentToGreeting_thenStatusOKAndGreetingReturned() throws Exception {
+ mockMvc.perform(get("/greeting").header("accept-language", "de"))
+ .andExpect(status().isOk())
+ .andExpect(content().string("Hallo!"));
+ }
+
+ @Test
+ public void whenGetRequestSentToDouble_thenStatusOKAndCorrectResultReturned() throws Exception {
+ mockMvc.perform(get("/double").header("my-number", 2))
+ .andExpect(status().isOk())
+ .andExpect(content().string("2 * 2 = 4"));
+ }
+
+ @Test
+ public void whenGetRequestSentToGetBaseUrl_thenStatusOkAndHostReturned() throws Exception {
+ mockMvc.perform(get("/getBaseUrl").header("host", "localhost:8080"))
+ .andExpect(status().isOk())
+ .andExpect(content().string("Base URL = http://localhost:8080"));
+ }
+
+ @Test
+ public void whenGetRequestSentToNonRequiredHeaderWithoutHeader_thenStatusOKAndMessageReturned() throws Exception {
+ mockMvc.perform(get("/nonRequiredHeader"))
+ .andExpect(status().isOk())
+ .andExpect(content().string("Was the optional header present? No!"));
+ }
+
+ @Test
+ public void whenGetRequestSentToDefaultWithoutHeader_thenStatusOKAndMessageReturned() throws Exception {
+ mockMvc.perform(get("/default"))
+ .andExpect(status().isOk())
+ .andExpect(content().string("Optional Header is 3600"));
+ }
+}