1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.web.servlet.mvc.annotation;
18
19 import java.beans.PropertyEditorSupport;
20 import java.io.IOException;
21 import java.io.Serializable;
22 import java.io.UnsupportedEncodingException;
23 import java.io.Writer;
24 import java.lang.annotation.ElementType;
25 import java.lang.annotation.Retention;
26 import java.lang.annotation.RetentionPolicy;
27 import java.lang.annotation.Target;
28 import java.lang.reflect.Method;
29 import java.security.Principal;
30 import java.text.SimpleDateFormat;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.Calendar;
34 import java.util.Collection;
35 import java.util.Collections;
36 import java.util.Date;
37 import java.util.GregorianCalendar;
38 import java.util.HashSet;
39 import java.util.Iterator;
40 import java.util.LinkedHashSet;
41 import java.util.LinkedList;
42 import java.util.List;
43 import java.util.Locale;
44 import java.util.Map;
45 import java.util.Set;
46 import javax.servlet.ServletConfig;
47 import javax.servlet.ServletContext;
48 import javax.servlet.ServletException;
49 import javax.servlet.http.Cookie;
50 import javax.servlet.http.HttpServletRequest;
51 import javax.servlet.http.HttpServletResponse;
52 import javax.servlet.http.HttpSession;
53 import javax.validation.constraints.NotNull;
54 import javax.xml.bind.annotation.XmlRootElement;
55
56 import org.junit.Test;
57
58 import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
59 import org.springframework.aop.interceptor.SimpleTraceInterceptor;
60 import org.springframework.aop.support.DefaultPointcutAdvisor;
61 import org.springframework.beans.BeansException;
62 import org.springframework.beans.PropertyEditorRegistrar;
63 import org.springframework.beans.PropertyEditorRegistry;
64 import org.springframework.beans.factory.BeanCreationException;
65 import org.springframework.beans.factory.annotation.Autowired;
66 import org.springframework.beans.factory.annotation.Value;
67 import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
68 import org.springframework.beans.factory.support.RootBeanDefinition;
69 import org.springframework.beans.propertyeditors.CustomDateEditor;
70 import org.springframework.context.annotation.AnnotationConfigUtils;
71 import org.springframework.core.MethodParameter;
72 import org.springframework.core.convert.converter.Converter;
73 import org.springframework.format.support.FormattingConversionServiceFactoryBean;
74 import org.springframework.http.HttpEntity;
75 import org.springframework.http.HttpHeaders;
76 import org.springframework.http.HttpInputMessage;
77 import org.springframework.http.HttpOutputMessage;
78 import org.springframework.http.HttpStatus;
79 import org.springframework.http.MediaType;
80 import org.springframework.http.ResponseEntity;
81 import org.springframework.http.converter.ByteArrayHttpMessageConverter;
82 import org.springframework.http.converter.HttpMessageConverter;
83 import org.springframework.http.converter.HttpMessageNotReadableException;
84 import org.springframework.http.converter.HttpMessageNotWritableException;
85 import org.springframework.http.converter.StringHttpMessageConverter;
86 import org.springframework.http.converter.xml.MarshallingHttpMessageConverter;
87 import org.springframework.mock.web.test.MockHttpServletRequest;
88 import org.springframework.mock.web.test.MockHttpServletResponse;
89 import org.springframework.mock.web.test.MockMultipartFile;
90 import org.springframework.mock.web.test.MockMultipartHttpServletRequest;
91 import org.springframework.mock.web.test.MockServletConfig;
92 import org.springframework.mock.web.test.MockServletContext;
93 import org.springframework.oxm.jaxb.Jaxb2Marshaller;
94 import org.springframework.stereotype.Controller;
95 import org.springframework.tests.sample.beans.DerivedTestBean;
96 import org.springframework.tests.sample.beans.GenericBean;
97 import org.springframework.tests.sample.beans.ITestBean;
98 import org.springframework.tests.sample.beans.TestBean;
99 import org.springframework.ui.ExtendedModelMap;
100 import org.springframework.ui.Model;
101 import org.springframework.ui.ModelMap;
102 import org.springframework.util.MultiValueMap;
103 import org.springframework.util.SerializationTestUtils;
104 import org.springframework.util.StringUtils;
105 import org.springframework.validation.BindingResult;
106 import org.springframework.validation.Errors;
107 import org.springframework.validation.FieldError;
108 import org.springframework.validation.annotation.Validated;
109 import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
110 import org.springframework.web.bind.WebDataBinder;
111 import org.springframework.web.bind.annotation.CookieValue;
112 import org.springframework.web.bind.annotation.ExceptionHandler;
113 import org.springframework.web.bind.annotation.InitBinder;
114 import org.springframework.web.bind.annotation.ModelAttribute;
115 import org.springframework.web.bind.annotation.RequestBody;
116 import org.springframework.web.bind.annotation.RequestHeader;
117 import org.springframework.web.bind.annotation.RequestMapping;
118 import org.springframework.web.bind.annotation.RequestMethod;
119 import org.springframework.web.bind.annotation.RequestParam;
120 import org.springframework.web.bind.annotation.ResponseBody;
121 import org.springframework.web.bind.annotation.ResponseStatus;
122 import org.springframework.web.bind.annotation.SessionAttributes;
123 import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
124 import org.springframework.web.bind.support.WebArgumentResolver;
125 import org.springframework.web.bind.support.WebBindingInitializer;
126 import org.springframework.web.context.WebApplicationContext;
127 import org.springframework.web.context.request.NativeWebRequest;
128 import org.springframework.web.context.request.WebRequest;
129 import org.springframework.web.context.support.GenericWebApplicationContext;
130 import org.springframework.web.multipart.support.StringMultipartFileEditor;
131 import org.springframework.web.servlet.DispatcherServlet;
132 import org.springframework.web.servlet.ModelAndView;
133 import org.springframework.web.servlet.View;
134 import org.springframework.web.servlet.ViewResolver;
135 import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
136 import org.springframework.web.servlet.mvc.AbstractController;
137 import org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver;
138 import org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping;
139 import org.springframework.web.servlet.mvc.support.RedirectAttributes;
140 import org.springframework.web.servlet.view.InternalResourceViewResolver;
141 import org.springframework.web.util.NestedServletException;
142
143 import static org.hamcrest.Matchers.*;
144 import static org.junit.Assert.*;
145
146
147
148
149
150
151
152 @SuppressWarnings("deprecation")
153 public class ServletAnnotationControllerTests {
154
155 private DispatcherServlet servlet;
156
157 @Test
158 public void standardHandleMethod() throws Exception {
159 initServlet(MyController.class);
160
161 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
162 MockHttpServletResponse response = new MockHttpServletResponse();
163 servlet.service(request, response);
164 assertEquals("test", response.getContentAsString());
165 }
166
167 @Test
168 @SuppressWarnings("serial")
169 public void emptyRequestMapping() throws Exception {
170 servlet = new DispatcherServlet() {
171 @Override
172 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
173 GenericWebApplicationContext wac = new GenericWebApplicationContext();
174 wac.registerBeanDefinition("controller", new RootBeanDefinition(ControllerWithEmptyMapping.class));
175 RootBeanDefinition mbd = new RootBeanDefinition(ControllerClassNameHandlerMapping.class);
176 mbd.getPropertyValues().add("excludedPackages", null);
177 mbd.getPropertyValues().add("order", 0);
178 wac.registerBeanDefinition("mapping", mbd);
179 wac.registerBeanDefinition("mapping2", new RootBeanDefinition(DefaultAnnotationHandlerMapping.class));
180 wac.refresh();
181 return wac;
182 }
183 };
184 servlet.init(new MockServletConfig());
185
186 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/servletannotationcontrollertests.controllerwithemptymapping");
187 MockHttpServletResponse response = new MockHttpServletResponse();
188 servlet.service(request, response);
189 assertEquals("test", response.getContentAsString());
190 }
191
192 @Test
193 @SuppressWarnings("serial")
194 public void emptyValueMapping() throws Exception {
195 servlet = new DispatcherServlet() {
196 @Override
197 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
198 GenericWebApplicationContext wac = new GenericWebApplicationContext();
199 wac.registerBeanDefinition("controller", new RootBeanDefinition(ControllerWithEmptyValueMapping.class));
200 wac.refresh();
201 return wac;
202 }
203 };
204 servlet.init(new MockServletConfig());
205
206 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo");
207 request.setContextPath("/foo");
208 request.setServletPath("");
209 MockHttpServletResponse response = new MockHttpServletResponse();
210 servlet.service(request, response);
211 assertEquals("test", response.getContentAsString());
212 }
213
214 @Test
215 public void customAnnotationController() throws Exception {
216 initServlet(CustomAnnotationController.class);
217
218 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
219 MockHttpServletResponse response = new MockHttpServletResponse();
220 servlet.service(request, response);
221 assertEquals("Invalid response status code", HttpServletResponse.SC_OK, response.getStatus());
222 }
223
224 @Test
225 public void requiredParamMissing() throws Exception {
226 initServlet(RequiredParamController.class);
227
228 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
229 MockHttpServletResponse response = new MockHttpServletResponse();
230 servlet.service(request, response);
231 assertEquals("Invalid response status code", HttpServletResponse.SC_BAD_REQUEST, response.getStatus());
232 assertTrue(servlet.getWebApplicationContext().isSingleton("controller"));
233 }
234
235 @Test
236 public void typeConversionError() throws Exception {
237 initServlet(RequiredParamController.class);
238
239 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
240 request.addParameter("id", "foo");
241 MockHttpServletResponse response = new MockHttpServletResponse();
242 servlet.service(request, response);
243 assertEquals("Invalid response status code", HttpServletResponse.SC_BAD_REQUEST, response.getStatus());
244 }
245
246 @Test
247 public void optionalParamPresent() throws Exception {
248 initServlet(OptionalParamController.class);
249
250 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
251 request.addParameter("id", "val");
252 request.addParameter("flag", "true");
253 request.addHeader("header", "otherVal");
254 MockHttpServletResponse response = new MockHttpServletResponse();
255 servlet.service(request, response);
256 assertEquals("val-true-otherVal", response.getContentAsString());
257 }
258
259 @Test
260 public void optionalParamMissing() throws Exception {
261 initServlet(OptionalParamController.class);
262
263 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
264 MockHttpServletResponse response = new MockHttpServletResponse();
265 servlet.service(request, response);
266 assertEquals("null-false-null", response.getContentAsString());
267 }
268
269 @Test
270 public void defaultParameters() throws Exception {
271 initServlet(DefaultValueParamController.class);
272
273 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
274 MockHttpServletResponse response = new MockHttpServletResponse();
275 servlet.service(request, response);
276 assertEquals("foo--bar", response.getContentAsString());
277 }
278
279 @Test
280 @SuppressWarnings("serial")
281 public void defaultExpressionParameters() throws Exception {
282 servlet = new DispatcherServlet() {
283 @Override
284 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
285 GenericWebApplicationContext wac = new GenericWebApplicationContext();
286 wac.registerBeanDefinition("controller", new RootBeanDefinition(DefaultExpressionValueParamController.class));
287 RootBeanDefinition ppc = new RootBeanDefinition(PropertyPlaceholderConfigurer.class);
288 ppc.getPropertyValues().add("properties", "myKey=foo");
289 wac.registerBeanDefinition("ppc", ppc);
290 wac.refresh();
291 return wac;
292 }
293 };
294 servlet.init(new MockServletConfig());
295
296 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myApp/myPath.do");
297 request.setContextPath("/myApp");
298 MockHttpServletResponse response = new MockHttpServletResponse();
299 System.setProperty("myHeader", "bar");
300 try {
301 servlet.service(request, response);
302 }
303 finally {
304 System.clearProperty("myHeader");
305 }
306 assertEquals("foo-bar-/myApp", response.getContentAsString());
307 }
308
309 @Test
310 @SuppressWarnings("serial")
311 public void typeNestedSetBinding() throws Exception {
312 servlet = new DispatcherServlet() {
313 @Override
314 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
315 GenericWebApplicationContext wac = new GenericWebApplicationContext();
316 wac.registerBeanDefinition("controller", new RootBeanDefinition(NestedSetController.class));
317 RootBeanDefinition csDef = new RootBeanDefinition(FormattingConversionServiceFactoryBean.class);
318 csDef.getPropertyValues().add("converters", new TestBeanConverter());
319 RootBeanDefinition wbiDef = new RootBeanDefinition(ConfigurableWebBindingInitializer.class);
320 wbiDef.getPropertyValues().add("conversionService", csDef);
321 RootBeanDefinition adapterDef = new RootBeanDefinition(AnnotationMethodHandlerAdapter.class);
322 adapterDef.getPropertyValues().add("webBindingInitializer", wbiDef);
323 wac.registerBeanDefinition("handlerAdapter", adapterDef);
324 wac.refresh();
325 return wac;
326 }
327 };
328 servlet.init(new MockServletConfig());
329
330 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
331 request.addParameter("testBeanSet", new String[] {"1", "2"});
332 MockHttpServletResponse response = new MockHttpServletResponse();
333 servlet.service(request, response);
334 assertEquals("[1, 2]-org.springframework.tests.sample.beans.TestBean", response.getContentAsString());
335 }
336
337 @Test
338 public void methodNotAllowed() throws Exception {
339 initServlet(MethodNotAllowedController.class);
340
341 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
342 MockHttpServletResponse response = new MockHttpServletResponse();
343 servlet.service(request, response);
344 assertEquals("Invalid response status", HttpServletResponse.SC_METHOD_NOT_ALLOWED, response.getStatus());
345 String allowHeader = response.getHeader("Allow");
346 assertNotNull("No Allow header", allowHeader);
347 Set<String> allowedMethods = new HashSet<String>();
348 allowedMethods.addAll(Arrays.asList(StringUtils.delimitedListToStringArray(allowHeader, ", ")));
349 assertEquals("Invalid amount of supported methods", 6, allowedMethods.size());
350 assertTrue("PUT not allowed", allowedMethods.contains("PUT"));
351 assertTrue("DELETE not allowed", allowedMethods.contains("DELETE"));
352 assertTrue("HEAD not allowed", allowedMethods.contains("HEAD"));
353 assertTrue("TRACE not allowed", allowedMethods.contains("TRACE"));
354 assertTrue("OPTIONS not allowed", allowedMethods.contains("OPTIONS"));
355 assertTrue("POST not allowed", allowedMethods.contains("POST"));
356 }
357
358 @Test
359 @SuppressWarnings("serial")
360 public void proxiedStandardHandleMethod() throws Exception {
361 DispatcherServlet servlet = new DispatcherServlet() {
362 @Override
363 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
364 GenericWebApplicationContext wac = new GenericWebApplicationContext();
365 wac.registerBeanDefinition("controller", new RootBeanDefinition(MyController.class));
366 DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
367 autoProxyCreator.setBeanFactory(wac.getBeanFactory());
368 wac.getBeanFactory().addBeanPostProcessor(autoProxyCreator);
369 wac.getBeanFactory().registerSingleton("advisor", new DefaultPointcutAdvisor(new SimpleTraceInterceptor()));
370 wac.refresh();
371 return wac;
372 }
373 };
374 servlet.init(new MockServletConfig());
375
376 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
377 MockHttpServletResponse response = new MockHttpServletResponse();
378 servlet.service(request, response);
379 assertEquals("test", response.getContentAsString());
380 }
381
382 @Test
383 public void emptyParameterListHandleMethod() throws Exception {
384 @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
385 @Override
386 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
387 GenericWebApplicationContext wac = new GenericWebApplicationContext();
388 wac.registerBeanDefinition("controller",
389 new RootBeanDefinition(EmptyParameterListHandlerMethodController.class));
390 RootBeanDefinition vrDef = new RootBeanDefinition(InternalResourceViewResolver.class);
391 vrDef.getPropertyValues().add("suffix", ".jsp");
392 wac.registerBeanDefinition("viewResolver", vrDef);
393 wac.refresh();
394 return wac;
395 }
396 };
397 servlet.init(new MockServletConfig());
398
399 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/emptyParameterListHandler");
400 MockHttpServletResponse response = new MockHttpServletResponse();
401
402 EmptyParameterListHandlerMethodController.called = false;
403 servlet.service(request, response);
404 assertTrue(EmptyParameterListHandlerMethodController.called);
405 assertEquals("", response.getContentAsString());
406 }
407
408 @Test
409 public void sessionAttributeExposure() throws Exception {
410 @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
411 @Override
412 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
413 GenericWebApplicationContext wac = new GenericWebApplicationContext();
414 wac.registerBeanDefinition("controller", new RootBeanDefinition(MySessionAttributesController.class));
415 wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(ModelExposingViewResolver.class));
416 wac.refresh();
417 return wac;
418 }
419 };
420 servlet.init(new MockServletConfig());
421
422 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPage");
423 MockHttpServletResponse response = new MockHttpServletResponse();
424 servlet.service(request, response);
425 assertEquals("page1", request.getAttribute("viewName"));
426 HttpSession session = request.getSession();
427 assertTrue(session.getAttribute("object1") != null);
428 assertTrue(session.getAttribute("object2") != null);
429 assertTrue(((Map) session.getAttribute("model")).containsKey("object1"));
430 assertTrue(((Map) session.getAttribute("model")).containsKey("object2"));
431
432 request = new MockHttpServletRequest("POST", "/myPage");
433 request.setSession(session);
434 response = new MockHttpServletResponse();
435 servlet.service(request, response);
436 assertEquals("page2", request.getAttribute("viewName"));
437 assertTrue(session.getAttribute("object1") != null);
438 assertTrue(session.getAttribute("object2") != null);
439 assertTrue(((Map) session.getAttribute("model")).containsKey("object1"));
440 assertTrue(((Map) session.getAttribute("model")).containsKey("object2"));
441 }
442
443 @Test
444 public void sessionAttributeExposureWithInterface() throws Exception {
445 @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
446 @Override
447 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
448 GenericWebApplicationContext wac = new GenericWebApplicationContext();
449 wac.registerBeanDefinition("controller", new RootBeanDefinition(MySessionAttributesControllerImpl.class));
450 wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(ModelExposingViewResolver.class));
451 DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
452 autoProxyCreator.setBeanFactory(wac.getBeanFactory());
453 wac.getBeanFactory().addBeanPostProcessor(autoProxyCreator);
454 wac.getBeanFactory().registerSingleton("advisor", new DefaultPointcutAdvisor(new SimpleTraceInterceptor()));
455 wac.refresh();
456 return wac;
457 }
458 };
459 servlet.init(new MockServletConfig());
460
461 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPage");
462 MockHttpServletResponse response = new MockHttpServletResponse();
463 servlet.service(request, response);
464 assertEquals("page1", request.getAttribute("viewName"));
465 HttpSession session = request.getSession();
466 assertTrue(session.getAttribute("object1") != null);
467 assertTrue(session.getAttribute("object2") != null);
468 assertTrue(((Map) session.getAttribute("model")).containsKey("object1"));
469 assertTrue(((Map) session.getAttribute("model")).containsKey("object2"));
470
471 request = new MockHttpServletRequest("POST", "/myPage");
472 request.setSession(session);
473 response = new MockHttpServletResponse();
474 servlet.service(request, response);
475 assertEquals("page2", request.getAttribute("viewName"));
476 assertTrue(session.getAttribute("object1") != null);
477 assertTrue(session.getAttribute("object2") != null);
478 assertTrue(((Map) session.getAttribute("model")).containsKey("object1"));
479 assertTrue(((Map) session.getAttribute("model")).containsKey("object2"));
480 }
481
482 @Test
483 public void parameterizedAnnotatedInterface() throws Exception {
484 @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
485 @Override
486 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
487 GenericWebApplicationContext wac = new GenericWebApplicationContext();
488 wac.registerBeanDefinition("controller", new RootBeanDefinition(MyParameterizedControllerImpl.class));
489 wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(ModelExposingViewResolver.class));
490 wac.refresh();
491 return wac;
492 }
493 };
494 servlet.init(new MockServletConfig());
495
496 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPage");
497 MockHttpServletResponse response = new MockHttpServletResponse();
498 servlet.service(request, response);
499 assertEquals("page1", request.getAttribute("viewName"));
500 HttpSession session = request.getSession();
501 assertTrue(session.getAttribute("object1") != null);
502 assertTrue(session.getAttribute("object2") != null);
503 assertTrue(((Map) session.getAttribute("model")).containsKey("object1"));
504 assertTrue(((Map) session.getAttribute("model")).containsKey("object2"));
505 assertTrue(((Map) session.getAttribute("model")).containsKey("testBeanList"));
506
507 request = new MockHttpServletRequest("POST", "/myPage");
508 request.setSession(session);
509 response = new MockHttpServletResponse();
510 servlet.service(request, response);
511 assertEquals("page2", request.getAttribute("viewName"));
512 assertTrue(session.getAttribute("object1") != null);
513 assertTrue(session.getAttribute("object2") != null);
514 assertTrue(((Map) session.getAttribute("model")).containsKey("object1"));
515 assertTrue(((Map) session.getAttribute("model")).containsKey("object2"));
516 assertTrue(((Map) session.getAttribute("model")).containsKey("testBeanList"));
517 }
518
519 @Test
520 public void parameterizedAnnotatedInterfaceWithOverriddenMappingsInImpl() throws Exception {
521 @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
522 @Override
523 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
524 GenericWebApplicationContext wac = new GenericWebApplicationContext();
525 wac.registerBeanDefinition("controller",
526 new RootBeanDefinition(MyParameterizedControllerImplWithOverriddenMappings.class));
527 wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(ModelExposingViewResolver.class));
528 wac.refresh();
529 return wac;
530 }
531 };
532 servlet.init(new MockServletConfig());
533
534 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPage");
535 MockHttpServletResponse response = new MockHttpServletResponse();
536 servlet.service(request, response);
537 assertEquals("page1", request.getAttribute("viewName"));
538 HttpSession session = request.getSession();
539 assertTrue(session.getAttribute("object1") != null);
540 assertTrue(session.getAttribute("object2") != null);
541 assertTrue(((Map) session.getAttribute("model")).containsKey("object1"));
542 assertTrue(((Map) session.getAttribute("model")).containsKey("object2"));
543 assertTrue(((Map) session.getAttribute("model")).containsKey("testBeanList"));
544
545 request = new MockHttpServletRequest("POST", "/myPage");
546 request.setSession(session);
547 response = new MockHttpServletResponse();
548 servlet.service(request, response);
549 assertEquals("page2", request.getAttribute("viewName"));
550 assertTrue(session.getAttribute("object1") != null);
551 assertTrue(session.getAttribute("object2") != null);
552 assertTrue(((Map) session.getAttribute("model")).containsKey("object1"));
553 assertTrue(((Map) session.getAttribute("model")).containsKey("object2"));
554 assertTrue(((Map) session.getAttribute("model")).containsKey("testBeanList"));
555 }
556
557 @Test
558 public void adaptedHandleMethods() throws Exception {
559 doTestAdaptedHandleMethods(MyAdaptedController.class);
560 }
561
562 @Test
563 public void adaptedHandleMethods2() throws Exception {
564 doTestAdaptedHandleMethods(MyAdaptedController2.class);
565 }
566
567 @Test
568 public void adaptedHandleMethods3() throws Exception {
569 doTestAdaptedHandleMethods(MyAdaptedController3.class);
570 }
571
572 @SuppressWarnings("serial")
573 private void initServlet(final Class<?> controllerClass) throws ServletException {
574 servlet = new DispatcherServlet() {
575 @Override
576 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
577 GenericWebApplicationContext wac = new GenericWebApplicationContext();
578 wac.registerBeanDefinition("controller", new RootBeanDefinition(controllerClass));
579 wac.refresh();
580 return wac;
581 }
582 };
583 servlet.init(new MockServletConfig());
584 }
585
586 private void doTestAdaptedHandleMethods(final Class<?> controllerClass) throws Exception {
587 initServlet(controllerClass);
588
589 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath1.do");
590 MockHttpServletResponse response = new MockHttpServletResponse();
591 request.addParameter("param1", "value1");
592 request.addParameter("param2", "2");
593 servlet.service(request, response);
594 assertEquals("test", response.getContentAsString());
595
596 request = new MockHttpServletRequest("GET", "/myPath2.do");
597 request.addParameter("param1", "value1");
598 request.addParameter("param2", "2");
599 request.addHeader("header1", "10");
600 request.setCookies(new Cookie("cookie1", "3"));
601 response = new MockHttpServletResponse();
602 servlet.service(request, response);
603 assertEquals("test-value1-2-10-3", response.getContentAsString());
604
605 request = new MockHttpServletRequest("GET", "/myPath3.do");
606 request.addParameter("param1", "value1");
607 request.addParameter("param2", "2");
608 request.addParameter("name", "name1");
609 request.addParameter("age", "2");
610 response = new MockHttpServletResponse();
611 servlet.service(request, response);
612 assertEquals("test-name1-2", response.getContentAsString());
613
614 request = new MockHttpServletRequest("GET", "/myPath4.do");
615 request.addParameter("param1", "value1");
616 request.addParameter("param2", "2");
617 request.addParameter("name", "name1");
618 request.addParameter("age", "value2");
619 response = new MockHttpServletResponse();
620 servlet.service(request, response);
621 assertEquals("test-name1-typeMismatch", response.getContentAsString());
622 }
623
624 @Test
625 public void formController() throws Exception {
626 @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
627 @Override
628 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
629 GenericWebApplicationContext wac = new GenericWebApplicationContext();
630 wac.registerBeanDefinition("controller", new RootBeanDefinition(MyFormController.class));
631 wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(TestViewResolver.class));
632 wac.refresh();
633 return wac;
634 }
635 };
636 servlet.init(new MockServletConfig());
637
638 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
639 request.addParameter("name", "name1");
640 request.addParameter("age", "value2");
641 MockHttpServletResponse response = new MockHttpServletResponse();
642 servlet.service(request, response);
643 assertEquals("myView-name1-typeMismatch-tb1-myValue", response.getContentAsString());
644 }
645
646 @Test
647 public void modelFormController() throws Exception {
648 @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
649 @Override
650 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
651 GenericWebApplicationContext wac = new GenericWebApplicationContext();
652 wac.registerBeanDefinition("controller", new RootBeanDefinition(MyModelFormController.class));
653 wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(TestViewResolver.class));
654 wac.refresh();
655 return wac;
656 }
657 };
658 servlet.init(new MockServletConfig());
659
660 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
661 request.addParameter("name", "name1");
662 request.addParameter("age", "value2");
663 MockHttpServletResponse response = new MockHttpServletResponse();
664 servlet.service(request, response);
665 assertEquals("myPath-name1-typeMismatch-tb1-myValue-yourValue", response.getContentAsString());
666 }
667
668 @Test
669 @SuppressWarnings("serial")
670 public void proxiedFormController() throws Exception {
671 DispatcherServlet servlet = new DispatcherServlet() {
672 @Override
673 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
674 GenericWebApplicationContext wac = new GenericWebApplicationContext();
675 wac.registerBeanDefinition("controller", new RootBeanDefinition(MyFormController.class));
676 wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(TestViewResolver.class));
677 DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
678 autoProxyCreator.setBeanFactory(wac.getBeanFactory());
679 wac.getBeanFactory().addBeanPostProcessor(autoProxyCreator);
680 wac.getBeanFactory()
681 .registerSingleton("advisor", new DefaultPointcutAdvisor(new SimpleTraceInterceptor()));
682 wac.refresh();
683 return wac;
684 }
685 };
686 servlet.init(new MockServletConfig());
687
688 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
689 request.addParameter("name", "name1");
690 request.addParameter("age", "value2");
691 MockHttpServletResponse response = new MockHttpServletResponse();
692 servlet.service(request, response);
693 assertEquals("myView-name1-typeMismatch-tb1-myValue", response.getContentAsString());
694 }
695
696 @Test
697 public void commandProvidingFormControllerWithCustomEditor() throws Exception {
698 @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
699 @Override
700 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
701 GenericWebApplicationContext wac = new GenericWebApplicationContext();
702 wac.registerBeanDefinition("controller",
703 new RootBeanDefinition(MyCommandProvidingFormController.class));
704 wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(TestViewResolver.class));
705 RootBeanDefinition adapterDef = new RootBeanDefinition(AnnotationMethodHandlerAdapter.class);
706 adapterDef.getPropertyValues().add("webBindingInitializer", new MyWebBindingInitializer());
707 wac.registerBeanDefinition("handlerAdapter", adapterDef);
708 wac.refresh();
709 return wac;
710 }
711 };
712 servlet.init(new MockServletConfig());
713
714 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
715 request.addParameter("defaultName", "myDefaultName");
716 request.addParameter("age", "value2");
717 request.addParameter("date", "2007-10-02");
718 MockHttpServletResponse response = new MockHttpServletResponse();
719 servlet.service(request, response);
720 assertEquals("myView-String:myDefaultName-typeMismatch-tb1-myOriginalValue", response.getContentAsString());
721 }
722
723 @Test
724 public void typedCommandProvidingFormController() throws Exception {
725 @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
726 @Override
727 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
728 GenericWebApplicationContext wac = new GenericWebApplicationContext();
729 wac.registerBeanDefinition("controller",
730 new RootBeanDefinition(MyTypedCommandProvidingFormController.class));
731 wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(TestViewResolver.class));
732 RootBeanDefinition adapterDef = new RootBeanDefinition(AnnotationMethodHandlerAdapter.class);
733 adapterDef.getPropertyValues().add("webBindingInitializer", new MyWebBindingInitializer());
734 adapterDef.getPropertyValues().add("customArgumentResolver", new MySpecialArgumentResolver());
735 wac.registerBeanDefinition("handlerAdapter", adapterDef);
736 wac.refresh();
737 return wac;
738 }
739 };
740 servlet.init(new MockServletConfig());
741
742 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
743 request.addParameter("defaultName", "10");
744 request.addParameter("age", "value2");
745 request.addParameter("date", "2007-10-02");
746 MockHttpServletResponse response = new MockHttpServletResponse();
747 servlet.service(request, response);
748 assertEquals("myView-Integer:10-typeMismatch-tb1-myOriginalValue", response.getContentAsString());
749
750 request = new MockHttpServletRequest("GET", "/myOtherPath.do");
751 request.addParameter("defaultName", "10");
752 request.addParameter("age", "value2");
753 request.addParameter("date", "2007-10-02");
754 response = new MockHttpServletResponse();
755 servlet.service(request, response);
756 assertEquals("myView-myName-typeMismatch-tb1-myOriginalValue", response.getContentAsString());
757
758 request = new MockHttpServletRequest("GET", "/myThirdPath.do");
759 request.addParameter("defaultName", "10");
760 request.addParameter("age", "100");
761 request.addParameter("date", "2007-10-02");
762 response = new MockHttpServletResponse();
763 servlet.service(request, response);
764 assertEquals("myView-special-99-special-99", response.getContentAsString());
765 }
766
767 @Test
768 public void binderInitializingCommandProvidingFormController() throws Exception {
769 @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
770 @Override
771 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
772 GenericWebApplicationContext wac = new GenericWebApplicationContext();
773 wac.registerBeanDefinition("controller",
774 new RootBeanDefinition(MyBinderInitializingCommandProvidingFormController.class));
775 wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(TestViewResolver.class));
776 wac.refresh();
777 return wac;
778 }
779 };
780 servlet.init(new MockServletConfig());
781
782 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
783 request.addParameter("defaultName", "myDefaultName");
784 request.addParameter("age", "value2");
785 request.addParameter("date", "2007-10-02");
786 MockHttpServletResponse response = new MockHttpServletResponse();
787 servlet.service(request, response);
788 assertEquals("myView-String:myDefaultName-typeMismatch-tb1-myOriginalValue", response.getContentAsString());
789 }
790
791 @Test
792 public void specificBinderInitializingCommandProvidingFormController() throws Exception {
793 @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
794 @Override
795 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
796 GenericWebApplicationContext wac = new GenericWebApplicationContext();
797 wac.registerBeanDefinition("controller",
798 new RootBeanDefinition(MySpecificBinderInitializingCommandProvidingFormController.class));
799 wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(TestViewResolver.class));
800 wac.refresh();
801 return wac;
802 }
803 };
804 servlet.init(new MockServletConfig());
805
806 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
807 request.addParameter("defaultName", "myDefaultName");
808 request.addParameter("age", "value2");
809 request.addParameter("date", "2007-10-02");
810 MockHttpServletResponse response = new MockHttpServletResponse();
811 servlet.service(request, response);
812 assertEquals("myView-String:myDefaultName-typeMismatch-tb1-myOriginalValue", response.getContentAsString());
813 }
814
815 @Test
816 public void parameterDispatchingController() throws Exception {
817 final MockServletContext servletContext = new MockServletContext();
818 final MockServletConfig servletConfig = new MockServletConfig(servletContext);
819
820 @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
821 @Override
822 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
823 GenericWebApplicationContext wac = new GenericWebApplicationContext();
824 wac.setServletContext(servletContext);
825 RootBeanDefinition bd = new RootBeanDefinition(MyParameterDispatchingController.class);
826
827 wac.registerBeanDefinition("controller", bd);
828 AnnotationConfigUtils.registerAnnotationConfigProcessors(wac);
829 wac.getBeanFactory().registerResolvableDependency(ServletConfig.class, servletConfig);
830 wac.refresh();
831 return wac;
832 }
833 };
834 servlet.init(servletConfig);
835
836 MockHttpServletRequest request = new MockHttpServletRequest(servletContext, "GET", "/myPath.do");
837 MockHttpServletResponse response = new MockHttpServletResponse();
838 HttpSession session = request.getSession();
839 servlet.service(request, response);
840 assertEquals("myView", response.getContentAsString());
841 assertSame(servletContext, request.getAttribute("servletContext"));
842 assertSame(servletConfig, request.getAttribute("servletConfig"));
843 assertSame(session.getId(), request.getAttribute("sessionId"));
844 assertSame(request.getRequestURI(), request.getAttribute("requestUri"));
845 assertSame(request.getLocale(), request.getAttribute("locale"));
846
847 request = new MockHttpServletRequest(servletContext, "GET", "/myPath.do");
848 response = new MockHttpServletResponse();
849 session = request.getSession();
850 servlet.service(request, response);
851 assertEquals("myView", response.getContentAsString());
852 assertSame(servletContext, request.getAttribute("servletContext"));
853 assertSame(servletConfig, request.getAttribute("servletConfig"));
854 assertSame(session.getId(), request.getAttribute("sessionId"));
855 assertSame(request.getRequestURI(), request.getAttribute("requestUri"));
856
857 request = new MockHttpServletRequest(servletContext, "GET", "/myPath.do");
858 request.addParameter("view", "other");
859 response = new MockHttpServletResponse();
860 servlet.service(request, response);
861 assertEquals("myOtherView", response.getContentAsString());
862
863 request = new MockHttpServletRequest(servletContext, "GET", "/myPath.do");
864 request.addParameter("view", "my");
865 request.addParameter("lang", "de");
866 response = new MockHttpServletResponse();
867 servlet.service(request, response);
868 assertEquals("myLangView", response.getContentAsString());
869
870 request = new MockHttpServletRequest(servletContext, "GET", "/myPath.do");
871 request.addParameter("surprise", "!");
872 response = new MockHttpServletResponse();
873 servlet.service(request, response);
874 assertEquals("mySurpriseView", response.getContentAsString());
875
876 MyParameterDispatchingController deserialized = (MyParameterDispatchingController) SerializationTestUtils
877 .serializeAndDeserialize(servlet.getWebApplicationContext().getBean("controller"));
878 assertNotNull(deserialized.request);
879 assertNotNull(deserialized.session);
880 }
881
882 @Test
883 public void constrainedParameterDispatchingController() throws Exception {
884 final MockServletContext servletContext = new MockServletContext();
885 final MockServletConfig servletConfig = new MockServletConfig(servletContext);
886
887 @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
888 @Override
889 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
890 GenericWebApplicationContext wac = new GenericWebApplicationContext();
891 wac.setServletContext(servletContext);
892 RootBeanDefinition bd = new RootBeanDefinition(MyConstrainedParameterDispatchingController.class);
893 bd.setScope(WebApplicationContext.SCOPE_REQUEST);
894 wac.registerBeanDefinition("controller", bd);
895 wac.refresh();
896 return wac;
897 }
898 };
899 servlet.init(servletConfig);
900
901 MockHttpServletRequest request = new MockHttpServletRequest(servletContext, "GET", "/myPath.do");
902 request.addParameter("view", "other");
903 MockHttpServletResponse response = new MockHttpServletResponse();
904 servlet.service(request, response);
905 assertEquals(400, response.getStatus());
906
907 request = new MockHttpServletRequest(servletContext, "GET", "/myPath.do");
908 request.addParameter("active", "true");
909 request.addParameter("view", "other");
910 response = new MockHttpServletResponse();
911 servlet.service(request, response);
912 assertEquals("myOtherView", response.getContentAsString());
913
914 request = new MockHttpServletRequest(servletContext, "GET", "/myPath.do");
915 request.addParameter("view", "my");
916 request.addParameter("lang", "de");
917 response = new MockHttpServletResponse();
918 servlet.service(request, response);
919 assertEquals(400, response.getStatus());
920
921 request = new MockHttpServletRequest(servletContext, "GET", "/myPath.do");
922 request.addParameter("view", "my");
923 request.addParameter("lang", "de");
924 request.addParameter("active", "true");
925 response = new MockHttpServletResponse();
926 servlet.service(request, response);
927 assertEquals("myLangView", response.getContentAsString());
928 }
929
930 @Test
931 public void methodNameDispatchingController() throws Exception {
932 @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
933 @Override
934 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
935 GenericWebApplicationContext wac = new GenericWebApplicationContext();
936 wac.registerBeanDefinition("controller", new RootBeanDefinition(MethodNameDispatchingController.class));
937 wac.refresh();
938 return wac;
939 }
940 };
941 servlet.init(new MockServletConfig());
942
943 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myHandle.do");
944 MockHttpServletResponse response = new MockHttpServletResponse();
945 servlet.service(request, response);
946 assertEquals("myView", response.getContentAsString());
947
948 request = new MockHttpServletRequest("GET", "/myOtherHandle.do");
949 response = new MockHttpServletResponse();
950 servlet.service(request, response);
951 assertEquals("myOtherView", response.getContentAsString());
952
953 request = new MockHttpServletRequest("POST", "/myLangHandle.do");
954 response = new MockHttpServletResponse();
955 servlet.service(request, response);
956 assertEquals("myLangView", response.getContentAsString());
957
958 request = new MockHttpServletRequest("POST", "/mySurpriseHandle.do");
959 response = new MockHttpServletResponse();
960 servlet.service(request, response);
961 assertEquals("mySurpriseView", response.getContentAsString());
962 }
963
964 @Test
965 public void methodNameDispatchingControllerWithSuffix() throws Exception {
966 @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
967 @Override
968 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
969 GenericWebApplicationContext wac = new GenericWebApplicationContext();
970 wac.registerBeanDefinition("controller", new RootBeanDefinition(MethodNameDispatchingController.class));
971 InternalPathMethodNameResolver methodNameResolver = new InternalPathMethodNameResolver();
972 methodNameResolver.setSuffix("Handle");
973 RootBeanDefinition adapterDef = new RootBeanDefinition(AnnotationMethodHandlerAdapter.class);
974 adapterDef.getPropertyValues().add("methodNameResolver", methodNameResolver);
975 wac.registerBeanDefinition("handlerAdapter", adapterDef);
976 wac.refresh();
977 return wac;
978 }
979 };
980 servlet.init(new MockServletConfig());
981
982 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/my.do");
983 MockHttpServletResponse response = new MockHttpServletResponse();
984 servlet.service(request, response);
985 assertEquals("myView", response.getContentAsString());
986
987 request = new MockHttpServletRequest("GET", "/myOther.do");
988 response = new MockHttpServletResponse();
989 servlet.service(request, response);
990 assertEquals("myOtherView", response.getContentAsString());
991
992 request = new MockHttpServletRequest("POST", "/myLang.do");
993 response = new MockHttpServletResponse();
994 servlet.service(request, response);
995 assertEquals("myLangView", response.getContentAsString());
996
997 request = new MockHttpServletRequest("POST", "/mySurprise.do");
998 response = new MockHttpServletResponse();
999 servlet.service(request, response);
1000 assertEquals("mySurpriseView", response.getContentAsString());
1001 }
1002
1003 @Test
1004 public void controllerClassNamePlusMethodNameDispatchingController() throws Exception {
1005 @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
1006 @Override
1007 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
1008 GenericWebApplicationContext wac = new GenericWebApplicationContext();
1009 RootBeanDefinition mapping = new RootBeanDefinition(ControllerClassNameHandlerMapping.class);
1010 mapping.getPropertyValues().add("excludedPackages", null);
1011 wac.registerBeanDefinition("handlerMapping", mapping);
1012 wac.registerBeanDefinition("controller", new RootBeanDefinition(MethodNameDispatchingController.class));
1013 wac.refresh();
1014 return wac;
1015 }
1016 };
1017 servlet.init(new MockServletConfig());
1018
1019 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/methodnamedispatching/myHandle");
1020 MockHttpServletResponse response = new MockHttpServletResponse();
1021 servlet.service(request, response);
1022 assertEquals("myView", response.getContentAsString());
1023
1024 request = new MockHttpServletRequest("GET", "/methodnamedispatching/myOtherHandle.do");
1025 response = new MockHttpServletResponse();
1026 servlet.service(request, response);
1027 assertEquals("myOtherView", response.getContentAsString());
1028
1029 request = new MockHttpServletRequest("POST", "/methodnamedispatching/myLangHandle.x");
1030 response = new MockHttpServletResponse();
1031 servlet.service(request, response);
1032 assertEquals("myLangView", response.getContentAsString());
1033
1034 request = new MockHttpServletRequest("POST", "/methodnamedispatching/mySurpriseHandle.y");
1035 response = new MockHttpServletResponse();
1036 servlet.service(request, response);
1037 assertEquals("mySurpriseView", response.getContentAsString());
1038 }
1039
1040 @Test
1041 public void postMethodNameDispatchingController() throws Exception {
1042 @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
1043 @Override
1044 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
1045 GenericWebApplicationContext wac = new GenericWebApplicationContext();
1046 wac.registerBeanDefinition("controller",
1047 new RootBeanDefinition(MyPostMethodNameDispatchingController.class));
1048 wac.refresh();
1049 return wac;
1050 }
1051 };
1052 servlet.init(new MockServletConfig());
1053
1054 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myHandle.do");
1055 MockHttpServletResponse response = new MockHttpServletResponse();
1056 servlet.service(request, response);
1057 assertEquals(405, response.getStatus());
1058
1059 request = new MockHttpServletRequest("POST", "/myUnknownHandle.do");
1060 request.addParameter("myParam", "myValue");
1061 response = new MockHttpServletResponse();
1062 servlet.service(request, response);
1063 assertEquals(404, response.getStatus());
1064
1065 request = new MockHttpServletRequest("POST", "/myHandle.do");
1066 request.addParameter("myParam", "myValue");
1067 response = new MockHttpServletResponse();
1068 servlet.service(request, response);
1069 assertEquals("myView", response.getContentAsString());
1070
1071 request = new MockHttpServletRequest("POST", "/myOtherHandle.do");
1072 request.addParameter("myParam", "myValue");
1073 response = new MockHttpServletResponse();
1074 servlet.service(request, response);
1075 assertEquals("myOtherView", response.getContentAsString());
1076
1077 request = new MockHttpServletRequest("POST", "/myLangHandle.do");
1078 request.addParameter("myParam", "myValue");
1079 response = new MockHttpServletResponse();
1080 servlet.service(request, response);
1081 assertEquals("myLangView", response.getContentAsString());
1082
1083 request = new MockHttpServletRequest("POST", "/mySurpriseHandle.do");
1084 request.addParameter("myParam", "myValue");
1085 response = new MockHttpServletResponse();
1086 servlet.service(request, response);
1087 assertEquals("mySurpriseView", response.getContentAsString());
1088 }
1089
1090 @Test
1091 public void relativePathDispatchingController() throws Exception {
1092 initServlet(MyRelativePathDispatchingController.class);
1093 servlet.init(new MockServletConfig());
1094
1095 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myApp/myHandle");
1096 MockHttpServletResponse response = new MockHttpServletResponse();
1097 servlet.service(request, response);
1098 assertEquals("myView", response.getContentAsString());
1099
1100 request = new MockHttpServletRequest("GET", "/myApp/myOther");
1101 response = new MockHttpServletResponse();
1102 servlet.service(request, response);
1103 assertEquals("myOtherView", response.getContentAsString());
1104
1105 request = new MockHttpServletRequest("GET", "/myApp/myLang");
1106 response = new MockHttpServletResponse();
1107 servlet.service(request, response);
1108 assertEquals("myLangView", response.getContentAsString());
1109
1110 request = new MockHttpServletRequest("GET", "/myApp/surprise.do");
1111 response = new MockHttpServletResponse();
1112 servlet.service(request, response);
1113 assertEquals("mySurpriseView", response.getContentAsString());
1114 }
1115
1116 @Test
1117 public void relativeMethodPathDispatchingController() throws Exception {
1118 initServlet(MyRelativeMethodPathDispatchingController.class);
1119 servlet.init(new MockServletConfig());
1120
1121 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myApp/myHandle");
1122 MockHttpServletResponse response = new MockHttpServletResponse();
1123 servlet.service(request, response);
1124 assertEquals("myView", response.getContentAsString());
1125
1126 request = new MockHttpServletRequest("GET", "/yourApp/myOther");
1127 response = new MockHttpServletResponse();
1128 servlet.service(request, response);
1129 assertEquals("myOtherView", response.getContentAsString());
1130
1131 request = new MockHttpServletRequest("GET", "/hisApp/myLang");
1132 response = new MockHttpServletResponse();
1133 servlet.service(request, response);
1134 assertEquals("myLangView", response.getContentAsString());
1135
1136 request = new MockHttpServletRequest("GET", "/herApp/surprise.do");
1137 response = new MockHttpServletResponse();
1138 servlet.service(request, response);
1139 assertEquals("mySurpriseView", response.getContentAsString());
1140 }
1141
1142 @Test
1143 public void nullCommandController() throws Exception {
1144 initServlet(MyNullCommandController.class);
1145 servlet.init(new MockServletConfig());
1146
1147 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath");
1148 request.setUserPrincipal(new OtherPrincipal());
1149 MockHttpServletResponse response = new MockHttpServletResponse();
1150 servlet.service(request, response);
1151 assertEquals("myView", response.getContentAsString());
1152 }
1153
1154 @Test
1155 public void equivalentMappingsWithSameMethodName() throws Exception {
1156 initServlet(ChildController.class);
1157 servlet.init(new MockServletConfig());
1158
1159 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/child/test");
1160 request.addParameter("childId", "100");
1161 MockHttpServletResponse response = new MockHttpServletResponse();
1162 try {
1163 servlet.service(request, response);
1164 fail("Didn't fail with due to ambiguous method mapping");
1165 }
1166 catch (NestedServletException ex) {
1167 assertTrue(ex.getCause() instanceof IllegalStateException);
1168 assertTrue(ex.getCause().getMessage().contains("doGet"));
1169 }
1170 }
1171
1172 @Test
1173 public void pathOrdering() throws ServletException, IOException {
1174 initServlet(PathOrderingController.class);
1175
1176 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/dir/myPath1.do");
1177 MockHttpServletResponse response = new MockHttpServletResponse();
1178 servlet.service(request, response);
1179 assertEquals("method1", response.getContentAsString());
1180 }
1181
1182 @Test
1183 public void requestBodyResponseBody() throws ServletException, IOException {
1184 initServlet(RequestResponseBodyController.class);
1185
1186 MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something");
1187 String requestBody = "Hello World";
1188 request.setContent(requestBody.getBytes("UTF-8"));
1189 request.addHeader("Content-Type", "text/plain; charset=utf-8");
1190 request.addHeader("Accept", "text/*, */*");
1191 MockHttpServletResponse response = new MockHttpServletResponse();
1192 servlet.service(request, response);
1193 assertEquals(200, response.getStatus());
1194 assertEquals(requestBody, response.getContentAsString());
1195 }
1196
1197 @Test
1198 public void responseBodyNoAcceptableMediaType() throws ServletException, IOException {
1199 @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
1200 @Override
1201 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
1202 GenericWebApplicationContext wac = new GenericWebApplicationContext();
1203 wac.registerBeanDefinition("controller", new RootBeanDefinition(RequestResponseBodyController.class));
1204 RootBeanDefinition converterDef = new RootBeanDefinition(StringHttpMessageConverter.class);
1205 converterDef.getPropertyValues().add("supportedMediaTypes", new MediaType("text", "plain"));
1206 RootBeanDefinition adapterDef = new RootBeanDefinition(AnnotationMethodHandlerAdapter.class);
1207 StringHttpMessageConverter converter = new StringHttpMessageConverter();
1208 converter.setSupportedMediaTypes(Collections.singletonList(new MediaType("text", "plain")));
1209 adapterDef.getPropertyValues().add("messageConverters", converter);
1210 wac.registerBeanDefinition("handlerAdapter", adapterDef);
1211 wac.refresh();
1212 return wac;
1213 }
1214 };
1215 servlet.init(new MockServletConfig());
1216
1217 MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something");
1218 String requestBody = "Hello World";
1219 request.setContent(requestBody.getBytes("UTF-8"));
1220 request.addHeader("Content-Type", "text/plain; charset=utf-8");
1221 request.addHeader("Accept", "application/pdf, application/msword");
1222 MockHttpServletResponse response = new MockHttpServletResponse();
1223 servlet.service(request, response);
1224 assertEquals(406, response.getStatus());
1225 }
1226
1227 @Test
1228 public void responseBodyWildCardMediaType() throws ServletException, IOException {
1229 initServlet(RequestResponseBodyController.class);
1230
1231 MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something");
1232 String requestBody = "Hello World";
1233 request.setContent(requestBody.getBytes("UTF-8"));
1234 request.addHeader("Content-Type", "text/plain; charset=utf-8");
1235 request.addHeader("Accept", "*/*");
1236 MockHttpServletResponse response = new MockHttpServletResponse();
1237 servlet.service(request, response);
1238 assertEquals(requestBody, response.getContentAsString());
1239 }
1240
1241 @Test
1242 public void unsupportedRequestBody() throws ServletException, IOException {
1243 @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
1244 @Override
1245 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
1246 GenericWebApplicationContext wac = new GenericWebApplicationContext();
1247 wac.registerBeanDefinition("controller", new RootBeanDefinition(RequestResponseBodyController.class));
1248 RootBeanDefinition adapterDef = new RootBeanDefinition(AnnotationMethodHandlerAdapter.class);
1249 adapterDef.getPropertyValues().add("messageConverters", new ByteArrayHttpMessageConverter());
1250 wac.registerBeanDefinition("handlerAdapter", adapterDef);
1251 wac.refresh();
1252 return wac;
1253 }
1254 };
1255 servlet.init(new MockServletConfig());
1256
1257 MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something");
1258 String requestBody = "Hello World";
1259 request.setContent(requestBody.getBytes("UTF-8"));
1260 request.addHeader("Content-Type", "application/pdf");
1261 MockHttpServletResponse response = new MockHttpServletResponse();
1262 servlet.service(request, response);
1263 assertEquals(415, response.getStatus());
1264 assertNotNull("No Accept response header set", response.getHeader("Accept"));
1265 }
1266
1267 @Test
1268 public void responseBodyNoAcceptHeader() throws ServletException, IOException {
1269 initServlet(RequestResponseBodyController.class);
1270
1271 MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something");
1272 String requestBody = "Hello World";
1273 request.setContent(requestBody.getBytes("UTF-8"));
1274 request.addHeader("Content-Type", "text/plain; charset=utf-8");
1275 MockHttpServletResponse response = new MockHttpServletResponse();
1276 servlet.service(request, response);
1277 assertEquals(200, response.getStatus());
1278 assertEquals(requestBody, response.getContentAsString());
1279 }
1280
1281 @Test
1282 public void badRequestRequestBody() throws ServletException, IOException {
1283 @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
1284 @Override
1285 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
1286 GenericWebApplicationContext wac = new GenericWebApplicationContext();
1287 wac.registerBeanDefinition("controller", new RootBeanDefinition(RequestResponseBodyController.class));
1288 RootBeanDefinition adapterDef = new RootBeanDefinition(AnnotationMethodHandlerAdapter.class);
1289 adapterDef.getPropertyValues().add("messageConverters", new NotReadableMessageConverter());
1290 wac.registerBeanDefinition("handlerAdapter", adapterDef);
1291 wac.refresh();
1292 return wac;
1293 }
1294 };
1295 servlet.init(new MockServletConfig());
1296
1297 MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something");
1298 String requestBody = "Hello World";
1299 request.setContent(requestBody.getBytes("UTF-8"));
1300 request.addHeader("Content-Type", "application/pdf");
1301 MockHttpServletResponse response = new MockHttpServletResponse();
1302 servlet.service(request, response);
1303 assertEquals("Invalid response status code", HttpServletResponse.SC_BAD_REQUEST, response.getStatus());
1304 }
1305
1306 @Test
1307 public void httpEntity() throws ServletException, IOException {
1308 initServlet(ResponseEntityController.class);
1309
1310 MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/foo");
1311 String requestBody = "Hello World";
1312 request.setContent(requestBody.getBytes("UTF-8"));
1313 request.addHeader("Content-Type", "text/plain; charset=utf-8");
1314 request.addHeader("Accept", "text/*, */*");
1315 request.addHeader("MyRequestHeader", "MyValue");
1316 MockHttpServletResponse response = new MockHttpServletResponse();
1317 servlet.service(request, response);
1318 assertEquals(201, response.getStatus());
1319 assertEquals(requestBody, response.getContentAsString());
1320 assertEquals("MyValue", response.getHeader("MyResponseHeader"));
1321
1322 request = new MockHttpServletRequest("PUT", "/bar");
1323 response = new MockHttpServletResponse();
1324 servlet.service(request, response);
1325 assertEquals("MyValue", response.getHeader("MyResponseHeader"));
1326 assertEquals(404, response.getStatus());
1327 }
1328
1329
1330
1331
1332
1333 @Test
1334 public void overlappingMesssageConvertersRequestBody() throws ServletException, IOException {
1335 @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
1336 @Override
1337 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
1338 GenericWebApplicationContext wac = new GenericWebApplicationContext();
1339 wac.registerBeanDefinition("controller", new RootBeanDefinition(RequestResponseBodyController.class));
1340 RootBeanDefinition adapterDef = new RootBeanDefinition(AnnotationMethodHandlerAdapter.class);
1341 List<HttpMessageConverter> messageConverters = new ArrayList<HttpMessageConverter>();
1342 messageConverters.add(new StringHttpMessageConverter());
1343 messageConverters
1344 .add(new SimpleMessageConverter(new MediaType("application","json"), MediaType.ALL));
1345 adapterDef.getPropertyValues().add("messageConverters", messageConverters);
1346 wac.registerBeanDefinition("handlerAdapter", adapterDef);
1347 wac.refresh();
1348 return wac;
1349 }
1350 };
1351 servlet.init(new MockServletConfig());
1352
1353 MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something");
1354 request.setContent("Hello World".getBytes("UTF-8"));
1355 request.addHeader("Content-Type", "text/plain; charset=utf-8");
1356 request.addHeader("Accept", "application/json, text/javascript, */*");
1357 MockHttpServletResponse response = new MockHttpServletResponse();
1358 servlet.service(request, response);
1359 assertEquals("Invalid response status code", "application/json", response.getHeader("Content-Type"));
1360 }
1361
1362 @Test
1363 public void responseBodyVoid() throws ServletException, IOException {
1364 initServlet(ResponseBodyVoidController.class);
1365
1366 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/something");
1367 request.addHeader("Accept", "text/*, */*");
1368 MockHttpServletResponse response = new MockHttpServletResponse();
1369 servlet.service(request, response);
1370 assertEquals(200, response.getStatus());
1371 }
1372
1373 @Test
1374 public void responseBodyArgMismatch() throws ServletException, IOException {
1375 @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
1376 @Override
1377 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
1378 GenericWebApplicationContext wac = new GenericWebApplicationContext();
1379 wac.registerBeanDefinition("controller", new RootBeanDefinition(RequestBodyArgMismatchController.class));
1380
1381 Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
1382 marshaller.setClassesToBeBound(A.class, B.class);
1383 try {
1384 marshaller.afterPropertiesSet();
1385 }
1386 catch (Exception ex) {
1387 throw new BeanCreationException(ex.getMessage(), ex);
1388 }
1389
1390 MarshallingHttpMessageConverter messageConverter = new MarshallingHttpMessageConverter(marshaller);
1391
1392 RootBeanDefinition adapterDef = new RootBeanDefinition(AnnotationMethodHandlerAdapter.class);
1393 adapterDef.getPropertyValues().add("messageConverters", messageConverter);
1394 wac.registerBeanDefinition("handlerAdapter", adapterDef);
1395 wac.refresh();
1396 return wac;
1397 }
1398 };
1399 servlet.init(new MockServletConfig());
1400
1401
1402 MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something");
1403 String requestBody = "<b/>";
1404 request.setContent(requestBody.getBytes("UTF-8"));
1405 request.addHeader("Content-Type", "application/xml; charset=utf-8");
1406 MockHttpServletResponse response = new MockHttpServletResponse();
1407 servlet.service(request, response);
1408 assertEquals(400, response.getStatus());
1409 }
1410
1411
1412 @Test
1413 public void contentTypeHeaders() throws ServletException, IOException {
1414 initServlet(ContentTypeHeadersController.class);
1415
1416 MockHttpServletRequest request = new MockHttpServletRequest("POST", "/something");
1417 request.addHeader("Content-Type", "application/pdf");
1418 MockHttpServletResponse response = new MockHttpServletResponse();
1419 servlet.service(request, response);
1420 assertEquals("pdf", response.getContentAsString());
1421
1422 request = new MockHttpServletRequest("POST", "/something");
1423 request.addHeader("Content-Type", "text/html");
1424 response = new MockHttpServletResponse();
1425 servlet.service(request, response);
1426 assertEquals("text", response.getContentAsString());
1427
1428 request = new MockHttpServletRequest("POST", "/something");
1429 request.addHeader("Content-Type", "application/xml");
1430 response = new MockHttpServletResponse();
1431 servlet.service(request, response);
1432 assertEquals(404, response.getStatus());
1433 }
1434
1435 @Test
1436 public void negatedContentTypeHeaders() throws ServletException, IOException {
1437 initServlet(NegatedContentTypeHeadersController.class);
1438
1439 MockHttpServletRequest request = new MockHttpServletRequest("POST", "/something");
1440 request.addHeader("Content-Type", "application/pdf");
1441 MockHttpServletResponse response = new MockHttpServletResponse();
1442 servlet.service(request, response);
1443 assertEquals("pdf", response.getContentAsString());
1444
1445 request = new MockHttpServletRequest("POST", "/something");
1446 request.addHeader("Content-Type", "text/html");
1447 response = new MockHttpServletResponse();
1448 servlet.service(request, response);
1449 assertEquals("non-pdf", response.getContentAsString());
1450 }
1451
1452 @Test
1453 public void acceptHeaders() throws ServletException, IOException {
1454 initServlet(AcceptHeadersController.class);
1455
1456 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/something");
1457 request.addHeader("Accept", "text/html");
1458 MockHttpServletResponse response = new MockHttpServletResponse();
1459 servlet.service(request, response);
1460 assertEquals("html", response.getContentAsString());
1461
1462 request = new MockHttpServletRequest("GET", "/something");
1463 request.addHeader("Accept", "application/xml");
1464 response = new MockHttpServletResponse();
1465 servlet.service(request, response);
1466 assertEquals("xml", response.getContentAsString());
1467
1468 request = new MockHttpServletRequest("GET", "/something");
1469 request.addHeader("Accept", "application/xml, text/html");
1470 response = new MockHttpServletResponse();
1471 servlet.service(request, response);
1472 assertEquals("xml", response.getContentAsString());
1473
1474 request = new MockHttpServletRequest("GET", "/something");
1475 request.addHeader("Accept", "text/html;q=0.9, application/xml");
1476 response = new MockHttpServletResponse();
1477 servlet.service(request, response);
1478 assertEquals("xml", response.getContentAsString());
1479 }
1480
1481 @Test
1482 public void responseStatus() throws ServletException, IOException {
1483 initServlet(ResponseStatusController.class);
1484
1485 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/something");
1486 MockHttpServletResponse response = new MockHttpServletResponse();
1487 servlet.service(request, response);
1488 assertEquals("something", response.getContentAsString());
1489 assertEquals(201, response.getStatus());
1490 assertEquals("It's alive!", response.getErrorMessage());
1491 }
1492
1493 @Test
1494 public void mavResolver() throws ServletException, IOException {
1495 @SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
1496 @Override
1497 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
1498 GenericWebApplicationContext wac = new GenericWebApplicationContext();
1499 wac.registerBeanDefinition("controller", new RootBeanDefinition(ModelAndViewResolverController.class));
1500 RootBeanDefinition adapterDef = new RootBeanDefinition(AnnotationMethodHandlerAdapter.class);
1501 adapterDef.getPropertyValues().add("customModelAndViewResolver", new MyModelAndViewResolver());
1502 wac.registerBeanDefinition("handlerAdapter", adapterDef);
1503 wac.refresh();
1504 return wac;
1505 }
1506 };
1507 servlet.init(new MockServletConfig());
1508
1509 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
1510 MockHttpServletResponse response = new MockHttpServletResponse();
1511 servlet.service(request, response);
1512 assertEquals("myValue", response.getContentAsString());
1513
1514 }
1515
1516 @Test
1517 public void bindingCookieValue() throws ServletException, IOException {
1518 initServlet(BindingCookieValueController.class);
1519
1520 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test");
1521 request.setCookies(new Cookie("date", "2008-11-18"));
1522 MockHttpServletResponse response = new MockHttpServletResponse();
1523 servlet.service(request, response);
1524 assertEquals("test-2008", response.getContentAsString());
1525 }
1526
1527 @Test
1528 public void ambiguousParams() throws ServletException, IOException {
1529 initServlet(AmbiguousParamsController.class);
1530
1531 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test");
1532 MockHttpServletResponse response = new MockHttpServletResponse();
1533 servlet.service(request, response);
1534 assertEquals("noParams", response.getContentAsString());
1535
1536 request = new MockHttpServletRequest("GET", "/test");
1537 request.addParameter("myParam", "42");
1538 response = new MockHttpServletResponse();
1539 servlet.service(request, response);
1540 assertEquals("myParam-42", response.getContentAsString());
1541 }
1542
1543 @Test
1544 public void bridgeMethods() throws Exception {
1545 initServlet(TestControllerImpl.class);
1546
1547 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/method");
1548 MockHttpServletResponse response = new MockHttpServletResponse();
1549 servlet.service(request, response);
1550 }
1551
1552 @Test
1553 public void requestParamMap() throws Exception {
1554 initServlet(RequestParamMapController.class);
1555
1556 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/map");
1557 request.addParameter("key1", "value1");
1558 request.addParameter("key2", new String[]{"value21", "value22"});
1559 MockHttpServletResponse response = new MockHttpServletResponse();
1560
1561 servlet.service(request, response);
1562 assertEquals("key1=value1,key2=value21", response.getContentAsString());
1563
1564 request.setRequestURI("/multiValueMap");
1565 response = new MockHttpServletResponse();
1566
1567 servlet.service(request, response);
1568 assertEquals("key1=[value1],key2=[value21,value22]", response.getContentAsString());
1569 }
1570
1571 @Test
1572 public void requestHeaderMap() throws Exception {
1573 initServlet(RequestHeaderMapController.class);
1574
1575 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/map");
1576 request.addHeader("Content-Type", "text/html");
1577 request.addHeader("Custom-Header", new String[]{"value21", "value22"});
1578 MockHttpServletResponse response = new MockHttpServletResponse();
1579
1580 servlet.service(request, response);
1581 assertEquals("Content-Type=text/html,Custom-Header=value21", response.getContentAsString());
1582
1583 request.setRequestURI("/multiValueMap");
1584 response = new MockHttpServletResponse();
1585
1586 servlet.service(request, response);
1587 assertEquals("Content-Type=[text/html],Custom-Header=[value21,value22]", response.getContentAsString());
1588
1589 request.setRequestURI("/httpHeaders");
1590 response = new MockHttpServletResponse();
1591
1592 servlet.service(request, response);
1593 assertEquals("Content-Type=[text/html],Custom-Header=[value21,value22]", response.getContentAsString());
1594 }
1595
1596 @Test
1597 @SuppressWarnings("serial")
1598 public void controllerClassNameNoTypeLevelAnn() throws Exception {
1599 servlet = new DispatcherServlet() {
1600 @Override
1601 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent)
1602 throws BeansException {
1603 GenericWebApplicationContext wac = new GenericWebApplicationContext();
1604 wac.registerBeanDefinition("controller", new RootBeanDefinition(BookController.class));
1605 RootBeanDefinition mapping = new RootBeanDefinition(ControllerClassNameHandlerMapping.class);
1606 mapping.getPropertyValues().add("excludedPackages", null);
1607 wac.registerBeanDefinition("handlerMapping", mapping);
1608 wac.refresh();
1609 return wac;
1610 }
1611 };
1612 servlet.init(new MockServletConfig());
1613
1614 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/book/list");
1615 MockHttpServletResponse response = new MockHttpServletResponse();
1616 servlet.service(request, response);
1617 assertEquals("list", response.getContentAsString());
1618
1619 request = new MockHttpServletRequest("GET", "/book/show");
1620 request.addParameter("id", "12");
1621 response = new MockHttpServletResponse();
1622 servlet.service(request, response);
1623 assertEquals("show-id=12", response.getContentAsString());
1624
1625 request = new MockHttpServletRequest("POST", "/book");
1626 response = new MockHttpServletResponse();
1627 servlet.service(request, response);
1628 assertEquals("create", response.getContentAsString());
1629 }
1630
1631 @Test
1632 @SuppressWarnings("serial")
1633 public void simpleUrlHandlerMapping() throws Exception {
1634 servlet = new DispatcherServlet() {
1635 @Override
1636 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent)
1637 throws BeansException {
1638 GenericWebApplicationContext wac = new GenericWebApplicationContext();
1639 wac.registerBeanDefinition("controller", new RootBeanDefinition(BookController.class));
1640 RootBeanDefinition hmDef = new RootBeanDefinition(SimpleUrlHandlerMapping.class);
1641 hmDef.getPropertyValues().add("mappings", "/book/*=controller\n/book=controller");
1642 wac.registerBeanDefinition("handlerMapping", hmDef);
1643 wac.refresh();
1644 return wac;
1645 }
1646 };
1647 servlet.init(new MockServletConfig());
1648
1649 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/book/list");
1650 MockHttpServletResponse response = new MockHttpServletResponse();
1651 servlet.service(request, response);
1652 assertEquals("list", response.getContentAsString());
1653
1654 request = new MockHttpServletRequest("GET", "/book/show");
1655 request.addParameter("id", "12");
1656 response = new MockHttpServletResponse();
1657 servlet.service(request, response);
1658 assertEquals("show-id=12", response.getContentAsString());
1659
1660 request = new MockHttpServletRequest("POST", "/book");
1661 response = new MockHttpServletResponse();
1662 servlet.service(request, response);
1663 assertEquals("create", response.getContentAsString());
1664 }
1665
1666 @Test
1667 public void requestMappingInterface() throws Exception {
1668 initServlet(IMyControllerImpl.class);
1669
1670 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/handle");
1671 MockHttpServletResponse response = new MockHttpServletResponse();
1672 servlet.service(request, response);
1673 assertEquals("handle null", response.getContentAsString());
1674
1675 request = new MockHttpServletRequest("GET", "/handle");
1676 request.addParameter("p", "value");
1677 response = new MockHttpServletResponse();
1678 servlet.service(request, response);
1679 assertEquals("handle value", response.getContentAsString());
1680 }
1681
1682 @Test
1683 @SuppressWarnings("serial")
1684 public void requestMappingInterfaceWithProxy() throws Exception {
1685 DispatcherServlet servlet = new DispatcherServlet() {
1686 @Override
1687 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
1688 GenericWebApplicationContext wac = new GenericWebApplicationContext();
1689 wac.registerBeanDefinition("controller", new RootBeanDefinition(IMyControllerImpl.class));
1690 DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
1691 autoProxyCreator.setBeanFactory(wac.getBeanFactory());
1692 wac.getBeanFactory().addBeanPostProcessor(autoProxyCreator);
1693 wac.getBeanFactory().registerSingleton("advisor", new DefaultPointcutAdvisor(new SimpleTraceInterceptor()));
1694 wac.refresh();
1695 return wac;
1696 }
1697 };
1698 servlet.init(new MockServletConfig());
1699
1700 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/handle");
1701 MockHttpServletResponse response = new MockHttpServletResponse();
1702 servlet.service(request, response);
1703 assertEquals("handle null", response.getContentAsString());
1704
1705 request = new MockHttpServletRequest("GET", "/handle");
1706 request.addParameter("p", "value");
1707 response = new MockHttpServletResponse();
1708 servlet.service(request, response);
1709 assertEquals("handle value", response.getContentAsString());
1710 }
1711
1712 @Test
1713 public void requestMappingBaseClass() throws Exception {
1714 initServlet(MyAbstractControllerImpl.class);
1715
1716 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/handle");
1717 MockHttpServletResponse response = new MockHttpServletResponse();
1718 servlet.service(request, response);
1719 assertEquals("handle", response.getContentAsString());
1720
1721 }
1722
1723 @Test
1724 public void trailingSlash() throws Exception {
1725 initServlet(TrailingSlashController.class);
1726
1727 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo/");
1728 MockHttpServletResponse response = new MockHttpServletResponse();
1729 servlet.service(request, response);
1730 assertEquals("templatePath", response.getContentAsString());
1731 }
1732
1733 @Test
1734 public void testMatchWithoutMethodLevelPath() throws Exception {
1735 initServlet(NoPathGetAndM2PostController.class);
1736
1737 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/t1/m2");
1738 MockHttpServletResponse response = new MockHttpServletResponse();
1739 servlet.service(request, response);
1740 assertEquals(405, response.getStatus());
1741 }
1742
1743
1744
1745 @Test
1746 public void testHeadersCondition() throws Exception {
1747 initServlet(HeadersConditionController.class);
1748
1749
1750 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
1751 MockHttpServletResponse response = new MockHttpServletResponse();
1752 servlet.service(request, response);
1753
1754 assertEquals(200, response.getStatus());
1755 assertEquals("home", response.getForwardedUrl());
1756
1757
1758 request = new MockHttpServletRequest("GET", "/");
1759 request.addHeader("Accept", "*/*");
1760 response = new MockHttpServletResponse();
1761 servlet.service(request, response);
1762
1763 assertEquals(200, response.getStatus());
1764 assertEquals("home", response.getForwardedUrl());
1765
1766
1767 request = new MockHttpServletRequest("GET", "/");
1768 request.addHeader("Accept", "application/json");
1769 response = new MockHttpServletResponse();
1770 servlet.service(request, response);
1771
1772 assertEquals(200, response.getStatus());
1773 assertEquals("application/json", response.getHeader("Content-Type"));
1774 assertEquals("homeJson", response.getContentAsString());
1775 }
1776
1777 @Test
1778 public void redirectAttribute() throws Exception {
1779 initServlet(RedirectAttributesController.class);
1780 try {
1781 servlet.service(new MockHttpServletRequest("GET", "/"), new MockHttpServletResponse());
1782 }
1783 catch (NestedServletException ex) {
1784 assertTrue(ex.getMessage().contains("not assignable from the actual model"));
1785 }
1786 }
1787
1788
1789
1790
1791 @Test
1792 public void customMapEditor() throws Exception {
1793 initServlet(CustomMapEditorController.class);
1794
1795 MockHttpServletRequest request = new MockHttpServletRequest("GET", "/handle");
1796 request.addParameter("map", "bar");
1797 MockHttpServletResponse response = new MockHttpServletResponse();
1798
1799 servlet.service(request, response);
1800
1801 assertEquals("test-{foo=bar}", response.getContentAsString());
1802 }
1803
1804 @Test
1805 public void multipartFileAsSingleString() throws Exception {
1806 initServlet(MultipartController.class);
1807
1808 MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
1809 request.setRequestURI("/singleString");
1810 request.addFile(new MockMultipartFile("content", "Juergen".getBytes()));
1811 MockHttpServletResponse response = new MockHttpServletResponse();
1812 servlet.service(request, response);
1813 assertEquals("Juergen", response.getContentAsString());
1814 }
1815
1816 @Test
1817 public void regularParameterAsSingleString() throws Exception {
1818 initServlet(MultipartController.class);
1819
1820 MockHttpServletRequest request = new MockHttpServletRequest();
1821 request.setRequestURI("/singleString");
1822 request.setMethod("POST");
1823 request.addParameter("content", "Juergen");
1824 MockHttpServletResponse response = new MockHttpServletResponse();
1825 servlet.service(request, response);
1826 assertEquals("Juergen", response.getContentAsString());
1827 }
1828
1829 @Test
1830 public void multipartFileAsStringArray() throws Exception {
1831 initServlet(MultipartController.class);
1832
1833 MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
1834 request.setRequestURI("/stringArray");
1835 request.addFile(new MockMultipartFile("content", "Juergen".getBytes()));
1836 MockHttpServletResponse response = new MockHttpServletResponse();
1837 servlet.service(request, response);
1838 assertEquals("Juergen", response.getContentAsString());
1839 }
1840
1841 @Test
1842 public void regularParameterAsStringArray() throws Exception {
1843 initServlet(MultipartController.class);
1844
1845 MockHttpServletRequest request = new MockHttpServletRequest();
1846 request.setRequestURI("/stringArray");
1847 request.setMethod("POST");
1848 request.addParameter("content", "Juergen");
1849 MockHttpServletResponse response = new MockHttpServletResponse();
1850 servlet.service(request, response);
1851 assertEquals("Juergen", response.getContentAsString());
1852 }
1853
1854 @Test
1855 public void multipartFilesAsStringArray() throws Exception {
1856 initServlet(MultipartController.class);
1857
1858 MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
1859 request.setRequestURI("/stringArray");
1860 request.addFile(new MockMultipartFile("content", "Juergen".getBytes()));
1861 request.addFile(new MockMultipartFile("content", "Eva".getBytes()));
1862 MockHttpServletResponse response = new MockHttpServletResponse();
1863 servlet.service(request, response);
1864 assertEquals("Juergen-Eva", response.getContentAsString());
1865 }
1866
1867 @Test
1868 public void regularParametersAsStringArray() throws Exception {
1869 initServlet(MultipartController.class);
1870
1871 MockHttpServletRequest request = new MockHttpServletRequest();
1872 request.setRequestURI("/stringArray");
1873 request.setMethod("POST");
1874 request.addParameter("content", "Juergen");
1875 request.addParameter("content", "Eva");
1876 MockHttpServletResponse response = new MockHttpServletResponse();
1877 servlet.service(request, response);
1878 assertEquals("Juergen-Eva", response.getContentAsString());
1879 }
1880
1881 @Test
1882 @SuppressWarnings("serial")
1883 public void parameterCsvAsIntegerArray() throws Exception {
1884 servlet = new DispatcherServlet() {
1885 @Override
1886 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
1887 GenericWebApplicationContext wac = new GenericWebApplicationContext();
1888 wac.registerBeanDefinition("controller", new RootBeanDefinition(CsvController.class));
1889 RootBeanDefinition csDef = new RootBeanDefinition(FormattingConversionServiceFactoryBean.class);
1890 RootBeanDefinition wbiDef = new RootBeanDefinition(ConfigurableWebBindingInitializer.class);
1891 wbiDef.getPropertyValues().add("conversionService", csDef);
1892 RootBeanDefinition adapterDef = new RootBeanDefinition(AnnotationMethodHandlerAdapter.class);
1893 adapterDef.getPropertyValues().add("webBindingInitializer", wbiDef);
1894 wac.registerBeanDefinition("handlerAdapter", adapterDef);
1895 wac.refresh();
1896 return wac;
1897 }
1898 };
1899 servlet.init(new MockServletConfig());
1900
1901 MockHttpServletRequest request = new MockHttpServletRequest();
1902 request.setRequestURI("/integerArray");
1903 request.setMethod("POST");
1904 request.addParameter("content", "1,2");
1905 MockHttpServletResponse response = new MockHttpServletResponse();
1906 servlet.service(request, response);
1907 assertEquals("1-2", response.getContentAsString());
1908 }
1909
1910 @Test
1911 @SuppressWarnings("serial")
1912 public void parameterCsvAsIntegerSet() throws Exception {
1913 servlet = new DispatcherServlet() {
1914 @Override
1915 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
1916 GenericWebApplicationContext wac = new GenericWebApplicationContext();
1917 wac.registerBeanDefinition("controller", new RootBeanDefinition(CsvController.class));
1918 RootBeanDefinition csDef = new RootBeanDefinition(FormattingConversionServiceFactoryBean.class);
1919 RootBeanDefinition wbiDef = new RootBeanDefinition(ConfigurableWebBindingInitializer.class);
1920 wbiDef.getPropertyValues().add("conversionService", csDef);
1921 RootBeanDefinition adapterDef = new RootBeanDefinition(AnnotationMethodHandlerAdapter.class);
1922 adapterDef.getPropertyValues().add("webBindingInitializer", wbiDef);
1923 wac.registerBeanDefinition("handlerAdapter", adapterDef);
1924 wac.refresh();
1925 return wac;
1926 }
1927 };
1928 servlet.init(new MockServletConfig());
1929
1930 MockHttpServletRequest request = new MockHttpServletRequest();
1931 request.setRequestURI("/integerSet");
1932 request.setMethod("POST");
1933 request.addParameter("content", "1,2");
1934 MockHttpServletResponse response = new MockHttpServletResponse();
1935 servlet.service(request, response);
1936 assertEquals("1-2", response.getContentAsString());
1937 }
1938
1939 @Test
1940 @SuppressWarnings("serial")
1941 public void parameterCsvAsIntegerSetWithCustomSeparator() throws Exception {
1942 servlet = new DispatcherServlet() {
1943 @Override
1944 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
1945 GenericWebApplicationContext wac = new GenericWebApplicationContext();
1946 wac.registerBeanDefinition("controller", new RootBeanDefinition(CsvController.class));
1947 RootBeanDefinition csDef = new RootBeanDefinition(FormattingConversionServiceFactoryBean.class);
1948 RootBeanDefinition wbiDef = new RootBeanDefinition(ConfigurableWebBindingInitializer.class);
1949 wbiDef.getPropertyValues().add("conversionService", csDef);
1950 wbiDef.getPropertyValues().add("propertyEditorRegistrars", new RootBeanDefinition(ListEditorRegistrar.class));
1951 RootBeanDefinition adapterDef = new RootBeanDefinition(AnnotationMethodHandlerAdapter.class);
1952 adapterDef.getPropertyValues().add("webBindingInitializer", wbiDef);
1953 wac.registerBeanDefinition("handlerAdapter", adapterDef);
1954 wac.refresh();
1955 return wac;
1956 }
1957 };
1958 servlet.init(new MockServletConfig());
1959
1960 MockHttpServletRequest request = new MockHttpServletRequest();
1961 request.setRequestURI("/integerSet");
1962 request.setMethod("POST");
1963 request.addParameter("content", "1;2");
1964 MockHttpServletResponse response = new MockHttpServletResponse();
1965 servlet.service(request, response);
1966 assertEquals("1-2", response.getContentAsString());
1967 }
1968
1969 public static class ListEditorRegistrar implements PropertyEditorRegistrar {
1970
1971 @Override
1972 public void registerCustomEditors(PropertyEditorRegistry registry) {
1973 registry.registerCustomEditor(Set.class, new ListEditor());
1974 }
1975 }
1976
1977 public static class ListEditor extends PropertyEditorSupport {
1978
1979 @SuppressWarnings("unchecked")
1980 @Override
1981 public String getAsText() {
1982 return StringUtils.collectionToDelimitedString((Collection<String>) getValue(), ";");
1983 }
1984
1985 @Override
1986 public void setAsText(String text) throws IllegalArgumentException {
1987 Set<String> s = new LinkedHashSet<String>();
1988 for (String t : text.split(";")) {
1989 s.add(t);
1990 }
1991 setValue(s);
1992 }
1993 }
1994
1995
1996
1997
1998
1999
2000 @RequestMapping("/myPath.do")
2001 private static class MyController extends AbstractController {
2002
2003 @Override
2004 protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
2005 throws Exception {
2006 response.getWriter().write("test");
2007 return null;
2008 }
2009 }
2010
2011 @Controller
2012 private static class ControllerWithEmptyMapping {
2013
2014 @RequestMapping
2015 public void myPath2(HttpServletResponse response) throws IOException {
2016 response.getWriter().write("test");
2017 }
2018 }
2019
2020 @Controller
2021 private static class ControllerWithEmptyValueMapping {
2022
2023 @RequestMapping("")
2024 public void myPath2(HttpServletResponse response) throws IOException {
2025 throw new IllegalStateException("test");
2026 }
2027
2028 @RequestMapping("/bar")
2029 public void myPath3(HttpServletResponse response) throws IOException {
2030 response.getWriter().write("testX");
2031 }
2032
2033 @ExceptionHandler
2034 public void myPath2(Exception ex, HttpServletResponse response) throws IOException {
2035 response.getWriter().write(ex.getMessage());
2036 }
2037 }
2038
2039 @Controller
2040 private static class MyAdaptedController {
2041
2042 @RequestMapping("/myPath1.do")
2043 public void myHandle(HttpServletRequest request, HttpServletResponse response) throws IOException {
2044 response.getWriter().write("test");
2045 }
2046
2047 @RequestMapping("/myPath2.do")
2048 public void myHandle(@RequestParam("param1") String p1, @RequestParam("param2") int p2,
2049 @RequestHeader("header1") long h1, @CookieValue("cookie1") Cookie c1,
2050 HttpServletResponse response) throws IOException {
2051 response.getWriter().write("test-" + p1 + "-" + p2 + "-" + h1 + "-" + c1.getValue());
2052 }
2053
2054 @RequestMapping("/myPath3")
2055 public void myHandle(TestBean tb, HttpServletResponse response) throws IOException {
2056 response.getWriter().write("test-" + tb.getName() + "-" + tb.getAge());
2057 }
2058
2059 @RequestMapping("/myPath4.do")
2060 public void myHandle(TestBean tb, Errors errors, HttpServletResponse response) throws IOException {
2061 response.getWriter().write("test-" + tb.getName() + "-" + errors.getFieldError("age").getCode());
2062 }
2063 }
2064
2065 @Controller
2066 @RequestMapping("/*.do")
2067 private static class MyAdaptedController2 {
2068
2069 @RequestMapping
2070 public void myHandle(HttpServletRequest request, HttpServletResponse response) throws IOException {
2071 response.getWriter().write("test");
2072 }
2073
2074 @RequestMapping("/myPath2.do")
2075 public void myHandle(@RequestParam("param1") String p1, int param2, HttpServletResponse response,
2076 @RequestHeader("header1") String h1, @CookieValue("cookie1") String c1) throws IOException {
2077 response.getWriter().write("test-" + p1 + "-" + param2 + "-" + h1 + "-" + c1);
2078 }
2079
2080 @RequestMapping("/myPath3")
2081 public void myHandle(TestBean tb, HttpServletResponse response) throws IOException {
2082 response.getWriter().write("test-" + tb.getName() + "-" + tb.getAge());
2083 }
2084
2085 @RequestMapping("/myPath4.*")
2086 public void myHandle(TestBean tb, Errors errors, HttpServletResponse response) throws IOException {
2087 response.getWriter().write("test-" + tb.getName() + "-" + errors.getFieldError("age").getCode());
2088 }
2089 }
2090
2091 @Controller
2092 private static class MyAdaptedControllerBase<T> {
2093
2094 @RequestMapping("/myPath2.do")
2095 public void myHandle(@RequestParam("param1") T p1, int param2, @RequestHeader Integer header1,
2096 @CookieValue int cookie1, HttpServletResponse response) throws IOException {
2097 response.getWriter().write("test-" + p1 + "-" + param2 + "-" + header1 + "-" + cookie1);
2098 }
2099
2100 @InitBinder
2101 public void initBinder(@RequestParam("param1") String p1, @RequestParam(value="paramX", required=false) String px, int param2) {
2102 assertNull(px);
2103 }
2104
2105 @ModelAttribute
2106 public void modelAttribute(@RequestParam("param1") String p1, @RequestParam(value="paramX", required=false) String px, int param2) {
2107 assertNull(px);
2108 }
2109 }
2110
2111 @RequestMapping("/*.do")
2112 private static class MyAdaptedController3 extends MyAdaptedControllerBase<String> {
2113
2114 @RequestMapping
2115 public void myHandle(HttpServletRequest request, HttpServletResponse response) throws IOException {
2116 response.getWriter().write("test");
2117 }
2118
2119 @Override
2120 public void myHandle(@RequestParam("param1") String p1, int param2, @RequestHeader Integer header1,
2121 @CookieValue int cookie1, HttpServletResponse response) throws IOException {
2122 response.getWriter().write("test-" + p1 + "-" + param2 + "-" + header1 + "-" + cookie1);
2123 }
2124
2125 @RequestMapping("/myPath3")
2126 public void myHandle(TestBean tb, HttpServletResponse response) throws IOException {
2127 response.getWriter().write("test-" + tb.getName() + "-" + tb.getAge());
2128 }
2129
2130 @RequestMapping("/myPath4.*")
2131 public void myHandle(TestBean tb, Errors errors, HttpServletResponse response) throws IOException {
2132 response.getWriter().write("test-" + tb.getName() + "-" + errors.getFieldError("age").getCode());
2133 }
2134
2135 @Override
2136 @InitBinder
2137 public void initBinder(@RequestParam("param1") String p1, @RequestParam(value="paramX", required=false) String px, int param2) {
2138 assertNull(px);
2139 }
2140
2141 @Override
2142 @ModelAttribute
2143 public void modelAttribute(@RequestParam("param1") String p1, @RequestParam(value="paramX", required=false) String px, int param2) {
2144 assertNull(px);
2145 }
2146 }
2147
2148 @Controller
2149 @RequestMapping(method = RequestMethod.GET)
2150 private static class EmptyParameterListHandlerMethodController {
2151
2152 static boolean called;
2153
2154 @RequestMapping("/emptyParameterListHandler")
2155 public void emptyParameterListHandler() {
2156 EmptyParameterListHandlerMethodController.called = true;
2157 }
2158
2159 @RequestMapping("/nonEmptyParameterListHandler")
2160 public void nonEmptyParameterListHandler(HttpServletResponse response) {
2161 }
2162 }
2163
2164 @Controller
2165 @RequestMapping("/myPage")
2166 @SessionAttributes({"object1", "object2"})
2167 public static class MySessionAttributesController {
2168
2169 @RequestMapping(method = RequestMethod.GET)
2170 public String get(Model model) {
2171 model.addAttribute("object1", new Object());
2172 model.addAttribute("object2", new Object());
2173 return "page1";
2174 }
2175
2176 @RequestMapping(method = RequestMethod.POST)
2177 public String post(@ModelAttribute("object1") Object object1) {
2178
2179 return "page2";
2180
2181 }
2182 }
2183
2184 @RequestMapping("/myPage")
2185 @SessionAttributes({"object1", "object2"})
2186 public interface MySessionAttributesControllerIfc {
2187
2188 @RequestMapping(method = RequestMethod.GET)
2189 String get(Model model);
2190
2191 @RequestMapping(method = RequestMethod.POST)
2192 String post(@ModelAttribute("object1") Object object1);
2193 }
2194
2195 @Controller
2196 public static class MySessionAttributesControllerImpl implements MySessionAttributesControllerIfc {
2197
2198 @Override
2199 public String get(Model model) {
2200 model.addAttribute("object1", new Object());
2201 model.addAttribute("object2", new Object());
2202 return "page1";
2203 }
2204
2205 @Override
2206 public String post(@ModelAttribute("object1") Object object1) {
2207
2208 return "page2";
2209 }
2210 }
2211
2212 @RequestMapping("/myPage")
2213 @SessionAttributes({"object1", "object2"})
2214 public interface MyParameterizedControllerIfc<T> {
2215
2216 @ModelAttribute("testBeanList")
2217 List<TestBean> getTestBeans();
2218
2219 @RequestMapping(method = RequestMethod.GET)
2220 String get(Model model);
2221 }
2222
2223 public interface MyEditableParameterizedControllerIfc<T> extends MyParameterizedControllerIfc<T> {
2224
2225 @RequestMapping(method = RequestMethod.POST)
2226 String post(@ModelAttribute("object1") T object);
2227 }
2228
2229 @Controller
2230 public static class MyParameterizedControllerImpl implements MyEditableParameterizedControllerIfc<TestBean> {
2231
2232 @Override
2233 public List<TestBean> getTestBeans() {
2234 List<TestBean> list = new LinkedList<TestBean>();
2235 list.add(new TestBean("tb1"));
2236 list.add(new TestBean("tb2"));
2237 return list;
2238 }
2239
2240 @Override
2241 public String get(Model model) {
2242 model.addAttribute("object1", new TestBean());
2243 model.addAttribute("object2", new TestBean());
2244 return "page1";
2245 }
2246
2247 @Override
2248 public String post(TestBean object) {
2249
2250 return "page2";
2251 }
2252 }
2253
2254 @Controller
2255 public static class MyParameterizedControllerImplWithOverriddenMappings implements MyEditableParameterizedControllerIfc<TestBean> {
2256
2257 @Override
2258 @ModelAttribute("testBeanList")
2259 public List<TestBean> getTestBeans() {
2260 List<TestBean> list = new LinkedList<TestBean>();
2261 list.add(new TestBean("tb1"));
2262 list.add(new TestBean("tb2"));
2263 return list;
2264 }
2265
2266 @Override
2267 @RequestMapping(method = RequestMethod.GET)
2268 public String get(Model model) {
2269 model.addAttribute("object1", new TestBean());
2270 model.addAttribute("object2", new TestBean());
2271 return "page1";
2272 }
2273
2274 @Override
2275 @RequestMapping(method = RequestMethod.POST)
2276 public String post(@ModelAttribute("object1") TestBean object1) {
2277
2278 return "page2";
2279 }
2280 }
2281
2282 @Controller
2283 public static class MyFormController {
2284
2285 @ModelAttribute("testBeanList")
2286 public List<TestBean> getTestBeans() {
2287 List<TestBean> list = new LinkedList<TestBean>();
2288 list.add(new TestBean("tb1"));
2289 list.add(new TestBean("tb2"));
2290 return list;
2291 }
2292
2293 @RequestMapping("/myPath.do")
2294 public String myHandle(@ModelAttribute("myCommand") TestBean tb, BindingResult errors, ModelMap model) {
2295 FieldError error = errors.getFieldError("age");
2296 assertNotNull("Must have field error for age property", error);
2297 assertEquals("value2", error.getRejectedValue());
2298 if (!model.containsKey("myKey")) {
2299 model.addAttribute("myKey", "myValue");
2300 }
2301 return "myView";
2302 }
2303 }
2304
2305 public static class ValidTestBean extends TestBean {
2306
2307 @NotNull(groups = MyGroup.class)
2308 private String validCountry;
2309
2310 public void setValidCountry(String validCountry) {
2311 this.validCountry = validCountry;
2312 }
2313
2314 public String getValidCountry() {
2315 return this.validCountry;
2316 }
2317 }
2318
2319 @Controller
2320 public static class MyModelFormController {
2321
2322 @ModelAttribute
2323 public List<TestBean> getTestBeans() {
2324 List<TestBean> list = new LinkedList<TestBean>();
2325 list.add(new TestBean("tb1"));
2326 list.add(new TestBean("tb2"));
2327 return list;
2328 }
2329
2330 @RequestMapping("/myPath.do")
2331 @ModelAttribute("yourKey")
2332 public String myHandle(@ModelAttribute("myCommand") TestBean tb, BindingResult errors, Model model) {
2333 if (!model.containsAttribute("myKey")) {
2334 model.addAttribute("myKey", "myValue");
2335 }
2336 return "yourValue";
2337 }
2338 }
2339
2340 @Controller
2341 private static class MyCommandProvidingFormController<T, TB, TB2> extends MyFormController {
2342
2343 @SuppressWarnings("unused")
2344 @ModelAttribute("myCommand")
2345 private ValidTestBean createTestBean(@RequestParam T defaultName, Map<String, Object> model, @RequestParam Date date) {
2346 model.put("myKey", "myOriginalValue");
2347 ValidTestBean tb = new ValidTestBean();
2348 tb.setName(defaultName.getClass().getSimpleName() + ":" + defaultName.toString());
2349 return tb;
2350 }
2351
2352 @Override
2353 @RequestMapping("/myPath.do")
2354 public String myHandle(@ModelAttribute("myCommand") @Validated(MyGroup.class) TestBean tb, BindingResult errors, ModelMap model) {
2355 if (!errors.hasFieldErrors("validCountry")) {
2356 throw new IllegalStateException("Declarative validation not applied");
2357 }
2358 return super.myHandle(tb, errors, model);
2359 }
2360
2361 @RequestMapping("/myOtherPath.do")
2362 public String myOtherHandle(TB tb, BindingResult errors, ExtendedModelMap model, MySpecialArg arg) {
2363 TestBean tbReal = (TestBean) tb;
2364 tbReal.setName("myName");
2365 assertTrue(model.get("ITestBean") instanceof DerivedTestBean);
2366 assertNotNull(arg);
2367 return super.myHandle(tbReal, errors, model);
2368 }
2369
2370 @RequestMapping("/myThirdPath.do")
2371 public String myThirdHandle(TB tb, Model model) {
2372 model.addAttribute("testBean", new TestBean("special", 99));
2373 return "myView";
2374 }
2375
2376 @ModelAttribute
2377 protected TB2 getModelAttr() {
2378 return (TB2) new DerivedTestBean();
2379 }
2380 }
2381
2382 private static class MySpecialArg {
2383
2384 public MySpecialArg(String value) {
2385 }
2386 }
2387
2388 @Controller
2389 private static class MyTypedCommandProvidingFormController
2390 extends MyCommandProvidingFormController<Integer, TestBean, ITestBean> {
2391 }
2392
2393 @Validated(MyGroup.class)
2394 @Target({ElementType.PARAMETER})
2395 @Retention(RetentionPolicy.RUNTIME)
2396 public @interface MyValid {
2397 }
2398
2399 @Controller
2400 private static class MyBinderInitializingCommandProvidingFormController extends MyCommandProvidingFormController {
2401
2402 @SuppressWarnings("unused")
2403 @InitBinder
2404 private void initBinder(WebDataBinder binder) {
2405 binder.initBeanPropertyAccess();
2406 binder.setRequiredFields("sex");
2407 LocalValidatorFactoryBean vf = new LocalValidatorFactoryBean();
2408 vf.afterPropertiesSet();
2409 binder.setValidator(vf);
2410 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
2411 dateFormat.setLenient(false);
2412 binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
2413 }
2414
2415 @Override
2416 @RequestMapping("/myPath.do")
2417 public String myHandle(@ModelAttribute("myCommand") @MyValid TestBean tb, BindingResult errors, ModelMap model) {
2418 if (!errors.hasFieldErrors("sex")) {
2419 throw new IllegalStateException("requiredFields not applied");
2420 }
2421 return super.myHandle(tb, errors, model);
2422 }
2423 }
2424
2425 @Controller
2426 private static class MySpecificBinderInitializingCommandProvidingFormController
2427 extends MyCommandProvidingFormController {
2428
2429 @SuppressWarnings("unused")
2430 @InitBinder({"myCommand", "date"})
2431 private void initBinder(WebDataBinder binder, String date, @RequestParam("date") String[] date2) {
2432 LocalValidatorFactoryBean vf = new LocalValidatorFactoryBean();
2433 vf.afterPropertiesSet();
2434 binder.setValidator(vf);
2435 assertEquals("2007-10-02", date);
2436 assertEquals(1, date2.length);
2437 assertEquals("2007-10-02", date2[0]);
2438 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
2439 dateFormat.setLenient(false);
2440 binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
2441 }
2442 }
2443
2444 public interface MyGroup {
2445 }
2446
2447 private static class MyWebBindingInitializer implements WebBindingInitializer {
2448
2449 @Override
2450 public void initBinder(WebDataBinder binder, WebRequest request) {
2451 LocalValidatorFactoryBean vf = new LocalValidatorFactoryBean();
2452 vf.afterPropertiesSet();
2453 binder.setValidator(vf);
2454 assertNotNull(request.getLocale());
2455 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
2456 dateFormat.setLenient(false);
2457 binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
2458 }
2459 }
2460
2461 private static class MySpecialArgumentResolver implements WebArgumentResolver {
2462
2463 @Override
2464 public Object resolveArgument(MethodParameter methodParameter, NativeWebRequest webRequest) {
2465 if (methodParameter.getParameterType().equals(MySpecialArg.class)) {
2466 return new MySpecialArg("myValue");
2467 }
2468 return UNRESOLVED;
2469 }
2470 }
2471
2472 @SuppressWarnings("serial")
2473 @Controller
2474 @RequestMapping("/myPath.do")
2475 private static class MyParameterDispatchingController implements Serializable {
2476
2477 @Autowired
2478 private transient ServletContext servletContext;
2479
2480 @Autowired
2481 private transient ServletConfig servletConfig;
2482
2483 @Autowired
2484 private HttpServletRequest request;
2485
2486 @Autowired
2487 private HttpServletResponse response;
2488
2489 @Autowired
2490 private HttpSession session;
2491
2492 @Autowired
2493 private WebRequest webRequest;
2494
2495 @RequestMapping
2496 public void myHandle(HttpServletResponse response, HttpServletRequest request) throws IOException {
2497 if (this.servletContext == null || this.servletConfig == null || this.request == null ||
2498 this.response == null || this.session == null || this.webRequest == null) {
2499 throw new IllegalStateException();
2500 }
2501 response.getWriter().write("myView");
2502 request.setAttribute("servletContext", this.servletContext);
2503 request.setAttribute("servletConfig", this.servletConfig);
2504 request.setAttribute("sessionId", this.session.getId());
2505 request.setAttribute("requestUri", this.request.getRequestURI());
2506 request.setAttribute("locale", this.webRequest.getLocale());
2507 }
2508
2509 @RequestMapping(params = {"view", "!lang"})
2510 public void myOtherHandle(HttpServletResponse response) throws IOException {
2511 response.getWriter().write("myOtherView");
2512 }
2513
2514 @RequestMapping(method = RequestMethod.GET, params = {"view=my", "lang=de"})
2515 public void myLangHandle(HttpServletResponse response) throws IOException {
2516 response.getWriter().write("myLangView");
2517 }
2518
2519 @RequestMapping(method = {RequestMethod.POST, RequestMethod.GET}, params = "surprise")
2520 public void mySurpriseHandle(HttpServletResponse response) throws IOException {
2521 response.getWriter().write("mySurpriseView");
2522 }
2523 }
2524
2525 @Controller
2526 @RequestMapping(value = "/myPath.do", params = {"active"})
2527 private static class MyConstrainedParameterDispatchingController {
2528
2529 @RequestMapping(params = {"view", "!lang"})
2530 public void myOtherHandle(HttpServletResponse response) throws IOException {
2531 response.getWriter().write("myOtherView");
2532 }
2533
2534 @RequestMapping(method = RequestMethod.GET, params = {"view=my", "lang=de"})
2535 public void myLangHandle(HttpServletResponse response) throws IOException {
2536 response.getWriter().write("myLangView");
2537 }
2538 }
2539
2540 @Controller
2541 @RequestMapping(value = "/*.do", method = RequestMethod.POST, params = "myParam=myValue")
2542 private static class MyPostMethodNameDispatchingController extends MethodNameDispatchingController {
2543
2544 }
2545
2546 @Controller
2547 @RequestMapping("/myApp/*")
2548 private static class MyRelativePathDispatchingController {
2549
2550 @RequestMapping
2551 public void myHandle(HttpServletResponse response) throws IOException {
2552 response.getWriter().write("myView");
2553 }
2554
2555 @RequestMapping("*Other")
2556 public void myOtherHandle(HttpServletResponse response) throws IOException {
2557 response.getWriter().write("myOtherView");
2558 }
2559
2560 @RequestMapping("myLang")
2561 public void myLangHandle(HttpServletResponse response) throws IOException {
2562 response.getWriter().write("myLangView");
2563 }
2564
2565 @RequestMapping("surprise")
2566 public void mySurpriseHandle(HttpServletResponse response) throws IOException {
2567 response.getWriter().write("mySurpriseView");
2568 }
2569 }
2570
2571 @Controller
2572 private static class MyRelativeMethodPathDispatchingController {
2573
2574 @RequestMapping("**/myHandle")
2575 public void myHandle(HttpServletResponse response) throws IOException {
2576 response.getWriter().write("myView");
2577 }
2578
2579 @RequestMapping("/**/*Other")
2580 public void myOtherHandle(HttpServletResponse response) throws IOException {
2581 response.getWriter().write("myOtherView");
2582 }
2583
2584 @RequestMapping("**/myLang")
2585 public void myLangHandle(HttpServletResponse response) throws IOException {
2586 response.getWriter().write("myLangView");
2587 }
2588
2589 @RequestMapping("/**/surprise")
2590 public void mySurpriseHandle(HttpServletResponse response) throws IOException {
2591 response.getWriter().write("mySurpriseView");
2592 }
2593 }
2594
2595 @Controller
2596 private static class MyNullCommandController {
2597
2598 @ModelAttribute
2599 public TestBean getTestBean() {
2600 return null;
2601 }
2602
2603 @ModelAttribute
2604 public Principal getPrincipal() {
2605 return new TestPrincipal();
2606 }
2607
2608 @RequestMapping("/myPath")
2609 public void handle(@ModelAttribute TestBean testBean,
2610 Errors errors,
2611 @ModelAttribute TestPrincipal modelPrinc,
2612 OtherPrincipal requestPrinc,
2613 Writer writer) throws IOException {
2614 assertNull(testBean);
2615 assertNotNull(modelPrinc);
2616 assertNotNull(requestPrinc);
2617 assertFalse(errors.hasErrors());
2618 errors.reject("myCode");
2619 writer.write("myView");
2620 }
2621 }
2622
2623 private static class TestPrincipal implements Principal {
2624
2625 @Override
2626 public String getName() {
2627 return "test";
2628 }
2629 }
2630
2631 private static class OtherPrincipal implements Principal {
2632
2633 @Override
2634 public String getName() {
2635 return "other";
2636 }
2637 }
2638
2639 private static class TestViewResolver implements ViewResolver {
2640
2641 @Override
2642 public View resolveViewName(final String viewName, Locale locale) throws Exception {
2643 return new View() {
2644 @Override
2645 public String getContentType() {
2646 return null;
2647 }
2648
2649 @Override
2650 @SuppressWarnings({"unchecked", "deprecation"})
2651 public void render(Map model, HttpServletRequest request, HttpServletResponse response)
2652 throws Exception {
2653 TestBean tb = (TestBean) model.get("testBean");
2654 if (tb == null) {
2655 tb = (TestBean) model.get("myCommand");
2656 }
2657 if (tb.getName() != null && tb.getName().endsWith("myDefaultName")) {
2658 assertEquals(107, tb.getDate().getYear());
2659 }
2660 Errors errors = (Errors) model.get(BindingResult.MODEL_KEY_PREFIX + "testBean");
2661 if (errors == null) {
2662 errors = (Errors) model.get(BindingResult.MODEL_KEY_PREFIX + "myCommand");
2663 }
2664 if (errors.hasFieldErrors("date")) {
2665 throw new IllegalStateException();
2666 }
2667 if (model.containsKey("ITestBean")) {
2668 assertTrue(model.get(BindingResult.MODEL_KEY_PREFIX + "ITestBean") instanceof Errors);
2669 }
2670 List<TestBean> testBeans = (List<TestBean>) model.get("testBeanList");
2671 if (errors.hasFieldErrors("age")) {
2672 response.getWriter()
2673 .write(viewName + "-" + tb.getName() + "-" + errors.getFieldError("age").getCode() +
2674 "-" + testBeans.get(0).getName() + "-" + model.get("myKey") +
2675 (model.containsKey("yourKey") ? "-" + model.get("yourKey") : ""));
2676 }
2677 else {
2678 response.getWriter().write(viewName + "-" + tb.getName() + "-" + tb.getAge() + "-" +
2679 errors.getFieldValue("name") + "-" + errors.getFieldValue("age"));
2680 }
2681 }
2682 };
2683 }
2684 }
2685
2686 public static class ModelExposingViewResolver implements ViewResolver {
2687
2688 @Override
2689 public View resolveViewName(final String viewName, Locale locale) throws Exception {
2690 return new View() {
2691 @Override
2692 public String getContentType() {
2693 return null;
2694 }
2695 @Override
2696 public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) {
2697 request.setAttribute("viewName", viewName);
2698 request.getSession().setAttribute("model", model);
2699 }
2700 };
2701 }
2702 }
2703
2704 public static class ParentController {
2705
2706 @RequestMapping(method = RequestMethod.GET)
2707 public void doGet(HttpServletRequest req, HttpServletResponse resp) {
2708 }
2709 }
2710
2711 @Controller
2712 @RequestMapping("/child/test")
2713 public static class ChildController extends ParentController {
2714
2715 @RequestMapping(method = RequestMethod.GET)
2716 public void doGet(HttpServletRequest req, HttpServletResponse resp, @RequestParam("childId") String id) {
2717 }
2718 }
2719
2720 @Controller
2721 @Target({ElementType.TYPE})
2722 @Retention(RetentionPolicy.RUNTIME)
2723 public @interface MyControllerAnnotation {
2724 }
2725
2726 @MyControllerAnnotation
2727 public static class CustomAnnotationController {
2728
2729 @RequestMapping("/myPath.do")
2730 public void myHandle() {
2731 }
2732 }
2733
2734 @Controller
2735 public static class RequiredParamController {
2736
2737 @RequestMapping("/myPath.do")
2738 public void myHandle(@RequestParam(value = "id", required = true) int id,
2739 @RequestHeader(value = "header", required = true) String header) {
2740 }
2741 }
2742
2743 @Controller
2744 public static class OptionalParamController {
2745
2746 @RequestMapping("/myPath.do")
2747 public void myHandle(@RequestParam(required = false) String id,
2748 @RequestParam(required = false) boolean flag,
2749 @RequestHeader(value = "header", required = false) String header,
2750 HttpServletResponse response) throws IOException {
2751 response.getWriter().write(String.valueOf(id) + "-" + flag + "-" + String.valueOf(header));
2752 }
2753 }
2754
2755 @Controller
2756 public static class DefaultValueParamController {
2757
2758 @RequestMapping("/myPath.do")
2759 public void myHandle(@RequestParam(value = "id", defaultValue = "foo") String id,
2760 @RequestParam(value = "otherId", defaultValue = "") String id2,
2761 @RequestHeader(defaultValue = "bar") String header,
2762 HttpServletResponse response) throws IOException {
2763 response.getWriter().write(String.valueOf(id) + "-" + String.valueOf(id2) + "-" + String.valueOf(header));
2764 }
2765 }
2766
2767 @Controller
2768 public static class DefaultExpressionValueParamController {
2769
2770 @RequestMapping("/myPath.do")
2771 public void myHandle(@RequestParam(value = "id", defaultValue = "${myKey}") String id,
2772 @RequestHeader(defaultValue = "#{systemProperties.myHeader}") String header,
2773 @Value("#{request.contextPath}") String contextPath,
2774 HttpServletResponse response) throws IOException {
2775 response.getWriter().write(String.valueOf(id) + "-" + String.valueOf(header) + "-" + contextPath);
2776 }
2777 }
2778
2779 @Controller
2780 public static class NestedSetController {
2781
2782 @RequestMapping("/myPath.do")
2783 public void myHandle(GenericBean gb, HttpServletResponse response) throws Exception {
2784 response.getWriter().write(gb.getTestBeanSet().toString() + "-" +
2785 gb.getTestBeanSet().iterator().next().getClass().getName());
2786 }
2787 }
2788
2789 public static class TestBeanConverter implements Converter<String, ITestBean> {
2790
2791 @Override
2792 public ITestBean convert(String source) {
2793 return new TestBean(source);
2794 }
2795 }
2796
2797 @Controller
2798 public static class MethodNotAllowedController {
2799
2800 @RequestMapping(value = "/myPath.do", method = RequestMethod.DELETE)
2801 public void delete() {
2802 }
2803
2804 @RequestMapping(value = "/myPath.do", method = RequestMethod.HEAD)
2805 public void head() {
2806 }
2807
2808 @RequestMapping(value = "/myPath.do", method = RequestMethod.OPTIONS)
2809 public void options() {
2810 }
2811
2812 @RequestMapping(value = "/myPath.do", method = RequestMethod.POST)
2813 public void post() {
2814 }
2815
2816 @RequestMapping(value = "/myPath.do", method = RequestMethod.PUT)
2817 public void put() {
2818 }
2819
2820 @RequestMapping(value = "/myPath.do", method = RequestMethod.TRACE)
2821 public void trace() {
2822 }
2823
2824 @RequestMapping(value = "/otherPath.do", method = RequestMethod.GET)
2825 public void get() {
2826 }
2827 }
2828
2829 @Controller
2830 public static class PathOrderingController {
2831
2832 @RequestMapping(value = {"/dir/myPath1.do", "/**/*.do"})
2833 public void method1(Writer writer) throws IOException {
2834 writer.write("method1");
2835 }
2836
2837 @RequestMapping("/dir/*.do")
2838 public void method2(Writer writer) throws IOException {
2839 writer.write("method2");
2840 }
2841 }
2842
2843 @Controller
2844 public static class RequestResponseBodyController {
2845
2846 @RequestMapping(value = "/something", method = RequestMethod.PUT)
2847 @ResponseBody
2848 public String handle(@RequestBody String body) throws IOException {
2849 return body;
2850 }
2851 }
2852
2853 @Controller
2854 public static class ResponseBodyVoidController {
2855
2856 @RequestMapping("/something")
2857 @ResponseBody
2858 public void handle() throws IOException {
2859 }
2860 }
2861
2862 @Controller
2863 public static class RequestBodyArgMismatchController {
2864
2865 @RequestMapping(value = "/something", method = RequestMethod.PUT)
2866 public void handle(@RequestBody A a) throws IOException {
2867 }
2868 }
2869
2870 @XmlRootElement
2871 public static class A {
2872
2873 }
2874
2875 @XmlRootElement
2876 public static class B {
2877
2878 }
2879
2880
2881 public static class NotReadableMessageConverter implements HttpMessageConverter {
2882
2883 @Override
2884 public boolean canRead(Class clazz, MediaType mediaType) {
2885 return true;
2886 }
2887
2888 @Override
2889 public boolean canWrite(Class clazz, MediaType mediaType) {
2890 return true;
2891 }
2892
2893 @Override
2894 public List getSupportedMediaTypes() {
2895 return Collections.singletonList(new MediaType("application", "pdf"));
2896 }
2897
2898 @Override
2899 public Object read(Class clazz, HttpInputMessage inputMessage)
2900 throws IOException, HttpMessageNotReadableException {
2901 throw new HttpMessageNotReadableException("Could not read");
2902 }
2903
2904 @Override
2905 public void write(Object o, MediaType contentType, HttpOutputMessage outputMessage)
2906 throws IOException, HttpMessageNotWritableException {
2907 throw new UnsupportedOperationException("Not implemented");
2908 }
2909 }
2910
2911 public static class SimpleMessageConverter implements HttpMessageConverter {
2912
2913 private final List<MediaType> supportedMediaTypes;
2914
2915 public SimpleMessageConverter(MediaType... supportedMediaTypes) {
2916 this.supportedMediaTypes = Arrays.asList(supportedMediaTypes);
2917 }
2918
2919 @Override
2920 public boolean canRead(Class clazz, MediaType mediaType) {
2921 return supportedMediaTypes.contains(mediaType);
2922 }
2923
2924 @Override
2925 public boolean canWrite(Class clazz, MediaType mediaType) {
2926 return supportedMediaTypes.contains(mediaType);
2927 }
2928
2929 @Override
2930 public List getSupportedMediaTypes() {
2931 return supportedMediaTypes;
2932 }
2933
2934 @Override
2935 public Object read(Class clazz, HttpInputMessage inputMessage)
2936 throws IOException, HttpMessageNotReadableException {
2937 return null;
2938 }
2939
2940 @Override
2941 public void write(Object o, MediaType contentType, HttpOutputMessage outputMessage)
2942 throws IOException, HttpMessageNotWritableException {
2943 outputMessage.getHeaders().setContentType(contentType);
2944 outputMessage.getBody();
2945 }
2946 }
2947
2948 @Controller
2949 public static class ContentTypeHeadersController {
2950
2951 @RequestMapping(value = "/something", headers = "content-type=application/pdf")
2952 public void handlePdf(Writer writer) throws IOException {
2953 writer.write("pdf");
2954 }
2955
2956 @RequestMapping(value = "/something", headers = "content-type=text/*")
2957 public void handleHtml(Writer writer) throws IOException {
2958 writer.write("text");
2959 }
2960 }
2961
2962 @Controller
2963 public static class NegatedContentTypeHeadersController {
2964
2965 @RequestMapping(value = "/something", headers = "content-type=application/pdf")
2966 public void handlePdf(Writer writer) throws IOException {
2967 writer.write("pdf");
2968 }
2969
2970 @RequestMapping(value = "/something", headers = "content-type!=application/pdf")
2971 public void handleNonPdf(Writer writer) throws IOException {
2972 writer.write("non-pdf");
2973 }
2974
2975 }
2976
2977 @Controller
2978 public static class AcceptHeadersController {
2979
2980 @RequestMapping(value = "/something", headers = "accept=text/html")
2981 public void handleHtml(Writer writer) throws IOException {
2982 writer.write("html");
2983 }
2984
2985 @RequestMapping(value = "/something", headers = "accept=application/xml")
2986 public void handleXml(Writer writer) throws IOException {
2987 writer.write("xml");
2988 }
2989 }
2990
2991 @Controller
2992 public static class ResponseStatusController {
2993
2994 @RequestMapping("/something")
2995 @ResponseStatus(value = HttpStatus.CREATED, reason = "It's alive!")
2996 public void handle(Writer writer) throws IOException {
2997 writer.write("something");
2998 }
2999 }
3000
3001 @Controller
3002 public static class ModelAndViewResolverController {
3003
3004 @RequestMapping("/")
3005 public MySpecialArg handle() {
3006 return new MySpecialArg("foo");
3007 }
3008 }
3009
3010 public static class MyModelAndViewResolver implements ModelAndViewResolver {
3011
3012 @Override
3013 public ModelAndView resolveModelAndView(Method handlerMethod,
3014 Class handlerType,
3015 Object returnValue,
3016 ExtendedModelMap implicitModel,
3017 NativeWebRequest webRequest) {
3018 if (returnValue instanceof MySpecialArg) {
3019 return new ModelAndView(new View() {
3020 @Override
3021 public String getContentType() {
3022 return "text/html";
3023 }
3024
3025 @Override
3026 public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
3027 throws Exception {
3028 response.getWriter().write("myValue");
3029 }
3030
3031 });
3032 }
3033 return UNRESOLVED;
3034 }
3035 }
3036
3037 @Controller
3038 @RequestMapping("/test*")
3039 private static class AmbiguousParamsController {
3040
3041 @RequestMapping(method = RequestMethod.GET)
3042 public void noParams(Writer writer) throws IOException {
3043 writer.write("noParams");
3044 }
3045
3046 @RequestMapping(params = "myParam")
3047 public void param(@RequestParam("myParam") int myParam, Writer writer) throws IOException {
3048 writer.write("myParam-" + myParam);
3049 }
3050 }
3051
3052 @Controller
3053 @RequestMapping("/test*")
3054 public static class BindingCookieValueController {
3055
3056 @InitBinder
3057 public void initBinder(WebDataBinder binder) {
3058 binder.initBeanPropertyAccess();
3059 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
3060 dateFormat.setLenient(false);
3061 binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
3062 }
3063
3064 @RequestMapping(method = RequestMethod.GET)
3065 public void handle(@CookieValue("date") Date date, Writer writer) throws IOException {
3066 assertEquals("Invalid path variable value", new GregorianCalendar(2008, 10, 18).getTime(), date);
3067 Calendar c = new GregorianCalendar();
3068 c.setTime(date);
3069 writer.write("test-" + c.get(Calendar.YEAR));
3070 }
3071 }
3072
3073 public interface TestController<T> {
3074
3075 ModelAndView method(T object);
3076 }
3077
3078 public static class MyEntity {
3079
3080 }
3081
3082 @Controller
3083 public static class TestControllerImpl implements TestController<MyEntity> {
3084
3085 @Override
3086 @RequestMapping("/method")
3087 public ModelAndView method(MyEntity object) {
3088 return new ModelAndView("/something");
3089 }
3090 }
3091
3092 @Controller
3093 public static class RequestParamMapController {
3094
3095 @RequestMapping("/map")
3096 public void map(@RequestParam Map<String, String> params, Writer writer) throws IOException {
3097 for (Iterator<Map.Entry<String, String>> it = params.entrySet().iterator(); it.hasNext();) {
3098 Map.Entry<String, String> entry = it.next();
3099 writer.write(entry.getKey() + "=" + entry.getValue());
3100 if (it.hasNext()) {
3101 writer.write(',');
3102 }
3103
3104 }
3105 }
3106
3107 @RequestMapping("/multiValueMap")
3108 public void multiValueMap(@RequestParam MultiValueMap<String, String> params, Writer writer)
3109 throws IOException {
3110 for (Iterator<Map.Entry<String, List<String>>> it1 = params.entrySet().iterator(); it1.hasNext();) {
3111 Map.Entry<String, List<String>> entry = it1.next();
3112 writer.write(entry.getKey() + "=[");
3113 for (Iterator<String> it2 = entry.getValue().iterator(); it2.hasNext();) {
3114 String value = it2.next();
3115 writer.write(value);
3116 if (it2.hasNext()) {
3117 writer.write(',');
3118 }
3119 }
3120 writer.write(']');
3121 if (it1.hasNext()) {
3122 writer.write(',');
3123 }
3124 }
3125 }
3126 }
3127
3128 @Controller
3129 public static class RequestHeaderMapController {
3130
3131 @RequestMapping("/map")
3132 public void map(@RequestHeader Map<String, String> headers, Writer writer) throws IOException {
3133 for (Iterator<Map.Entry<String, String>> it = headers.entrySet().iterator(); it.hasNext();) {
3134 Map.Entry<String, String> entry = it.next();
3135 writer.write(entry.getKey() + "=" + entry.getValue());
3136 if (it.hasNext()) {
3137 writer.write(',');
3138 }
3139
3140 }
3141 }
3142
3143 @RequestMapping("/multiValueMap")
3144 public void multiValueMap(@RequestHeader MultiValueMap<String, String> headers, Writer writer)
3145 throws IOException {
3146 for (Iterator<Map.Entry<String, List<String>>> it1 = headers.entrySet().iterator(); it1.hasNext();) {
3147 Map.Entry<String, List<String>> entry = it1.next();
3148 writer.write(entry.getKey() + "=[");
3149 for (Iterator<String> it2 = entry.getValue().iterator(); it2.hasNext();) {
3150 String value = it2.next();
3151 writer.write(value);
3152 if (it2.hasNext()) {
3153 writer.write(',');
3154 }
3155 }
3156 writer.write(']');
3157 if (it1.hasNext()) {
3158 writer.write(',');
3159 }
3160 }
3161 }
3162
3163 @RequestMapping("/httpHeaders")
3164 public void httpHeaders(@RequestHeader HttpHeaders headers, Writer writer) throws IOException {
3165 assertEquals("Invalid Content-Type", new MediaType("text", "html"), headers.getContentType());
3166 multiValueMap(headers, writer);
3167 }
3168
3169 }
3170
3171 @Controller
3172 public interface IMyController {
3173
3174 @RequestMapping("/handle")
3175 void handle(Writer writer, @RequestParam(value="p", required=false) String param) throws IOException;
3176 }
3177
3178 @Controller
3179 public static class IMyControllerImpl implements IMyController {
3180
3181 @Override
3182 public void handle(Writer writer, @RequestParam(value="p", required=false) String param) throws IOException {
3183 writer.write("handle " + param);
3184 }
3185 }
3186
3187 public static abstract class MyAbstractController {
3188
3189 @RequestMapping("/handle")
3190 public abstract void handle(Writer writer) throws IOException;
3191 }
3192
3193 @Controller
3194 public static class MyAbstractControllerImpl extends MyAbstractController {
3195
3196 @Override
3197 public void handle(Writer writer) throws IOException {
3198 writer.write("handle");
3199 }
3200 }
3201
3202 @Controller
3203 public static class TrailingSlashController {
3204
3205 @RequestMapping(value = "/", method = RequestMethod.GET)
3206 public void root(Writer writer) throws IOException {
3207 writer.write("root");
3208 }
3209
3210 @RequestMapping(value = "/{templatePath}/", method = RequestMethod.GET)
3211 public void templatePath(Writer writer) throws IOException {
3212 writer.write("templatePath");
3213 }
3214 }
3215
3216 @Controller
3217 public static class ResponseEntityController {
3218
3219 @RequestMapping("/foo")
3220 public ResponseEntity<String> foo(HttpEntity<byte[]> requestEntity) throws UnsupportedEncodingException {
3221 assertNotNull(requestEntity);
3222 assertEquals("MyValue", requestEntity.getHeaders().getFirst("MyRequestHeader"));
3223 String requestBody = new String(requestEntity.getBody(), "UTF-8");
3224 assertEquals("Hello World", requestBody);
3225
3226 HttpHeaders responseHeaders = new HttpHeaders();
3227 responseHeaders.set("MyResponseHeader", "MyValue");
3228 return new ResponseEntity<String>(requestBody, responseHeaders, HttpStatus.CREATED);
3229 }
3230
3231 @RequestMapping("/bar")
3232 public ResponseEntity<String> bar() {
3233 HttpHeaders responseHeaders = new HttpHeaders();
3234 responseHeaders.set("MyResponseHeader", "MyValue");
3235 return new ResponseEntity<String>(responseHeaders, HttpStatus.NOT_FOUND);
3236 }
3237
3238 }
3239
3240 @Controller
3241 public static class CustomMapEditorController {
3242
3243 @InitBinder
3244 public void initBinder(WebDataBinder binder) {
3245 binder.initBeanPropertyAccess();
3246 binder.registerCustomEditor(Map.class, new CustomMapEditor());
3247 }
3248
3249 @RequestMapping("/handle")
3250 public void handle(@RequestParam("map") Map map, Writer writer) throws IOException {
3251 writer.write("test-" + map);
3252 }
3253 }
3254
3255 public static class CustomMapEditor extends PropertyEditorSupport {
3256
3257 @Override
3258 public void setAsText(String text) throws IllegalArgumentException {
3259 if (StringUtils.hasText(text)) {
3260 setValue(Collections.singletonMap("foo", text));
3261 }
3262 else {
3263 setValue(null);
3264 }
3265 }
3266
3267 }
3268
3269 @Controller
3270 public static class MultipartController {
3271
3272 @InitBinder
3273 public void initBinder(WebDataBinder binder) {
3274 binder.registerCustomEditor(String.class, new StringMultipartFileEditor());
3275 }
3276
3277 @RequestMapping("/singleString")
3278 public void processMultipart(@RequestParam("content") String content, HttpServletResponse response) throws IOException {
3279 response.getWriter().write(content);
3280 }
3281
3282 @RequestMapping("/stringArray")
3283 public void processMultipart(@RequestParam("content") String[] content, HttpServletResponse response) throws IOException {
3284 response.getWriter().write(StringUtils.arrayToDelimitedString(content, "-"));
3285 }
3286 }
3287
3288 @Controller
3289 public static class CsvController {
3290
3291 @RequestMapping("/singleInteger")
3292 public void processCsv(@RequestParam("content") Integer content, HttpServletResponse response) throws IOException {
3293 response.getWriter().write(content.toString());
3294 }
3295
3296 @RequestMapping("/integerArray")
3297 public void processCsv(@RequestParam("content") Integer[] content, HttpServletResponse response) throws IOException {
3298 response.getWriter().write(StringUtils.arrayToDelimitedString(content, "-"));
3299 }
3300
3301 @RequestMapping("/integerSet")
3302 public void processCsv(@RequestParam("content") Set<Integer> content, HttpServletResponse response) throws IOException {
3303 assertThat(content.iterator().next(), instanceOf(Integer.class));
3304 response.getWriter().write(StringUtils.collectionToDelimitedString(content, "-"));
3305 }
3306 }
3307
3308 @Controller
3309 @RequestMapping("/t1")
3310 protected static class NoPathGetAndM2PostController {
3311 @RequestMapping(method = RequestMethod.GET)
3312 public void handle1(Writer writer) throws IOException {
3313 writer.write("handle1");
3314 }
3315
3316 @RequestMapping(value = "/m2", method = RequestMethod.POST)
3317 public void handle2(Writer writer) throws IOException {
3318 writer.write("handle2");
3319 }
3320 }
3321
3322 @Controller
3323 static class HeadersConditionController {
3324
3325 @RequestMapping(value = "/", method = RequestMethod.GET)
3326 public String home() {
3327 return "home";
3328 }
3329
3330 @RequestMapping(value = "/", method = RequestMethod.GET, headers="Accept=application/json")
3331 @ResponseBody
3332 public String homeJson() {
3333 return "homeJson";
3334 }
3335 }
3336
3337 @Controller
3338 static class RedirectAttributesController {
3339
3340 @RequestMapping(value = "/")
3341 public void handle(RedirectAttributes redirectAttrs) {
3342 }
3343 }
3344
3345 }