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