From 86c72ffd7b9e5a08295a559e5b1967a5a91b9f00 Mon Sep 17 00:00:00 2001 From: M-Abdelbaset <31687750+M-Abdelbaset@users.noreply.github.com> Date: Sat, 16 Nov 2019 01:07:27 +0200 Subject: [PATCH] Bael-3395: Spring optional path variables (#8193) * initial test cases * changes in @requestMapping * moving code to spring-mvc-basic-2 project --- .../ArticleViewerController.java | 25 ++++++++ .../ArticleViewerWithMapParamController.java | 29 ++++++++++ ...icleViewerWithOptionalParamController.java | 28 +++++++++ ...ViewerWithRequiredAttributeController.java | 26 +++++++++ ...iewerWithTwoSeparateMethodsController.java | 27 +++++++++ .../main/java/com/baeldung/model/Article.java | 22 +++++++ .../baeldung/controller/config/WebConfig.java | 2 +- ...rticleViewerControllerIntegrationTest.java | 54 ++++++++++++++++++ ...ollerWithOptionalParamIntegrationTest.java | 55 ++++++++++++++++++ ...rWithRequiredAttributeIntegrationTest.java | 55 ++++++++++++++++++ ...icleViewerWithMapParamIntegrationTest.java | 57 +++++++++++++++++++ ...WithTwoSeparateMethodsIntegrationTest.java | 56 ++++++++++++++++++ 12 files changed, 435 insertions(+), 1 deletion(-) create mode 100644 spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerController.java create mode 100644 spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithMapParamController.java create mode 100644 spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithOptionalParamController.java create mode 100644 spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithRequiredAttributeController.java create mode 100644 spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithTwoSeparateMethodsController.java create mode 100644 spring-mvc-basics-2/src/main/java/com/baeldung/model/Article.java create mode 100644 spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerControllerIntegrationTest.java create mode 100644 spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerControllerWithOptionalParamIntegrationTest.java create mode 100644 spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerControllerWithRequiredAttributeIntegrationTest.java create mode 100644 spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithMapParamIntegrationTest.java create mode 100644 spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithTwoSeparateMethodsIntegrationTest.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerController.java b/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerController.java new file mode 100644 index 0000000000..62c2502242 --- /dev/null +++ b/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerController.java @@ -0,0 +1,25 @@ +package com.baeldung.controller.optionalpathvars; + +import static com.baeldung.model.Article.DEFAULT_ARTICLE; + +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.model.Article; + +@RestController +public class ArticleViewerController { + + @RequestMapping(value = {"/article", "/article/{id}"}) + public Article getArticle(@PathVariable(name = "id") Integer articleId) { + + if (articleId != null) { + return new Article(articleId); + } else { + return DEFAULT_ARTICLE; + } + + } + +} \ No newline at end of file diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithMapParamController.java b/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithMapParamController.java new file mode 100644 index 0000000000..d16cf4115c --- /dev/null +++ b/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithMapParamController.java @@ -0,0 +1,29 @@ +package com.baeldung.controller.optionalpathvars; + +import static com.baeldung.model.Article.DEFAULT_ARTICLE; + +import java.util.Map; + +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.model.Article; + +@RestController +@RequestMapping(value = "/mapParam") +public class ArticleViewerWithMapParamController { + + @RequestMapping(value = {"/article", "/article/{id}"}) + public Article getArticle(@PathVariable Map pathVarsMap) { + + String articleId = pathVarsMap.get("id"); + + if (articleId != null) { + return new Article(Integer.valueOf(articleId)); + } else { + return DEFAULT_ARTICLE; + } + } + +} \ No newline at end of file diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithOptionalParamController.java b/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithOptionalParamController.java new file mode 100644 index 0000000000..fd7b900535 --- /dev/null +++ b/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithOptionalParamController.java @@ -0,0 +1,28 @@ +package com.baeldung.controller.optionalpathvars; + +import static com.baeldung.model.Article.DEFAULT_ARTICLE; + +import java.util.Optional; + +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.model.Article;; + +@RestController +@RequestMapping("/optionalParam") +public class ArticleViewerWithOptionalParamController { + + @RequestMapping(value = {"/article", "/article/{id}"}) + public Article getArticle(@PathVariable(name = "id") Optional optionalArticleId) { + + if(optionalArticleId.isPresent()) { + Integer articleId = optionalArticleId.get(); + return new Article(articleId); + }else { + return DEFAULT_ARTICLE; + } + } + +} \ No newline at end of file diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithRequiredAttributeController.java b/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithRequiredAttributeController.java new file mode 100644 index 0000000000..d9b36f93e8 --- /dev/null +++ b/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithRequiredAttributeController.java @@ -0,0 +1,26 @@ +package com.baeldung.controller.optionalpathvars; + +import static com.baeldung.model.Article.DEFAULT_ARTICLE; + +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.model.Article;; + +@RestController +@RequestMapping(value = "/requiredAttribute") +public class ArticleViewerWithRequiredAttributeController { + + @RequestMapping(value = {"/article", "/article/{id}"}) + public Article getArticle(@PathVariable(name = "id", required = false) Integer articleId) { + + if (articleId != null) { + return new Article(articleId); + } else { + return DEFAULT_ARTICLE; + } + + } + +} \ No newline at end of file diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithTwoSeparateMethodsController.java b/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithTwoSeparateMethodsController.java new file mode 100644 index 0000000000..0b66b6cf43 --- /dev/null +++ b/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithTwoSeparateMethodsController.java @@ -0,0 +1,27 @@ +package com.baeldung.controller.optionalpathvars; + +import static com.baeldung.model.Article.DEFAULT_ARTICLE; + +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.model.Article; + +@RestController +@RequestMapping(value = "/seperateMethods") +public class ArticleViewerWithTwoSeparateMethodsController { + + @RequestMapping(value = "/article/{id}") + public Article getArticle(@PathVariable(name = "id") Integer articleId) { + + return new Article(articleId); + } + + @RequestMapping(value = "/article") + public Article getDefaultArticle() { + + return DEFAULT_ARTICLE; + } + +} \ No newline at end of file diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/model/Article.java b/spring-mvc-basics-2/src/main/java/com/baeldung/model/Article.java new file mode 100644 index 0000000000..141bd17db7 --- /dev/null +++ b/spring-mvc-basics-2/src/main/java/com/baeldung/model/Article.java @@ -0,0 +1,22 @@ +package com.baeldung.model; + +public class Article { + + public static final Article DEFAULT_ARTICLE = new Article(12); + + private Integer id; + + public Article(Integer articleId) { + this.id = articleId; + } + + public Integer getId() { + return id; + } + + @Override + public String toString() { + return "Article [id=" + id + "]"; + } + +} diff --git a/spring-mvc-basics-2/src/main/java/org/baeldung/controller/config/WebConfig.java b/spring-mvc-basics-2/src/main/java/org/baeldung/controller/config/WebConfig.java index 485c1d9032..018c530f18 100644 --- a/spring-mvc-basics-2/src/main/java/org/baeldung/controller/config/WebConfig.java +++ b/spring-mvc-basics-2/src/main/java/org/baeldung/controller/config/WebConfig.java @@ -11,7 +11,7 @@ import org.springframework.web.servlet.view.InternalResourceViewResolver; @Configuration @EnableWebMvc -@ComponentScan(basePackages = { "org.baeldung.controller.controller", "org.baeldung.controller.config" }) +@ComponentScan(basePackages = { "org.baeldung.controller.controller", "com.baeldung.controller", "org.baeldung.controller.config" }) public class WebConfig implements WebMvcConfigurer { @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { diff --git a/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerControllerIntegrationTest.java b/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerControllerIntegrationTest.java new file mode 100644 index 0000000000..2fb3569fc1 --- /dev/null +++ b/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerControllerIntegrationTest.java @@ -0,0 +1,54 @@ +package com.baeldung.controller.optionalpathvars; + +import org.junit.Before; +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 org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; +import org.baeldung.controller.config.WebConfig; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration(classes = { WebConfig.class }) +public class ArticleViewerControllerIntegrationTest { + + @Autowired + private WebApplicationContext wac; + + private MockMvc mockMvc; + + @Before + public void setup() throws Exception { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + public void whenIdPathVariableIsPassed_thenResponseOK() throws Exception { + + int articleId = 5; + + this.mockMvc + .perform(MockMvcRequestBuilders.get("/article/{id}", articleId)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.id").value(articleId)); + + } + + @Test + public void whenIdPathVariableIsNotPassed_thenResponse500() throws Exception { + + this.mockMvc + .perform(MockMvcRequestBuilders.get("/article")) + .andExpect(MockMvcResultMatchers.status().isInternalServerError()); + + } + + +} \ No newline at end of file diff --git a/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerControllerWithOptionalParamIntegrationTest.java b/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerControllerWithOptionalParamIntegrationTest.java new file mode 100644 index 0000000000..629e37f963 --- /dev/null +++ b/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerControllerWithOptionalParamIntegrationTest.java @@ -0,0 +1,55 @@ +package com.baeldung.controller.optionalpathvars; + +import org.junit.Before; +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 org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import com.baeldung.model.Article; +import org.baeldung.controller.config.WebConfig; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration(classes = { WebConfig.class }) +public class ArticleViewerControllerWithOptionalParamIntegrationTest { + + @Autowired + private WebApplicationContext wac; + + private MockMvc mockMvc; + + @Before + public void setup() throws Exception { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + public void givenOPtionalParam_whenIdPathVariableIsPassed_thenResponseOK() throws Exception { + + int articleId = 154; + + this.mockMvc + .perform(MockMvcRequestBuilders.get("/optionalParam/article/{id}", articleId)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.id").value(articleId)); + + } + + @Test + public void givenOPtionalParam_whenIdPathVariableIsNotPassed_thenResponseOK() throws Exception { + + this.mockMvc + .perform(MockMvcRequestBuilders.get("/optionalParam/article")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.id").value(Article.DEFAULT_ARTICLE.getId())); + + } +} \ No newline at end of file diff --git a/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerControllerWithRequiredAttributeIntegrationTest.java b/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerControllerWithRequiredAttributeIntegrationTest.java new file mode 100644 index 0000000000..00494171c0 --- /dev/null +++ b/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerControllerWithRequiredAttributeIntegrationTest.java @@ -0,0 +1,55 @@ +package com.baeldung.controller.optionalpathvars; + +import org.junit.Before; +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 org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import com.baeldung.model.Article; +import org.baeldung.controller.config.WebConfig; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration(classes = { WebConfig.class }) +public class ArticleViewerControllerWithRequiredAttributeIntegrationTest { + + @Autowired + private WebApplicationContext wac; + + private MockMvc mockMvc; + + @Before + public void setup() throws Exception { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + public void givenRequiredAttributeIsFalse_whenIdPathVariableIsPassed_thenResponseOK() throws Exception { + + int articleId = 154; + + this.mockMvc + .perform(MockMvcRequestBuilders.get("/requiredAttribute/article/{id}", articleId)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.id").value(articleId)); + + } + + @Test + public void givenRequiredAttributeIsFalse_whenIdPathVariableIsNotPassed_thenResponseOK() throws Exception { + + this.mockMvc + .perform(MockMvcRequestBuilders.get("/requiredAttribute/article")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.id").value(Article.DEFAULT_ARTICLE.getId())); + + } +} \ No newline at end of file diff --git a/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithMapParamIntegrationTest.java b/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithMapParamIntegrationTest.java new file mode 100644 index 0000000000..3c82b11578 --- /dev/null +++ b/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithMapParamIntegrationTest.java @@ -0,0 +1,57 @@ +package com.baeldung.controller.optionalpathvars; + +import org.junit.Before; +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 org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import com.baeldung.model.Article; +import org.baeldung.controller.config.WebConfig; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration(classes = { WebConfig.class }) +public class ArticleViewerWithMapParamIntegrationTest { + + @Autowired + private WebApplicationContext wac; + + private MockMvc mockMvc; + + @Before + public void setup() throws Exception { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + public void givenPathVarsMapParam_whenIdPathVariableIsPassed_thenResponseOK() throws Exception { + + int articleId = 5; + + this.mockMvc + .perform(MockMvcRequestBuilders.get("/mapParam/article/{id}", articleId)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.id").value(articleId)); + + } + + @Test + public void givenPathVarsMapParam_whenIdPathVariableIsNotPassed_thenResponseOK() throws Exception { + + this.mockMvc + .perform(MockMvcRequestBuilders.get("/mapParam/article")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.id").value(Article.DEFAULT_ARTICLE.getId())); + + } + + +} \ No newline at end of file diff --git a/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithTwoSeparateMethodsIntegrationTest.java b/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithTwoSeparateMethodsIntegrationTest.java new file mode 100644 index 0000000000..9532270c43 --- /dev/null +++ b/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithTwoSeparateMethodsIntegrationTest.java @@ -0,0 +1,56 @@ +package com.baeldung.controller.optionalpathvars; + +import org.junit.Before; +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 org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import com.baeldung.model.Article; +import org.baeldung.controller.config.WebConfig; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration(classes = { WebConfig.class }) +public class ArticleViewerWithTwoSeparateMethodsIntegrationTest { + + @Autowired + private WebApplicationContext wac; + + private MockMvc mockMvc; + + @Before + public void setup() throws Exception { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + public void givenTwoSeparateMethods_whenIdPathVariableIsPassed_thenResponseOK() throws Exception { + + int articleId = 5; + + this.mockMvc + .perform(MockMvcRequestBuilders.get("/seperateMethods/article/{id}", articleId)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.id").value(articleId)); + + } + + @Test + public void givenTwoSeparateMethods_whenIdPathVariableIsNotPassed_thenResponseOK() throws Exception { + + this.mockMvc + .perform(MockMvcRequestBuilders.get("/seperateMethods/article")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.id").value(Article.DEFAULT_ARTICLE.getId())); + + } + +} \ No newline at end of file