1 /* 2 * Copyright 2002-2010 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.springframework.web.servlet.mvc.method.annotation; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertTrue; 21 22 import java.io.IOException; 23 import java.io.Writer; 24 import java.text.SimpleDateFormat; 25 import java.util.Date; 26 import java.util.GregorianCalendar; 27 import java.util.HashMap; 28 import java.util.Locale; 29 import java.util.Map; 30 31 import javax.servlet.http.HttpServletRequest; 32 import javax.servlet.http.HttpServletResponse; 33 34 import org.junit.Test; 35 import org.springframework.beans.factory.support.RootBeanDefinition; 36 import org.springframework.beans.propertyeditors.CustomDateEditor; 37 import org.springframework.context.ApplicationContextInitializer; 38 import org.springframework.mock.web.MockHttpServletRequest; 39 import org.springframework.mock.web.MockHttpServletResponse; 40 import org.springframework.stereotype.Controller; 41 import org.springframework.web.bind.WebDataBinder; 42 import org.springframework.web.bind.annotation.InitBinder; 43 import org.springframework.web.bind.annotation.PathVariable; 44 import org.springframework.web.bind.annotation.RequestMapping; 45 import org.springframework.web.bind.annotation.RequestMethod; 46 import org.springframework.web.context.WebApplicationContext; 47 import org.springframework.web.context.support.GenericWebApplicationContext; 48 import org.springframework.web.method.HandlerMethod; 49 import org.springframework.web.servlet.View; 50 import org.springframework.web.servlet.ViewResolver; 51 import org.springframework.web.servlet.mvc.annotation.UriTemplateServletAnnotationControllerTests; 52 import org.springframework.web.servlet.view.AbstractView; 53 54 /** 55 * The origin of this test class is {@link UriTemplateServletAnnotationControllerTests}. 56 * 57 * Tests in this class run against the {@link HandlerMethod} infrastructure: 58 * <ul> 59 * <li>RequestMappingHandlerMapping 60 * <li>RequestMappingHandlerAdapter 61 * <li>ExceptionHandlerExceptionResolver 62 * </ul> 63 * 64 * <p>Rather than against the existing infrastructure: 65 * <ul> 66 * <li>DefaultAnnotationHandlerMapping 67 * <li>AnnotationMethodHandlerAdapter 68 * <li>AnnotationMethodHandlerExceptionResolver 69 * </ul> 70 * 71 * @author Rossen Stoyanchev 72 * @since 3.1 73 */ 74 public class UriTemplateServletAnnotationControllerHandlerMethodTests extends AbstractServletHandlerMethodTests { 75 76 @Test simple()77 public void simple() throws Exception { 78 initServletWithControllers(SimpleUriTemplateController.class); 79 80 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/42"); 81 MockHttpServletResponse response = new MockHttpServletResponse(); 82 getServlet().service(request, response); 83 assertEquals("test-42", response.getContentAsString()); 84 } 85 86 @Test multiple()87 public void multiple() throws Exception { 88 initServletWithControllers(MultipleUriTemplateController.class); 89 90 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42/bookings/21-other"); 91 MockHttpServletResponse response = new MockHttpServletResponse(); 92 getServlet().service(request, response); 93 assertEquals("test-42-21-other", response.getContentAsString()); 94 } 95 96 @Test pathVarsInModel()97 public void pathVarsInModel() throws Exception { 98 final Map<String, Object> pathVars = new HashMap<String, Object>(); 99 pathVars.put("hotel", "42"); 100 pathVars.put("booking", 21); 101 pathVars.put("other", "other"); 102 103 WebApplicationContext wac = 104 initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { 105 public void initialize(GenericWebApplicationContext context) { 106 RootBeanDefinition beanDef = new RootBeanDefinition(ModelValidatingViewResolver.class); 107 beanDef.getConstructorArgumentValues().addGenericArgumentValue(pathVars); 108 context.registerBeanDefinition("viewResolver", beanDef); 109 } 110 }, ViewRenderingController.class); 111 112 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42/bookings/21-other"); 113 getServlet().service(request, new MockHttpServletResponse()); 114 115 ModelValidatingViewResolver resolver = wac.getBean(ModelValidatingViewResolver.class); 116 assertEquals(3, resolver.validatedAttrCount); 117 } 118 119 @Test binding()120 public void binding() throws Exception { 121 initServletWithControllers(BindingUriTemplateController.class); 122 123 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42/dates/2008-11-18"); 124 MockHttpServletResponse response = new MockHttpServletResponse(); 125 getServlet().service(request, response); 126 assertEquals(200, response.getStatus()); 127 128 request = new MockHttpServletRequest("GET", "/hotels/42/dates/2008-foo-bar"); 129 response = new MockHttpServletResponse(); 130 getServlet().service(request, response); 131 assertEquals(400, response.getStatus()); 132 133 initServletWithControllers(NonBindingUriTemplateController.class); 134 request = new MockHttpServletRequest("GET", "/hotels/42/dates/2008-foo-bar"); 135 response = new MockHttpServletResponse(); 136 getServlet().service(request, response); 137 assertEquals(500, response.getStatus()); 138 } 139 140 @Test ambiguous()141 public void ambiguous() throws Exception { 142 initServletWithControllers(AmbiguousUriTemplateController.class); 143 144 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/new"); 145 MockHttpServletResponse response = new MockHttpServletResponse(); 146 getServlet().service(request, response); 147 assertEquals("specific", response.getContentAsString()); 148 } 149 150 @Test relative()151 public void relative() throws Exception { 152 initServletWithControllers(RelativePathUriTemplateController.class); 153 154 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42/bookings/21"); 155 MockHttpServletResponse response = new MockHttpServletResponse(); 156 getServlet().service(request, response); 157 assertEquals("test-42-21", response.getContentAsString()); 158 159 request = new MockHttpServletRequest("GET", "/hotels/42/bookings/21.html"); 160 response = new MockHttpServletResponse(); 161 getServlet().service(request, response); 162 assertEquals("test-42-21", response.getContentAsString()); 163 } 164 165 @Test extension()166 public void extension() throws Exception { 167 initServletWithControllers(SimpleUriTemplateController.class); 168 169 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/42.xml"); 170 MockHttpServletResponse response = new MockHttpServletResponse(); 171 getServlet().service(request, response); 172 assertEquals("test-42", response.getContentAsString()); 173 174 } 175 176 @Test typeConversionError()177 public void typeConversionError() throws Exception { 178 initServletWithControllers(SimpleUriTemplateController.class); 179 180 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo.xml"); 181 MockHttpServletResponse response = new MockHttpServletResponse(); 182 getServlet().service(request, response); 183 assertEquals("Invalid response status code", HttpServletResponse.SC_BAD_REQUEST, response.getStatus()); 184 } 185 186 @Test explicitSubPath()187 public void explicitSubPath() throws Exception { 188 initServletWithControllers(ExplicitSubPathController.class); 189 190 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42"); 191 MockHttpServletResponse response = new MockHttpServletResponse(); 192 getServlet().service(request, response); 193 assertEquals("test-42", response.getContentAsString()); 194 } 195 196 @Test implicitSubPath()197 public void implicitSubPath() throws Exception { 198 initServletWithControllers(ImplicitSubPathController.class); 199 200 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42"); 201 MockHttpServletResponse response = new MockHttpServletResponse(); 202 getServlet().service(request, response); 203 assertEquals("test-42", response.getContentAsString()); 204 } 205 206 @Test crud()207 public void crud() throws Exception { 208 initServletWithControllers(CrudController.class); 209 210 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels"); 211 MockHttpServletResponse response = new MockHttpServletResponse(); 212 getServlet().service(request, response); 213 assertEquals("list", response.getContentAsString()); 214 215 request = new MockHttpServletRequest("GET", "/hotels/"); 216 response = new MockHttpServletResponse(); 217 getServlet().service(request, response); 218 assertEquals("list", response.getContentAsString()); 219 220 request = new MockHttpServletRequest("POST", "/hotels"); 221 response = new MockHttpServletResponse(); 222 getServlet().service(request, response); 223 assertEquals("create", response.getContentAsString()); 224 225 request = new MockHttpServletRequest("GET", "/hotels/42"); 226 response = new MockHttpServletResponse(); 227 getServlet().service(request, response); 228 assertEquals("show-42", response.getContentAsString()); 229 230 request = new MockHttpServletRequest("GET", "/hotels/42/"); 231 response = new MockHttpServletResponse(); 232 getServlet().service(request, response); 233 assertEquals("show-42", response.getContentAsString()); 234 235 request = new MockHttpServletRequest("PUT", "/hotels/42"); 236 response = new MockHttpServletResponse(); 237 getServlet().service(request, response); 238 assertEquals("createOrUpdate-42", response.getContentAsString()); 239 240 request = new MockHttpServletRequest("DELETE", "/hotels/42"); 241 response = new MockHttpServletResponse(); 242 getServlet().service(request, response); 243 assertEquals("remove-42", response.getContentAsString()); 244 } 245 246 @Test methodNotSupported()247 public void methodNotSupported() throws Exception { 248 initServletWithControllers(MethodNotAllowedController.class); 249 250 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/1"); 251 MockHttpServletResponse response = new MockHttpServletResponse(); 252 getServlet().service(request, response); 253 assertEquals(200, response.getStatus()); 254 255 request = new MockHttpServletRequest("POST", "/hotels/1"); 256 response = new MockHttpServletResponse(); 257 getServlet().service(request, response); 258 assertEquals(405, response.getStatus()); 259 260 request = new MockHttpServletRequest("GET", "/hotels"); 261 response = new MockHttpServletResponse(); 262 getServlet().service(request, response); 263 assertEquals(200, response.getStatus()); 264 265 request = new MockHttpServletRequest("POST", "/hotels"); 266 response = new MockHttpServletResponse(); 267 getServlet().service(request, response); 268 assertEquals(405, response.getStatus()); 269 } 270 271 @Test multiPaths()272 public void multiPaths() throws Exception { 273 initServletWithControllers(MultiPathController.class); 274 275 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/category/page/5"); 276 MockHttpServletResponse response = new MockHttpServletResponse(); 277 getServlet().service(request, response); 278 assertEquals("handle4-page-5", response.getContentAsString()); 279 280 request = new MockHttpServletRequest("GET", "/category/page/5.html"); 281 response = new MockHttpServletResponse(); 282 getServlet().service(request, response); 283 assertEquals("handle4-page-5", response.getContentAsString()); 284 } 285 286 @Test customRegex()287 public void customRegex() throws Exception { 288 initServletWithControllers(CustomRegexController.class); 289 290 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/42"); 291 MockHttpServletResponse response = new MockHttpServletResponse(); 292 getServlet().service(request, response); 293 assertEquals("test-42", response.getContentAsString()); 294 } 295 296 /* 297 * See SPR-6640 298 */ 299 @Test menuTree()300 public void menuTree() throws Exception { 301 initServletWithControllers(MenuTreeController.class); 302 303 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/book/menu/type/M5"); 304 MockHttpServletResponse response = new MockHttpServletResponse(); 305 getServlet().service(request, response); 306 assertEquals("M5", response.getContentAsString()); 307 } 308 309 /* 310 * See SPR-6876 311 */ 312 @Test variableNames()313 public void variableNames() throws Exception { 314 initServletWithControllers(VariableNamesController.class); 315 316 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test/foo"); 317 MockHttpServletResponse response = new MockHttpServletResponse(); 318 getServlet().service(request, response); 319 assertEquals("foo-foo", response.getContentAsString()); 320 321 request = new MockHttpServletRequest("DELETE", "/test/bar"); 322 response = new MockHttpServletResponse(); 323 getServlet().service(request, response); 324 assertEquals("bar-bar", response.getContentAsString()); 325 } 326 327 /* 328 * See SPR-8543 329 */ 330 @Test variableNamesWithUrlExtension()331 public void variableNamesWithUrlExtension() throws Exception { 332 initServletWithControllers(VariableNamesController.class); 333 334 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test/foo.json"); 335 MockHttpServletResponse response = new MockHttpServletResponse(); 336 getServlet().service(request, response); 337 assertEquals("foo-foo", response.getContentAsString()); 338 } 339 340 /* 341 * See SPR-6978 342 */ 343 @Test doIt()344 public void doIt() throws Exception { 345 initServletWithControllers(Spr6978Controller.class); 346 347 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo/100"); 348 MockHttpServletResponse response = new MockHttpServletResponse(); 349 getServlet().service(request, response); 350 assertEquals("loadEntity:foo:100", response.getContentAsString()); 351 352 request = new MockHttpServletRequest("POST", "/foo/100"); 353 response = new MockHttpServletResponse(); 354 getServlet().service(request, response); 355 assertEquals("publish:foo:100", response.getContentAsString()); 356 357 request = new MockHttpServletRequest("GET", "/module/100"); 358 response = new MockHttpServletResponse(); 359 getServlet().service(request, response); 360 assertEquals("loadModule:100", response.getContentAsString()); 361 362 request = new MockHttpServletRequest("POST", "/module/100"); 363 response = new MockHttpServletResponse(); 364 getServlet().service(request, response); 365 assertEquals("publish:module:100", response.getContentAsString()); 366 367 } 368 369 370 /* 371 * Controllers 372 */ 373 374 @Controller 375 public static class SimpleUriTemplateController { 376 377 @RequestMapping("/{root}") handle(@athVariableR) int root, Writer writer)378 public void handle(@PathVariable("root") int root, Writer writer) throws IOException { 379 assertEquals("Invalid path variable value", 42, root); 380 writer.write("test-" + root); 381 } 382 383 } 384 385 @Controller 386 public static class MultipleUriTemplateController { 387 388 @RequestMapping("/hotels/{hotel}/bookings/{booking}-{other}") handle(@athVariableR) String hotel, @PathVariable int booking, @PathVariable String other, Writer writer)389 public void handle(@PathVariable("hotel") String hotel, 390 @PathVariable int booking, 391 @PathVariable String other, 392 Writer writer) throws IOException { 393 assertEquals("Invalid path variable value", "42", hotel); 394 assertEquals("Invalid path variable value", 21, booking); 395 writer.write("test-" + hotel + "-" + booking + "-" + other); 396 } 397 398 } 399 400 @Controller 401 public static class ViewRenderingController { 402 403 @RequestMapping("/hotels/{hotel}/bookings/{booking}-{other}") handle(@athVariableR) String hotel, @PathVariable int booking, @PathVariable String other)404 public void handle(@PathVariable("hotel") String hotel, @PathVariable int booking, @PathVariable String other) { 405 assertEquals("Invalid path variable value", "42", hotel); 406 assertEquals("Invalid path variable value", 21, booking); 407 } 408 409 } 410 411 @Controller 412 public static class BindingUriTemplateController { 413 414 @InitBinder initBinder(WebDataBinder binder, @PathVariable(R) String hotel)415 public void initBinder(WebDataBinder binder, @PathVariable("hotel") String hotel) { 416 assertEquals("Invalid path variable value", "42", hotel); 417 binder.initBeanPropertyAccess(); 418 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); 419 dateFormat.setLenient(false); 420 binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false)); 421 } 422 423 @RequestMapping("/hotels/{hotel}/dates/{date}") handle(@athVariableR) String hotel, @PathVariable Date date, Writer writer)424 public void handle(@PathVariable("hotel") String hotel, @PathVariable Date date, Writer writer) 425 throws IOException { 426 assertEquals("Invalid path variable value", "42", hotel); 427 assertEquals("Invalid path variable value", new GregorianCalendar(2008, 10, 18).getTime(), date); 428 writer.write("test-" + hotel); 429 } 430 } 431 432 @Controller 433 public static class NonBindingUriTemplateController { 434 435 @RequestMapping("/hotels/{hotel}/dates/{date}") handle(@athVariableR) String hotel, @PathVariable Date date, Writer writer)436 public void handle(@PathVariable("hotel") String hotel, @PathVariable Date date, Writer writer) 437 throws IOException { 438 } 439 440 } 441 442 @Controller 443 @RequestMapping("/hotels/{hotel}") 444 public static class RelativePathUriTemplateController { 445 446 @RequestMapping("bookings/{booking}") handle(@athVariableR) String hotel, @PathVariable int booking, Writer writer)447 public void handle(@PathVariable("hotel") String hotel, @PathVariable int booking, Writer writer) 448 throws IOException { 449 assertEquals("Invalid path variable value", "42", hotel); 450 assertEquals("Invalid path variable value", 21, booking); 451 writer.write("test-" + hotel + "-" + booking); 452 } 453 454 } 455 456 @Controller 457 @RequestMapping("/hotels") 458 public static class AmbiguousUriTemplateController { 459 460 @RequestMapping("/{hotel}") handleVars(@athVariableR) String hotel, Writer writer)461 public void handleVars(@PathVariable("hotel") String hotel, Writer writer) throws IOException { 462 assertEquals("Invalid path variable value", "42", hotel); 463 writer.write("variables"); 464 } 465 466 @RequestMapping("/new") handleSpecific(Writer writer)467 public void handleSpecific(Writer writer) throws IOException { 468 writer.write("specific"); 469 } 470 471 @RequestMapping("/*") handleWildCard(Writer writer)472 public void handleWildCard(Writer writer) throws IOException { 473 writer.write("wildcard"); 474 } 475 476 } 477 478 @Controller 479 @RequestMapping("/hotels/*") 480 public static class ExplicitSubPathController { 481 482 @RequestMapping("{hotel}") handleHotel(@athVariable String hotel, Writer writer)483 public void handleHotel(@PathVariable String hotel, Writer writer) throws IOException { 484 writer.write("test-" + hotel); 485 } 486 487 } 488 489 @Controller 490 @RequestMapping("hotels") 491 public static class ImplicitSubPathController { 492 493 @RequestMapping("{hotel}") handleHotel(@athVariable String hotel, Writer writer)494 public void handleHotel(@PathVariable String hotel, Writer writer) throws IOException { 495 writer.write("test-" + hotel); 496 } 497 } 498 499 @Controller 500 public static class CustomRegexController { 501 502 @RequestMapping("/{root:\\d+}") handle(@athVariableR) int root, Writer writer)503 public void handle(@PathVariable("root") int root, Writer writer) throws IOException { 504 assertEquals("Invalid path variable value", 42, root); 505 writer.write("test-" + root); 506 } 507 508 } 509 510 @Controller 511 public static class DoubleController { 512 513 @RequestMapping("/lat/{latitude}/long/{longitude}") testLatLong(@athVariable Double latitude, @PathVariable Double longitude, Writer writer)514 public void testLatLong(@PathVariable Double latitude, @PathVariable Double longitude, Writer writer) 515 throws IOException { 516 writer.write("latitude-" + latitude + "-longitude-" + longitude); 517 } 518 519 } 520 521 522 @Controller 523 @RequestMapping("hotels") 524 public static class CrudController { 525 526 @RequestMapping(method = RequestMethod.GET) list(Writer writer)527 public void list(Writer writer) throws IOException { 528 writer.write("list"); 529 } 530 531 @RequestMapping(method = RequestMethod.POST) create(Writer writer)532 public void create(Writer writer) throws IOException { 533 writer.write("create"); 534 } 535 536 @RequestMapping(value = "/{hotel}", method = RequestMethod.GET) show(@athVariable String hotel, Writer writer)537 public void show(@PathVariable String hotel, Writer writer) throws IOException { 538 writer.write("show-" + hotel); 539 } 540 541 @RequestMapping(value = "{hotel}", method = RequestMethod.PUT) createOrUpdate(@athVariable String hotel, Writer writer)542 public void createOrUpdate(@PathVariable String hotel, Writer writer) throws IOException { 543 writer.write("createOrUpdate-" + hotel); 544 } 545 546 @RequestMapping(value = "{hotel}", method = RequestMethod.DELETE) remove(@athVariable String hotel, Writer writer)547 public void remove(@PathVariable String hotel, Writer writer) throws IOException { 548 writer.write("remove-" + hotel); 549 } 550 551 } 552 553 @Controller 554 @RequestMapping("/hotels") 555 public static class MethodNotAllowedController { 556 557 @RequestMapping(method = RequestMethod.GET) list(Writer writer)558 public void list(Writer writer) { 559 } 560 561 @RequestMapping(method = RequestMethod.GET, value = "{hotelId}") show(@athVariable long hotelId, Writer writer)562 public void show(@PathVariable long hotelId, Writer writer) { 563 } 564 565 @RequestMapping(method = RequestMethod.PUT, value = "{hotelId}") createOrUpdate(@athVariable long hotelId, Writer writer)566 public void createOrUpdate(@PathVariable long hotelId, Writer writer) { 567 } 568 569 @RequestMapping(method = RequestMethod.DELETE, value = "/{hotelId}") remove(@athVariable long hotelId, Writer writer)570 public void remove(@PathVariable long hotelId, Writer writer) { 571 } 572 } 573 574 @Controller 575 @RequestMapping("/category") 576 public static class MultiPathController { 577 578 @RequestMapping(value = {"/{category}/page/{page}", "/**/{category}/page/{page}"}) category(@athVariable String category, @PathVariable int page, Writer writer)579 public void category(@PathVariable String category, @PathVariable int page, Writer writer) throws IOException { 580 writer.write("handle1-"); 581 writer.write("category-" + category); 582 writer.write("page-" + page); 583 } 584 585 @RequestMapping(value = {"/{category}", "/**/{category}"}) category(@athVariable String category, Writer writer)586 public void category(@PathVariable String category, Writer writer) throws IOException { 587 writer.write("handle2-"); 588 writer.write("category-" + category); 589 } 590 591 @RequestMapping(value = {""}) category(Writer writer)592 public void category(Writer writer) throws IOException { 593 writer.write("handle3"); 594 } 595 596 @RequestMapping(value = {"/page/{page}"}) category(@athVariable int page, Writer writer)597 public void category(@PathVariable int page, Writer writer) throws IOException { 598 writer.write("handle4-"); 599 writer.write("page-" + page); 600 } 601 602 } 603 604 @Controller 605 @RequestMapping("/*/menu/**") 606 public static class MenuTreeController { 607 608 @RequestMapping("type/{var}") getFirstLevelFunctionNodes(@athVariableR) String var, Writer writer)609 public void getFirstLevelFunctionNodes(@PathVariable("var") String var, Writer writer) throws IOException { 610 writer.write(var); 611 } 612 } 613 614 @Controller 615 @RequestMapping("/test") 616 public static class VariableNamesController { 617 618 @RequestMapping(value = "/{foo}", method=RequestMethod.GET) foo(@athVariable String foo, Writer writer)619 public void foo(@PathVariable String foo, Writer writer) throws IOException { 620 writer.write("foo-" + foo); 621 } 622 623 @RequestMapping(value = "/{bar}", method=RequestMethod.DELETE) bar(@athVariable String bar, Writer writer)624 public void bar(@PathVariable String bar, Writer writer) throws IOException { 625 writer.write("bar-" + bar); 626 } 627 } 628 629 @Controller 630 public static class Spr6978Controller { 631 632 @RequestMapping(value = "/{type}/{id}", method = RequestMethod.GET) loadEntity(@athVariable final String type, @PathVariable final long id, Writer writer)633 public void loadEntity(@PathVariable final String type, @PathVariable final long id, Writer writer) 634 throws IOException { 635 writer.write("loadEntity:" + type + ":" + id); 636 } 637 638 @RequestMapping(value = "/module/{id}", method = RequestMethod.GET) loadModule(@athVariable final long id, Writer writer)639 public void loadModule(@PathVariable final long id, Writer writer) throws IOException { 640 writer.write("loadModule:" + id); 641 } 642 643 @RequestMapping(value = "/{type}/{id}", method = RequestMethod.POST) publish(@athVariable final String type, @PathVariable final long id, Writer writer)644 public void publish(@PathVariable final String type, @PathVariable final long id, Writer writer) 645 throws IOException { 646 writer.write("publish:" + type + ":" + id); 647 } 648 } 649 650 public static class ModelValidatingViewResolver implements ViewResolver { 651 652 private final Map<String, Object> attrsToValidate; 653 654 int validatedAttrCount; 655 ModelValidatingViewResolver(Map<String, Object> attrsToValidate)656 public ModelValidatingViewResolver(Map<String, Object> attrsToValidate) { 657 this.attrsToValidate = attrsToValidate; 658 } 659 resolveViewName(final String viewName, Locale locale)660 public View resolveViewName(final String viewName, Locale locale) throws Exception { 661 return new AbstractView () { 662 public String getContentType() { 663 return null; 664 } 665 @Override 666 protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, 667 HttpServletResponse response) throws Exception { 668 for (String key : attrsToValidate.keySet()) { 669 assertTrue("Model should contain attribute named " + key, model.containsKey(key)); 670 assertEquals(attrsToValidate.get(key), model.get(key)); 671 validatedAttrCount++; 672 } 673 } 674 }; 675 } 676 } 677 678 // @Ignore("ControllerClassNameHandlerMapping") 679 // public void controllerClassName() throws Exception { 680 681 // @Ignore("useDefaultSuffixPattern property not supported") 682 // public void doubles() throws Exception { 683 684 // @Ignore("useDefaultSuffixPattern property not supported") 685 // public void noDefaultSuffixPattern() throws Exception { 686 687 } 688