diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java index dcdf713ecf7..7d3324c0dad 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -252,10 +252,8 @@ public class MvcUriComponentsBuilder { * controller.getAddressesForCountry("US") * builder = MvcUriComponentsBuilder.fromMethodCall(controller); * - * *
Note: This method extracts values from "Forwarded"
* and "X-Forwarded-*" headers if found. See class-level docs.
- *
* @param info either the value returned from a "mock" controller
* invocation or the "mock" controller itself after an invocation
* @return a UriComponents instance
@@ -725,6 +723,16 @@ public class MvcUriComponentsBuilder {
}
+ public interface MethodInvocationInfo {
+
+ Class> getControllerType();
+
+ Method getControllerMethod();
+
+ Object[] getArgumentValues();
+ }
+
+
private static class ControllerMethodInvocationInterceptor
implements org.springframework.cglib.proxy.MethodInterceptor, MethodInterceptor {
@@ -737,27 +745,27 @@ public class MvcUriComponentsBuilder {
private static final Method getControllerType =
ReflectionUtils.findMethod(MethodInvocationInfo.class, "getControllerType");
+ private final Class> controllerType;
+
private Method controllerMethod;
private Object[] argumentValues;
- private Class> controllerType;
-
ControllerMethodInvocationInterceptor(Class> controllerType) {
this.controllerType = controllerType;
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) {
- if (getControllerMethod.equals(method)) {
+ if (getControllerType.equals(method)) {
+ return this.controllerType;
+ }
+ else if (getControllerMethod.equals(method)) {
return this.controllerMethod;
}
else if (getArgumentValues.equals(method)) {
return this.argumentValues;
}
- else if (getControllerType.equals(method)) {
- return this.controllerType;
- }
else if (ReflectionUtils.isObjectMethod(method)) {
return ReflectionUtils.invokeMethod(method, obj, args);
}
@@ -765,7 +773,13 @@ public class MvcUriComponentsBuilder {
this.controllerMethod = method;
this.argumentValues = args;
Class> returnType = method.getReturnType();
- return (void.class == returnType ? null : returnType.cast(initProxy(returnType, this)));
+ try {
+ return (returnType == void.class ? null : returnType.cast(initProxy(returnType, this)));
+ }
+ catch (Throwable ex) {
+ throw new IllegalStateException(
+ "Failed to create proxy for controller method return type: " + method, ex);
+ }
}
}
@@ -776,16 +790,6 @@ public class MvcUriComponentsBuilder {
}
- public interface MethodInvocationInfo {
-
- Method getControllerMethod();
-
- Object[] getArgumentValues();
-
- Class> getControllerType();
- }
-
-
public static class MethodArgumentBuilder {
private final Class> controllerType;
diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilderTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilderTests.java
index daa1108aedc..3ed05870c68 100644
--- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilderTests.java
+++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilderTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2016 the original author or authors.
+ * Copyright 2012-2018 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.
@@ -16,10 +16,6 @@
package org.springframework.web.servlet.mvc.method.annotation;
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
-import static org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder.*;
-
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -44,6 +40,7 @@ import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.mock.web.test.MockServletContext;
import org.springframework.stereotype.Controller;
import org.springframework.util.MultiValueMap;
+import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -58,6 +55,10 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+import static org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder.*;
+
/**
* Unit tests for {@link org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder}.
*
@@ -73,12 +74,12 @@ public class MvcUriComponentsBuilderTests {
@Before
- public void setUp() {
+ public void setup() {
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(this.request));
}
@After
- public void tearDown() {
+ public void reset() {
RequestContextHolder.resetRequestAttributes();
}
@@ -134,15 +135,15 @@ public class MvcUriComponentsBuilderTests {
}
@Test
- public void testFromMethodNamePathVariable() throws Exception {
- UriComponents uriComponents = fromMethodName(
- ControllerWithMethods.class, "methodWithPathVariable", new Object[]{"1"}).build();
+ public void testFromMethodNamePathVariable() {
+ UriComponents uriComponents = fromMethodName(ControllerWithMethods.class,
+ "methodWithPathVariable", "1").build();
assertThat(uriComponents.toUriString(), is("http://localhost/something/1/foo"));
}
@Test
- public void testFromMethodNameTypeLevelPathVariable() throws Exception {
+ public void testFromMethodNameTypeLevelPathVariable() {
this.request.setContextPath("/myapp");
UriComponents uriComponents = fromMethodName(
PersonsAddressesController.class, "getAddressesForCountry", "DE").buildAndExpand("1");
@@ -151,7 +152,7 @@ public class MvcUriComponentsBuilderTests {
}
@Test
- public void testFromMethodNameTwoPathVariables() throws Exception {
+ public void testFromMethodNameTwoPathVariables() {
DateTime now = DateTime.now();
UriComponents uriComponents = fromMethodName(
ControllerWithMethods.class, "methodWithTwoPathVariables", 1, now).build();
@@ -160,7 +161,7 @@ public class MvcUriComponentsBuilderTests {
}
@Test
- public void testFromMethodNameWithPathVarAndRequestParam() throws Exception {
+ public void testFromMethodNameWithPathVarAndRequestParam() {
UriComponents uriComponents = fromMethodName(
ControllerWithMethods.class, "methodForNextPage", "1", 10, 5).build();
@@ -170,59 +171,56 @@ public class MvcUriComponentsBuilderTests {
assertThat(queryParams.get("offset"), contains("10"));
}
- // SPR-12977
-
- @Test
- public void fromMethodNameWithBridgedMethod() throws Exception {
+ @Test // SPR-12977
+ public void fromMethodNameWithBridgedMethod() {
UriComponents uriComponents = fromMethodName(PersonCrudController.class, "get", (long) 42).build();
+
assertThat(uriComponents.toUriString(), is("http://localhost/42"));
}
- // SPR-11391
-
- @Test
- public void testFromMethodNameTypeLevelPathVariableWithoutArgumentValue() throws Exception {
+ @Test // SPR-11391
+ public void testFromMethodNameTypeLevelPathVariableWithoutArgumentValue() {
UriComponents uriComponents = fromMethodName(UserContactController.class, "showCreate", 123).build();
assertThat(uriComponents.getPath(), is("/user/123/contacts/create"));
}
@Test
- public void testFromMethodNameNotMapped() throws Exception {
+ public void testFromMethodNameNotMapped() {
UriComponents uriComponents = fromMethodName(UnmappedController.class, "unmappedMethod").build();
assertThat(uriComponents.toUriString(), is("http://localhost/"));
}
@Test
- public void testFromMethodNameWithCustomBaseUrlViaStaticCall() throws Exception {
+ public void testFromMethodNameWithCustomBaseUrlViaStaticCall() {
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://example.org:9090/base");
UriComponents uriComponents = fromMethodName(builder, ControllerWithMethods.class,
- "methodWithPathVariable", new Object[] {"1"}).build();
+ "methodWithPathVariable", "1").build();
assertEquals("http://example.org:9090/base/something/1/foo", uriComponents.toString());
assertEquals("http://example.org:9090/base", builder.toUriString());
}
@Test
- public void testFromMethodNameWithCustomBaseUrlViaInstance() throws Exception {
+ public void testFromMethodNameWithCustomBaseUrlViaInstance() {
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://example.org:9090/base");
MvcUriComponentsBuilder mvcBuilder = MvcUriComponentsBuilder.relativeTo(builder);
UriComponents uriComponents = mvcBuilder.withMethodName(ControllerWithMethods.class,
- "methodWithPathVariable", new Object[] {"1"}).build();
+ "methodWithPathVariable", "1").build();
assertEquals("http://example.org:9090/base/something/1/foo", uriComponents.toString());
assertEquals("http://example.org:9090/base", builder.toUriString());
}
@Test
- public void testFromMethodNameWithMetaAnnotation() throws Exception {
+ public void testFromMethodNameWithMetaAnnotation() {
UriComponents uriComponents = fromMethodName(MetaAnnotationController.class, "handleInput").build();
assertThat(uriComponents.toUriString(), is("http://localhost/input"));
}
- @Test // SPR-14405
- public void testFromMappingNameWithOptionalParam() throws Exception {
+ @Test // SPR-14405
+ public void testFromMappingNameWithOptionalParam() {
UriComponents uriComponents = fromMethodName(ControllerWithMethods.class,
"methodWithOptionalParam", new Object[] {null}).build();
@@ -247,8 +245,8 @@ public class MvcUriComponentsBuilderTests {
@Test
public void testFromMethodCallWithTypeLevelUriVars() {
- UriComponents uriComponents = fromMethodCall(on(
- PersonsAddressesController.class).getAddressesForCountry("DE")).buildAndExpand(15);
+ UriComponents uriComponents = fromMethodCall(
+ on(PersonsAddressesController.class).getAddressesForCountry("DE")).buildAndExpand(15);
assertThat(uriComponents.toUriString(), endsWith("/people/15/addresses/DE"));
}
@@ -256,8 +254,8 @@ public class MvcUriComponentsBuilderTests {
@Test
public void testFromMethodCallWithPathVar() {
- UriComponents uriComponents = fromMethodCall(on(
- ControllerWithMethods.class).methodWithPathVariable("1")).build();
+ UriComponents uriComponents = fromMethodCall(
+ on(ControllerWithMethods.class).methodWithPathVariable("1")).build();
assertThat(uriComponents.toUriString(), startsWith("http://localhost"));
assertThat(uriComponents.toUriString(), endsWith("/something/1/foo"));
@@ -265,8 +263,8 @@ public class MvcUriComponentsBuilderTests {
@Test
public void testFromMethodCallWithPathVarAndRequestParams() {
- UriComponents uriComponents = fromMethodCall(on(
- ControllerWithMethods.class).methodForNextPage("1", 10, 5)).build();
+ UriComponents uriComponents = fromMethodCall(
+ on(ControllerWithMethods.class).methodForNextPage("1", 10, 5)).build();
assertThat(uriComponents.getPath(), is("/something/1/foo"));
@@ -277,8 +275,8 @@ public class MvcUriComponentsBuilderTests {
@Test
public void testFromMethodCallWithPathVarAndMultiValueRequestParams() {
- UriComponents uriComponents = fromMethodCall(on(
- ControllerWithMethods.class).methodWithMultiValueRequestParams("1", Arrays.asList(3, 7), 5)).build();
+ UriComponents uriComponents = fromMethodCall(
+ on(ControllerWithMethods.class).methodWithMultiValueRequestParams("1", Arrays.asList(3, 7), 5)).build();
assertThat(uriComponents.getPath(), is("/something/1/foo"));
@@ -307,7 +305,7 @@ public class MvcUriComponentsBuilderTests {
}
@Test
- public void testFromMappingName() throws Exception {
+ public void testFromMappingName() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setServletContext(new MockServletContext());
context.register(WebConfig.class);
@@ -324,7 +322,7 @@ public class MvcUriComponentsBuilderTests {
}
@Test
- public void testFromMappingNameWithCustomBaseUrl() throws Exception {
+ public void testFromMappingNameWithCustomBaseUrl() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setServletContext(new MockServletContext());
context.register(WebConfig.class);
@@ -362,6 +360,13 @@ public class MvcUriComponentsBuilderTests {
assertThat(uriComponents.toUriString(), startsWith("http://barfoo:8888"));
}
+ @Test // SPR-16710
+ public void withStringReturnType() {
+ UriComponents uriComponents = MvcUriComponentsBuilder.fromMethodCall(
+ on(BookingController.class).getBooking(21L)).buildAndExpand(42);
+ assertEquals("http://localhost/hotels/42/bookings/21", uriComponents.encode().toUri().toString());
+ }
+
static class Person {
@@ -372,15 +377,16 @@ public class MvcUriComponentsBuilderTests {
}
}
+
@RequestMapping("/people")
interface PersonController {
-
}
- private class PersonControllerImpl implements PersonController {
+ private class PersonControllerImpl implements PersonController {
}
+
@RequestMapping("/people/{id}/addresses")
private static class PersonsAddressesController {
@@ -390,11 +396,12 @@ public class MvcUriComponentsBuilderTests {
}
}
- @RequestMapping({ "/persons", "/people" })
- private class InvalidController {
+ @RequestMapping({"/persons", "/people"})
+ private class InvalidController {
}
+
private class UnmappedController {
@RequestMapping
@@ -402,6 +409,7 @@ public class MvcUriComponentsBuilderTests {
}
}
+
@RequestMapping("/something")
static class ControllerWithMethods {
@@ -439,11 +447,13 @@ public class MvcUriComponentsBuilderTests {
}
}
- @RequestMapping("/extended") @SuppressWarnings("WeakerAccess")
- static class ExtendedController extends ControllerWithMethods {
+ @RequestMapping("/extended")
+ @SuppressWarnings("WeakerAccess")
+ static class ExtendedController extends ControllerWithMethods {
}
+
@RequestMapping("/user/{userId}/contacts")
private static class UserContactController {
@@ -453,11 +463,13 @@ public class MvcUriComponentsBuilderTests {
}
}
+
static abstract class AbstractCrudController