Order auto-configured ProblemDetailsExceptionHandler beans
Add `@Order(0)` to the WebMVC and Webflux `ProblemDetailsExceptionHandler` beans. This makes it easier to create custom `@ControllerAdvice` beans that must be ordered before or after the `ProblemDetailsExceptionHandler`. See gh-36288
This commit is contained in:
parent
e677eb7759
commit
9955ee7e8a
|
@ -357,6 +357,7 @@ public class WebFluxAutoConfiguration {
|
|||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ResponseEntityExceptionHandler.class)
|
||||
@Order(0)
|
||||
ProblemDetailsExceptionHandler problemDetailsExceptionHandler() {
|
||||
return new ProblemDetailsExceptionHandler();
|
||||
}
|
||||
|
|
|
@ -662,6 +662,7 @@ public class WebMvcAutoConfiguration {
|
|||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ResponseEntityExceptionHandler.class)
|
||||
@Order(0)
|
||||
ProblemDetailsExceptionHandler problemDetailsExceptionHandler() {
|
||||
return new ProblemDetailsExceptionHandler();
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import java.util.Map;
|
|||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jakarta.validation.ValidatorFactory;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
|
@ -80,6 +81,7 @@ import org.springframework.validation.Validator;
|
|||
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.filter.reactive.HiddenHttpMethodFilter;
|
||||
import org.springframework.web.method.ControllerAdviceBean;
|
||||
import org.springframework.web.reactive.HandlerMapping;
|
||||
import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
|
||||
import org.springframework.web.reactive.config.BlockingExecutionConfigurer;
|
||||
|
@ -671,6 +673,24 @@ class WebFluxAutoConfigurationTests {
|
|||
.hasSingleBean(CustomExceptionHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void problemDetailsIsOrderedBetweenLowestAndHighestOrderedControllerHandlers() {
|
||||
this.contextRunner.withPropertyValues("spring.webflux.problemdetails.enabled:true")
|
||||
.withUserConfiguration(OrderedControllerAdviceBeansConfiguration.class)
|
||||
.run((context) -> {
|
||||
|
||||
List<Class<?>> controllerAdviceClasses = ControllerAdviceBean.findAnnotatedBeans(context)
|
||||
.stream()
|
||||
.map(ControllerAdviceBean::getBeanType)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
assertThat(controllerAdviceClasses).containsExactly(
|
||||
OrderedControllerAdviceBeansConfiguration.HighestOrderedControllerAdvice.class,
|
||||
ProblemDetailsExceptionHandler.class,
|
||||
OrderedControllerAdviceBeansConfiguration.LowestOrderedControllerAdvice.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void asyncTaskExecutorWithApplicationTaskExecutor() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(TaskExecutionAutoConfiguration.class))
|
||||
|
@ -1016,6 +1036,25 @@ class WebFluxAutoConfigurationTests {
|
|||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Import({ OrderedControllerAdviceBeansConfiguration.LowestOrderedControllerAdvice.class,
|
||||
OrderedControllerAdviceBeansConfiguration.HighestOrderedControllerAdvice.class })
|
||||
static class OrderedControllerAdviceBeansConfiguration {
|
||||
|
||||
@ControllerAdvice
|
||||
@Order
|
||||
static class LowestOrderedControllerAdvice {
|
||||
|
||||
}
|
||||
|
||||
@ControllerAdvice
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
static class HighestOrderedControllerAdvice {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Aspect
|
||||
static class ExceptionHandlerInterceptor {
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ import java.util.Map;
|
|||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
@ -51,6 +52,8 @@ import org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguratio
|
|||
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.validation.ValidatorAdapter;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfigurationTests.OrderedControllerAdviceBeansConfiguration.HighestOrderedControllerAdvice;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfigurationTests.OrderedControllerAdviceBeansConfiguration.LowestOrderedControllerAdvice;
|
||||
import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext;
|
||||
import org.springframework.boot.test.context.runner.ContextConsumer;
|
||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||
|
@ -65,6 +68,8 @@ import org.springframework.context.ApplicationContext;
|
|||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
@ -89,6 +94,7 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
|||
import org.springframework.web.filter.FormContentFilter;
|
||||
import org.springframework.web.filter.HiddenHttpMethodFilter;
|
||||
import org.springframework.web.filter.RequestContextFilter;
|
||||
import org.springframework.web.method.ControllerAdviceBean;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.FlashMap;
|
||||
import org.springframework.web.servlet.FlashMapManager;
|
||||
|
@ -972,6 +978,22 @@ class WebMvcAutoConfigurationTests {
|
|||
.hasSingleBean(CustomExceptionHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void problemDetailsIsOrderedBetweenLowestAndHighestOrderedControllerHandlers() {
|
||||
this.contextRunner.withPropertyValues("spring.mvc.problemdetails.enabled:true")
|
||||
.withUserConfiguration(OrderedControllerAdviceBeansConfiguration.class)
|
||||
.run((context) -> {
|
||||
|
||||
List<Class<?>> controllerAdviceClasses = ControllerAdviceBean.findAnnotatedBeans(context)
|
||||
.stream()
|
||||
.map(ControllerAdviceBean::getBeanType)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
assertThat(controllerAdviceClasses).containsExactly(HighestOrderedControllerAdvice.class,
|
||||
ProblemDetailsExceptionHandler.class, LowestOrderedControllerAdvice.class);
|
||||
});
|
||||
}
|
||||
|
||||
private void assertResourceHttpRequestHandler(AssertableWebApplicationContext context,
|
||||
Consumer<ResourceHttpRequestHandler> handlerConsumer) {
|
||||
Map<String, Object> handlerMap = getHandlerMap(context.getBean("resourceHandlerMapping", HandlerMapping.class));
|
||||
|
@ -1496,6 +1518,24 @@ class WebMvcAutoConfigurationTests {
|
|||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Import({ LowestOrderedControllerAdvice.class, HighestOrderedControllerAdvice.class })
|
||||
static class OrderedControllerAdviceBeansConfiguration {
|
||||
|
||||
@ControllerAdvice
|
||||
@Order
|
||||
static class LowestOrderedControllerAdvice {
|
||||
|
||||
}
|
||||
|
||||
@ControllerAdvice
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
static class HighestOrderedControllerAdvice {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ControllerAdvice
|
||||
static class CustomExceptionHandler extends ResponseEntityExceptionHandler {
|
||||
|
||||
|
|
Loading…
Reference in New Issue