Merge pull request #14784 from niket17590/feature/BAEL-6695-BooleanValidation
BAEL-6695 Boolean Validation in Spring Boot
This commit is contained in:
		
						commit
						c2522bf470
					
				| @ -105,6 +105,7 @@ | |||||||
|         <module>spring-boot-documentation</module> |         <module>spring-boot-documentation</module> | ||||||
|         <module>spring-boot-3-url-matching</module> |         <module>spring-boot-3-url-matching</module> | ||||||
|         <module>spring-boot-graalvm-docker</module> |         <module>spring-boot-graalvm-docker</module> | ||||||
|  |         <module>spring-boot-validations</module> | ||||||
|     </modules> |     </modules> | ||||||
| 
 | 
 | ||||||
|     <dependencyManagement> |     <dependencyManagement> | ||||||
|  | |||||||
							
								
								
									
										35
									
								
								spring-boot-modules/spring-boot-validations/pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								spring-boot-modules/spring-boot-validations/pom.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,35 @@ | |||||||
|  | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  |          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||||
|  |     <modelVersion>4.0.0</modelVersion> | ||||||
|  |     <parent> | ||||||
|  |         <groupId>com.baeldung.spring-boot-modules</groupId> | ||||||
|  |         <artifactId>spring-boot-modules</artifactId> | ||||||
|  |         <version>1.0.0-SNAPSHOT</version> | ||||||
|  |     </parent> | ||||||
|  |     <artifactId>spring-boot-validations</artifactId> | ||||||
|  |     <name>spring-boot-validations</name> | ||||||
|  |     <description>Demo of Validations in Spring Boot</description> | ||||||
|  |     <dependencies> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.springframework.boot</groupId> | ||||||
|  |             <artifactId>spring-boot-starter-web</artifactId> | ||||||
|  |         </dependency> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.springframework.boot</groupId> | ||||||
|  |             <artifactId>spring-boot-starter-test</artifactId> | ||||||
|  |             <scope>test</scope> | ||||||
|  |         </dependency> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.springframework.boot</groupId> | ||||||
|  |             <artifactId>spring-boot-starter-validation</artifactId> | ||||||
|  |         </dependency> | ||||||
|  |     </dependencies> | ||||||
|  |     <build> | ||||||
|  |         <plugins> | ||||||
|  |             <plugin> | ||||||
|  |                 <groupId>org.springframework.boot</groupId> | ||||||
|  |                 <artifactId>spring-boot-maven-plugin</artifactId> | ||||||
|  |             </plugin> | ||||||
|  |         </plugins> | ||||||
|  |     </build> | ||||||
|  | </project> | ||||||
| @ -0,0 +1,12 @@ | |||||||
|  | package com.baeldung; | ||||||
|  | 
 | ||||||
|  | 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); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,33 @@ | |||||||
|  | package com.baeldung.controller; | ||||||
|  | 
 | ||||||
|  | import javax.validation.Valid; | ||||||
|  | 
 | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.http.ResponseEntity; | ||||||
|  | import org.springframework.web.bind.annotation.PostMapping; | ||||||
|  | import org.springframework.web.bind.annotation.RequestBody; | ||||||
|  | import org.springframework.web.bind.annotation.RestController; | ||||||
|  | 
 | ||||||
|  | import com.baeldung.dto.BooleanObject; | ||||||
|  | import com.baeldung.service.ValidationService; | ||||||
|  | 
 | ||||||
