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 c4d2b96af6e9..46c3ab1543b5 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 @@ -780,7 +780,9 @@ private static T initProxy( else if (controllerType.isInterface()) { ClassLoader classLoader = controllerType.getClassLoader(); - if (classLoader == null) { // JDK interface type from bootstrap loader + if (classLoader == null || classLoader.getParent() == null) { + // JDK interface type from bootstrap loader or platform loader -> + // use higher-level loader which can see Spring infrastructure classes classLoader = MethodInvocationInfo.class.getClassLoader(); } Class[] ifcs = new Class[] {controllerType, MethodInvocationInfo.class}; 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 04f341ee32a8..4e988c324009 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 @@ -21,6 +21,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.sql.Savepoint; import java.util.Arrays; import java.util.Date; import java.util.List; @@ -384,14 +385,6 @@ public void fromMethodCallWithObjectReturnType() { assertThat(uriComponents.encode().toUri().toString()).isEqualTo("http://localhost/hotels/42/bookings/21"); } - @Test // SPR-16710 - public void fromMethodCallWithCharSequenceReturnType() { - UriComponents uriComponents = fromMethodCall( - on(BookingControllerWithCharSequence.class).getBooking(21L)).buildAndExpand(42); - - assertThat(uriComponents.encode().toUri().toString()).isEqualTo("http://localhost/hotels/42/bookings/21"); - } - @Test // SPR-16710 public void fromMethodCallWithStringReturnType() { assertThatIllegalStateException().isThrownBy(() -> { @@ -409,6 +402,22 @@ public void fromMethodNameWithStringReturnType() { assertThat(uriComponents.encode().toUri().toString()).isEqualTo("http://localhost/hotels/42/bookings/21"); } + @Test // gh-30210 + public void fromMethodCallWithCharSequenceReturnType() { + UriComponents uriComponents = fromMethodCall( + on(BookingControllerWithCharSequence.class).getBooking(21L)).buildAndExpand(42); + + assertThat(uriComponents.encode().toUri().toString()).isEqualTo("http://localhost/hotels/42/bookings/21"); + } + + @Test // gh-30210 + public void fromMethodCallWithJdbc30115ReturnType() { + UriComponents uriComponents = fromMethodCall( + on(BookingControllerWithJdbcSavepoint.class).getBooking(21L)).buildAndExpand(42); + + assertThat(uriComponents.encode().toUri().toString()).isEqualTo("http://localhost/hotels/42/bookings/21"); + } + @Test public void fromMappingNamePlain() { initWebApplicationContext(WebConfig.class); @@ -716,6 +725,17 @@ public Object getBooking(@PathVariable Long booking) { } + @Controller + @RequestMapping("/hotels/{hotel}") + static class BookingControllerWithString { + + @GetMapping("/bookings/{booking}") + public String getBooking(@PathVariable Long booking) { + return "url"; + } + } + + @Controller @RequestMapping("/hotels/{hotel}") static class BookingControllerWithCharSequence { @@ -729,11 +749,11 @@ public CharSequence getBooking(@PathVariable Long booking) { @Controller @RequestMapping("/hotels/{hotel}") - static class BookingControllerWithString { + static class BookingControllerWithJdbcSavepoint { @GetMapping("/bookings/{booking}") - public String getBooking(@PathVariable Long booking) { - return "url"; + public Savepoint getBooking(@PathVariable Long booking) { + return null; } }