Use MessageSource in HandlerMethod for error reason
Closes gh-27156
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,6 +29,8 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.core.BridgeMethodResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ResolvableType;
|
||||
@@ -70,6 +72,9 @@ public class HandlerMethod {
|
||||
@Nullable
|
||||
private final BeanFactory beanFactory;
|
||||
|
||||
@Nullable
|
||||
private final MessageSource messageSource;
|
||||
|
||||
private final Class<?> beanType;
|
||||
|
||||
private final Method method;
|
||||
@@ -101,6 +106,7 @@ public class HandlerMethod {
|
||||
Assert.notNull(method, "Method is required");
|
||||
this.bean = bean;
|
||||
this.beanFactory = null;
|
||||
this.messageSource = null;
|
||||
this.beanType = ClassUtils.getUserClass(bean);
|
||||
this.method = method;
|
||||
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
|
||||
@@ -118,6 +124,7 @@ public class HandlerMethod {
|
||||
Assert.notNull(methodName, "Method name is required");
|
||||
this.bean = bean;
|
||||
this.beanFactory = null;
|
||||
this.messageSource = null;
|
||||
this.beanType = ClassUtils.getUserClass(bean);
|
||||
this.method = bean.getClass().getMethod(methodName, parameterTypes);
|
||||
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(this.method);
|
||||
@@ -132,11 +139,23 @@ public class HandlerMethod {
|
||||
* re-create the {@code HandlerMethod} with an initialized bean.
|
||||
*/
|
||||
public HandlerMethod(String beanName, BeanFactory beanFactory, Method method) {
|
||||
this(beanName, beanFactory, null, method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Variant of {@link #HandlerMethod(String, BeanFactory, Method)} that
|
||||
* also accepts a {@link MessageSource}.
|
||||
*/
|
||||
public HandlerMethod(
|
||||
String beanName, BeanFactory beanFactory,
|
||||
@Nullable MessageSource messageSource, Method method) {
|
||||
|
||||
Assert.hasText(beanName, "Bean name is required");
|
||||
Assert.notNull(beanFactory, "BeanFactory is required");
|
||||
Assert.notNull(method, "Method is required");
|
||||
this.bean = beanName;
|
||||
this.beanFactory = beanFactory;
|
||||
this.messageSource = messageSource;
|
||||
Class<?> beanType = beanFactory.getType(beanName);
|
||||
if (beanType == null) {
|
||||
throw new IllegalStateException("Cannot resolve bean type for bean with name '" + beanName + "'");
|
||||
@@ -156,6 +175,7 @@ public class HandlerMethod {
|
||||
Assert.notNull(handlerMethod, "HandlerMethod is required");
|
||||
this.bean = handlerMethod.bean;
|
||||
this.beanFactory = handlerMethod.beanFactory;
|
||||
this.messageSource = handlerMethod.messageSource;
|
||||
this.beanType = handlerMethod.beanType;
|
||||
this.method = handlerMethod.method;
|
||||
this.bridgedMethod = handlerMethod.bridgedMethod;
|
||||
@@ -174,6 +194,7 @@ public class HandlerMethod {
|
||||
Assert.notNull(handler, "Handler object is required");
|
||||
this.bean = handler;
|
||||
this.beanFactory = handlerMethod.beanFactory;
|
||||
this.messageSource = handlerMethod.messageSource;
|
||||
this.beanType = handlerMethod.beanType;
|
||||
this.method = handlerMethod.method;
|
||||
this.bridgedMethod = handlerMethod.bridgedMethod;
|
||||
@@ -199,8 +220,13 @@ public class HandlerMethod {
|
||||
annotation = AnnotatedElementUtils.findMergedAnnotation(getBeanType(), ResponseStatus.class);
|
||||
}
|
||||
if (annotation != null) {
|
||||
String reason = annotation.reason();
|
||||
String resolvedReason = (StringUtils.hasText(reason) && this.messageSource != null ?
|
||||
this.messageSource.getMessage(reason, null, reason, LocaleContextHolder.getLocale()) :
|
||||
reason);
|
||||
|
||||
this.responseStatus = annotation.code();
|
||||
this.responseStatusReason = annotation.reason();
|
||||
this.responseStatusReason = resolvedReason;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -258,7 +258,9 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
|
||||
protected HandlerMethod createHandlerMethod(Object handler, Method method) {
|
||||
if (handler instanceof String) {
|
||||
return new HandlerMethod((String) handler,
|
||||
obtainApplicationContext().getAutowireCapableBeanFactory(), method);
|
||||
obtainApplicationContext().getAutowireCapableBeanFactory(),
|
||||
obtainApplicationContext(),
|
||||
method);
|
||||
}
|
||||
return new HandlerMethod(handler, method);
|
||||
}
|
||||
|
||||
@@ -337,7 +337,9 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
|
||||
protected HandlerMethod createHandlerMethod(Object handler, Method method) {
|
||||
if (handler instanceof String) {
|
||||
return new HandlerMethod((String) handler,
|
||||
obtainApplicationContext().getAutowireCapableBeanFactory(), method);
|
||||
obtainApplicationContext().getAutowireCapableBeanFactory(),
|
||||
obtainApplicationContext(),
|
||||
method);
|
||||
}
|
||||
return new HandlerMethod(handler, method);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -29,6 +30,9 @@ import javax.servlet.http.HttpServletResponse;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
@@ -47,12 +51,14 @@ import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
import org.springframework.web.filter.ShallowEtagHeaderFilter;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.method.annotation.RequestParamMethodArgumentResolver;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolverComposite;
|
||||
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
|
||||
import org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite;
|
||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
import org.springframework.web.servlet.view.RedirectView;
|
||||
import org.springframework.web.testfixture.method.ResolvableMethod;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
|
||||
|
||||
@@ -180,6 +186,39 @@ public class ServletInvocableHandlerMethodTests {
|
||||
.as("When a status reason w/ used, the request is handled").isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invokeAndHandle_responseStatusAndReasonCode() throws Exception {
|
||||
Locale locale = Locale.ENGLISH;
|
||||
|
||||
String beanName = "handler";
|
||||
StaticApplicationContext context = new StaticApplicationContext();
|
||||
context.registerBean(beanName, Handler.class);
|
||||
context.addMessage("BadRequest.error", locale, "Bad request message");
|
||||
context.refresh();
|
||||
|
||||
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
|
||||
System.out.println(beanFactory.getType(beanName));
|
||||
|
||||
LocaleContextHolder.setLocale(locale);
|
||||
try {
|
||||
Method method = ResolvableMethod.on(Handler.class)
|
||||
.named("responseStatusWithReasonCode")
|
||||
.resolveMethod();
|
||||
|
||||
HandlerMethod handlerMethod = new HandlerMethod(beanName, beanFactory, context, method);
|
||||
handlerMethod = handlerMethod.createWithResolvedBean();
|
||||
|
||||
new ServletInvocableHandlerMethod(handlerMethod)
|
||||
.invokeAndHandle(this.webRequest, this.mavContainer);
|
||||
}
|
||||
finally {
|
||||
LocaleContextHolder.resetLocaleContext();
|
||||
}
|
||||
|
||||
assertThat(this.response.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST.value());
|
||||
assertThat(this.response.getErrorMessage()).isEqualTo("Bad request message");
|
||||
}
|
||||
|
||||
@Test // gh-23775, gh-24635
|
||||
public void invokeAndHandle_ETagFilterHasNoImpactWhenETagPresent() throws Exception {
|
||||
|
||||
@@ -417,6 +456,11 @@ public class ServletInvocableHandlerMethodTests {
|
||||
return "foo";
|
||||
}
|
||||
|
||||
@ResponseStatus(code = HttpStatus.BAD_REQUEST, reason = "BadRequest.error")
|
||||
public String responseStatusWithReasonCode() {
|
||||
return "foo";
|
||||
}
|
||||
|
||||
@ComposedResponseStatus(responseStatus = HttpStatus.BAD_REQUEST)
|
||||
public void composedResponseStatus() {
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user