|  | @RestController | ||||||
|  | public class ValidationController { | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     ValidationService service; | ||||||
|  | 
 | ||||||
|  |     @PostMapping("/validateBoolean") | ||||||
|  |     public ResponseEntity<String> processBooleanObject(@RequestBody @Valid BooleanObject booleanObj) { | ||||||
|  |         return ResponseEntity.ok("BooleanObject is valid"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @PostMapping("/validateBooleanAtService") | ||||||
|  |     public ResponseEntity<String> processBooleanObjectAtService() { | ||||||
|  |         BooleanObject boolObj = new BooleanObject(); | ||||||
|  |         boolObj.setBoolField(Boolean.TRUE); | ||||||
|  |         boolObj.setTrueField(Boolean.FALSE); | ||||||
|  |         service.processBoolean(boolObj); | ||||||
|  |         return ResponseEntity.ok("BooleanObject is valid"); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,37 @@ | |||||||
|  | package com.baeldung.controlleradvice; | ||||||
|  | 
 | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  | 
 | ||||||
|  | import javax.validation.ConstraintViolationException; | ||||||
|  | 
 | ||||||
|  | import org.springframework.http.HttpStatus; | ||||||
|  | import org.springframework.web.bind.MethodArgumentNotValidException; | ||||||
|  | import org.springframework.web.bind.annotation.ExceptionHandler; | ||||||
|  | import org.springframework.web.bind.annotation.ResponseStatus; | ||||||
|  | import org.springframework.web.bind.annotation.RestControllerAdvice; | ||||||
|  | 
 | ||||||
|  | @RestControllerAdvice | ||||||
|  | public class GlobalExceptionHandler { | ||||||
|  | 
 | ||||||
|  |     @ExceptionHandler(MethodArgumentNotValidException.class) | ||||||
|  |     @ResponseStatus(value = HttpStatus.BAD_REQUEST) | ||||||
|  |     public String handleValidationException(MethodArgumentNotValidException ex) { | ||||||
|  |         return ex.getBindingResult() | ||||||
|  |             .getFieldErrors() | ||||||
|  |             .stream() | ||||||
|  |             .map(e -> e.getDefaultMessage()) | ||||||
|  |             .collect(Collectors.joining(",")); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @ExceptionHandler(IllegalArgumentException.class) | ||||||
|  |     @ResponseStatus(value = HttpStatus.BAD_REQUEST) | ||||||
|  |     public String handleIllegalArugmentException(IllegalArgumentException ex) { | ||||||
|  |         return ex.getMessage(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @ExceptionHandler(ConstraintViolationException.class) | ||||||
|  |     @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) | ||||||
|  |     public String handleConstraintViolationException(ConstraintViolationException ex) { | ||||||
|  |         return ex.getMessage(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,21 @@ | |||||||
|  | package com.baeldung.deserializer; | ||||||
|  | 
 | ||||||
|  | import java.io.IOException; | ||||||
|  | 
 | ||||||
|  | import com.fasterxml.jackson.core.JsonParser; | ||||||
|  | import com.fasterxml.jackson.databind.DeserializationContext; | ||||||
|  | import com.fasterxml.jackson.databind.JsonDeserializer; | ||||||
|  | 
 | ||||||
|  | public class BooleanDeserializer extends JsonDeserializer<Boolean> { | ||||||
|  |     @Override | ||||||
|  |     public Boolean deserialize(JsonParser parser, DeserializationContext context) throws IOException { | ||||||
|  |         String value = parser.getText(); | ||||||
|  |         if (value != null && value.equals("+")) { | ||||||
|  |             return Boolean.TRUE; | ||||||
|  |         } else if (value != null && value.equals("-")) { | ||||||
|  |             return Boolean.FALSE; | ||||||
|  |         } else { | ||||||
|  |             throw new IllegalArgumentException("Only values accepted as Boolean are + and -"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,56 @@ | |||||||
|  | package com.baeldung.dto; | ||||||
|  | 
 | ||||||
|  | import javax.validation.constraints.AssertFalse; | ||||||
|  | import javax.validation.constraints.AssertTrue; | ||||||
|  | import javax.validation.constraints.NotNull; | ||||||
|  | 
 | ||||||
|  | import com.baeldung.deserializer.BooleanDeserializer; | ||||||
|  | import com.fasterxml.jackson.databind.annotation.JsonDeserialize; | ||||||
|  | 
 | ||||||
|  | public class BooleanObject { | ||||||
|  | 
 | ||||||
|  |     @NotNull(message = "boolField cannot be null") | ||||||
|  |     Boolean boolField; | ||||||
|  | 
 | ||||||
|  |     @AssertTrue(message = "trueField must have true value") | ||||||
|  |     Boolean trueField; | ||||||
|  | 
 | ||||||
|  |     @NotNull(message = "falseField cannot be null") | ||||||
|  |     @AssertFalse(message = "falseField must have false value") | ||||||
|  |     Boolean falseField; | ||||||
|  | 
 | ||||||
|  |     @JsonDeserialize(using = BooleanDeserializer.class) | ||||||
|  |     Boolean boolStringVar; | ||||||
|  | 
 | ||||||
|  |     public Boolean getBoolField() { | ||||||
|  |         return boolField; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setBoolField(Boolean boolField) { | ||||||
|  |         this.boolField = boolField; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Boolean getTrueField() { | ||||||
|  |         return trueField; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setTrueField(Boolean trueField) { | ||||||
|  |         this.trueField = trueField; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Boolean getFalseField() { | ||||||
|  |         return falseField; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setFalseField(Boolean falseField) { | ||||||
|  |         this.falseField = falseField; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Boolean getBoolStringVar() { | ||||||
|  |         return boolStringVar; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setBoolStringVar(Boolean boolStringVar) { | ||||||
|  |         this.boolStringVar = boolStringVar; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,17 @@ | |||||||
|  | package com.baeldung.service; | ||||||
|  | 
 | ||||||
|  | import javax.validation.Valid; | ||||||
|  | 
 | ||||||
|  | import org.springframework.stereotype.Service; | ||||||
|  | import org.springframework.validation.annotation.Validated; | ||||||
|  | 
 | ||||||
|  | import com.baeldung.dto.BooleanObject; | ||||||
|  | 
 | ||||||
|  | @Service | ||||||
|  | @Validated | ||||||
|  | public class ValidationService { | ||||||
|  | 
 | ||||||
|  |     public void processBoolean(@Valid BooleanObject booleanObj) { | ||||||
|  |         // further processing | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,125 @@ | |||||||
|  | package com.baeldung.controller; | ||||||
|  | 
 | ||||||
|  | import static org.junit.jupiter.api.Assertions.assertEquals; | ||||||
|  | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; | ||||||
|  | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | ||||||
|  | 
 | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.junit.jupiter.api.extension.ExtendWith; | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; | ||||||
|  | import org.springframework.boot.test.context.TestConfiguration; | ||||||
|  | import org.springframework.context.annotation.Bean; | ||||||
|  | import org.springframework.test.context.junit.jupiter.SpringExtension; | ||||||
|  | import org.springframework.test.web.servlet.MockMvc; | ||||||
|  | 
 | ||||||
|  | import com.baeldung.service.ValidationService; | ||||||
|  | 
 | ||||||
|  | @ExtendWith(SpringExtension.class) | ||||||
|  | @WebMvcTest(controllers = ValidationController.class) | ||||||
|  | class ValidationControllerUnitTest { | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     private MockMvc mockMvc; | ||||||
|  | 
 | ||||||
|  |     @TestConfiguration | ||||||
|  |     static class EmployeeServiceImplTestContextConfiguration { | ||||||
|  |         @Bean | ||||||
|  |         public ValidationService validationService() { | ||||||
|  |             return new ValidationService() { | ||||||
|  |             }; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     ValidationService service; | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void whenNullInputForBooleanField_thenHttpBadRequestAsHttpResponse() throws Exception { | ||||||
|  |         String postBody = "{\"boolField\":null,\"trueField\":true,\"falseField\":false,\"boolStringVar\":\"+\"}"; | ||||||
|  | 
 | ||||||
|  |         mockMvc.perform(post("/validateBoolean").contentType("application/json") | ||||||
|  |             .content(postBody)) | ||||||
|  |             .andExpect(status().isBadRequest()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void whenInvalidInputForTrueBooleanField_thenErrorResponse() throws Exception { | ||||||
|  |         String postBody = "{\"boolField\":true,\"trueField\":false,\"falseField\":false,\"boolStringVar\":\"+\"}"; | ||||||
|  | 
 | ||||||
|  |         String output = mockMvc.perform(post("/validateBoolean").contentType("application/json") | ||||||
|  |             .content(postBody)) | ||||||
|  |             .andReturn() | ||||||
|  |             .getResponse() | ||||||
|  |             .getContentAsString(); | ||||||
|  | 
 | ||||||
|  |         assertEquals("trueField must have true value", output); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void whenInvalidInputForFalseBooleanField_thenErrorResponse() throws Exception { | ||||||
|  |         String postBody = "{\"boolField\":true,\"trueField\":true,\"falseField\":true,\"boolStringVar\":\"+\"}"; | ||||||
|  | 
 | ||||||
|  |         String output = mockMvc.perform(post("/validateBoolean").contentType("application/json") | ||||||
|  |             .content(postBody)) | ||||||
|  |             .andReturn() | ||||||
|  |             .getResponse() | ||||||
|  |             .getContentAsString(); | ||||||
|  | 
 | ||||||
|  |         assertEquals("falseField must have false value", output); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void whenInvalidBooleanFromJson_thenErrorResponse() throws Exception { | ||||||
|  |         String postBody = "{\"boolField\":true,\"trueField\":true,\"falseField\":false,\"boolStringVar\":\"plus\"}"; | ||||||
|  | 
 | ||||||
|  |         String output = mockMvc.perform(post("/validateBoolean").contentType("application/json") | ||||||
|  |             .content(postBody)) | ||||||
|  |             .andReturn() | ||||||
|  |             .getResponse() | ||||||
|  |             .getContentAsString(); | ||||||
|  | 
 | ||||||
|  |         assertEquals("Only values accepted as Boolean are + and -", output); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void whenAllBooleanFieldsValid_thenCorrectResponse() throws Exception { | ||||||
|  |         String postBody = "{\"boolField\":true,\"trueField\":true,\"falseField\":false,\"boolStringVar\":\"+\"}"; | ||||||
|  | 
 | ||||||
|  |         String output = mockMvc.perform(post("/validateBoolean").contentType("application/json") | ||||||
|  |             .content(postBody)) | ||||||
|  |             .andReturn() | ||||||
|  |             .getResponse() | ||||||
|  |             .getContentAsString(); | ||||||
|  | 
 | ||||||
|  |         assertEquals("BooleanObject is valid", output); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenAllBooleanFieldsValid_whenServiceValidationFails_thenErrorResponse() throws Exception { | ||||||
|  |         mockMvc.perform(post("/validateBooleanAtService").contentType("application/json")) | ||||||
|  |             .andExpect(status().isInternalServerError()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void whenNullInputForTrueBooleanField_thenCorrectResponse() throws Exception { | ||||||
|  |         String postBody = "{\"boolField\":true,\"trueField\":null,\"falseField\":false,\"boolStringVar\":\"+\"}"; | ||||||
|  | 
 | ||||||
|  |         mockMvc.perform(post("/validateBoolean").contentType("application/json") | ||||||
|  |             .content(postBody)) | ||||||
|  |             .andExpect(status().isOk()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void whenNullInputForFalseBooleanField_thenHttpBadRequestAsHttpResponse() throws Exception { | ||||||
|  |         String postBody = "{\"boolField\":true,\"trueField\":true,\"falseField\":null,\"boolStringVar\":\"+\"}"; | ||||||
|  | 
 | ||||||
|  |         String output = mockMvc.perform(post("/validateBoolean").contentType("application/json") | ||||||
|  |             .content(postBody)) | ||||||
|  |             .andReturn() | ||||||
|  |             .getResponse() | ||||||
|  |             .getContentAsString(); | ||||||
|  | 
 | ||||||
|  |         assertEquals("falseField cannot be null", output); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,21 @@ | |||||||
|  | package com.baeldung.dto; | ||||||
|  | 
 | ||||||
|  | import static org.junit.jupiter.api.Assertions.assertEquals; | ||||||
|  | 
 | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | 
 | ||||||
|  | class BooleanUnitTest { | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenInputAsString_whenStringToBoolean_thenValidBooleanConversion() { | ||||||
|  |         assertEquals(Boolean.TRUE, Boolean.valueOf("TRUE")); | ||||||
|  |         assertEquals(Boolean.FALSE, Boolean.valueOf("false")); | ||||||
|  |         assertEquals(Boolean.TRUE, Boolean.parseBoolean("True")); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenInputAsboolean_whenbooleanToBoolean_thenValidBooleanConversion() { | ||||||
|  |         assertEquals(Boolean.TRUE, Boolean.valueOf(true)); | ||||||
|  |         assertEquals(Boolean.FALSE, Boolean.valueOf(false)); | ||||||
|  |     } | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user