Use MessageSource for @ExceptionHandler methods
Follow-up for commit bb816c123c
See gh-27203
This commit is contained in:
parent
5b3f11c543
commit
f2be4e9320
|
|
@ -102,11 +102,20 @@ public class HandlerMethod {
|
|||
* Create an instance from a bean instance and a method.
|
||||
*/
|
||||
public HandlerMethod(Object bean, Method method) {
|
||||
this(bean, method, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Variant of {@link #HandlerMethod(Object, Method)} that
|
||||
* also accepts a {@link MessageSource}.
|
||||
*/
|
||||
public HandlerMethod(Object bean, Method method, @Nullable MessageSource messageSource) {
|
||||
Assert.notNull(bean, "Bean is required");
|
||||
Assert.notNull(method, "Method is required");
|
||||
this.bean = bean;
|
||||
this.beanFactory = null;
|
||||
this.messageSource = null;
|
||||
this.messageSource = messageSource;
|
||||
this.beanType = ClassUtils.getUserClass(bean);
|
||||
this.method = method;
|
||||
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import java.lang.reflect.InvocationTargetException;
|
|||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.core.CoroutinesUtils;
|
||||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||
import org.springframework.core.KotlinDetector;
|
||||
|
|
@ -71,6 +72,14 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
|||
super(bean, method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Variant of {@link #InvocableHandlerMethod(Object, Method)} that
|
||||
* also accepts a {@link MessageSource}.
|
||||
*/
|
||||
public InvocableHandlerMethod(Object bean, Method method, @Nullable MessageSource messageSource) {
|
||||
super(bean, method, messageSource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new handler method with the given bean instance, method name and parameters.
|
||||
* @param bean the object bean
|
||||
|
|
|
|||
|
|
@ -483,7 +483,7 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
|
|||
}
|
||||
Method method = resolver.resolveMethod(exception);
|
||||
if (method != null) {
|
||||
return new ServletInvocableHandlerMethod(handlerMethod.getBean(), method);
|
||||
return new ServletInvocableHandlerMethod(handlerMethod.getBean(), method, this.applicationContext);
|
||||
}
|
||||
// For advice applicability check below (involving base packages, assignable types
|
||||
// and annotation presence), use target class instead of interface-based proxy.
|
||||
|
|
@ -498,7 +498,7 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
|
|||
ExceptionHandlerMethodResolver resolver = entry.getValue();
|
||||
Method method = resolver.resolveMethod(exception);
|
||||
if (method != null) {
|
||||
return new ServletInvocableHandlerMethod(advice.resolveBean(), method);
|
||||
return new ServletInvocableHandlerMethod(advice.resolveBean(), method, this.applicationContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import java.util.concurrent.Callable;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.core.KotlinDetector;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ResolvableType;
|
||||
|
|
@ -68,6 +69,13 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
|
|||
@Nullable
|
||||
private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
|
||||
|
||||
/**
|
||||
* Variant of {@link #ServletInvocableHandlerMethod(Object, Method)} that
|
||||
* also accepts a {@link MessageSource}.
|
||||
*/
|
||||
public ServletInvocableHandlerMethod(Object handler, Method method, @Nullable MessageSource messageSource) {
|
||||
super(handler, method, messageSource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance from the given handler and method.
|
||||
|
|
|
|||
|
|
@ -19,7 +19,9 @@ package org.springframework.web.servlet.mvc.method.annotation;
|
|||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.io.Writer;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
|
@ -30,8 +32,11 @@ import org.springframework.beans.FatalBeanException;
|
|||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
|
|
@ -42,6 +47,7 @@ import org.springframework.util.ClassUtils;
|
|||
import org.springframework.web.HttpRequestHandler;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.context.support.WebApplicationObjectSupport;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
|
|
@ -333,6 +339,28 @@ public class ExceptionHandlerExceptionResolverTests {
|
|||
assertThat(this.response.getContentAsString()).isEqualTo(rootCause.toString());
|
||||
}
|
||||
|
||||
@Test //gh-27156
|
||||
void resolveExceptionWithReasonResovledByMessageSource() throws Exception {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MyConfig.class);
|
||||
StaticApplicationContext context = new StaticApplicationContext(ctx);
|
||||
Locale locale = Locale.ENGLISH;
|
||||
context.addMessage("gateway.timeout", locale, "Gateway Timeout");
|
||||
context.refresh();
|
||||
LocaleContextHolder.setLocale(locale);
|
||||
this.resolver.setApplicationContext(context);
|
||||
this.resolver.afterPropertiesSet();
|
||||
|
||||
SocketTimeoutException ex = new SocketTimeoutException();
|
||||
HandlerMethod handlerMethod = new HandlerMethod(new ResponseBodyController(), "handle");
|
||||
ModelAndView mav = this.resolver.resolveException(this.request, this.response, handlerMethod, ex);
|
||||
|
||||
assertThat(mav).as("Exception was not handled").isNotNull();
|
||||
assertThat(mav.isEmpty()).isTrue();
|
||||
assertThat(this.response.getStatus()).isEqualTo(HttpStatus.GATEWAY_TIMEOUT.value());
|
||||
assertThat(this.response.getErrorMessage()).isEqualTo("Gateway Timeout");
|
||||
assertThat(this.response.getContentAsString()).isEqualTo("");
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveExceptionControllerAdviceHandler() throws Exception {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MyControllerAdviceConfig.class);
|
||||
|
|
@ -530,6 +558,16 @@ public class ExceptionHandlerExceptionResolverTests {
|
|||
}
|
||||
}
|
||||
|
||||
@RestControllerAdvice
|
||||
@Order(3)
|
||||
static class ResponseStatusTestExceptionResolver {
|
||||
|
||||
@ExceptionHandler(SocketTimeoutException.class)
|
||||
@ResponseStatus(code = HttpStatus.GATEWAY_TIMEOUT, reason = "gateway.timeout")
|
||||
public void handleException(SocketTimeoutException ex) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class MyConfig {
|
||||
|
|
@ -543,6 +581,11 @@ public class ExceptionHandlerExceptionResolverTests {
|
|||
public AnotherTestExceptionResolver anotherTestExceptionResolver() {
|
||||
return new AnotherTestExceptionResolver();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ResponseStatusTestExceptionResolver responseStatusTestExceptionResolver() {
|
||||
return new ResponseStatusTestExceptionResolver();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue