Skip to content

Commit 7ee6130

Browse files
committed
Revised reference example for linkable controller method signature
Issue: SPR-16710
1 parent 97ee94f commit 7ee6130

File tree

2 files changed

+131
-72
lines changed

2 files changed

+131
-72
lines changed

spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilderTests.java

Lines changed: 118 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import org.springframework.web.context.request.ServletRequestAttributes;
5151
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
5252
import org.springframework.web.servlet.DispatcherServlet;
53+
import org.springframework.web.servlet.ModelAndView;
5354
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
5455
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
5556
import org.springframework.web.util.UriComponents;
@@ -85,38 +86,38 @@ public void reset() {
8586

8687

8788
@Test
88-
public void testFromController() {
89+
public void fromControllerPlain() {
8990
UriComponents uriComponents = fromController(PersonControllerImpl.class).build();
9091
assertThat(uriComponents.toUriString(), Matchers.endsWith("/people"));
9192
}
9293

9394
@Test
94-
public void testFromControllerUriTemplate() {
95+
public void fromControllerUriTemplate() {
9596
UriComponents uriComponents = fromController(PersonsAddressesController.class).buildAndExpand(15);
9697
assertThat(uriComponents.toUriString(), endsWith("/people/15/addresses"));
9798
}
9899

99100
@Test
100-
public void testFromControllerSubResource() {
101+
public void fromControllerSubResource() {
101102
UriComponents uriComponents = fromController(PersonControllerImpl.class).pathSegment("something").build();
102103

103104
assertThat(uriComponents.toUriString(), endsWith("/people/something"));
104105
}
105106

106107
@Test
107-
public void testFromControllerTwoTypeLevelMappings() {
108+
public void fromControllerTwoTypeLevelMappings() {
108109
UriComponents uriComponents = fromController(InvalidController.class).build();
109110
assertThat(uriComponents.toUriString(), is("http://localhost/persons"));
110111
}
111112

112113
@Test
113-
public void testFromControllerNotMapped() {
114+
public void fromControllerNotMapped() {
114115
UriComponents uriComponents = fromController(UnmappedController.class).build();
115116
assertThat(uriComponents.toUriString(), is("http://localhost/"));
116117
}
117118

118119
@Test
119-
public void testFromControllerWithCustomBaseUrlViaStaticCall() {
120+
public void fromControllerWithCustomBaseUrlViaStaticCall() {
120121
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://example.org:9090/base");
121122
UriComponents uriComponents = fromController(builder, PersonControllerImpl.class).build();
122123

@@ -125,25 +126,49 @@ public void testFromControllerWithCustomBaseUrlViaStaticCall() {
125126
}
126127

127128
@Test
128-
public void testFromControllerWithCustomBaseUrlViaInstance() {
129+
public void fromControllerWithCustomBaseUrlViaInstance() {
129130
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://example.org:9090/base");
130-
MvcUriComponentsBuilder mvcBuilder = MvcUriComponentsBuilder.relativeTo(builder);
131+
MvcUriComponentsBuilder mvcBuilder = relativeTo(builder);
131132
UriComponents uriComponents = mvcBuilder.withController(PersonControllerImpl.class).build();
132133

133134
assertEquals("http://example.org:9090/base/people", uriComponents.toString());
134135
assertEquals("http://example.org:9090/base", builder.toUriString());
135136
}
136137

137138
@Test
138-
public void testFromMethodNamePathVariable() {
139+
public void usesForwardedHostAsHostIfHeaderIsSet() {
140+
this.request.addHeader("X-Forwarded-Host", "somethingDifferent");
141+
UriComponents uriComponents = fromController(PersonControllerImpl.class).build();
142+
143+
assertThat(uriComponents.toUriString(), startsWith("http://somethingDifferent"));
144+
}
145+
146+
@Test
147+
public void usesForwardedHostAndPortFromHeader() {
148+
request.addHeader("X-Forwarded-Host", "foobar:8088");
149+
UriComponents uriComponents = fromController(PersonControllerImpl.class).build();
150+
151+
assertThat(uriComponents.toUriString(), startsWith("http://foobar:8088"));
152+
}
153+
154+
@Test
155+
public void usesFirstHostOfXForwardedHost() {
156+
request.addHeader("X-Forwarded-Host", "barfoo:8888, localhost:8088");
157+
UriComponents uriComponents = fromController(PersonControllerImpl.class).build();
158+
159+
assertThat(uriComponents.toUriString(), startsWith("http://barfoo:8888"));
160+
}
161+
162+
@Test
163+
public void fromMethodNamePathVariable() {
139164
UriComponents uriComponents = fromMethodName(ControllerWithMethods.class,
140165
"methodWithPathVariable", "1").build();
141166

142167
assertThat(uriComponents.toUriString(), is("http://localhost/something/1/foo"));
143168
}
144169

145170
@Test
146-
public void testFromMethodNameTypeLevelPathVariable() {
171+
public void fromMethodNameTypeLevelPathVariable() {
147172
this.request.setContextPath("/myapp");
148173
UriComponents uriComponents = fromMethodName(
149174
PersonsAddressesController.class, "getAddressesForCountry", "DE").buildAndExpand("1");
@@ -152,7 +177,7 @@ public void testFromMethodNameTypeLevelPathVariable() {
152177
}
153178

154179
@Test
155-
public void testFromMethodNameTwoPathVariables() {
180+
public void fromMethodNameTwoPathVariables() {
156181
DateTime now = DateTime.now();
157182
UriComponents uriComponents = fromMethodName(
158183
ControllerWithMethods.class, "methodWithTwoPathVariables", 1, now).build();
@@ -161,7 +186,7 @@ public void testFromMethodNameTwoPathVariables() {
161186
}
162187

163188
@Test
164-
public void testFromMethodNameWithPathVarAndRequestParam() {
189+
public void fromMethodNameWithPathVarAndRequestParam() {
165190
UriComponents uriComponents = fromMethodName(
166191
ControllerWithMethods.class, "methodForNextPage", "1", 10, 5).build();
167192

@@ -179,21 +204,21 @@ public void fromMethodNameWithBridgedMethod() {
179204
}
180205

181206
@Test // SPR-11391
182-
public void testFromMethodNameTypeLevelPathVariableWithoutArgumentValue() {
207+
public void fromMethodNameTypeLevelPathVariableWithoutArgumentValue() {
183208
UriComponents uriComponents = fromMethodName(UserContactController.class, "showCreate", 123).build();
184209

185210
assertThat(uriComponents.getPath(), is("/user/123/contacts/create"));
186211
}
187212

188213
@Test
189-
public void testFromMethodNameNotMapped() {
214+
public void fromMethodNameNotMapped() {
190215
UriComponents uriComponents = fromMethodName(UnmappedController.class, "unmappedMethod").build();
191216

192217
assertThat(uriComponents.toUriString(), is("http://localhost/"));
193218
}
194219

195220
@Test
196-
public void testFromMethodNameWithCustomBaseUrlViaStaticCall() {
221+
public void fromMethodNameWithCustomBaseUrlViaStaticCall() {
197222
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://example.org:9090/base");
198223
UriComponents uriComponents = fromMethodName(builder, ControllerWithMethods.class,
199224
"methodWithPathVariable", "1").build();
@@ -203,57 +228,57 @@ public void testFromMethodNameWithCustomBaseUrlViaStaticCall() {
203228
}
204229

205230
@Test
206-
public void testFromMethodNameWithCustomBaseUrlViaInstance() {
231+
public void fromMethodNameWithCustomBaseUrlViaInstance() {
207232
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://example.org:9090/base");
208-
MvcUriComponentsBuilder mvcBuilder = MvcUriComponentsBuilder.relativeTo(builder);
233+
MvcUriComponentsBuilder mvcBuilder = relativeTo(builder);
209234
UriComponents uriComponents = mvcBuilder.withMethodName(ControllerWithMethods.class,
210235
"methodWithPathVariable", "1").build();
211236

212237
assertEquals("http://example.org:9090/base/something/1/foo", uriComponents.toString());
213238
assertEquals("http://example.org:9090/base", builder.toUriString());
214239
}
215240

216-
@Test
217-
public void testFromMethodNameWithMetaAnnotation() {
218-
UriComponents uriComponents = fromMethodName(MetaAnnotationController.class, "handleInput").build();
219-
assertThat(uriComponents.toUriString(), is("http://localhost/input"));
220-
}
221-
222241
@Test // SPR-14405
223-
public void testFromMappingNameWithOptionalParam() {
242+
public void fromMethodNameWithOptionalParam() {
224243
UriComponents uriComponents = fromMethodName(ControllerWithMethods.class,
225244
"methodWithOptionalParam", new Object[] {null}).build();
226245

227246
assertThat(uriComponents.toUriString(), is("http://localhost/something/optional-param"));
228247
}
229248

230249
@Test
231-
public void testFromMethodCall() {
250+
public void fromMethodNameWithMetaAnnotation() {
251+
UriComponents uriComponents = fromMethodName(MetaAnnotationController.class, "handleInput").build();
252+
253+
assertThat(uriComponents.toUriString(), is("http://localhost/input"));
254+
}
255+
256+
@Test
257+
public void fromMethodCallPlain() {
232258
UriComponents uriComponents = fromMethodCall(on(ControllerWithMethods.class).myMethod(null)).build();
233259

234260
assertThat(uriComponents.toUriString(), startsWith("http://localhost"));
235261
assertThat(uriComponents.toUriString(), endsWith("/something/else"));
236262
}
237263

238264
@Test
239-
public void testFromMethodCallOnSubclass() {
265+
public void fromMethodCallOnSubclass() {
240266
UriComponents uriComponents = fromMethodCall(on(ExtendedController.class).myMethod(null)).build();
241267

242268
assertThat(uriComponents.toUriString(), startsWith("http://localhost"));
243269
assertThat(uriComponents.toUriString(), endsWith("/extended/else"));
244270
}
245271

246272
@Test
247-
public void testFromMethodCallWithTypeLevelUriVars() {
273+
public void fromMethodCallWithTypeLevelUriVars() {
248274
UriComponents uriComponents = fromMethodCall(
249275
on(PersonsAddressesController.class).getAddressesForCountry("DE")).buildAndExpand(15);
250276

251277
assertThat(uriComponents.toUriString(), endsWith("/people/15/addresses/DE"));
252278
}
253279

254-
255280
@Test
256-
public void testFromMethodCallWithPathVar() {
281+
public void fromMethodCallWithPathVariable() {
257282
UriComponents uriComponents = fromMethodCall(
258283
on(ControllerWithMethods.class).methodWithPathVariable("1")).build();
259284

@@ -262,7 +287,7 @@ public void testFromMethodCallWithPathVar() {
262287
}
263288

264289
@Test
265-
public void testFromMethodCallWithPathVarAndRequestParams() {
290+
public void fromMethodCallWithPathVariableAndRequestParams() {
266291
UriComponents uriComponents = fromMethodCall(
267292
on(ControllerWithMethods.class).methodForNextPage("1", 10, 5)).build();
268293

@@ -274,7 +299,7 @@ public void testFromMethodCallWithPathVarAndRequestParams() {
274299
}
275300

276301
@Test
277-
public void testFromMethodCallWithPathVarAndMultiValueRequestParams() {
302+
public void fromMethodCallWithPathVariableAndMultiValueRequestParams() {
278303
UriComponents uriComponents = fromMethodCall(
279304
on(ControllerWithMethods.class).methodWithMultiValueRequestParams("1", Arrays.asList(3, 7), 5)).build();
280305

@@ -286,7 +311,7 @@ public void testFromMethodCallWithPathVarAndMultiValueRequestParams() {
286311
}
287312

288313
@Test
289-
public void testFromMethodCallWithCustomBaseUrlViaStaticCall() {
314+
public void fromMethodCallWithCustomBaseUrlViaStaticCall() {
290315
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://example.org:9090/base");
291316
UriComponents uriComponents = fromMethodCall(builder, on(ControllerWithMethods.class).myMethod(null)).build();
292317

@@ -295,17 +320,49 @@ public void testFromMethodCallWithCustomBaseUrlViaStaticCall() {
295320
}
296321

297322
@Test
298-
public void testFromMethodCallWithCustomBaseUrlViaInstance() {
323+
public void fromMethodCallWithCustomBaseUrlViaInstance() {
299324
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://example.org:9090/base");
300-
MvcUriComponentsBuilder mvcBuilder = MvcUriComponentsBuilder.relativeTo(builder);
325+
MvcUriComponentsBuilder mvcBuilder = relativeTo(builder);
301326
UriComponents result = mvcBuilder.withMethodCall(on(ControllerWithMethods.class).myMethod(null)).build();
302327

303328
assertEquals("http://example.org:9090/base/something/else", result.toString());
304329
assertEquals("http://example.org:9090/base", builder.toUriString());
305330
}
306331

332+
@Test // SPR-16710
333+
public void fromMethodCallWithModelAndViewReturnType() {
334+
UriComponents uriComponents = fromMethodCall(
335+
on(BookingControllerWithModelAndView.class).getBooking(21L)).buildAndExpand(42);
336+
337+
assertEquals("http://localhost/hotels/42/bookings/21", uriComponents.encode().toUri().toString());
338+
}
339+
340+
@Test // SPR-16710
341+
public void fromMethodCallWithObjectReturnType() {
342+
UriComponents uriComponents = fromMethodCall(
343+
on(BookingControllerWithObject.class).getBooking(21L)).buildAndExpand(42);
344+
345+
assertEquals("http://localhost/hotels/42/bookings/21", uriComponents.encode().toUri().toString());
346+
}
347+
348+
@Test(expected = IllegalStateException.class) // SPR-16710
349+
public void fromMethodCallWithStringReturnType() {
350+
UriComponents uriComponents = fromMethodCall(
351+
on(BookingControllerWithString.class).getBooking(21L)).buildAndExpand(42);
352+
353+
assertEquals("http://localhost/hotels/42/bookings/21", uriComponents.encode().toUri().toString());
354+
}
355+
356+
@Test // SPR-16710
357+
public void fromMethodNameWithStringReturnType() {
358+
UriComponents uriComponents = fromMethodName(
359+
BookingControllerWithString.class, "getBooking", 21L).buildAndExpand(42);
360+
361+
assertEquals("http://localhost/hotels/42/bookings/21", uriComponents.encode().toUri().toString());
362+
}
363+
307364
@Test
308-
public void testFromMappingName() {
365+
public void fromMappingNamePlain() {
309366
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
310367
context.setServletContext(new MockServletContext());
311368
context.register(WebConfig.class);
@@ -317,12 +374,12 @@ public void testFromMappingName() {
317374
this.request.setContextPath("/base");
318375

319376
String mappingName = "PAC#getAddressesForCountry";
320-
String url = MvcUriComponentsBuilder.fromMappingName(mappingName).arg(0, "DE").buildAndExpand(123);
377+
String url = fromMappingName(mappingName).arg(0, "DE").buildAndExpand(123);
321378
assertEquals("/base/people/123/addresses/DE", url);
322379
}
323380

324381
@Test
325-
public void testFromMappingNameWithCustomBaseUrl() {
382+
public void fromMappingNameWithCustomBaseUrl() {
326383
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
327384
context.setServletContext(new MockServletContext());
328385
context.register(WebConfig.class);
@@ -331,42 +388,11 @@ public void testFromMappingNameWithCustomBaseUrl() {
331388
this.request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, context);
332389

333390
UriComponentsBuilder baseUrl = UriComponentsBuilder.fromUriString("http://example.org:9999/base");
334-
MvcUriComponentsBuilder mvcBuilder = MvcUriComponentsBuilder.relativeTo(baseUrl);
391+
MvcUriComponentsBuilder mvcBuilder = relativeTo(baseUrl);
335392
String url = mvcBuilder.withMappingName("PAC#getAddressesForCountry").arg(0, "DE").buildAndExpand(123);
336393
assertEquals("http://example.org:9999/base/people/123/addresses/DE", url);
337394
}
338395

339-
@Test
340-
public void usesForwardedHostAsHostIfHeaderIsSet() {
341-
this.request.addHeader("X-Forwarded-Host", "somethingDifferent");
342-
UriComponents uriComponents = fromController(PersonControllerImpl.class).build();
343-
344-
assertThat(uriComponents.toUriString(), startsWith("http://somethingDifferent"));
345-
}
346-
347-
@Test
348-
public void usesForwardedHostAndPortFromHeader() {
349-
request.addHeader("X-Forwarded-Host", "foobar:8088");
350-
UriComponents uriComponents = fromController(PersonControllerImpl.class).build();
351-
352-
assertThat(uriComponents.toUriString(), startsWith("http://foobar:8088"));
353-
}
354-
355-
@Test
356-
public void usesFirstHostOfXForwardedHost() {
357-
request.addHeader("X-Forwarded-Host", "barfoo:8888, localhost:8088");
358-
UriComponents uriComponents = fromController(PersonControllerImpl.class).build();
359-
360-
assertThat(uriComponents.toUriString(), startsWith("http://barfoo:8888"));
361-
}
362-
363-
@Test // SPR-16710
364-
public void withStringReturnType() {
365-
UriComponents uriComponents = MvcUriComponentsBuilder.fromMethodCall(
366-
on(BookingController.class).getBooking(21L)).buildAndExpand(42);
367-
assertEquals("http://localhost/hotels/42/bookings/21", uriComponents.encode().toUri().toString());
368-
}
369-
370396

371397
static class Person {
372398

@@ -516,12 +542,34 @@ public PersonsAddressesController controller() {
516542

517543
@Controller
518544
@RequestMapping("/hotels/{hotel}")
519-
public class BookingController {
545+
static class BookingControllerWithModelAndView {
546+
547+
@GetMapping("/bookings/{booking}")
548+
public ModelAndView getBooking(@PathVariable Long booking) {
549+
return new ModelAndView("url");
550+
}
551+
}
552+
553+
554+
@Controller
555+
@RequestMapping("/hotels/{hotel}")
556+
static class BookingControllerWithObject {
520557

521558
@GetMapping("/bookings/{booking}")
522559
public Object getBooking(@PathVariable Long booking) {
523560
return "url";
524561
}
525562
}
526563

564+
565+
@Controller
566+
@RequestMapping("/hotels/{hotel}")
567+
static class BookingControllerWithString {
568+
569+
@GetMapping("/bookings/{booking}")
570+
public String getBooking(@PathVariable Long booking) {
571+
return "url";
572+
}
573+
}
574+
527575
}

0 commit comments

Comments
 (0)