From 2122cbcb1bcdbf4cc38545a01ec13171b6487798 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Fri, 24 Jun 2011 10:09:28 +0000 Subject: [PATCH] SPR-8484 Add path variables to the model via AbstractView.render(..) rather than HandlerMethodArgumentResolver --- .../org/springframework/web/servlet/View.java | 11 +- .../PathVariableMethodArgumentResolver.java | 16 +- .../web/servlet/view/AbstractView.java | 38 ++++- .../web/servlet/view/RedirectView.java | 16 +- .../servlet/view/UrlBasedViewResolver.java | 21 ++- .../view/json/MappingJacksonJsonView.java | 1 + .../web/servlet/view/xml/MarshallingView.java | 10 +- ...MappingHandlerAdapterIntegrationTests.java | 5 +- .../annotation/ServletHandlerMethodTests.java | 5 - .../UriTemplateServletHandlerMethodTests.java | 80 +++++++++- ...thVariableMethodArgumentResolverTests.java | 33 +++- .../web/servlet/view/BaseViewTests.java | 142 +++++++++++++----- .../view/InternalResourceViewTests.java | 80 +++++----- .../view/RedirectViewUriTemplateTests.java | 4 +- .../view/json/MappingJacksonJsonViewTest.java | 5 + .../view/velocity/VelocityViewTests.java | 95 ++++++------ .../view/xml/MarshallingViewTests.java | 22 ++- 17 files changed, 422 insertions(+), 162 deletions(-) diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/View.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/View.java index e5c07de93fe..7ca5be4519b 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/View.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/View.java @@ -45,11 +45,18 @@ public interface View { /** * Name of the {@link HttpServletRequest} attribute that contains the response status code. - *

Note: This attribute is not required to be supported by all - * View implementations. + *

Note: This attribute is not required to be supported by all View implementations. */ String RESPONSE_STATUS_ATTRIBUTE = View.class.getName() + ".responseStatus"; + /** + * Name of the {@link HttpServletRequest} attribute that contains a Map with path variables. + * The map consists of String-based URI template variable names as keys and their corresponding + * Object-based values -- extracted from segments of the URL and type converted. + * + *

Note: This attribute is not required to be supported by all View implementations. + */ + String PATH_VARIABLES = View.class.getName() + ".pathVariables"; /** * Return the content type of the view, if predetermined. diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/PathVariableMethodArgumentResolver.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/PathVariableMethodArgumentResolver.java index 4596ddf9e15..c3ddfab1c4f 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/PathVariableMethodArgumentResolver.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/PathVariableMethodArgumentResolver.java @@ -16,10 +16,9 @@ package org.springframework.web.servlet.mvc.method.annotation.support; +import java.util.HashMap; import java.util.Map; -import javax.servlet.ServletException; - import org.springframework.core.MethodParameter; import org.springframework.web.bind.ServletRequestBindingException; import org.springframework.web.bind.WebDataBinder; @@ -30,6 +29,7 @@ import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.method.annotation.support.AbstractNamedValueMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer; import org.springframework.web.servlet.HandlerMapping; +import org.springframework.web.servlet.View; /** * Resolves method arguments annotated with an @{@link PathVariable}. @@ -78,14 +78,20 @@ public class PathVariableMethodArgumentResolver extends AbstractNamedValueMethod } @Override + @SuppressWarnings("unchecked") protected void handleResolvedValue(Object arg, String name, MethodParameter parameter, ModelAndViewContainer mavContainer, - NativeWebRequest webRequest) { - if (mavContainer != null) { - mavContainer.addAttribute(name, arg); + NativeWebRequest request) { + String key = View.PATH_VARIABLES; + int scope = RequestAttributes.SCOPE_REQUEST; + Map pathVars = (Map) request.getAttribute(key, scope); + if (pathVars == null) { + pathVars = new HashMap(); + request.setAttribute(key, pathVars, scope); } + pathVars.put(name, arg); } private static class PathVariableNamedValueInfo extends NamedValueInfo { diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/AbstractView.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/AbstractView.java index 2a2d29d10a7..b6b8690800b 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/AbstractView.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/AbstractView.java @@ -70,6 +70,8 @@ public abstract class AbstractView extends WebApplicationObjectSupport implement /** Map of static attributes, keyed by attribute name (String) */ private final Map staticAttributes = new HashMap(); + /** Whether or not the view should add path variables in the model */ + private boolean exposePathVariables = true; /** * Set the view's name. Helpful for traceability. @@ -216,10 +218,31 @@ public abstract class AbstractView extends WebApplicationObjectSupport implement * manipulating the Map but rather just for checking the contents. * @return the static attributes in this view */ - public Map getStaticAttributes() { + public Map getStaticAttributes() { return Collections.unmodifiableMap(this.staticAttributes); } + /** + * Whether to add path variables in the model or not. + *

Path variables are commonly bound to URI template variables through the {@code @PathVariable} + * annotation. They're are effectively URI template variables with type conversion applied to + * them to derive typed Object values. Such values are frequently needed in views for + * constructing links to the same and other URLs. + *

Path variables added to the model override static attributes (see {@link #setAttributes(Properties)}) + * but not attributes already present in the model. + *

By default this flag is set to {@code true}. Concrete view types can override this. + * @param exposePathVariables {@code true} to expose path variables, and {@code false} otherwise. + */ + public void setExposePathVariables(boolean exposePathVariables) { + this.exposePathVariables = exposePathVariables; + } + + /** + * Returns the value of the flag indicating whether path variables should be added to the model or not. + */ + public boolean isExposePathVariables() { + return exposePathVariables; + } /** * Prepares the view given the specified model, merging it with static @@ -232,11 +255,20 @@ public abstract class AbstractView extends WebApplicationObjectSupport implement logger.trace("Rendering view with name '" + this.beanName + "' with model " + model + " and static attributes " + this.staticAttributes); } + + @SuppressWarnings("unchecked") + Map pathVars = this.exposePathVariables ? + (Map) request.getAttribute(View.PATH_VARIABLES) : null; // Consolidate static and dynamic model attributes. - Map mergedModel = - new HashMap(this.staticAttributes.size() + (model != null ? model.size() : 0)); + int size = this.staticAttributes.size(); + size += (model != null) ? model.size() : 0; + size += (pathVars != null) ? pathVars.size() : 0; + Map mergedModel = new HashMap(size); mergedModel.putAll(this.staticAttributes); + if (pathVars != null) { + mergedModel.putAll(pathVars); + } if (model != null) { mergedModel.putAll(model); } diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/RedirectView.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/RedirectView.java index 396157c50a2..e35cd532a40 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/RedirectView.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/RedirectView.java @@ -238,9 +238,9 @@ public class RedirectView extends AbstractUrlBasedView { model = removeKeys(model, redirectUri.getVariableNames()); } if (this.exposeModelAttributes) { - List uriTemplateVarNames = getUriTemplateVarNames(request); - if (!uriTemplateVarNames.isEmpty()) { - model = removeKeys(model, uriTemplateVarNames); + List pathVarNames = getPathVarNames(request); + if (!pathVarNames.isEmpty()) { + model = removeKeys(model, pathVarNames); } appendQueryProperties(targetUrl, model, enc); } @@ -274,12 +274,12 @@ public class RedirectView extends AbstractUrlBasedView { } /** - * Returns URI template variable names for the current request; or an empty list. + * Returns the names of PathVariable for the current request; or an empty list. */ @SuppressWarnings("unchecked") - private List getUriTemplateVarNames(HttpServletRequest request) { - String key = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE; - Map map = (Map) request.getAttribute(key); + private List getPathVarNames(HttpServletRequest request) { + String key = View.PATH_VARIABLES; + Map map = (Map) request.getAttribute(key); return (map != null) ? new ArrayList(map.keySet()) : Collections.emptyList(); } @@ -307,7 +307,7 @@ public class RedirectView extends AbstractUrlBasedView { boolean first = (getUrl().indexOf('?') < 0); for (Map.Entry entry : queryProperties(model).entrySet()) { Object rawValue = entry.getValue(); - Iterator valueIter; + Iterator valueIter; if (rawValue != null && rawValue.getClass().isArray()) { valueIter = Arrays.asList(ObjectUtils.toObjectArray(rawValue)).iterator(); } diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/UrlBasedViewResolver.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/UrlBasedViewResolver.java index f3933fbf504..3c6fcf50ef3 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/UrlBasedViewResolver.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/UrlBasedViewResolver.java @@ -121,6 +121,7 @@ public class UrlBasedViewResolver extends AbstractCachingViewResolver implements /** Map of static attributes, keyed by attribute name (String) */ private final Map staticAttributes = new HashMap(); + private Boolean exposePathVariables; /** * Set the view class that should be used to create views. @@ -337,6 +338,22 @@ public class UrlBasedViewResolver extends AbstractCachingViewResolver implements return this.order; } + /** + * Whether views resolved by this resolver should add path variables the model or not. + * The default setting is to allow each View decide (see {@link AbstractView#setExposePathVariables(boolean)}. + * However, you can use this property to override that. + * @param exposePathVariables + *
    + *
  • {@code true} - all Views resolved by this resolver will expose path variables + *
  • {@code false} - no Views resolved by this resolver will expose path variables + *
  • {@code null} - individual Views can decide for themselves (this is used by the default) + *
      + * @see AbstractView#setExposePathVariables(boolean) + */ + public void setExposePathVariables(Boolean exposePathVariables) { + this.exposePathVariables = exposePathVariables; + } + @Override protected void initApplicationContext() { super.initApplicationContext(); @@ -345,7 +362,6 @@ public class UrlBasedViewResolver extends AbstractCachingViewResolver implements } } - /** * This implementation returns just the view name, * as this ViewResolver doesn't support localized resolution. @@ -444,6 +460,9 @@ public class UrlBasedViewResolver extends AbstractCachingViewResolver implements } view.setRequestContextAttribute(getRequestContextAttribute()); view.setAttributesMap(getAttributesMap()); + if (this.exposePathVariables != null) { + view.setExposePathVariables(exposePathVariables); + } return view; } diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/json/MappingJacksonJsonView.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/json/MappingJacksonJsonView.java index 18407f9effc..9e1c9364c16 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/json/MappingJacksonJsonView.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/json/MappingJacksonJsonView.java @@ -73,6 +73,7 @@ public class MappingJacksonJsonView extends AbstractView { */ public MappingJacksonJsonView() { setContentType(DEFAULT_CONTENT_TYPE); + setExposePathVariables(false); } /** diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/xml/MarshallingView.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/xml/MarshallingView.java index 323a62e4240..fc2356aae36 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/xml/MarshallingView.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/xml/MarshallingView.java @@ -18,6 +18,7 @@ package org.springframework.web.servlet.view.xml; import java.io.ByteArrayOutputStream; import java.util.Map; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -58,6 +59,7 @@ public class MarshallingView extends AbstractView { */ public MarshallingView() { setContentType(DEFAULT_CONTENT_TYPE); + setExposePathVariables(false); } /** @@ -67,6 +69,7 @@ public class MarshallingView extends AbstractView { Assert.notNull(marshaller, "'marshaller' must not be null"); setContentType(DEFAULT_CONTENT_TYPE); this.marshaller = marshaller; + setExposePathVariables(false); } /** @@ -93,8 +96,9 @@ public class MarshallingView extends AbstractView { } @Override - protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response) - throws Exception { + protected void renderMergedOutputModel(Map model, + HttpServletRequest request, + HttpServletResponse response) throws Exception { Object toBeMarshalled = locateToBeMarshalled(model); if (toBeMarshalled == null) { throw new ServletException("Unable to locate object to be marshalled in model: " + model); @@ -119,7 +123,7 @@ public class MarshallingView extends AbstractView { * supported by the marshaller * @see #setModelKey(String) */ - protected Object locateToBeMarshalled(Map model) throws ServletException { + protected Object locateToBeMarshalled(Map model) throws ServletException { if (this.modelKey != null) { Object o = model.get(this.modelKey); if (o == null) { diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterIntegrationTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterIntegrationTests.java index d74f659c958..a22771de536 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterIntegrationTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterIntegrationTests.java @@ -88,8 +88,7 @@ import org.springframework.web.servlet.mvc.method.annotation.support.ServletWebA * *

      If you wish to add high-level tests, consider the following other "integration"-style tests: *

        - *
      • {@link HandlerMethodAdapterAnnotationDetectionTests} - *
      • {@link HandlerMethodMappingAnnotationDetectionTests} + *
      • {@link HandlerMethodAnnotationDetectionTests} *
      • {@link ServletHandlerMethodTests} *
      * @@ -293,7 +292,7 @@ public class RequestMappingHandlerAdapterIntegrationTests { @ModelAttribute OtherUser otherUser, Model model) throws Exception { - model.addAttribute("cookie", cookie).addAttribute("header", header) + model.addAttribute("cookie", cookie).addAttribute("pathvar", pathvar).addAttribute("header", header) .addAttribute("systemHeader", systemHeader).addAttribute("headerMap", headerMap) .addAttribute("dateParam", dateParam).addAttribute("paramMap", paramMap) .addAttribute("paramByConvention", paramByConvention).addAttribute("value", value) diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletHandlerMethodTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletHandlerMethodTests.java index 54e287a552d..385a5853e11 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletHandlerMethodTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletHandlerMethodTests.java @@ -698,11 +698,6 @@ public class ServletHandlerMethodTests { assertNotNull(deserialized.session); } - - - - - @Test public void relativePathDispatchingController() throws Exception { initDispatcherServlet(MyRelativePathDispatchingController.class, null); diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/UriTemplateServletHandlerMethodTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/UriTemplateServletHandlerMethodTests.java index 209e41d58cd..75baedcd051 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/UriTemplateServletHandlerMethodTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/UriTemplateServletHandlerMethodTests.java @@ -17,14 +17,19 @@ package org.springframework.web.servlet.mvc.method.annotation; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.io.IOException; import java.io.Writer; import java.text.SimpleDateFormat; import java.util.Date; import java.util.GregorianCalendar; +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; @@ -42,9 +47,12 @@ 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.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.support.DefaultHandlerExceptionResolver; +import org.springframework.web.servlet.view.AbstractView; /** * The origin of this test class is {@link UriTemplateServletAnnotationControllerTests} with the tests in this class @@ -79,6 +87,29 @@ public class UriTemplateServletHandlerMethodTests { assertEquals("test-42-21-other", response.getContentAsString()); } + @Test + public void pathVarsInModel() throws Exception { + final Map pathVars = new HashMap(); + pathVars.put("hotel", "42"); + pathVars.put("booking", 21); + pathVars.put("other", "other"); + + WebApplicationContext wac = + initDispatcherServlet(ViewRenderingController.class, new BeanDefinitionRegistrar() { + public void register(GenericWebApplicationContext context) { + RootBeanDefinition beanDef = new RootBeanDefinition(ModelValidatingViewResolver.class); + beanDef.getConstructorArgumentValues().addGenericArgumentValue(pathVars); + context.registerBeanDefinition("viewResolver", beanDef); + } + }); + + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42/bookings/21-other"); + servlet.service(request, new MockHttpServletResponse()); + + ModelValidatingViewResolver resolver = wac.getBean(ModelValidatingViewResolver.class); + assertEquals(3, resolver.validatedAttrCount); + } + @Test public void binding() throws Exception { initDispatcherServlet(BindingUriTemplateController.class, null); @@ -349,6 +380,17 @@ public class UriTemplateServletHandlerMethodTests { } + @Controller + public static class ViewRenderingController { + + @RequestMapping("/hotels/{hotel}/bookings/{booking}-{other}") + public void handle(@PathVariable("hotel") String hotel, @PathVariable int booking, @PathVariable String other) { + assertEquals("Invalid path variable value", "42", hotel); + assertEquals("Invalid path variable value", 21, booking); + } + + } + @Controller public static class BindingUriTemplateController { @@ -588,18 +630,47 @@ public class UriTemplateServletHandlerMethodTests { } } + public static class ModelValidatingViewResolver implements ViewResolver { + + private final Map attrsToValidate; + + int validatedAttrCount; + + public ModelValidatingViewResolver(Map attrsToValidate) { + this.attrsToValidate = attrsToValidate; + } + + public View resolveViewName(final String viewName, Locale locale) throws Exception { + return new AbstractView () { + public String getContentType() { + return null; + } + @Override + protected void renderMergedOutputModel(Map model, HttpServletRequest request, + HttpServletResponse response) throws Exception { + for (String key : attrsToValidate.keySet()) { + assertTrue("Model should contain attribute named " + key, model.containsKey(key)); + assertEquals(attrsToValidate.get(key), model.get(key)); + validatedAttrCount++; + } + } + }; + } + } + private interface BeanDefinitionRegistrar { public void register(GenericWebApplicationContext context); } @SuppressWarnings("serial") - private void initDispatcherServlet(final Class controllerClass, final BeanDefinitionRegistrar registrar) + 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) { - GenericWebApplicationContext wac = new GenericWebApplicationContext(); wac.registerBeanDefinition("controller", new RootBeanDefinition(controllerClass)); Class mappingType = RequestMappingHandlerMapping.class; @@ -625,7 +696,10 @@ public class UriTemplateServletHandlerMethodTests { return wac; } }; + servlet.init(new MockServletConfig()); + + return wac; } // @Ignore("ControllerClassNameHandlerMapping") diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/PathVariableMethodArgumentResolverTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/PathVariableMethodArgumentResolverTests.java index c455267500f..86bd1882bbe 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/PathVariableMethodArgumentResolverTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/PathVariableMethodArgumentResolverTests.java @@ -18,6 +18,7 @@ package org.springframework.web.servlet.mvc.method.annotation.support; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -35,7 +36,7 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.context.request.ServletWebRequest; import org.springframework.web.method.support.ModelAndViewContainer; import org.springframework.web.servlet.HandlerMapping; -import org.springframework.web.servlet.mvc.method.annotation.support.PathVariableMethodArgumentResolver; +import org.springframework.web.servlet.View; /** * Test fixture with {@link PathVariableMethodArgumentResolver}. @@ -76,14 +77,40 @@ public class PathVariableMethodArgumentResolverTests { } @Test - public void resolveStringArgument() throws Exception { + public void resolveArgument() throws Exception { Map uriTemplateVars = new HashMap(); uriTemplateVars.put("name", "value"); request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVars); String result = (String) resolver.resolveArgument(paramNamedString, mavContainer, webRequest, null); assertEquals("PathVariable not resolved correctly", "value", result); - assertEquals("PathVariable not added to the model", "value", mavContainer.getAttribute("name")); + + @SuppressWarnings("unchecked") + Map pathVars = (Map) request.getAttribute(View.PATH_VARIABLES); + assertNotNull(pathVars); + assertEquals(1, pathVars.size()); + assertEquals("value", pathVars.get("name")); + } + + @SuppressWarnings("unchecked") + @Test + public void resolveArgumentWithExistingPathVars() throws Exception { + Map uriTemplateVars = new HashMap(); + uriTemplateVars.put("name", "value"); + request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVars); + + Map pathVars = new HashMap(); + uriTemplateVars.put("oldName", "oldValue"); + request.setAttribute(View.PATH_VARIABLES, uriTemplateVars); + + String result = (String) resolver.resolveArgument(paramNamedString, mavContainer, webRequest, null); + assertEquals("PathVariable not resolved correctly", "value", result); + + pathVars = (Map) request.getAttribute(View.PATH_VARIABLES); + assertNotNull(pathVars); + assertEquals(2, pathVars.size()); + assertEquals("value", pathVars.get("name")); + assertEquals("oldValue", pathVars.get("oldName")); } @Test(expected = ServletRequestBindingException.class) diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/BaseViewTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/BaseViewTests.java index 89948025eb3..0f3c63a5e57 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/BaseViewTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/BaseViewTests.java @@ -15,6 +15,10 @@ */ package org.springframework.web.servlet.view; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; import java.io.IOException; import java.util.HashMap; @@ -28,13 +32,13 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import junit.framework.TestCase; -import org.easymock.MockControl; import org.springframework.context.ApplicationContextException; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockServletContext; import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.servlet.View; /** * Tests for AbstractView. Not called AbstractViewTests as @@ -45,21 +49,21 @@ import org.springframework.web.context.WebApplicationContext; public class BaseViewTests extends TestCase { public void testRenderWithoutStaticAttributes() throws Exception { - MockControl mc = MockControl.createControl(WebApplicationContext.class); - WebApplicationContext wac = (WebApplicationContext) mc.getMock(); + + WebApplicationContext wac = createMock(WebApplicationContext.class); wac.getServletContext(); - mc.setReturnValue(new MockServletContext()); - mc.replay(); + expectLastCall().andReturn(new MockServletContext()); + replay(wac); HttpServletRequest request = new MockHttpServletRequest(); HttpServletResponse response = new MockHttpServletResponse(); - TestView tv = new TestView(request, response, wac); + TestView tv = new TestView(wac); // Check superclass handles duplicate init tv.setApplicationContext(wac); tv.setApplicationContext(wac); - Map model = new HashMap(); + Map model = new HashMap(); model.put("foo", "bar"); model.put("something", new Object()); tv.render(model, request, response); @@ -68,22 +72,21 @@ public class BaseViewTests extends TestCase { checkContainsAll(model, tv.model); assertTrue(tv.inited); - mc.verify(); + verify(wac); } /** * Test attribute passing, NOT CSV parsing. */ public void testRenderWithStaticAttributesNoCollision() throws Exception { - MockControl mc = MockControl.createControl(WebApplicationContext.class); - WebApplicationContext wac = (WebApplicationContext) mc.getMock(); + WebApplicationContext wac = createMock(WebApplicationContext.class); wac.getServletContext(); - mc.setReturnValue(new MockServletContext()); - mc.replay(); + expectLastCall().andReturn(new MockServletContext()); + replay(wac); HttpServletRequest request = new MockHttpServletRequest(); HttpServletResponse response = new MockHttpServletResponse(); - TestView tv = new TestView(request, response, wac); + TestView tv = new TestView(wac); tv.setApplicationContext(wac); Properties p = new Properties(); @@ -91,8 +94,8 @@ public class BaseViewTests extends TestCase { p.setProperty("something", "else"); tv.setAttributes(p); - Map model = new HashMap(); - model.put("one", new HashMap()); + Map model = new HashMap(); + model.put("one", new HashMap()); model.put("two", new Object()); tv.render(model, request, response); @@ -101,19 +104,52 @@ public class BaseViewTests extends TestCase { checkContainsAll(p, tv.model); assertTrue(tv.inited); - mc.verify(); + verify(wac); } - - public void testDynamicModelOverridesStaticAttributesIfCollision() throws Exception { - MockControl mc = MockControl.createControl(WebApplicationContext.class); - WebApplicationContext wac = (WebApplicationContext) mc.getMock(); + + public void testPathVarsOverrideStaticAttributes() throws Exception { + WebApplicationContext wac = createMock(WebApplicationContext.class); wac.getServletContext(); - mc.setReturnValue(new MockServletContext()); - mc.replay(); + expectLastCall().andReturn(new MockServletContext()); + replay(wac); HttpServletRequest request = new MockHttpServletRequest(); HttpServletResponse response = new MockHttpServletResponse(); - TestView tv = new TestView(request, response, wac); + + TestView tv = new TestView(wac); + tv.setApplicationContext(wac); + + Properties p = new Properties(); + p.setProperty("one", "bar"); + p.setProperty("something", "else"); + tv.setAttributes(p); + + Map pathVars = new HashMap(); + pathVars.put("one", new HashMap()); + pathVars.put("two", new Object()); + request.setAttribute(View.PATH_VARIABLES, pathVars); + + tv.render(new HashMap(), request, response); + + // Check it contains all + checkContainsAll(pathVars, tv.model); + assertTrue(tv.model.size() == 3); + // will have old something from properties + assertTrue(tv.model.get("something").equals("else")); + + assertTrue(tv.inited); + verify(wac); + } + + public void testDynamicModelOverridesStaticAttributesIfCollision() throws Exception { + WebApplicationContext wac = createMock(WebApplicationContext.class); + wac.getServletContext(); + expectLastCall().andReturn(new MockServletContext()); + replay(wac); + + HttpServletRequest request = new MockHttpServletRequest(); + HttpServletResponse response = new MockHttpServletResponse(); + TestView tv = new TestView(wac); tv.setApplicationContext(wac); Properties p = new Properties(); @@ -121,8 +157,8 @@ public class BaseViewTests extends TestCase { p.setProperty("something", "else"); tv.setAttributes(p); - Map model = new HashMap(); - model.put("one", new HashMap()); + Map model = new HashMap(); + model.put("one", new HashMap()); model.put("two", new Object()); tv.render(model, request, response); @@ -133,7 +169,40 @@ public class BaseViewTests extends TestCase { assertTrue(tv.model.get("something").equals("else")); assertTrue(tv.inited); - mc.verify(); + verify(wac); + } + + public void testDynamicModelOverridesPathVariables() throws Exception { + WebApplicationContext wac = createMock(WebApplicationContext.class); + wac.getServletContext(); + expectLastCall().andReturn(new MockServletContext()); + replay(wac); + + TestView tv = new TestView(wac); + tv.setApplicationContext(wac); + + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + + Map pathVars = new HashMap(); + pathVars.put("one", "bar"); + pathVars.put("something", "else"); + request.setAttribute(View.PATH_VARIABLES, pathVars); + + Map model = new HashMap(); + model.put("one", new HashMap()); + model.put("two", new Object()); + + tv.render(model, request, response); + + // Check it contains all + checkContainsAll(model, tv.model); + assertEquals(3, tv.model.size()); + // will have old something from path variables + assertTrue(tv.model.get("something").equals("else")); + + assertTrue(tv.inited); + verify(wac); } public void testIgnoresNullAttributes() { @@ -170,7 +239,7 @@ public class BaseViewTests extends TestCase { public void testAttributeCSVParsingValidWithWeirdCharacters() { AbstractView v = new ConcreteView(); - String fooval = "owfie fue&3[][[[2 \n\n \r \t 8£3"; + String fooval = "owfie fue&3[][[[2 \n\n \r \t 8�3"; // Also tests empty value String kingval = ""; v.setAttributesCSV("foo=(" + fooval + "),king={" + kingval + "},f1=[we]"); @@ -224,9 +293,10 @@ public class BaseViewTests extends TestCase { * @param expected * @param actual */ - private void checkContainsAll(Map expected, Map actual) { - Set keys = expected.keySet(); - for (Iterator iter = keys.iterator(); iter.hasNext();) { + @SuppressWarnings({ "rawtypes", "unchecked" }) + private void checkContainsAll(Map expected, Map actual) { + Set keys = expected.keySet(); + for (Iterator iter = keys.iterator(); iter.hasNext();) { String key = (String) iter.next(); //System.out.println("Checking model key " + key); assertTrue("Value for model key '" + key + "' must match", actual.get(key) == expected.get(key)); @@ -239,7 +309,7 @@ public class BaseViewTests extends TestCase { */ private class ConcreteView extends AbstractView { // Do-nothing concrete subclass - protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response) + protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { throw new UnsupportedOperationException(); } @@ -250,21 +320,17 @@ public class BaseViewTests extends TestCase { * behaviour */ private class TestView extends AbstractView { - private HttpServletRequest request; - private HttpServletResponse response; private WebApplicationContext wac; public boolean inited; /** Captured model in render */ - public Map model; + public Map model; - public TestView(HttpServletRequest request, HttpServletResponse response, WebApplicationContext wac) { - this.request = request; - this.response = response; + public TestView(WebApplicationContext wac) { this.wac = wac; } - protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response) + protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // do nothing this.model = model; diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/InternalResourceViewTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/InternalResourceViewTests.java index 9fc970ea6d7..3e80049a099 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/InternalResourceViewTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/InternalResourceViewTests.java @@ -16,6 +16,11 @@ package org.springframework.web.servlet.view; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + import java.util.HashMap; import java.util.Iterator; import java.util.Set; @@ -23,12 +28,12 @@ import java.util.Set; import javax.servlet.http.HttpServletRequest; import junit.framework.TestCase; -import org.easymock.MockControl; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockRequestDispatcher; import org.springframework.mock.web.MockServletContext; +import org.springframework.web.servlet.View; import org.springframework.web.util.WebUtils; /** @@ -52,7 +57,7 @@ public class InternalResourceViewTests extends TestCase { } public void testForward() throws Exception { - HashMap model = new HashMap(); + HashMap model = new HashMap(); Object obj = new Integer(1); model.put("foo", "bar"); model.put("I", obj); @@ -77,8 +82,8 @@ public class InternalResourceViewTests extends TestCase { view.render(model, request, response); assertEquals(url, response.getForwardedUrl()); - Set keys = model.keySet(); - for (Iterator it = keys.iterator(); it.hasNext();) { + Set keys = model.keySet(); + for (Iterator it = keys.iterator(); it.hasNext();) { String key = (String) it.next(); assertEquals(model.get(key), request.getAttribute(key)); } @@ -91,7 +96,7 @@ public class InternalResourceViewTests extends TestCase { } public void testForwardWithForwardAttributesPresent() throws Exception { - HashMap model = new HashMap(); + HashMap model = new HashMap(); Object obj = new Integer(1); model.put("foo", "bar"); model.put("I", obj); @@ -122,8 +127,8 @@ public class InternalResourceViewTests extends TestCase { view.render(model, request, response); assertEquals(url, response.getForwardedUrl()); - Set keys = model.keySet(); - for (Iterator it = keys.iterator(); it.hasNext();) { + Set keys = model.keySet(); + for (Iterator it = keys.iterator(); it.hasNext();) { String key = (String) it.next(); assertEquals(model.get(key), request.getAttribute(key)); } @@ -136,25 +141,26 @@ public class InternalResourceViewTests extends TestCase { } public void testAlwaysInclude() throws Exception { - HashMap model = new HashMap(); + HashMap model = new HashMap(); Object obj = new Integer(1); model.put("foo", "bar"); model.put("I", obj); String url = "forward-to"; - MockControl reqControl = MockControl.createControl(HttpServletRequest.class); - HttpServletRequest request = (HttpServletRequest) reqControl.getMock(); - Set keys = model.keySet(); - for (Iterator iter = keys.iterator(); iter.hasNext();) { + HttpServletRequest request = createMock(HttpServletRequest.class); + request.getAttribute(View.PATH_VARIABLES); + expectLastCall().andReturn(null); + Set keys = model.keySet(); + for (Iterator iter = keys.iterator(); iter.hasNext();) { String key = (String) iter.next(); request.setAttribute(key, model.get(key)); - reqControl.setVoidCallable(1); + expectLastCall().times(1); } request.getRequestDispatcher(url); - reqControl.setReturnValue(new MockRequestDispatcher(url)); - reqControl.replay(); + expectLastCall().andReturn(new MockRequestDispatcher(url)); + replay(request); MockHttpServletResponse response = new MockHttpServletResponse(); InternalResourceView v = new InternalResourceView(); @@ -164,31 +170,32 @@ public class InternalResourceViewTests extends TestCase { // Can now try multiple tests v.render(model, request, response); assertEquals(url, response.getIncludedUrl()); - reqControl.verify(); + verify(request); } public void testIncludeOnAttribute() throws Exception { - HashMap model = new HashMap(); + HashMap model = new HashMap(); Object obj = new Integer(1); model.put("foo", "bar"); model.put("I", obj); String url = "forward-to"; - MockControl reqControl = MockControl.createControl(HttpServletRequest.class); - HttpServletRequest request = (HttpServletRequest) reqControl.getMock(); - Set keys = model.keySet(); - for (Iterator iter = keys.iterator(); iter.hasNext();) { + HttpServletRequest request = createMock(HttpServletRequest.class); + request.getAttribute(View.PATH_VARIABLES); + expectLastCall().andReturn(null); + Set keys = model.keySet(); + for (Iterator iter = keys.iterator(); iter.hasNext();) { String key = (String) iter.next(); request.setAttribute(key, model.get(key)); - reqControl.setVoidCallable(1); + expectLastCall().times(1); } request.getAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE); - reqControl.setReturnValue("somepath"); + expectLastCall().andReturn("somepath"); request.getRequestDispatcher(url); - reqControl.setReturnValue(new MockRequestDispatcher(url)); - reqControl.replay(); + expectLastCall().andReturn(new MockRequestDispatcher(url)); + replay(request); MockHttpServletResponse response = new MockHttpServletResponse(); InternalResourceView v = new InternalResourceView(); @@ -197,31 +204,32 @@ public class InternalResourceViewTests extends TestCase { // Can now try multiple tests v.render(model, request, response); assertEquals(url, response.getIncludedUrl()); - reqControl.verify(); + verify(request); } public void testIncludeOnCommitted() throws Exception { - HashMap model = new HashMap(); + HashMap model = new HashMap(); Object obj = new Integer(1); model.put("foo", "bar"); model.put("I", obj); String url = "forward-to"; - MockControl reqControl = MockControl.createControl(HttpServletRequest.class); - HttpServletRequest request = (HttpServletRequest) reqControl.getMock(); - Set keys = model.keySet(); - for (Iterator iter = keys.iterator(); iter.hasNext();) { + HttpServletRequest request = createMock(HttpServletRequest.class); + request.getAttribute(View.PATH_VARIABLES); + expectLastCall().andReturn(null); + Set keys = model.keySet(); + for (Iterator iter = keys.iterator(); iter.hasNext();) { String key = (String) iter.next(); request.setAttribute(key, model.get(key)); - reqControl.setVoidCallable(1); + expectLastCall().times(1); } request.getAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE); - reqControl.setReturnValue(null); + expectLastCall().andReturn(null); request.getRequestDispatcher(url); - reqControl.setReturnValue(new MockRequestDispatcher(url)); - reqControl.replay(); + expectLastCall().andReturn(new MockRequestDispatcher(url)); + replay(request); MockHttpServletResponse response = new MockHttpServletResponse(); response.setCommitted(true); @@ -231,7 +239,7 @@ public class InternalResourceViewTests extends TestCase { // Can now try multiple tests v.render(model, request, response); assertEquals(url, response.getIncludedUrl()); - reqControl.verify(); + verify(request); } } diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/RedirectViewUriTemplateTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/RedirectViewUriTemplateTests.java index 2279c7b8492..e6b1f962e90 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/RedirectViewUriTemplateTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/RedirectViewUriTemplateTests.java @@ -25,7 +25,7 @@ import org.junit.Before; import org.junit.Test; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.web.servlet.HandlerMapping; +import org.springframework.web.servlet.View; public class RedirectViewUriTemplateTests { @@ -84,7 +84,7 @@ public class RedirectViewUriTemplateTests { Map uriTemplatVars = new HashMap(); uriTemplatVars.put("name1", "value1"); uriTemplatVars.put("name2", "value2"); - request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplatVars); + request.setAttribute(View.PATH_VARIABLES, uriTemplatVars); String url = "http://url.somewhere.com"; RedirectView redirectView = new RedirectView(url + "/{name2}"); diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/json/MappingJacksonJsonViewTest.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/json/MappingJacksonJsonViewTest.java index 710ec53dc95..7b0a8e0c7d2 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/json/MappingJacksonJsonViewTest.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/json/MappingJacksonJsonViewTest.java @@ -74,6 +74,11 @@ public class MappingJacksonJsonViewTest { view = new MappingJacksonJsonView(); } + @Test + public void isExposePathVars() { + assertEquals("Must not expose path variables", false, view.isExposePathVariables()); + } + @Test public void renderSimpleMap() throws Exception { diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/velocity/VelocityViewTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/velocity/VelocityViewTests.java index a4fb650257f..8dd8c0a2ebe 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/velocity/VelocityViewTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/velocity/VelocityViewTests.java @@ -16,10 +16,20 @@ package org.springframework.web.servlet.view.velocity; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + import java.io.IOException; import java.util.HashMap; import java.util.Locale; import java.util.Map; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -31,16 +41,14 @@ import org.apache.velocity.exception.ParseErrorException; import org.apache.velocity.tools.generic.DateTool; import org.apache.velocity.tools.generic.MathTool; import org.apache.velocity.tools.generic.NumberTool; -import org.easymock.MockControl; -import static org.junit.Assert.*; import org.junit.Test; - import org.springframework.context.ApplicationContextException; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockServletContext; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; +import org.springframework.web.servlet.View; import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver; import org.springframework.web.servlet.view.AbstractView; @@ -54,13 +62,12 @@ public class VelocityViewTests { @Test public void testNoVelocityConfig() throws Exception { VelocityView vv = new VelocityView(); - MockControl wmc = MockControl.createControl(WebApplicationContext.class); - WebApplicationContext wac = (WebApplicationContext) wmc.getMock(); + WebApplicationContext wac = createMock(WebApplicationContext.class); wac.getBeansOfType(VelocityConfig.class, true, false); - wmc.setReturnValue(new HashMap()); + expectLastCall().andReturn(new HashMap()); wac.getParentBeanFactory(); - wmc.setReturnValue(null); - wmc.replay(); + expectLastCall().andReturn(null); + replay(wac); vv.setUrl("anythingButNull"); try { @@ -72,7 +79,7 @@ public class VelocityViewTests { assertTrue(ex.getMessage().contains("VelocityConfig")); } - wmc.verify(); + verify(wac); } @Test @@ -118,13 +125,12 @@ public class VelocityViewTests { * If it's non null it will be checked */ private void testValidTemplateName(final Exception mergeTemplateFailureException) throws Exception { - Map model = new HashMap(); + Map model = new HashMap(); model.put("foo", "bar"); final String templateName = "test.vm"; - MockControl wmc = MockControl.createControl(WebApplicationContext.class); - WebApplicationContext wac = (WebApplicationContext) wmc.getMock(); + WebApplicationContext wac = createMock(WebApplicationContext.class); MockServletContext sc = new MockServletContext(); sc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac); @@ -135,14 +141,14 @@ public class VelocityViewTests { } }; wac.getBeansOfType(VelocityConfig.class, true, false); - Map configurers = new HashMap(); + Map configurers = new HashMap(); configurers.put("velocityConfigurer", vc); - wmc.setReturnValue(configurers); + expectLastCall().andReturn(configurers); wac.getParentBeanFactory(); - wmc.setReturnValue(null); + expectLastCall().andReturn(null); wac.getServletContext(); - wmc.setReturnValue(sc, 3); - wmc.replay(); + expectLastCall().andReturn(sc).times(3); + replay(wac); HttpServletRequest request = new MockHttpServletRequest(); final HttpServletResponse expectedResponse = new MockHttpServletResponse(); @@ -172,15 +178,14 @@ public class VelocityViewTests { assertEquals(ex, mergeTemplateFailureException); } - wmc.verify(); + verify(wac); } @Test public void testKeepExistingContentType() throws Exception { final String templateName = "test.vm"; - MockControl wmc = MockControl.createControl(WebApplicationContext.class); - WebApplicationContext wac = (WebApplicationContext) wmc.getMock(); + WebApplicationContext wac = createMock(WebApplicationContext.class); MockServletContext sc = new MockServletContext(); sc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac); @@ -191,14 +196,14 @@ public class VelocityViewTests { } }; wac.getBeansOfType(VelocityConfig.class, true, false); - Map configurers = new HashMap(); + Map configurers = new HashMap(); configurers.put("velocityConfigurer", vc); - wmc.setReturnValue(configurers); + expectLastCall().andReturn(configurers); wac.getParentBeanFactory(); - wmc.setReturnValue(null); + expectLastCall().andReturn(null); wac.getServletContext(); - wmc.setReturnValue(sc, 3); - wmc.replay(); + expectLastCall().andReturn(sc).times(3); + replay(wac); HttpServletRequest request = new MockHttpServletRequest(); final HttpServletResponse expectedResponse = new MockHttpServletResponse(); @@ -209,16 +214,16 @@ public class VelocityViewTests { assertTrue(template == expectedTemplate); assertTrue(response == expectedResponse); } - protected void exposeHelpers(Map model, HttpServletRequest request) throws Exception { + protected void exposeHelpers(Map model, HttpServletRequest request) throws Exception { model.put("myHelper", "myValue"); } }; vv.setUrl(templateName); vv.setApplicationContext(wac); - vv.render(new HashMap(), request, expectedResponse); + vv.render(new HashMap(), request, expectedResponse); - wmc.verify(); + verify(wac); assertEquals("myContentType", expectedResponse.getContentType()); } @@ -226,12 +231,12 @@ public class VelocityViewTests { public void testExposeHelpers() throws Exception { final String templateName = "test.vm"; - MockControl wmc = MockControl.createControl(WebApplicationContext.class); - WebApplicationContext wac = (WebApplicationContext) wmc.getMock(); + WebApplicationContext wac = createMock(WebApplicationContext.class); wac.getParentBeanFactory(); - wmc.setReturnValue(null); + expectLastCall().andReturn(null); wac.getServletContext(); - wmc.setReturnValue(new MockServletContext()); + expectLastCall().andReturn(new MockServletContext()); + final Template expectedTemplate = new Template(); VelocityConfig vc = new VelocityConfig() { public VelocityEngine getVelocityEngine() { @@ -239,19 +244,21 @@ public class VelocityViewTests { } }; wac.getBeansOfType(VelocityConfig.class, true, false); - Map configurers = new HashMap(); + Map configurers = new HashMap(); configurers.put("velocityConfigurer", vc); - wmc.setReturnValue(configurers); - wmc.replay(); + expectLastCall().andReturn(configurers); + replay(wac); + // let it ask for locale - MockControl reqControl = MockControl.createControl(HttpServletRequest.class); - HttpServletRequest req = (HttpServletRequest) reqControl.getMock(); + HttpServletRequest req = createMock(HttpServletRequest.class); + req.getAttribute(View.PATH_VARIABLES); + expectLastCall().andReturn(null); req.getAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE); - reqControl.setReturnValue(new AcceptHeaderLocaleResolver()); + expectLastCall().andReturn(new AcceptHeaderLocaleResolver()); req.getLocale(); - reqControl.setReturnValue(Locale.CANADA); - reqControl.replay(); + expectLastCall().andReturn(Locale.CANADA); + replay(req); final HttpServletResponse expectedResponse = new MockHttpServletResponse(); @@ -272,7 +279,7 @@ public class VelocityViewTests { assertTrue(numberTool.getLocale().equals(Locale.CANADA)); } - protected void exposeHelpers(Map model, HttpServletRequest request) throws Exception { + protected void exposeHelpers(Map model, HttpServletRequest request) throws Exception { model.put("myHelper", "myValue"); } }; @@ -286,10 +293,10 @@ public class VelocityViewTests { vv.setNumberToolAttribute("numberTool"); vv.setExposeSpringMacroHelpers(false); - vv.render(new HashMap(), req, expectedResponse); + vv.render(new HashMap(), req, expectedResponse); - wmc.verify(); - reqControl.verify(); + verify(wac); + verify(req); assertEquals(AbstractView.DEFAULT_CONTENT_TYPE, expectedResponse.getContentType()); } diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/xml/MarshallingViewTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/xml/MarshallingViewTests.java index 637b571af0e..c0aa447ee92 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/xml/MarshallingViewTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/xml/MarshallingViewTests.java @@ -50,12 +50,22 @@ public class MarshallingViewTests { assertEquals("Invalid content type", "application/xml", view.getContentType()); } + @Test + public void isExposePathVars() { + assertEquals("Must not expose path variables", false, view.isExposePathVariables()); + } + + @Test + public void isExposePathVarsDefaultConstructor() { + assertEquals("Must not expose path variables", false, new MarshallingView().isExposePathVariables()); + } + @Test public void renderModelKey() throws Exception { Object toBeMarshalled = new Object(); String modelKey = "key"; view.setModelKey(modelKey); - Map model = new HashMap(); + Map model = new HashMap(); model.put(modelKey, toBeMarshalled); MockHttpServletRequest request = new MockHttpServletRequest(); @@ -76,7 +86,7 @@ public class MarshallingViewTests { Object toBeMarshalled = new Object(); String modelKey = "key"; view.setModelKey("invalidKey"); - Map model = new HashMap(); + Map model = new HashMap(); model.put(modelKey, toBeMarshalled); MockHttpServletRequest request = new MockHttpServletRequest(); @@ -97,7 +107,7 @@ public class MarshallingViewTests { @Test public void renderNullModelValue() throws Exception { String modelKey = "key"; - Map model = new HashMap(); + Map model = new HashMap(); model.put(modelKey, null); MockHttpServletRequest request = new MockHttpServletRequest(); @@ -120,7 +130,7 @@ public class MarshallingViewTests { Object toBeMarshalled = new Object(); String modelKey = "key"; view.setModelKey(modelKey); - Map model = new HashMap(); + Map model = new HashMap(); model.put(modelKey, toBeMarshalled); MockHttpServletRequest request = new MockHttpServletRequest(); @@ -143,7 +153,7 @@ public class MarshallingViewTests { public void renderNoModelKey() throws Exception { Object toBeMarshalled = new Object(); String modelKey = "key"; - Map model = new HashMap(); + Map model = new HashMap(); model.put(modelKey, toBeMarshalled); MockHttpServletRequest request = new MockHttpServletRequest(); @@ -163,7 +173,7 @@ public class MarshallingViewTests { public void testRenderUnsupportedModel() throws Exception { Object toBeMarshalled = new Object(); String modelKey = "key"; - Map model = new HashMap(); + Map model = new HashMap(); model.put(modelKey, toBeMarshalled); MockHttpServletRequest request = new MockHttpServletRequest();