SPR-13033: Use @RequestMapping of correct class
MvcUriComponentsBuilder::fromMethodCall creates wrong URLs with derived controller classes. The @RequestMapping of the declaring class of the method that is called is used instead of the @RequstMapping of the given controller class. https://jira.spring.io/browse/SPR-13033
This commit is contained in:
@@ -254,7 +254,7 @@ public class MvcUriComponentsBuilder {
|
|||||||
public static UriComponentsBuilder fromMethodCall(UriComponentsBuilder builder, Object invocationInfo) {
|
public static UriComponentsBuilder fromMethodCall(UriComponentsBuilder builder, Object invocationInfo) {
|
||||||
Assert.isInstanceOf(MethodInvocationInfo.class, invocationInfo);
|
Assert.isInstanceOf(MethodInvocationInfo.class, invocationInfo);
|
||||||
MethodInvocationInfo info = (MethodInvocationInfo) invocationInfo;
|
MethodInvocationInfo info = (MethodInvocationInfo) invocationInfo;
|
||||||
return fromMethod(builder, info.getControllerMethod(), info.getArgumentValues());
|
return fromMethod(builder, info.getControllerType(), info.getControllerMethod(), info.getArgumentValues());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -362,8 +362,12 @@ public class MvcUriComponentsBuilder {
|
|||||||
* @return a UriComponentsBuilder instance, never {@code null}
|
* @return a UriComponentsBuilder instance, never {@code null}
|
||||||
*/
|
*/
|
||||||
public static UriComponentsBuilder fromMethod(UriComponentsBuilder baseUrl, Method method, Object... args) {
|
public static UriComponentsBuilder fromMethod(UriComponentsBuilder baseUrl, Method method, Object... args) {
|
||||||
|
return fromMethod(baseUrl, method.getDeclaringClass(), method, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static UriComponentsBuilder fromMethod(UriComponentsBuilder baseUrl, Class<?> controllerType, Method method, Object... args) {
|
||||||
baseUrl = getBaseUrlToUse(baseUrl);
|
baseUrl = getBaseUrlToUse(baseUrl);
|
||||||
String typePath = getTypeRequestMapping(method.getDeclaringClass());
|
String typePath = getTypeRequestMapping(controllerType);
|
||||||
String methodPath = getMethodRequestMapping(method);
|
String methodPath = getMethodRequestMapping(method);
|
||||||
String path = pathMatcher.combine(typePath, methodPath);
|
String path = pathMatcher.combine(typePath, methodPath);
|
||||||
baseUrl.path(path);
|
baseUrl.path(path);
|
||||||
@@ -560,7 +564,7 @@ public class MvcUriComponentsBuilder {
|
|||||||
*/
|
*/
|
||||||
public static <T> T controller(Class<T> controllerType) {
|
public static <T> T controller(Class<T> controllerType) {
|
||||||
Assert.notNull(controllerType, "'controllerType' must not be null");
|
Assert.notNull(controllerType, "'controllerType' must not be null");
|
||||||
return initProxy(controllerType, new ControllerMethodInvocationInterceptor());
|
return initProxy(controllerType, new ControllerMethodInvocationInterceptor(controllerType));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@@ -634,10 +638,18 @@ public class MvcUriComponentsBuilder {
|
|||||||
private static final Method getArgumentValues =
|
private static final Method getArgumentValues =
|
||||||
ReflectionUtils.findMethod(MethodInvocationInfo.class, "getArgumentValues");
|
ReflectionUtils.findMethod(MethodInvocationInfo.class, "getArgumentValues");
|
||||||
|
|
||||||
|
private static final Method getControllerType =
|
||||||
|
ReflectionUtils.findMethod(MethodInvocationInfo.class, "getControllerType");
|
||||||
|
|
||||||
private Method controllerMethod;
|
private Method controllerMethod;
|
||||||
|
|
||||||
private Object[] argumentValues;
|
private Object[] argumentValues;
|
||||||
|
|
||||||
|
private Class<?> controllerType;
|
||||||
|
|
||||||
|
ControllerMethodInvocationInterceptor(Class<?> controllerType) {
|
||||||
|
this.controllerType = controllerType;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) {
|
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) {
|
||||||
@@ -647,6 +659,9 @@ public class MvcUriComponentsBuilder {
|
|||||||
else if (getArgumentValues.equals(method)) {
|
else if (getArgumentValues.equals(method)) {
|
||||||
return this.argumentValues;
|
return this.argumentValues;
|
||||||
}
|
}
|
||||||
|
else if (getControllerType.equals(method)) {
|
||||||
|
return this.controllerType;
|
||||||
|
}
|
||||||
else if (ReflectionUtils.isObjectMethod(method)) {
|
else if (ReflectionUtils.isObjectMethod(method)) {
|
||||||
return ReflectionUtils.invokeMethod(method, obj, args);
|
return ReflectionUtils.invokeMethod(method, obj, args);
|
||||||
}
|
}
|
||||||
@@ -670,6 +685,8 @@ public class MvcUriComponentsBuilder {
|
|||||||
Method getControllerMethod();
|
Method getControllerMethod();
|
||||||
|
|
||||||
Object[] getArgumentValues();
|
Object[] getArgumentValues();
|
||||||
|
|
||||||
|
Class<?> getControllerType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -229,6 +229,14 @@ public class MvcUriComponentsBuilderTests {
|
|||||||
assertThat(uriComponents.toUriString(), endsWith("/something/else"));
|
assertThat(uriComponents.toUriString(), endsWith("/something/else"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFromMethodCallOnSubclass() {
|
||||||
|
UriComponents uriComponents = fromMethodCall(on(ExtendedController.class).myMethod(null)).build();
|
||||||
|
|
||||||
|
assertThat(uriComponents.toUriString(), startsWith("http://localhost"));
|
||||||
|
assertThat(uriComponents.toUriString(), endsWith("/extended/else"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFromMethodCallWithTypeLevelUriVars() {
|
public void testFromMethodCallWithTypeLevelUriVars() {
|
||||||
UriComponents uriComponents = fromMethodCall(on(
|
UriComponents uriComponents = fromMethodCall(on(
|
||||||
@@ -418,6 +426,11 @@ public class MvcUriComponentsBuilderTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/extended")
|
||||||
|
static class ExtendedController extends ControllerWithMethods {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@RequestMapping("/user/{userId}/contacts")
|
@RequestMapping("/user/{userId}/contacts")
|
||||||
static class UserContactController {
|
static class UserContactController {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user