SPR-6464 Add @FlashAttributes annotation and FlashStatus method argument
This commit is contained in:
@@ -50,8 +50,10 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.SessionAttributes;
|
||||
import org.springframework.web.bind.support.DefaultDataBinderFactory;
|
||||
import org.springframework.web.bind.support.DefaultSessionAttributeStore;
|
||||
import org.springframework.web.bind.support.FlashStatus;
|
||||
import org.springframework.web.bind.support.SessionAttributeStore;
|
||||
import org.springframework.web.bind.support.SessionStatus;
|
||||
import org.springframework.web.bind.support.SimpleFlashStatus;
|
||||
import org.springframework.web.bind.support.SimpleSessionStatus;
|
||||
import org.springframework.web.bind.support.WebBindingInitializer;
|
||||
import org.springframework.web.bind.support.WebDataBinderFactory;
|
||||
@@ -59,6 +61,7 @@ import org.springframework.web.context.request.ServletWebRequest;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.method.HandlerMethodSelector;
|
||||
import org.springframework.web.method.annotation.FlashAttributesHandler;
|
||||
import org.springframework.web.method.annotation.ModelFactory;
|
||||
import org.springframework.web.method.annotation.SessionAttributesHandler;
|
||||
import org.springframework.web.method.annotation.support.ErrorsMethodArgumentResolver;
|
||||
@@ -146,6 +149,9 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
|
||||
private final Map<Class<?>, SessionAttributesHandler> sessionAttributesHandlerCache =
|
||||
new ConcurrentHashMap<Class<?>, SessionAttributesHandler>();
|
||||
|
||||
private final Map<Class<?>, FlashAttributesHandler> flashAttributesHandlerCache =
|
||||
new ConcurrentHashMap<Class<?>, FlashAttributesHandler>();
|
||||
|
||||
private HandlerMethodArgumentResolverComposite argumentResolvers;
|
||||
|
||||
private HandlerMethodArgumentResolverComposite initBinderArgumentResolvers;
|
||||
@@ -481,19 +487,27 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the given handler type defines any handler-specific session attributes via {@link SessionAttributes}.
|
||||
* Also initializes the sessionAttributesHandlerCache for the given handler type.
|
||||
* Whether the given handler type defines any handler-specific session attributes
|
||||
* via {@link SessionAttributes}.
|
||||
*/
|
||||
private boolean hasSessionAttributes(Class<?> handlerType) {
|
||||
SessionAttributesHandler handler = null;
|
||||
SessionAttributesHandler sessionAttrsHandler = null;
|
||||
synchronized(this.sessionAttributesHandlerCache) {
|
||||
handler = this.sessionAttributesHandlerCache.get(handlerType);
|
||||
if (handler == null) {
|
||||
handler = new SessionAttributesHandler(handlerType, sessionAttributeStore);
|
||||
this.sessionAttributesHandlerCache.put(handlerType, handler);
|
||||
sessionAttrsHandler = this.sessionAttributesHandlerCache.get(handlerType);
|
||||
if (sessionAttrsHandler == null) {
|
||||
sessionAttrsHandler = new SessionAttributesHandler(handlerType, sessionAttributeStore);
|
||||
this.sessionAttributesHandlerCache.put(handlerType, sessionAttrsHandler);
|
||||
}
|
||||
}
|
||||
return handler.hasSessionAttributes();
|
||||
FlashAttributesHandler flashAttrsHandler = null;
|
||||
synchronized(this.flashAttributesHandlerCache) {
|
||||
flashAttrsHandler = this.flashAttributesHandlerCache.get(handlerType);
|
||||
if (flashAttrsHandler == null) {
|
||||
flashAttrsHandler = new FlashAttributesHandler(handlerType);
|
||||
this.flashAttributesHandlerCache.put(handlerType, flashAttrsHandler);
|
||||
}
|
||||
}
|
||||
return sessionAttrsHandler.hasSessionAttributes() || flashAttrsHandler.hasFlashAttributes();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -509,12 +523,13 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
|
||||
|
||||
ServletWebRequest webRequest = new ServletWebRequest(request, response);
|
||||
SessionStatus sessionStatus = new SimpleSessionStatus();
|
||||
FlashStatus flashStatus = new SimpleFlashStatus();
|
||||
|
||||
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
|
||||
modelFactory.initModel(webRequest, mavContainer, requestMethod);
|
||||
|
||||
requestMethod.invokeAndHandle(webRequest, mavContainer, sessionStatus);
|
||||
modelFactory.updateModel(webRequest, mavContainer, sessionStatus);
|
||||
requestMethod.invokeAndHandle(webRequest, mavContainer, sessionStatus, flashStatus);
|
||||
modelFactory.updateModel(webRequest, mavContainer, sessionStatus, flashStatus);
|
||||
|
||||
if (!mavContainer.isResolveView()) {
|
||||
return null;
|
||||
@@ -569,7 +584,10 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
|
||||
modelAttrMethods.add(attrMethod);
|
||||
}
|
||||
|
||||
return new ModelFactory(modelAttrMethods, binderFactory, sessionAttributesHandlerCache.get(handlerType));
|
||||
SessionAttributesHandler sessionAttrsHandler = sessionAttributesHandlerCache.get(handlerType);
|
||||
FlashAttributesHandler flashAttrsHandler = flashAttributesHandlerCache.get(handlerType);
|
||||
|
||||
return new ModelFactory(modelAttrMethods, binderFactory, sessionAttrsHandler, flashAttrsHandler);
|
||||
}
|
||||
|
||||
private ServletInvocableHandlerMethod createRequestMappingMethod(HandlerMethod handlerMethod,
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.servlet.mvc.method.annotation;
|
||||
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import org.junit.After;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.mock.web.MockServletConfig;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver;
|
||||
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
|
||||
|
||||
/**
|
||||
* Base class for tests using on the DispatcherServlet and HandlerMethod infrastructure classes:
|
||||
* <ul>
|
||||
* <li>RequestMappingHandlerMapping
|
||||
* <li>RequestMappingHandlerAdapter
|
||||
* <li>ExceptionHandlerExceptionResolver
|
||||
* </ul>
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class AbstractServletHandlerMethodTests {
|
||||
|
||||
private DispatcherServlet servlet;
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
this.servlet = null;
|
||||
}
|
||||
|
||||
protected DispatcherServlet getServlet() {
|
||||
assertNotNull("DispatcherServlet not initialized", servlet);
|
||||
return servlet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a DispatcherServlet instance registering zero or more controller classes.
|
||||
*/
|
||||
protected WebApplicationContext initServletWithControllers(final Class<?>... controllerClasses)
|
||||
throws ServletException {
|
||||
return initServlet(null, controllerClasses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a DispatcherServlet instance registering zero or more controller classes
|
||||
* and also providing additional bean definitions through a callback.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
protected WebApplicationContext initServlet(
|
||||
final ApplicationContextInitializer<GenericWebApplicationContext> initializer,
|
||||
final Class<?>... controllerClasses) throws ServletException {
|
||||
|
||||
final GenericWebApplicationContext wac = new GenericWebApplicationContext();
|
||||
|
||||
servlet = new DispatcherServlet() {
|
||||
@Override
|
||||
protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
|
||||
for (Class<?> clazz : controllerClasses) {
|
||||
wac.registerBeanDefinition(clazz.getSimpleName(), new RootBeanDefinition(clazz));
|
||||
}
|
||||
|
||||
Class<?> mappingType = RequestMappingHandlerMapping.class;
|
||||
wac.registerBeanDefinition("handlerMapping", new RootBeanDefinition(mappingType));
|
||||
|
||||
Class<?> adapterType = RequestMappingHandlerAdapter.class;
|
||||
wac.registerBeanDefinition("handlerAdapter", new RootBeanDefinition(adapterType));
|
||||
|
||||
Class<?> resolverType = ExceptionHandlerExceptionResolver.class;
|
||||
wac.registerBeanDefinition("requestMappingResolver", new RootBeanDefinition(resolverType));
|
||||
|
||||
resolverType = ResponseStatusExceptionResolver.class;
|
||||
wac.registerBeanDefinition("responseStatusResolver", new RootBeanDefinition(resolverType));
|
||||
|
||||
resolverType = DefaultHandlerExceptionResolver.class;
|
||||
wac.registerBeanDefinition("defaultResolver", new RootBeanDefinition(resolverType));
|
||||
|
||||
if (initializer != null) {
|
||||
initializer.initialize(wac);
|
||||
}
|
||||
|
||||
wac.refresh();
|
||||
return wac;
|
||||
}
|
||||
};
|
||||
|
||||
servlet.init(new MockServletConfig());
|
||||
|
||||
return wac;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.servlet.mvc.method.annotation;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.FlashAttributes;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.support.FlashStatus;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||
import org.springframework.web.method.annotation.FlashAttributesHandler;
|
||||
import org.springframework.web.servlet.View;
|
||||
import org.springframework.web.servlet.ViewResolver;
|
||||
|
||||
/**
|
||||
* Test controllers with @{@link FlashAttributes} through the DispatcherServlet.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class FlashAttributesServletTests extends AbstractServletHandlerMethodTests {
|
||||
|
||||
private static final String MESSAGE_KEY = "message";
|
||||
|
||||
@Test
|
||||
public void successMessage() throws Exception {
|
||||
|
||||
initServletWithModelExposingViewResolver(MessageController.class);
|
||||
|
||||
MockHttpServletRequest req = new MockHttpServletRequest("GET", "/message");
|
||||
MockHttpServletResponse res = new MockHttpServletResponse();
|
||||
getServlet().service(req, res);
|
||||
|
||||
assertEquals(200, res.getStatus());
|
||||
assertNull(getModelAttribute(req, MESSAGE_KEY));
|
||||
assertNull(getFlashAttribute(req, MESSAGE_KEY));
|
||||
|
||||
req.setMethod("POST");
|
||||
getServlet().service(req, res);
|
||||
|
||||
assertEquals(200, res.getStatus());
|
||||
assertEquals("Yay!", ((Message) getModelAttribute(req, MESSAGE_KEY)).getText());
|
||||
assertEquals("Yay!", ((Message) getFlashAttribute(req, MESSAGE_KEY)).getText());
|
||||
|
||||
req.setMethod("GET");
|
||||
getServlet().service(req, res);
|
||||
|
||||
assertEquals(200, res.getStatus());
|
||||
assertEquals("Yay!", ((Message) getModelAttribute(req, MESSAGE_KEY)).getText());
|
||||
assertNull(getFlashAttribute(req, MESSAGE_KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void successMessageAcrossControllers() throws Exception {
|
||||
|
||||
initServletWithModelExposingViewResolver(MessageController.class, SecondMessageController.class);
|
||||
|
||||
MockHttpServletRequest req = new MockHttpServletRequest("POST", "/message");
|
||||
MockHttpServletResponse res = new MockHttpServletResponse();
|
||||
getServlet().service(req, res);
|
||||
|
||||
req.setParameter("another", "true");
|
||||
getServlet().service(req, res);
|
||||
|
||||
assertEquals(200, res.getStatus());
|
||||
assertEquals("Nay!", ((Message) getModelAttribute(req, MESSAGE_KEY)).getText());
|
||||
assertEquals("Nay!", ((Message) getFlashAttribute(req, MESSAGE_KEY)).getText());
|
||||
|
||||
req.setMethod("GET");
|
||||
req.setRequestURI("/second/message");
|
||||
getServlet().service(req, res);
|
||||
|
||||
assertEquals(200, res.getStatus());
|
||||
assertEquals("Nay!", ((Message) getModelAttribute(req, MESSAGE_KEY)).getText());
|
||||
assertNull(getFlashAttribute(req, MESSAGE_KEY));
|
||||
}
|
||||
|
||||
@Controller
|
||||
@FlashAttributes("message")
|
||||
static class MessageController {
|
||||
|
||||
@RequestMapping(value="/message", method=RequestMethod.GET)
|
||||
public void message(Model model) {
|
||||
}
|
||||
|
||||
@RequestMapping(value="/message", method=RequestMethod.POST)
|
||||
public String sendMessage(Model model, FlashStatus status) {
|
||||
status.setActive();
|
||||
model.addAttribute(Message.success("Yay!"));
|
||||
return "redirect:/message";
|
||||
}
|
||||
|
||||
@RequestMapping(value="/message", method=RequestMethod.POST, params="another")
|
||||
public String sendMessageToSecondController(Model model, FlashStatus status) {
|
||||
status.setActive();
|
||||
model.addAttribute(Message.error("Nay!"));
|
||||
return "redirect:/second/message";
|
||||
}
|
||||
}
|
||||
|
||||
@Controller
|
||||
static class SecondMessageController {
|
||||
|
||||
@RequestMapping(value="/second/message", method=RequestMethod.GET)
|
||||
public void message(Model model) {
|
||||
}
|
||||
}
|
||||
|
||||
private static class Message {
|
||||
|
||||
private final MessageType type;
|
||||
|
||||
private final String text;
|
||||
|
||||
private Message(MessageType type, String text) {
|
||||
this.type = type;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public static Message success(String text) {
|
||||
return new Message(MessageType.success, text);
|
||||
}
|
||||
|
||||
public static Message error(String text) {
|
||||
return new Message(MessageType.error, text);
|
||||
}
|
||||
|
||||
public MessageType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return type + ": " + text;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static enum MessageType {
|
||||
info, success, warning, error
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Object getModelAttribute(MockHttpServletRequest req, String key) {
|
||||
Map<String, ?> model = (Map<String, ?>) req.getAttribute(ModelExposingViewResolver.REQUEST_ATTRIBITE_MODEL);
|
||||
return model.get(key);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Object getFlashAttribute(MockHttpServletRequest req, String key) {
|
||||
String flashAttributesKey = FlashAttributesHandler.FLASH_ATTRIBUTES_SESSION_KEY;
|
||||
Map<String, Object> attrs = (Map<String, Object>) req.getSession().getAttribute(flashAttributesKey);
|
||||
return (attrs != null) ? attrs.get(key) : null;
|
||||
}
|
||||
|
||||
private WebApplicationContext initServletWithModelExposingViewResolver(Class<?>... controllerClasses)
|
||||
throws ServletException {
|
||||
|
||||
return initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() {
|
||||
public void initialize(GenericWebApplicationContext wac) {
|
||||
wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(ModelExposingViewResolver.class));
|
||||
}
|
||||
}, controllerClasses);
|
||||
}
|
||||
|
||||
static class ModelExposingViewResolver implements ViewResolver {
|
||||
|
||||
static String REQUEST_ATTRIBITE_MODEL = "ModelExposingViewResolver.model";
|
||||
|
||||
public View resolveViewName(final String viewName, Locale locale) throws Exception {
|
||||
return new View() {
|
||||
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||
request.setAttribute(REQUEST_ATTRIBITE_MODEL, model);
|
||||
}
|
||||
public String getContentType() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -92,7 +92,7 @@ import org.springframework.web.servlet.mvc.method.annotation.support.ServletWebA
|
||||
* <p>If you wish to add high-level tests, consider the following other "integration"-style tests:
|
||||
* <ul>
|
||||
* <li>{@link HandlerMethodAnnotationDetectionTests}
|
||||
* <li>{@link ServletHandlerMethodTests}
|
||||
* <li>{@link ServletAnnotationControllerHandlerMethodTests}
|
||||
* </ul>
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
|
||||
@@ -49,7 +49,7 @@ import org.springframework.web.servlet.mvc.method.annotation.support.ServletRequ
|
||||
*
|
||||
* <p>For higher-level adapter tests see:
|
||||
* <ul>
|
||||
* <li>{@link ServletHandlerMethodTests}
|
||||
* <li>{@link ServletAnnotationControllerHandlerMethodTests}
|
||||
* <li>{@link HandlerMethodAnnotationDetectionTests}
|
||||
* <li>{@link RequestMappingHandlerAdapterIntegrationTests}
|
||||
* </ul>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -28,16 +28,15 @@ import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.propertyeditors.CustomDateEditor;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.MockServletConfig;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.annotation.InitBinder;
|
||||
@@ -46,45 +45,51 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.View;
|
||||
import org.springframework.web.servlet.ViewResolver;
|
||||
import org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver;
|
||||
import org.springframework.web.servlet.mvc.annotation.UriTemplateServletAnnotationControllerTests;
|
||||
import org.springframework.web.servlet.mvc.annotation.UriTemplateServletAnnotationControllerTests.VariableNamesController;
|
||||
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
|
||||
import org.springframework.web.servlet.view.AbstractView;
|
||||
|
||||
/**
|
||||
* The origin of this test class is {@link UriTemplateServletAnnotationControllerTests} with the tests in this class
|
||||
* adapted to run against the HandlerMethod infrastructure rather than against the DefaultAnnotationHandlerMapping,
|
||||
* the AnnotationMethodHandlerAdapter, and the AnnotationMethodHandlerExceptionResolver. Tests that are not supported
|
||||
* are listed at the bottom.
|
||||
*
|
||||
* The origin of this test class is {@link UriTemplateServletAnnotationControllerTests}.
|
||||
*
|
||||
* Tests in this class run against the {@link HandlerMethod} infrastructure:
|
||||
* <ul>
|
||||
* <li>RequestMappingHandlerMapping
|
||||
* <li>RequestMappingHandlerAdapter
|
||||
* <li>ExceptionHandlerExceptionResolver
|
||||
* </ul>
|
||||
*
|
||||
* <p>Rather than against the existing infrastructure:
|
||||
* <ul>
|
||||
* <li>DefaultAnnotationHandlerMapping
|
||||
* <li>AnnotationMethodHandlerAdapter
|
||||
* <li>AnnotationMethodHandlerExceptionResolver
|
||||
* </ul>
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.1
|
||||
*/
|
||||
public class UriTemplateServletHandlerMethodTests {
|
||||
|
||||
private DispatcherServlet servlet;
|
||||
public class UriTemplateServletAnnotationControllerHandlerMethodTests extends AbstractServletHandlerMethodTests {
|
||||
|
||||
@Test
|
||||
public void simple() throws Exception {
|
||||
initDispatcherServlet(SimpleUriTemplateController.class, null);
|
||||
initServletWithControllers(SimpleUriTemplateController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/42");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("test-42", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiple() throws Exception {
|
||||
initDispatcherServlet(MultipleUriTemplateController.class, null);
|
||||
initServletWithControllers(MultipleUriTemplateController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42/bookings/21-other");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("test-42-21-other", response.getContentAsString());
|
||||
}
|
||||
|
||||
@@ -96,16 +101,16 @@ public class UriTemplateServletHandlerMethodTests {
|
||||
pathVars.put("other", "other");
|
||||
|
||||
WebApplicationContext wac =
|
||||
initDispatcherServlet(ViewRenderingController.class, new BeanDefinitionRegistrar() {
|
||||
public void register(GenericWebApplicationContext context) {
|
||||
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() {
|
||||
public void initialize(GenericWebApplicationContext context) {
|
||||
RootBeanDefinition beanDef = new RootBeanDefinition(ModelValidatingViewResolver.class);
|
||||
beanDef.getConstructorArgumentValues().addGenericArgumentValue(pathVars);
|
||||
context.registerBeanDefinition("viewResolver", beanDef);
|
||||
}
|
||||
});
|
||||
}, ViewRenderingController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42/bookings/21-other");
|
||||
servlet.service(request, new MockHttpServletResponse());
|
||||
getServlet().service(request, new MockHttpServletResponse());
|
||||
|
||||
ModelValidatingViewResolver resolver = wac.getBean(ModelValidatingViewResolver.class);
|
||||
assertEquals(3, resolver.validatedAttrCount);
|
||||
@@ -113,153 +118,153 @@ public class UriTemplateServletHandlerMethodTests {
|
||||
|
||||
@Test
|
||||
public void binding() throws Exception {
|
||||
initDispatcherServlet(BindingUriTemplateController.class, null);
|
||||
initServletWithControllers(BindingUriTemplateController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42/dates/2008-11-18");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals(200, response.getStatus());
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/hotels/42/dates/2008-foo-bar");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals(400, response.getStatus());
|
||||
|
||||
initDispatcherServlet(NonBindingUriTemplateController.class, null);
|
||||
initServletWithControllers(NonBindingUriTemplateController.class);
|
||||
request = new MockHttpServletRequest("GET", "/hotels/42/dates/2008-foo-bar");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals(500, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ambiguous() throws Exception {
|
||||
initDispatcherServlet(AmbiguousUriTemplateController.class, null);
|
||||
initServletWithControllers(AmbiguousUriTemplateController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/new");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("specific", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void relative() throws Exception {
|
||||
initDispatcherServlet(RelativePathUriTemplateController.class, null);
|
||||
initServletWithControllers(RelativePathUriTemplateController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42/bookings/21");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("test-42-21", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/hotels/42/bookings/21.html");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("test-42-21", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extension() throws Exception {
|
||||
initDispatcherServlet(SimpleUriTemplateController.class, null);
|
||||
initServletWithControllers(SimpleUriTemplateController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/42.xml");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("test-42", response.getContentAsString());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typeConversionError() throws Exception {
|
||||
initDispatcherServlet(SimpleUriTemplateController.class, null);
|
||||
initServletWithControllers(SimpleUriTemplateController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo.xml");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("Invalid response status code", HttpServletResponse.SC_BAD_REQUEST, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void explicitSubPath() throws Exception {
|
||||
initDispatcherServlet(ExplicitSubPathController.class, null);
|
||||
initServletWithControllers(ExplicitSubPathController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("test-42", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void implicitSubPath() throws Exception {
|
||||
initDispatcherServlet(ImplicitSubPathController.class, null);
|
||||
initServletWithControllers(ImplicitSubPathController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("test-42", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void crud() throws Exception {
|
||||
initDispatcherServlet(CrudController.class, null);
|
||||
initServletWithControllers(CrudController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("list", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/hotels/");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("list", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("POST", "/hotels");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("create", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/hotels/42");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("show-42", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/hotels/42/");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("show-42", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("PUT", "/hotels/42");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("createOrUpdate-42", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("DELETE", "/hotels/42");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("remove-42", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void methodNotSupported() throws Exception {
|
||||
initDispatcherServlet(MethodNotAllowedController.class, null);
|
||||
initServletWithControllers(MethodNotAllowedController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/1");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals(200, response.getStatus());
|
||||
|
||||
request = new MockHttpServletRequest("POST", "/hotels/1");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals(405, response.getStatus());
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/hotels");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals(200, response.getStatus());
|
||||
|
||||
request = new MockHttpServletRequest("POST", "/hotels");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals(405, response.getStatus());
|
||||
|
||||
|
||||
@@ -267,26 +272,26 @@ public class UriTemplateServletHandlerMethodTests {
|
||||
|
||||
@Test
|
||||
public void multiPaths() throws Exception {
|
||||
initDispatcherServlet(MultiPathController.class, null);
|
||||
initServletWithControllers(MultiPathController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/category/page/5");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("handle4-page-5", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/category/page/5.html");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("handle4-page-5", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customRegex() throws Exception {
|
||||
initDispatcherServlet(CustomRegexController.class, null);
|
||||
initServletWithControllers(CustomRegexController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/42");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("test-42", response.getContentAsString());
|
||||
}
|
||||
|
||||
@@ -295,11 +300,11 @@ public class UriTemplateServletHandlerMethodTests {
|
||||
*/
|
||||
@Test
|
||||
public void menuTree() throws Exception {
|
||||
initDispatcherServlet(MenuTreeController.class, null);
|
||||
initServletWithControllers(MenuTreeController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/book/menu/type/M5");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("M5", response.getContentAsString());
|
||||
}
|
||||
|
||||
@@ -308,16 +313,16 @@ public class UriTemplateServletHandlerMethodTests {
|
||||
*/
|
||||
@Test
|
||||
public void variableNames() throws Exception {
|
||||
initDispatcherServlet(VariableNamesController.class, null);
|
||||
initServletWithControllers(VariableNamesController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test/foo");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("foo-foo", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("DELETE", "/test/bar");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("bar-bar", response.getContentAsString());
|
||||
}
|
||||
|
||||
@@ -326,11 +331,11 @@ public class UriTemplateServletHandlerMethodTests {
|
||||
*/
|
||||
@Test
|
||||
public void variableNamesWithUrlExtension() throws Exception {
|
||||
initDispatcherServlet(VariableNamesController.class, null);
|
||||
initServletWithControllers(VariableNamesController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test/foo.json");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("foo-foo", response.getContentAsString());
|
||||
}
|
||||
|
||||
@@ -339,26 +344,26 @@ public class UriTemplateServletHandlerMethodTests {
|
||||
*/
|
||||
@Test
|
||||
public void doIt() throws Exception {
|
||||
initDispatcherServlet(Spr6978Controller.class, null);
|
||||
initServletWithControllers(Spr6978Controller.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo/100");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("loadEntity:foo:100", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("POST", "/foo/100");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("publish:foo:100", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/module/100");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("loadModule:100", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("POST", "/module/100");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
getServlet().service(request, response);
|
||||
assertEquals("publish:module:100", response.getContentAsString());
|
||||
|
||||
}
|
||||
@@ -672,50 +677,6 @@ public class UriTemplateServletHandlerMethodTests {
|
||||
}
|
||||
}
|
||||
|
||||
private interface BeanDefinitionRegistrar {
|
||||
public void register(GenericWebApplicationContext context);
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private WebApplicationContext initDispatcherServlet(final Class<?> controllerClass, final BeanDefinitionRegistrar registrar)
|
||||
throws ServletException {
|
||||
|
||||
final GenericWebApplicationContext wac = new GenericWebApplicationContext();
|
||||
|
||||
servlet = new DispatcherServlet() {
|
||||
@Override
|
||||
protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
|
||||
wac.registerBeanDefinition("controller", new RootBeanDefinition(controllerClass));
|
||||
|
||||
Class<?> mappingType = RequestMappingHandlerMapping.class;
|
||||
wac.registerBeanDefinition("handlerMapping", new RootBeanDefinition(mappingType));
|
||||
|
||||
Class<?> adapterType = RequestMappingHandlerAdapter.class;
|
||||
wac.registerBeanDefinition("handlerAdapter", new RootBeanDefinition(adapterType));
|
||||
|
||||
Class<?> resolverType = ExceptionHandlerExceptionResolver.class;
|
||||
wac.registerBeanDefinition("requestMappingResolver", new RootBeanDefinition(resolverType));
|
||||
|
||||
resolverType = ResponseStatusExceptionResolver.class;
|
||||
wac.registerBeanDefinition("responseStatusResolver", new RootBeanDefinition(resolverType));
|
||||
|
||||
resolverType = DefaultHandlerExceptionResolver.class;
|
||||
wac.registerBeanDefinition("defaultResolver", new RootBeanDefinition(resolverType));
|
||||
|
||||
if (registrar != null) {
|
||||
registrar.register(wac);
|
||||
}
|
||||
|
||||
wac.refresh();
|
||||
return wac;
|
||||
}
|
||||
};
|
||||
|
||||
servlet.init(new MockServletConfig());
|
||||
|
||||
return wac;
|
||||
}
|
||||
|
||||
// @Ignore("ControllerClassNameHandlerMapping")
|
||||
// public void controllerClassName() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user