From 16793411c089d0f7d75e1f88e9026cc9c71cb584 Mon Sep 17 00:00:00 2001
From: Azhwani <13301425+azhwani@users.noreply.github.com>
Date: Sun, 27 Nov 2022 15:50:55 +0100
Subject: [PATCH] BAEL-5978: Case Insensitive Enum Mapping in Spring Boot
(#13061)
* BAEL-5978: Case Insensitive Enum Mapping in Spring Boot
* Move code to a new module: spring-boot-request-params
---
.../spring-boot-request-params/README.md | 5 ++
.../spring-boot-request-params/pom.xml | 28 ++++++++++
.../EnumMappingMainApplication.java | 13 +++++
.../enummapping/config/EnumMappingConfig.java | 17 ++++++
.../controllers/EnumMappingController.java | 30 +++++++++++
.../converters/StringToLevelConverter.java | 19 +++++++
.../enummapping/editors/LevelEditor.java | 22 ++++++++
.../com/baeldung/enummapping/enums/Level.java | 7 +++
.../EnumMappingIntegrationTest.java | 52 +++++++++++++++++++
...StringToLevelConverterIntegrationTest.java | 37 +++++++++++++
.../editors/LevelEditorIntegrationTest.java | 34 ++++++++++++
11 files changed, 264 insertions(+)
create mode 100644 spring-boot-modules/spring-boot-request-params/README.md
create mode 100644 spring-boot-modules/spring-boot-request-params/pom.xml
create mode 100644 spring-boot-modules/spring-boot-request-params/src/main/java/com/baeldung/enummapping/EnumMappingMainApplication.java
create mode 100644 spring-boot-modules/spring-boot-request-params/src/main/java/com/baeldung/enummapping/config/EnumMappingConfig.java
create mode 100644 spring-boot-modules/spring-boot-request-params/src/main/java/com/baeldung/enummapping/controllers/EnumMappingController.java
create mode 100644 spring-boot-modules/spring-boot-request-params/src/main/java/com/baeldung/enummapping/converters/StringToLevelConverter.java
create mode 100644 spring-boot-modules/spring-boot-request-params/src/main/java/com/baeldung/enummapping/editors/LevelEditor.java
create mode 100644 spring-boot-modules/spring-boot-request-params/src/main/java/com/baeldung/enummapping/enums/Level.java
create mode 100644 spring-boot-modules/spring-boot-request-params/src/test/java/com/baeldung/enummapping/EnumMappingIntegrationTest.java
create mode 100644 spring-boot-modules/spring-boot-request-params/src/test/java/com/baeldung/enummapping/converters/StringToLevelConverterIntegrationTest.java
create mode 100644 spring-boot-modules/spring-boot-request-params/src/test/java/com/baeldung/enummapping/editors/LevelEditorIntegrationTest.java
diff --git a/spring-boot-modules/spring-boot-request-params/README.md b/spring-boot-modules/spring-boot-request-params/README.md
new file mode 100644
index 0000000000..f3ced26455
--- /dev/null
+++ b/spring-boot-modules/spring-boot-request-params/README.md
@@ -0,0 +1,5 @@
+## Spring Boot Request Params
+
+This module contains articles about Spring Boot Request Params
+
+### Relevant Articles:
diff --git a/spring-boot-modules/spring-boot-request-params/pom.xml b/spring-boot-modules/spring-boot-request-params/pom.xml
new file mode 100644
index 0000000000..526938860a
--- /dev/null
+++ b/spring-boot-modules/spring-boot-request-params/pom.xml
@@ -0,0 +1,28 @@
+
+
+ 4.0.0
+ spring-boot-request-params
+ spring-boot-request-params
+ jar
+ Module For Spring Boot Request Params
+
+
+ com.baeldung.spring-boot-modules
+ spring-boot-modules
+ 1.0.0-SNAPSHOT
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-request-params/src/main/java/com/baeldung/enummapping/EnumMappingMainApplication.java b/spring-boot-modules/spring-boot-request-params/src/main/java/com/baeldung/enummapping/EnumMappingMainApplication.java
new file mode 100644
index 0000000000..43145f13ad
--- /dev/null
+++ b/spring-boot-modules/spring-boot-request-params/src/main/java/com/baeldung/enummapping/EnumMappingMainApplication.java
@@ -0,0 +1,13 @@
+package com.baeldung.enummapping;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class EnumMappingMainApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(EnumMappingMainApplication.class, args);
+ }
+
+}
diff --git a/spring-boot-modules/spring-boot-request-params/src/main/java/com/baeldung/enummapping/config/EnumMappingConfig.java b/spring-boot-modules/spring-boot-request-params/src/main/java/com/baeldung/enummapping/config/EnumMappingConfig.java
new file mode 100644
index 0000000000..8078a3cb47
--- /dev/null
+++ b/spring-boot-modules/spring-boot-request-params/src/main/java/com/baeldung/enummapping/config/EnumMappingConfig.java
@@ -0,0 +1,17 @@
+package com.baeldung.enummapping.config;
+
+import org.springframework.boot.convert.ApplicationConversionService;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.format.FormatterRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import com.baeldung.enummapping.converters.StringToLevelConverter;
+
+@Configuration
+public class EnumMappingConfig implements WebMvcConfigurer {
+ @Override
+ public void addFormatters(FormatterRegistry registry) {
+ ApplicationConversionService.configure(registry);
+ registry.addConverter(new StringToLevelConverter());
+ }
+}
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-request-params/src/main/java/com/baeldung/enummapping/controllers/EnumMappingController.java b/spring-boot-modules/spring-boot-request-params/src/main/java/com/baeldung/enummapping/controllers/EnumMappingController.java
new file mode 100644
index 0000000000..d006b8f149
--- /dev/null
+++ b/spring-boot-modules/spring-boot-request-params/src/main/java/com/baeldung/enummapping/controllers/EnumMappingController.java
@@ -0,0 +1,30 @@
+package com.baeldung.enummapping.controllers;
+
+import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.InitBinder;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.baeldung.enummapping.editors.LevelEditor;
+import com.baeldung.enummapping.enums.Level;
+
+@RestController
+@RequestMapping("enummapping")
+public class EnumMappingController {
+
+ @InitBinder
+ public void initBinder(WebDataBinder dataBinder) {
+ dataBinder.registerCustomEditor(Level.class, new LevelEditor());
+ }
+
+ @GetMapping("/get")
+ public String getByLevel(@RequestParam(required = false) Level level) {
+ if (level != null) {
+ return level.name();
+ }
+ return "undefined";
+ }
+
+}
diff --git a/spring-boot-modules/spring-boot-request-params/src/main/java/com/baeldung/enummapping/converters/StringToLevelConverter.java b/spring-boot-modules/spring-boot-request-params/src/main/java/com/baeldung/enummapping/converters/StringToLevelConverter.java
new file mode 100644
index 0000000000..8adee1c4e5
--- /dev/null
+++ b/spring-boot-modules/spring-boot-request-params/src/main/java/com/baeldung/enummapping/converters/StringToLevelConverter.java
@@ -0,0 +1,19 @@
+package com.baeldung.enummapping.converters;
+
+import org.apache.commons.lang3.EnumUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.core.convert.converter.Converter;
+
+import com.baeldung.enummapping.enums.Level;
+
+public class StringToLevelConverter implements Converter {
+
+ @Override
+ public Level convert(String source) {
+ if (StringUtils.isBlank(source)) {
+ return null;
+ }
+ return EnumUtils.getEnum(Level.class, source.toUpperCase());
+ }
+
+}
diff --git a/spring-boot-modules/spring-boot-request-params/src/main/java/com/baeldung/enummapping/editors/LevelEditor.java b/spring-boot-modules/spring-boot-request-params/src/main/java/com/baeldung/enummapping/editors/LevelEditor.java
new file mode 100644
index 0000000000..d4f8e96ad8
--- /dev/null
+++ b/spring-boot-modules/spring-boot-request-params/src/main/java/com/baeldung/enummapping/editors/LevelEditor.java
@@ -0,0 +1,22 @@
+package com.baeldung.enummapping.editors;
+
+import java.beans.PropertyEditorSupport;
+
+import org.apache.commons.lang3.EnumUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import com.baeldung.enummapping.enums.Level;
+
+public class LevelEditor extends PropertyEditorSupport {
+
+ @Override
+ public void setAsText(String text) {
+ if (StringUtils.isBlank(text)) {
+ setValue(null);
+ } else {
+ setValue(EnumUtils.getEnum(Level.class, text.toUpperCase()));
+ }
+
+ }
+
+}
diff --git a/spring-boot-modules/spring-boot-request-params/src/main/java/com/baeldung/enummapping/enums/Level.java b/spring-boot-modules/spring-boot-request-params/src/main/java/com/baeldung/enummapping/enums/Level.java
new file mode 100644
index 0000000000..471e9c2f5c
--- /dev/null
+++ b/spring-boot-modules/spring-boot-request-params/src/main/java/com/baeldung/enummapping/enums/Level.java
@@ -0,0 +1,7 @@
+package com.baeldung.enummapping.enums;
+
+public enum Level {
+
+ LOW, MEDIUM, HIGH
+
+}
diff --git a/spring-boot-modules/spring-boot-request-params/src/test/java/com/baeldung/enummapping/EnumMappingIntegrationTest.java b/spring-boot-modules/spring-boot-request-params/src/test/java/com/baeldung/enummapping/EnumMappingIntegrationTest.java
new file mode 100644
index 0000000000..0fd1ce72d7
--- /dev/null
+++ b/spring-boot-modules/spring-boot-request-params/src/test/java/com/baeldung/enummapping/EnumMappingIntegrationTest.java
@@ -0,0 +1,52 @@
+package com.baeldung.enummapping;
+
+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.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.servlet.MockMvc;
+
+import com.baeldung.enummapping.controllers.EnumMappingController;
+import com.baeldung.enummapping.enums.Level;
+
+@RunWith(SpringRunner.class)
+@WebMvcTest(EnumMappingController.class)
+public class EnumMappingIntegrationTest {
+
+ @Autowired
+ private MockMvc mockMvc;
+
+ @Test
+ public void whenPassingLowerCaseEnumConstant_thenConvert() throws Exception {
+ mockMvc.perform(get("/enummapping/get?level=medium"))
+ .andExpect(status().isOk())
+ .andExpect(content().string(Level.MEDIUM.name()));
+ }
+
+ @Test
+ public void whenPassingUnknownEnumConstant_thenReturnUndefined() throws Exception {
+ mockMvc.perform(get("/enummapping/get?level=unknown"))
+ .andExpect(status().isOk())
+ .andExpect(content().string("undefined"));
+ }
+
+ @Test
+ public void whenPassingEmptyParameter_thenReturnUndefined() throws Exception {
+ mockMvc.perform(get("/enummapping/get?level="))
+ .andExpect(status().isOk())
+ .andExpect(content().string("undefined"));
+ }
+
+ @Test
+ public void whenPassingNoParameter_thenReturnUndefined() throws Exception {
+ mockMvc.perform(get("/enummapping/get"))
+ .andExpect(status().isOk())
+ .andExpect(content().string("undefined"));
+ }
+
+}
diff --git a/spring-boot-modules/spring-boot-request-params/src/test/java/com/baeldung/enummapping/converters/StringToLevelConverterIntegrationTest.java b/spring-boot-modules/spring-boot-request-params/src/test/java/com/baeldung/enummapping/converters/StringToLevelConverterIntegrationTest.java
new file mode 100644
index 0000000000..100f742f40
--- /dev/null
+++ b/spring-boot-modules/spring-boot-request-params/src/test/java/com/baeldung/enummapping/converters/StringToLevelConverterIntegrationTest.java
@@ -0,0 +1,37 @@
+package com.baeldung.enummapping.converters;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.core.convert.ConversionService;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import com.baeldung.enummapping.EnumMappingMainApplication;
+import com.baeldung.enummapping.enums.Level;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = EnumMappingMainApplication.class)
+public class StringToLevelConverterIntegrationTest {
+
+ @Autowired
+ ConversionService conversionService;
+
+ @Test
+ public void whenConvertStringToLevelEnumUsingCustomConverter_thenSuccess() {
+ assertThat(conversionService.convert("low", Level.class)).isEqualTo(Level.LOW);
+ }
+
+ @Test
+ public void whenStringIsEmpty_thenReturnNull() {
+ assertThat(conversionService.convert("", Level.class)).isNull();
+ }
+
+ @Test
+ public void whenStringIsNull_thenReturnNull() {
+ assertThat(conversionService.convert(null, Level.class)).isNull();
+ }
+
+}
diff --git a/spring-boot-modules/spring-boot-request-params/src/test/java/com/baeldung/enummapping/editors/LevelEditorIntegrationTest.java b/spring-boot-modules/spring-boot-request-params/src/test/java/com/baeldung/enummapping/editors/LevelEditorIntegrationTest.java
new file mode 100644
index 0000000000..ab01cbc1ed
--- /dev/null
+++ b/spring-boot-modules/spring-boot-request-params/src/test/java/com/baeldung/enummapping/editors/LevelEditorIntegrationTest.java
@@ -0,0 +1,34 @@
+package com.baeldung.enummapping.editors;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Test;
+
+import com.baeldung.enummapping.enums.Level;
+
+public class LevelEditorIntegrationTest {
+
+ private final LevelEditor levelEditor = new LevelEditor();
+
+ @Test
+ public void whenConvertStringToLevelEnumUsingCustomPropertyEditor_thenSuccess() {
+ levelEditor.setAsText("lOw");
+
+ assertThat(levelEditor.getValue()).isEqualTo(Level.LOW);
+ }
+
+ @Test
+ public void whenStringIsEmpty_thenReturnNull() {
+ levelEditor.setAsText("");
+
+ assertThat(levelEditor.getValue()).isNull();
+ }
+
+ @Test
+ public void whenStringIsNull_thenReturnNull() {
+ levelEditor.setAsText(null);
+
+ assertThat(levelEditor.getValue()).isNull();
+ }
+
+}