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