diff --git a/README.adoc b/README.adoc
index 119ba62..1b2d8de 100644
--- a/README.adoc
+++ b/README.adoc
@@ -33,6 +33,11 @@ NOTE: Documentation is very important to us, so if you find something missing fr
|===
|error-handling-spring-boot-starter |Spring Boot|Minimum Java version|Docs
+|https://github.com/wimdeblauwe/error-handling-spring-boot-starter/releases/tag/4.5.0[4.5.0]
+|3.3.x
+|17
+|https://wimdeblauwe.github.io/error-handling-spring-boot-starter/4.5.0/[Documentation 4.5.0]
+
|https://github.com/wimdeblauwe/error-handling-spring-boot-starter/releases/tag/4.4.0[4.4.0]
|3.3.x
|17
diff --git a/pom.xml b/pom.xml
index 316a967..d75c5d1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
io.github.wimdeblauwe
error-handling-spring-boot-starter
- 4.4.0
+ 4.5.0
Error Handling Spring Boot Starter
Spring Boot starter that configures error handling
diff --git a/src/docs/asciidoc/index.adoc b/src/docs/asciidoc/index.adoc
index 3ef0d37..594174c 100644
--- a/src/docs/asciidoc/index.adoc
+++ b/src/docs/asciidoc/index.adoc
@@ -472,8 +472,58 @@ The response JSON:
==== General override of error messages
-By using `error.handling.messages` property, it is possible to globally set an error message for a certain exception.
-This is most useful for the validation messages.
+By using `error.handling.messages` property, it is possible to globally set an error message for a certain exception or a certain validation annotation.
+
+===== Exception
+
+Suppose you have this defined:
+
+[source,properties]
+----
+error.handling.messages.com.company.application.user.UserNotFoundException=The user was not found
+----
+
+The response JSON:
+
+[source,json]
+----
+{
+ "code": "USER_NOT_FOUND",
+ "message": "The user was not found" //<.>
+}
+----
+
+<.> The output uses the configured override.
+
+This can also be used for exception types that are not part of your own application.
+
+For example:
+
+[source,properties]
+----
+error.handling.messages.jakarta.validation.ConstraintViolationException=There was a validation failure.
+----
+
+Will output the following JSON:
+
+[source,json]
+----
+{
+ "code": "VALIDATION_FAILED",
+ "message": "There was a validation failure.",
+ "fieldErrors": [
+ {
+ "code": "INVALID_SIZE",
+ "property": "name",
+ "message": "size must be between 10 and 2147483647",
+ "rejectedValue": "",
+ "path": "name"
+ }
+ ]
+}
+----
+
+===== Validation annotation
Suppose you have this defined:
@@ -1212,8 +1262,10 @@ import io.github.wimdeblauwe.errorhandlingspringbootstarter.mapper.ErrorMessageM
import io.github.wimdeblauwe.errorhandlingspringbootstarter.mapper.HttpStatusMapper;
import org.springframework.context.annotation.Bean;
+import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
public class WebSecurityConfiguration {
@Bean
@@ -1227,11 +1279,11 @@ public class WebSecurityConfiguration {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http,
UnauthorizedEntryPoint unauthorizedEntryPoint) throws Exception {
- http.httpBasic().disable();
+ http.httpBasic(AbstractHttpConfigurer::disable);
- http.authorizeHttpRequests().anyRequest().authenticated();
+ http.authorizeHttpRequests(customizer -> customizer.anyRequest().authenticated());
- http.exceptionHandling().authenticationEntryPoint(unauthorizedEntryPoint);//<.>
+ http.exceptionHandling(customizer -> customizer.authenticationEntryPoint(unauthorizedEntryPoint));//<.>
return http.build();
}
@@ -1258,6 +1310,7 @@ import io.github.wimdeblauwe.errorhandlingspringbootstarter.mapper.HttpStatusMap
import org.springframework.context.annotation.Bean;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
public class WebSecurityConfiguration {
@@ -1272,11 +1325,11 @@ public class WebSecurityConfiguration {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http,
AccessDeniedHandler accessDeniedHandler) throws Exception {
- http.httpBasic().disable();
+ http.httpBasic(AbstractHttpConfigurer::disable);
- http.authorizeHttpRequests().anyRequest().authenticated();
+ http.authorizeHttpRequests(customizer -> customizer.anyRequest().authenticated());
- http.exceptionHandling().accessDeniedHandler(accessDeniedHandler);//<.>
+ http.exceptionHandling(customizer -> customizer.accessDeniedHandler(accessDeniedHandler));//<.>
return http.build();
}
diff --git a/src/main/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/AbstractErrorHandlingConfiguration.java b/src/main/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/AbstractErrorHandlingConfiguration.java
index 04b4833..a043026 100644
--- a/src/main/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/AbstractErrorHandlingConfiguration.java
+++ b/src/main/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/AbstractErrorHandlingConfiguration.java
@@ -1,6 +1,7 @@
package io.github.wimdeblauwe.errorhandlingspringbootstarter;
import io.github.wimdeblauwe.errorhandlingspringbootstarter.handler.BindApiExceptionHandler;
+import io.github.wimdeblauwe.errorhandlingspringbootstarter.handler.HandlerMethodValidationExceptionHandler;
import io.github.wimdeblauwe.errorhandlingspringbootstarter.handler.HttpMessageNotReadableApiExceptionHandler;
import io.github.wimdeblauwe.errorhandlingspringbootstarter.handler.TypeMismatchApiExceptionHandler;
import io.github.wimdeblauwe.errorhandlingspringbootstarter.mapper.ErrorCodeMapper;
@@ -91,6 +92,14 @@ public BindApiExceptionHandler bindApiExceptionHandler(ErrorHandlingProperties p
return new BindApiExceptionHandler(properties, httpStatusMapper, errorCodeMapper, errorMessageMapper);
}
+ @Bean
+ @ConditionalOnMissingBean
+ public HandlerMethodValidationExceptionHandler handlerMethodValidationExceptionHandler(HttpStatusMapper httpStatusMapper,
+ ErrorCodeMapper errorCodeMapper,
+ ErrorMessageMapper errorMessageMapper) {
+ return new HandlerMethodValidationExceptionHandler(httpStatusMapper, errorCodeMapper, errorMessageMapper);
+ }
+
@Bean
@ConditionalOnMissingBean
public ApiErrorResponseSerializer apiErrorResponseSerializer(ErrorHandlingProperties properties) {
diff --git a/src/main/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/handler/ConstraintViolationApiExceptionHandler.java b/src/main/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/handler/ConstraintViolationApiExceptionHandler.java
index 1960ab9..cd7c048 100644
--- a/src/main/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/handler/ConstraintViolationApiExceptionHandler.java
+++ b/src/main/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/handler/ConstraintViolationApiExceptionHandler.java
@@ -4,14 +4,13 @@
import io.github.wimdeblauwe.errorhandlingspringbootstarter.mapper.ErrorCodeMapper;
import io.github.wimdeblauwe.errorhandlingspringbootstarter.mapper.ErrorMessageMapper;
import io.github.wimdeblauwe.errorhandlingspringbootstarter.mapper.HttpStatusMapper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.http.HttpStatus;
-
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import jakarta.validation.ElementKind;
import jakarta.validation.Path;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
import java.util.Comparator;
import java.util.Optional;
@@ -136,6 +135,7 @@ private String getMessage(ConstraintViolation> constraintViolation) {
}
private String getMessage(ConstraintViolationException exception) {
- return "Validation failed. Error count: " + exception.getConstraintViolations().size();
+ return errorMessageMapper.getErrorMessageIfConfiguredInProperties(exception)
+ .orElseGet(() -> "Validation failed. Error count: " + exception.getConstraintViolations().size());
}
}
diff --git a/src/main/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/handler/HandlerMethodValidationExceptionHandler.java b/src/main/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/handler/HandlerMethodValidationExceptionHandler.java
new file mode 100644
index 0000000..6ee22ba
--- /dev/null
+++ b/src/main/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/handler/HandlerMethodValidationExceptionHandler.java
@@ -0,0 +1,60 @@
+package io.github.wimdeblauwe.errorhandlingspringbootstarter.handler;
+
+import io.github.wimdeblauwe.errorhandlingspringbootstarter.ApiErrorResponse;
+import io.github.wimdeblauwe.errorhandlingspringbootstarter.ApiFieldError;
+import io.github.wimdeblauwe.errorhandlingspringbootstarter.ApiGlobalError;
+import io.github.wimdeblauwe.errorhandlingspringbootstarter.mapper.ErrorCodeMapper;
+import io.github.wimdeblauwe.errorhandlingspringbootstarter.mapper.ErrorMessageMapper;
+import io.github.wimdeblauwe.errorhandlingspringbootstarter.mapper.HttpStatusMapper;
+import org.springframework.context.MessageSourceResolvable;
+import org.springframework.http.HttpStatus;
+import org.springframework.validation.FieldError;
+import org.springframework.web.method.annotation.HandlerMethodValidationException;
+
+import java.util.List;
+import java.util.Optional;
+
+public class HandlerMethodValidationExceptionHandler extends AbstractApiExceptionHandler {
+
+ public HandlerMethodValidationExceptionHandler(HttpStatusMapper httpStatusMapper,
+ ErrorCodeMapper errorCodeMapper,
+ ErrorMessageMapper errorMessageMapper) {
+
+ super(httpStatusMapper, errorCodeMapper, errorMessageMapper);
+ }
+
+ @Override
+ public boolean canHandle(Throwable exception) {
+ return exception instanceof HandlerMethodValidationException;
+ }
+
+ @Override
+ public ApiErrorResponse handle(Throwable ex) {
+ var response = new ApiErrorResponse(HttpStatus.BAD_REQUEST, getErrorCode(ex), getErrorMessage(ex));
+ var validationException = (HandlerMethodValidationException) ex;
+ List extends MessageSourceResolvable> errors = validationException.getAllErrors();
+
+ errors.forEach(error -> {
+ if (error instanceof FieldError fieldError) {
+ var apiFieldError = new ApiFieldError(
+ errorCodeMapper.getErrorCode(fieldError.getCode()),
+ fieldError.getField(),
+ errorMessageMapper.getErrorMessage(fieldError.getCode(), fieldError.getDefaultMessage()),
+ fieldError.getRejectedValue(),
+ null);
+ response.addFieldError(apiFieldError);
+ } else {
+ var lastCode = Optional.ofNullable(error.getCodes())
+ .filter(codes -> codes.length > 0)
+ .map(codes -> codes[codes.length - 1])
+ .orElse(null);
+ var apiGlobalErrorMessage = new ApiGlobalError(
+ errorCodeMapper.getErrorCode(lastCode),
+ errorMessageMapper.getErrorMessage(lastCode, error.getDefaultMessage()));
+ response.addGlobalError(apiGlobalErrorMessage);
+ }
+ });
+
+ return response;
+ }
+}
diff --git a/src/main/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/mapper/ErrorMessageMapper.java b/src/main/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/mapper/ErrorMessageMapper.java
index f87c7d3..98e5d3d 100644
--- a/src/main/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/mapper/ErrorMessageMapper.java
+++ b/src/main/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/mapper/ErrorMessageMapper.java
@@ -2,6 +2,8 @@
import io.github.wimdeblauwe.errorhandlingspringbootstarter.ErrorHandlingProperties;
+import java.util.Optional;
+
import static org.springframework.util.StringUtils.hasText;
/**
@@ -22,6 +24,10 @@ public String getErrorMessage(Throwable exception) {
return exception.getMessage();
}
+ public Optional getErrorMessageIfConfiguredInProperties(Throwable exception) {
+ return Optional.ofNullable(getErrorMessageFromProperties(exception.getClass()));
+ }
+
public String getErrorMessage(String fieldSpecificCode, String code, String defaultMessage) {
if (properties.getMessages().containsKey(fieldSpecificCode)) {
return properties.getMessages().get(fieldSpecificCode);
diff --git a/src/main/resources/error-handling-defaults.properties b/src/main/resources/error-handling-defaults.properties
index 2f5fa11..e911ede 100644
--- a/src/main/resources/error-handling-defaults.properties
+++ b/src/main/resources/error-handling-defaults.properties
@@ -1,4 +1,6 @@
error.handling.codes.org.springframework.web.bind.MethodArgumentNotValidException=VALIDATION_FAILED
+error.handling.codes.org.springframework.web.method.annotation.HandlerMethodValidationException=VALIDATION_FAILED
+error.handling.messages.org.springframework.web.method.annotation.HandlerMethodValidationException=There was a validation failure.
error.handling.codes.org.springframework.http.converter.HttpMessageNotReadableException=MESSAGE_NOT_READABLE
error.handling.codes.jakarta.validation.ConstraintViolationException=VALIDATION_FAILED
error.handling.codes.org.springframework.beans.TypeMismatchException=TYPE_MISMATCH
diff --git a/src/test/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/handler/ConstraintViolationApiExceptionHandlerTest.java b/src/test/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/handler/ConstraintViolationApiExceptionHandlerTest.java
index 7773ec3..b2d95f0 100644
--- a/src/test/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/handler/ConstraintViolationApiExceptionHandlerTest.java
+++ b/src/test/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/handler/ConstraintViolationApiExceptionHandlerTest.java
@@ -110,6 +110,20 @@ void testErrorCodeOverride(@Autowired ErrorHandlingProperties properties) throws
;
}
+ @Test
+ @WithMockUser
+ void testErrorMessageOverride(@Autowired ErrorHandlingProperties properties) throws Exception {
+ properties.getMessages().put("jakarta.validation.ConstraintViolationException", "There was a validation failure.");
+ mockMvc.perform(post("/test/validation")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content("{\"value2\": \"\"}")
+ .with(csrf()))
+ .andExpect(status().isBadRequest())
+ .andExpect(jsonPath("code").value("VALIDATION_FAILED"))
+ .andExpect(jsonPath("message").value("There was a validation failure."))
+ ;
+ }
+
@Test
@WithMockUser
void testFieldErrorCodeOverride(@Autowired ErrorHandlingProperties properties) throws Exception {
diff --git a/src/test/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/handler/HandlerMethodValidationExceptionHandlerTest.java b/src/test/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/handler/HandlerMethodValidationExceptionHandlerTest.java
new file mode 100644
index 0000000..48cc96f
--- /dev/null
+++ b/src/test/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/handler/HandlerMethodValidationExceptionHandlerTest.java
@@ -0,0 +1,154 @@
+package io.github.wimdeblauwe.errorhandlingspringbootstarter.handler;
+
+import io.github.wimdeblauwe.errorhandlingspringbootstarter.ErrorHandlingProperties;
+import io.github.wimdeblauwe.errorhandlingspringbootstarter.servlet.ServletErrorHandlingConfiguration;
+import jakarta.validation.*;
+import jakarta.validation.constraints.NotNull;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.MediaType;
+import org.springframework.mock.web.MockPart;
+import org.springframework.security.test.context.support.WithMockUser;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestPart;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.lang.annotation.*;
+import java.nio.charset.StandardCharsets;
+import java.time.LocalDateTime;
+import java.util.List;
+
+import static org.hamcrest.Matchers.*;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+
+@WebMvcTest
+@ContextConfiguration(classes = {ServletErrorHandlingConfiguration.class,
+ HandlerMethodValidationExceptionHandlerTest.TestController.class})
+@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
+class HandlerMethodValidationExceptionHandlerTest {
+
+ @Autowired
+ private MockMvc mockMvc;
+
+ @Test
+ @WithMockUser
+ void testHandlerMethodViolationException() throws Exception {
+ mockMvc.perform(multipart("/test/update-event")
+ .part(new MockPart("eventRequest", null, "{}".getBytes(StandardCharsets.UTF_8), MediaType.APPLICATION_JSON))
+ .part(new MockPart("file", "file.jpg", new byte[0], MediaType.IMAGE_JPEG))
+ .with(request -> {
+ request.setMethod(HttpMethod.PUT.name());
+ return request;
+ })
+ .with(csrf()))
+ .andExpect(status().isBadRequest())
+ .andExpect(jsonPath("code").value("VALIDATION_FAILED"))
+ .andExpect(jsonPath("message").value("There was a validation failure."))
+ .andExpect(jsonPath("fieldErrors", hasSize(1)))
+ .andExpect(jsonPath("fieldErrors..code", allOf(hasItem("REQUIRED_NOT_NULL"))))
+ .andExpect(jsonPath("fieldErrors..property", allOf(hasItem("dateTime"))))
+ .andExpect(jsonPath("fieldErrors..message", allOf(hasItem("must not be null"))))
+ .andExpect(jsonPath("fieldErrors..rejectedValue", allOf(hasItem(nullValue()))))
+ .andExpect(jsonPath("globalErrors", hasSize(1)))
+ .andExpect(jsonPath("globalErrors..code", allOf(hasItem("ValidFileType"))))
+ .andExpect(jsonPath("globalErrors..message", allOf(hasItem(""))))
+ ;
+ }
+
+ @Test
+ @WithMockUser
+ void testHandlerMethodViolationException_customValidationAnnotationOverride(@Autowired ErrorHandlingProperties properties) throws Exception {
+ properties.getCodes().put("ValidFileType", "INVALID_FILE_TYPE");
+ properties.getMessages().put("ValidFileType", "The file type is invalid. Only text/plain and application/pdf allowed.");
+ mockMvc.perform(multipart("/test/update-event")
+ .part(new MockPart("eventRequest", null, "{}".getBytes(StandardCharsets.UTF_8), MediaType.APPLICATION_JSON))
+ .part(new MockPart("file", "file.jpg", new byte[0], MediaType.IMAGE_JPEG))
+ .with(request -> {
+ request.setMethod(HttpMethod.PUT.name());
+ return request;
+ })
+ .with(csrf()))
+ .andExpect(status().isBadRequest())
+ .andExpect(jsonPath("code").value("VALIDATION_FAILED"))
+ .andExpect(jsonPath("message").value("There was a validation failure."))
+ .andExpect(jsonPath("fieldErrors", hasSize(1)))
+ .andExpect(jsonPath("fieldErrors..code", allOf(hasItem("REQUIRED_NOT_NULL"))))
+ .andExpect(jsonPath("fieldErrors..property", allOf(hasItem("dateTime"))))
+ .andExpect(jsonPath("fieldErrors..message", allOf(hasItem("must not be null"))))
+ .andExpect(jsonPath("fieldErrors..rejectedValue", allOf(hasItem(nullValue()))))
+ .andExpect(jsonPath("globalErrors", hasSize(1)))
+ .andExpect(jsonPath("globalErrors..code", allOf(hasItem("INVALID_FILE_TYPE"))))
+ .andExpect(jsonPath("globalErrors..message", allOf(hasItem("The file type is invalid. Only text/plain and application/pdf allowed."))))
+ ;
+ }
+
+ @RestController
+ @RequestMapping
+ static class TestController {
+
+ @PutMapping("/test/update-event")
+ public void updateEvent(
+ @Valid @RequestPart EventRequest eventRequest,
+ @Valid @ValidFileType @RequestPart MultipartFile file) {
+
+ }
+ }
+
+ static class EventRequest {
+ @NotNull
+ private LocalDateTime dateTime;
+
+ public LocalDateTime getDateTime() {
+ return dateTime;
+ }
+
+ public void setDateTime(LocalDateTime dateTime) {
+ this.dateTime = dateTime;
+ }
+ }
+
+ @Documented
+ @Constraint(validatedBy = MultiPartFileValidator.class)
+ @Target(ElementType.PARAMETER)
+ @Retention(RetentionPolicy.RUNTIME)
+ @interface ValidFileType {
+
+ // Default list of allowed file types
+ String[] value() default {
+ MediaType.TEXT_PLAIN_VALUE,
+ MediaType.APPLICATION_PDF_VALUE
+ };
+
+ String message() default "";
+
+ Class>[] groups() default {};
+
+ Class extends Payload>[] payload() default {};
+ }
+
+ static class MultiPartFileValidator implements ConstraintValidator {
+
+ private List allowed;
+
+ @Override
+ public void initialize(ValidFileType constraintAnnotation) {
+ allowed = List.of(constraintAnnotation.value());
+ }
+
+ @Override
+ public boolean isValid(MultipartFile file, ConstraintValidatorContext context) {
+ return file == null || allowed.contains(file.getContentType());
+ }
+ }
+}
diff --git a/src/test/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/handler/SpringSecurityApiExceptionHandlerTest.java b/src/test/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/handler/SpringSecurityApiExceptionHandlerTest.java
index 62f9db3..2613b46 100644
--- a/src/test/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/handler/SpringSecurityApiExceptionHandlerTest.java
+++ b/src/test/java/io/github/wimdeblauwe/errorhandlingspringbootstarter/handler/SpringSecurityApiExceptionHandlerTest.java
@@ -17,6 +17,7 @@
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.AccessDeniedHandler;
@@ -130,15 +131,15 @@ public AccessDeniedHandler accessDeniedHandler(HttpStatusMapper httpStatusMapper
public SecurityFilterChain securityFilterChain(HttpSecurity http,
UnauthorizedEntryPoint unauthorizedEntryPoint,
AccessDeniedHandler accessDeniedHandler) throws Exception {
- http.httpBasic().disable();
+ http.httpBasic(AbstractHttpConfigurer::disable);
- http.authorizeHttpRequests()
- .requestMatchers("/test/spring-security/admin-global").hasRole("ADMIN")
- .anyRequest().authenticated();
+ http.authorizeHttpRequests(customizer -> customizer
+ .requestMatchers("/test/spring-security/admin-global").hasRole("ADMIN")
+ .anyRequest().authenticated());
- http.exceptionHandling()
- .authenticationEntryPoint(unauthorizedEntryPoint)
- .accessDeniedHandler(accessDeniedHandler);
+ http.exceptionHandling(customizer -> customizer
+ .authenticationEntryPoint(unauthorizedEntryPoint)
+ .accessDeniedHandler(accessDeniedHandler));
return http.build();
}