Merge branch 'eugenp:master' into PR-6910

This commit is contained in:
parthiv39731
2023-10-17 20:04:47 +05:30
committed by GitHub
220 changed files with 1131 additions and 557 deletions
+1
View File
@@ -106,6 +106,7 @@
<module>spring-boot-documentation</module>
<module>spring-boot-3-url-matching</module>
<module>spring-boot-graalvm-docker</module>
<module>spring-boot-validations</module>
</modules>
<dependencyManagement>
@@ -11,9 +11,10 @@
<description>This is a simple application demonstrating integration between Keycloak and Spring Boot.</description>
<parent>
<groupId>com.baeldung.spring-boot-modules</groupId>
<artifactId>spring-boot-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-3</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-boot-3</relativePath>
</parent>
<dependencies>
@@ -105,7 +106,7 @@
<start-class>com.baeldung.keycloak.SpringBootKeycloakApp</start-class>
<jaxb-runtime.version>4.0.0</jaxb-runtime.version>
<wsdl4j.version>1.6.3</wsdl4j.version>
<jaxb2-maven-plugin.version>2.5.0</jaxb2-maven-plugin.version>
<jaxb2-maven-plugin.version>3.1.0</jaxb2-maven-plugin.version>
</properties>
</project>
@@ -1,9 +1,9 @@
package com.baeldung.keycloak;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity
public class Customer {
@@ -10,8 +10,8 @@ import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@Component
public class KeycloakLogoutHandler implements LogoutHandler {
@@ -12,6 +12,7 @@ import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@Configuration
@EnableWebSecurity
@@ -32,7 +33,7 @@ class SecurityConfig {
@Bean
public SecurityFilterChain clientFilterChain(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/")
.requestMatchers(new AntPathRequestMatcher("/"))
.permitAll()
.anyRequest()
.authenticated();
@@ -48,7 +49,7 @@ class SecurityConfig {
@Bean
public SecurityFilterChain resourceServerFilterChain(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/customers*")
.requestMatchers(new AntPathRequestMatcher("/customers*"))
.hasRole("USER")
.anyRequest()
.authenticated();
@@ -8,7 +8,7 @@ import java.security.Principal;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequest;
@Controller
public class WebController {
@@ -10,7 +10,7 @@ import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
import javax.annotation.security.RolesAllowed;
import jakarta.annotation.security.RolesAllowed;
import java.util.Map;
@Endpoint
@@ -10,7 +10,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
@@ -112,7 +112,7 @@
</profiles>
<properties>
<springdoc.version>2.1.0</springdoc.version>
<springdoc.version>2.2.0</springdoc.version>
<springdoc-openapi-maven-plugin.version>1.4</springdoc-openapi-maven-plugin.version>
</properties>
@@ -0,0 +1,3 @@
### Relevant Articles
- [Validate Boolean Type in Spring Boot](https://www.baeldung.com/spring-boot-validate-boolean-type)
@@ -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));
}
}