From aff03df00cf3b3e3985a2b055b007ed9861c83e6 Mon Sep 17 00:00:00 2001 From: Torsten Krah Date: Mon, 13 Mar 2017 16:12:06 +0100 Subject: [PATCH] Support multiple TilesContainer per ServletContext - use explicit containerKey derived from the contextId to register TilesContainer to be able to use multiple definition unique to each WebApplicationContext (there maybe more than one in case of multiple DispatcherContext servlet registrations) Issue: SPR-11587 --- .../tiles3/SpringTilesContainerFactory.java | 127 ++++++++++++++++ .../view/tiles3/SpringTilesInitializer.java | 30 ++++ .../servlet/view/tiles3/TilesConfigurer.java | 139 +++--------------- .../web/servlet/view/tiles3/TilesView.java | 4 +- .../view/tiles3/TilesConfigurerTests.java | 77 +++++++++- .../tiles3/TilesViewIntegrationTests.java | 133 +++++++++++++++++ .../servlet/view/tiles3/TilesViewTests.java | 24 ++- .../view/tiles3/tiles-definitions-2nd.xml | 10 ++ 8 files changed, 417 insertions(+), 127 deletions(-) create mode 100644 spring-webmvc/src/main/java/org/springframework/web/servlet/view/tiles3/SpringTilesContainerFactory.java create mode 100644 spring-webmvc/src/main/java/org/springframework/web/servlet/view/tiles3/SpringTilesInitializer.java create mode 100644 spring-webmvc/src/test/java/org/springframework/web/servlet/view/tiles3/TilesViewIntegrationTests.java create mode 100644 spring-webmvc/src/test/resources/org/springframework/web/servlet/view/tiles3/tiles-definitions-2nd.xml diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/tiles3/SpringTilesContainerFactory.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/tiles3/SpringTilesContainerFactory.java new file mode 100644 index 000000000000..f82793f3426d --- /dev/null +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/tiles3/SpringTilesContainerFactory.java @@ -0,0 +1,127 @@ +package org.springframework.web.servlet.view.tiles3; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +import javax.servlet.jsp.JspFactory; + +import org.apache.tiles.TilesContainer; +import org.apache.tiles.definition.DefinitionsFactory; +import org.apache.tiles.definition.DefinitionsReader; +import org.apache.tiles.definition.dao.BaseLocaleUrlDefinitionDAO; +import org.apache.tiles.definition.dao.CachingLocaleUrlDefinitionDAO; +import org.apache.tiles.definition.digester.DigesterDefinitionsReader; +import org.apache.tiles.evaluator.AttributeEvaluator; +import org.apache.tiles.evaluator.AttributeEvaluatorFactory; +import org.apache.tiles.evaluator.BasicAttributeEvaluatorFactory; +import org.apache.tiles.evaluator.impl.DirectAttributeEvaluator; +import org.apache.tiles.factory.BasicTilesContainerFactory; +import org.apache.tiles.impl.mgmt.CachingTilesContainer; +import org.apache.tiles.locale.LocaleResolver; +import org.apache.tiles.preparer.factory.PreparerFactory; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.ApplicationContextAware; +import org.apache.tiles.request.ApplicationResource; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.PropertyAccessorFactory; +import org.springframework.web.servlet.view.tiles3.TilesConfigurer.TilesElActivator; + +/** + * @author Torsten Krah + */ +class SpringTilesContainerFactory extends BasicTilesContainerFactory { + + private TilesConfigurer tilesConfigurer; + + public SpringTilesContainerFactory(TilesConfigurer tilesConfigurer) { + this.tilesConfigurer = tilesConfigurer; + } + + @Override + protected TilesContainer createDecoratedContainer(TilesContainer originalContainer, ApplicationContext context) { + return (tilesConfigurer.useMutableTilesContainer ? new CachingTilesContainer(originalContainer) : originalContainer); + } + + @Override + protected List getSources(ApplicationContext applicationContext) { + if (tilesConfigurer.definitions != null) { + List result = new LinkedList<>(); + for (String definition : tilesConfigurer.definitions) { + Collection resources = applicationContext.getResources(definition); + if (resources != null) { + result.addAll(resources); + } + } + return result; + } else { + return super.getSources(applicationContext); + } + } + + @Override + protected BaseLocaleUrlDefinitionDAO instantiateLocaleDefinitionDao(ApplicationContext applicationContext, + LocaleResolver resolver) { + BaseLocaleUrlDefinitionDAO dao = super.instantiateLocaleDefinitionDao(applicationContext, resolver); + if (tilesConfigurer.checkRefresh && dao instanceof CachingLocaleUrlDefinitionDAO) { + ((CachingLocaleUrlDefinitionDAO) dao).setCheckRefresh(true); + } + return dao; + } + + @Override + protected DefinitionsReader createDefinitionsReader(ApplicationContext context) { + DigesterDefinitionsReader reader = (DigesterDefinitionsReader) super.createDefinitionsReader(context); + reader.setValidating(tilesConfigurer.validateDefinitions); + return reader; + } + + @Override + protected DefinitionsFactory createDefinitionsFactory(ApplicationContext applicationContext, + LocaleResolver resolver) { + + if (tilesConfigurer.definitionsFactoryClass != null) { + DefinitionsFactory factory = BeanUtils.instantiateClass(tilesConfigurer.definitionsFactoryClass); + if (factory instanceof ApplicationContextAware) { + ((ApplicationContextAware) factory).setApplicationContext(applicationContext); + } + BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(factory); + if (bw.isWritableProperty("localeResolver")) { + bw.setPropertyValue("localeResolver", resolver); + } + if (bw.isWritableProperty("definitionDAO")) { + bw.setPropertyValue("definitionDAO", createLocaleDefinitionDao(applicationContext, resolver)); + } + return factory; + } else { + return super.createDefinitionsFactory(applicationContext, resolver); + } + } + + @Override + protected PreparerFactory createPreparerFactory(ApplicationContext context) { + if (tilesConfigurer.preparerFactoryClass != null) { + return BeanUtils.instantiateClass(tilesConfigurer.preparerFactoryClass); + } else { + return super.createPreparerFactory(context); + } + } + + @Override + protected LocaleResolver createLocaleResolver(ApplicationContext context) { + return new SpringLocaleResolver(); + } + + @Override + protected AttributeEvaluatorFactory createAttributeEvaluatorFactory(ApplicationContext context, + LocaleResolver resolver) { + AttributeEvaluator evaluator; + if (TilesConfigurer.tilesElPresent && JspFactory.getDefaultFactory() != null) { + evaluator = new TilesElActivator().createEvaluator(tilesConfigurer.servletContext); + } else { + evaluator = new DirectAttributeEvaluator(); + } + return new BasicAttributeEvaluatorFactory(evaluator); + } +} diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/tiles3/SpringTilesInitializer.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/tiles3/SpringTilesInitializer.java new file mode 100644 index 000000000000..d284497a9c1f --- /dev/null +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/tiles3/SpringTilesInitializer.java @@ -0,0 +1,30 @@ +package org.springframework.web.servlet.view.tiles3; + +import org.apache.tiles.factory.AbstractTilesContainerFactory; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.startup.DefaultTilesInitializer; + +/** + * @author Torsten Krah + */ +class SpringTilesInitializer extends DefaultTilesInitializer { + + private TilesConfigurer tilesConfigurer; + private final String contextId; + + public SpringTilesInitializer(TilesConfigurer tilesConfigurer, final String contextId) { + super(); + this.tilesConfigurer = tilesConfigurer; + this.contextId = contextId; + } + + @Override + protected AbstractTilesContainerFactory createContainerFactory(ApplicationContext context) { + return new SpringTilesContainerFactory(this.tilesConfigurer); + } + + @Override + protected String getContainerKey(ApplicationContext applicationContext) { + return this.contextId; + } +} diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/tiles3/TilesConfigurer.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/tiles3/TilesConfigurer.java index a2aec332983e..55bcf1142942 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/tiles3/TilesConfigurer.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/tiles3/TilesConfigurer.java @@ -55,11 +55,11 @@ import org.apache.tiles.request.ApplicationContext; import org.apache.tiles.request.ApplicationContextAware; import org.apache.tiles.request.ApplicationResource; -import org.apache.tiles.startup.DefaultTilesInitializer; import org.apache.tiles.startup.TilesInitializer; import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanWrapper; +import org.springframework.beans.BeansException; import org.springframework.beans.PropertyAccessorFactory; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; @@ -122,9 +122,9 @@ * @see TilesView * @see TilesViewResolver */ -public class TilesConfigurer implements ServletContextAware, InitializingBean, DisposableBean { +public class TilesConfigurer implements ServletContextAware, InitializingBean, DisposableBean, org.springframework.context.ApplicationContextAware { - private static final boolean tilesElPresent = + static final boolean tilesElPresent = ClassUtils.isPresent("org.apache.tiles.el.ELAttributeEvaluator", TilesConfigurer.class.getClassLoader()); @@ -132,20 +132,21 @@ public class TilesConfigurer implements ServletContextAware, InitializingBean, D private TilesInitializer tilesInitializer; - private String[] definitions; + String[] definitions; - private boolean checkRefresh = false; + boolean checkRefresh = false; - private boolean validateDefinitions = true; + boolean validateDefinitions = true; - private Class definitionsFactoryClass; + Class definitionsFactoryClass; - private Class preparerFactoryClass; + Class preparerFactoryClass; - private boolean useMutableTilesContainer = false; + boolean useMutableTilesContainer = false; - private ServletContext servletContext; + ServletContext servletContext; + private org.springframework.context.ApplicationContext applicationContext; /** * Configure Tiles using a custom TilesInitializer, typically specified as an inner bean. @@ -159,7 +160,12 @@ public void setTilesInitializer(TilesInitializer tilesInitializer) { this.tilesInitializer = tilesInitializer; } - /** + @Override + public void setApplicationContext(org.springframework.context.ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } + + /** * Specify whether to apply Tiles 3.0's "complete-autoload" configuration. *

See {@link org.apache.tiles.extras.complete.CompleteAutoloadTilesContainerFactory} * for details on the complete-autoload mode. @@ -266,7 +272,7 @@ public void setServletContext(ServletContext servletContext) { public void afterPropertiesSet() throws TilesException { ApplicationContext preliminaryContext = new SpringWildcardServletTilesApplicationContext(this.servletContext); if (this.tilesInitializer == null) { - this.tilesInitializer = new SpringTilesInitializer(); + this.tilesInitializer = new SpringTilesInitializer(this, applicationContext.getId()); } this.tilesInitializer.initialize(preliminaryContext); } @@ -281,110 +287,7 @@ public void destroy() throws TilesException { } - private class SpringTilesInitializer extends DefaultTilesInitializer { - - @Override - protected AbstractTilesContainerFactory createContainerFactory(ApplicationContext context) { - return new SpringTilesContainerFactory(); - } - } - - - private class SpringTilesContainerFactory extends BasicTilesContainerFactory { - - @Override - protected TilesContainer createDecoratedContainer(TilesContainer originalContainer, ApplicationContext context) { - return (useMutableTilesContainer ? new CachingTilesContainer(originalContainer) : originalContainer); - } - - @Override - protected List getSources(ApplicationContext applicationContext) { - if (definitions != null) { - List result = new LinkedList<>(); - for (String definition : definitions) { - Collection resources = applicationContext.getResources(definition); - if (resources != null) { - result.addAll(resources); - } - } - return result; - } - else { - return super.getSources(applicationContext); - } - } - - @Override - protected BaseLocaleUrlDefinitionDAO instantiateLocaleDefinitionDao(ApplicationContext applicationContext, - LocaleResolver resolver) { - BaseLocaleUrlDefinitionDAO dao = super.instantiateLocaleDefinitionDao(applicationContext, resolver); - if (checkRefresh && dao instanceof CachingLocaleUrlDefinitionDAO) { - ((CachingLocaleUrlDefinitionDAO) dao).setCheckRefresh(true); - } - return dao; - } - - @Override - protected DefinitionsReader createDefinitionsReader(ApplicationContext context) { - DigesterDefinitionsReader reader = (DigesterDefinitionsReader) super.createDefinitionsReader(context); - reader.setValidating(validateDefinitions); - return reader; - } - - @Override - protected DefinitionsFactory createDefinitionsFactory(ApplicationContext applicationContext, - LocaleResolver resolver) { - - if (definitionsFactoryClass != null) { - DefinitionsFactory factory = BeanUtils.instantiateClass(definitionsFactoryClass); - if (factory instanceof ApplicationContextAware) { - ((ApplicationContextAware) factory).setApplicationContext(applicationContext); - } - BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(factory); - if (bw.isWritableProperty("localeResolver")) { - bw.setPropertyValue("localeResolver", resolver); - } - if (bw.isWritableProperty("definitionDAO")) { - bw.setPropertyValue("definitionDAO", createLocaleDefinitionDao(applicationContext, resolver)); - } - return factory; - } - else { - return super.createDefinitionsFactory(applicationContext, resolver); - } - } - - @Override - protected PreparerFactory createPreparerFactory(ApplicationContext context) { - if (preparerFactoryClass != null) { - return BeanUtils.instantiateClass(preparerFactoryClass); - } - else { - return super.createPreparerFactory(context); - } - } - - @Override - protected LocaleResolver createLocaleResolver(ApplicationContext context) { - return new SpringLocaleResolver(); - } - - @Override - protected AttributeEvaluatorFactory createAttributeEvaluatorFactory(ApplicationContext context, - LocaleResolver resolver) { - AttributeEvaluator evaluator; - if (tilesElPresent && JspFactory.getDefaultFactory() != null) { - evaluator = new TilesElActivator().createEvaluator(); - } - else { - evaluator = new DirectAttributeEvaluator(); - } - return new BasicAttributeEvaluatorFactory(evaluator); - } - } - - - private static class SpringCompleteAutoloadTilesInitializer extends CompleteAutoloadTilesInitializer { + private static class SpringCompleteAutoloadTilesInitializer extends CompleteAutoloadTilesInitializer { @Override protected AbstractTilesContainerFactory createContainerFactory(ApplicationContext context) { @@ -402,9 +305,9 @@ protected LocaleResolver createLocaleResolver(ApplicationContext applicationCont } - private class TilesElActivator { + static class TilesElActivator { - public AttributeEvaluator createEvaluator() { + public AttributeEvaluator createEvaluator(final ServletContext servletContext) { ELAttributeEvaluator evaluator = new ELAttributeEvaluator(); evaluator.setExpressionFactory( JspFactory.getDefaultFactory().getJspApplicationContext(servletContext).getExpressionFactory()); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/tiles3/TilesView.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/tiles3/TilesView.java index c7fc14c5219b..3cb167060cbc 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/tiles3/TilesView.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/tiles3/TilesView.java @@ -94,7 +94,8 @@ public void afterPropertiesSet() throws Exception { this.applicationContext = ServletUtil.getApplicationContext(getServletContext()); if (this.renderer == null) { - TilesContainer container = TilesAccess.getContainer(this.applicationContext); + TilesContainer container = TilesAccess.getContainer(this.applicationContext, + getWebApplicationContext().getId()); this.renderer = new DefinitionRenderer(container); } } @@ -129,6 +130,7 @@ protected void renderMergedOutputModel(Map model, HttpServletReq } Request tilesRequest = createTilesRequest(request, response); + TilesAccess.setCurrentContainer(tilesRequest, getWebApplicationContext().getId()); this.renderer.render(getUrl(), tilesRequest); } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/view/tiles3/TilesConfigurerTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/view/tiles3/TilesConfigurerTests.java index 283d1e6c0410..b79ca3f5fe1a 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/view/tiles3/TilesConfigurerTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/view/tiles3/TilesConfigurerTests.java @@ -16,18 +16,21 @@ package org.springframework.web.servlet.view.tiles3; +import org.apache.tiles.Definition; import org.apache.tiles.access.TilesAccess; import org.apache.tiles.impl.BasicTilesContainer; import org.apache.tiles.request.ApplicationContext; import org.apache.tiles.request.Request; import org.apache.tiles.request.servlet.ServletRequest; import org.apache.tiles.request.servlet.ServletUtil; +import org.junit.Assert; import org.junit.Test; import org.springframework.context.annotation.Configuration; import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.mock.web.test.MockHttpServletResponse; import org.springframework.mock.web.test.MockServletContext; +import org.springframework.web.context.support.StaticWebApplicationContext; import static org.junit.Assert.*; @@ -41,23 +44,91 @@ public class TilesConfigurerTests { @Test public void simpleBootstrap() { MockServletContext servletContext = new MockServletContext(); + StaticWebApplicationContext wac = new StaticWebApplicationContext(); + wac.setServletContext(servletContext); + wac.refresh(); TilesConfigurer tc = new TilesConfigurer(); tc.setDefinitions("/org/springframework/web/servlet/view/tiles3/tiles-definitions.xml"); tc.setCheckRefresh(true); tc.setServletContext(servletContext); + tc.setApplicationContext(wac); tc.afterPropertiesSet(); ApplicationContext tilesContext = ServletUtil.getApplicationContext(servletContext); - BasicTilesContainer container = (BasicTilesContainer) TilesAccess.getContainer(tilesContext); + BasicTilesContainer container = (BasicTilesContainer) TilesAccess.getContainer(tilesContext, wac.getId()); Request requestContext = new ServletRequest(container.getApplicationContext(), new MockHttpServletRequest(), new MockHttpServletResponse()); - assertNotNull(container.getDefinitionsFactory().getDefinition("test", requestContext)); + Definition definition = container.getDefinitionsFactory().getDefinition("test", requestContext); + assertNotNull(definition); + assertEquals("/WEB-INF/tiles/test.jsp", definition.getTemplateAttribute().getValue()); - tc.destroy(); + tc.destroy(); } + @Test + public void moreThanOneContextBootstrap() { + MockServletContext servletContext = new MockServletContext(); + + StaticWebApplicationContext wac1 = new StaticWebApplicationContext(); + wac1.setDisplayName("wac1"); + wac1.setId("wac1"); + wac1.setServletContext(servletContext); + wac1.refresh(); + + TilesConfigurer tc1 = new TilesConfigurer(); + tc1.setDefinitions("/org/springframework/web/servlet/view/tiles3/tiles-definitions.xml"); + tc1.setCheckRefresh(true); + tc1.setServletContext(servletContext); + tc1.setApplicationContext(wac1); + tc1.afterPropertiesSet(); + + + StaticWebApplicationContext wac2 = new StaticWebApplicationContext(); + wac2.setDisplayName("wac2"); + wac2.setId("wac2"); + wac2.setServletContext(servletContext); + wac2.refresh(); + + TilesConfigurer tc2 = new TilesConfigurer(); + tc2.setDefinitions("/org/springframework/web/servlet/view/tiles3/tiles-definitions-2nd.xml"); + tc2.setCheckRefresh(true); + tc2.setServletContext(servletContext); + tc2.setApplicationContext(wac2); + tc2.afterPropertiesSet(); + + ApplicationContext tilesContext = ServletUtil.getApplicationContext(servletContext); + assertNotNull(tilesContext.getApplicationScope().get(wac1.getId())); + assertNotNull(tilesContext.getApplicationScope().get(wac2.getId())); + assertNull(TilesAccess.getContainer(tilesContext)); + + try { + BasicTilesContainer container = (BasicTilesContainer) TilesAccess.getContainer(tilesContext, wac1.getId()); + Request requestContext = new ServletRequest(container.getApplicationContext(), + new MockHttpServletRequest(), new MockHttpServletResponse()); + Definition definition = container.getDefinitionsFactory().getDefinition("test", requestContext); + assertNotNull(definition); + assertEquals("/WEB-INF/tiles/test.jsp", definition.getTemplateAttribute().getValue()); + } finally { + + } + + try { + BasicTilesContainer container = (BasicTilesContainer) TilesAccess.getContainer(tilesContext, wac2.getId()); + Request requestContext = new ServletRequest(container.getApplicationContext(), + new MockHttpServletRequest(), new MockHttpServletResponse()); + Definition definition = container.getDefinitionsFactory().getDefinition("test2", requestContext); + assertNotNull(definition); + assertEquals("/WEB-INF/tiles/test2.jsp", definition.getTemplateAttribute().getValue()); + } finally { + + } + + + tc1.destroy(); + } + @Configuration public static class AppConfig { diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/view/tiles3/TilesViewIntegrationTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/view/tiles3/TilesViewIntegrationTests.java new file mode 100644 index 000000000000..76d8b93b7e46 --- /dev/null +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/view/tiles3/TilesViewIntegrationTests.java @@ -0,0 +1,133 @@ +/* + * Copyright 2002-2016 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.view.tiles3; + +import static org.junit.Assert.assertEquals; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tiles.definition.NoSuchDefinitionException; +import org.junit.Before; +import org.junit.Test; +import org.springframework.mock.web.test.MockHttpServletRequest; +import org.springframework.mock.web.test.MockHttpServletResponse; +import org.springframework.mock.web.test.MockServletContext; +import org.springframework.web.context.support.StaticWebApplicationContext; +import org.springframework.web.servlet.DispatcherServlet; + +/** + * Test fixture for {@link TilesView}. + * + * @author mick semb wever + * @author Sebastien Deleuze + */ +public class TilesViewIntegrationTests { + + private static final String VIEW_PATH = "test"; + + private static final String VIEW_PATH_2 = "test2"; + + private TilesView view1; + + private TilesView view2; + + private MockHttpServletRequest request1; + + private MockHttpServletResponse response1; + + private MockHttpServletRequest request2; + + private MockHttpServletResponse response2; + + + @Before + public void setUp() throws Exception { + final MockServletContext servletContext = new MockServletContext(); + + final StaticWebApplicationContext wac1 = new StaticWebApplicationContext(); + wac1.setDisplayName("wac1"); + wac1.setId("wac1"); + wac1.setServletContext(servletContext); + wac1.refresh(); + + request1 = new MockHttpServletRequest(); + request1.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac1); + + response1 = new MockHttpServletResponse(); + + final TilesConfigurer tc1 = new TilesConfigurer(); + tc1.setDefinitions("/org/springframework/web/servlet/view/tiles3/tiles-definitions.xml"); + tc1.setCheckRefresh(true); + tc1.setServletContext(servletContext); + tc1.setApplicationContext(wac1); + tc1.afterPropertiesSet(); + + final StaticWebApplicationContext wac2 = new StaticWebApplicationContext(); + wac2.setDisplayName("wac2"); + wac2.setId("wac2"); + wac2.setServletContext(servletContext); + wac2.refresh(); + + request2 = new MockHttpServletRequest(); + request2.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac2); + + response2 = new MockHttpServletResponse(); + + final TilesConfigurer tc2 = new TilesConfigurer(); + tc2.setDefinitions("/org/springframework/web/servlet/view/tiles3/tiles-definitions-2nd.xml"); + tc2.setCheckRefresh(true); + tc2.setServletContext(servletContext); + tc2.setApplicationContext(wac2); + tc2.afterPropertiesSet(); + + view1 = new TilesView(); + view1.setServletContext(servletContext); + view1.setApplicationContext(wac1); + view1.setUrl(VIEW_PATH); + view1.afterPropertiesSet(); + + view2 = new TilesView(); + view2.setServletContext(servletContext); + view2.setApplicationContext(wac2); + view2.setUrl(VIEW_PATH_2); + view2.afterPropertiesSet(); + } + + @Test + public void render() throws Exception { + Map model = new HashMap<>(); + model.put("modelAttribute", "modelValue"); + view1.render(model, request1, response1); + assertEquals("modelValue", request1.getAttribute("modelAttribute")); + view2.render(model, request2, response2); + assertEquals("modelValue", request2.getAttribute("modelAttribute")); + } + + @Test(expected = NoSuchDefinitionException.class) + public void renderPath1FromWac2() throws Exception { + Map model = new HashMap<>(); + view2.setUrl(VIEW_PATH); + view2.render(model, request2, response2); + } + + @Test(expected = NoSuchDefinitionException.class) + public void renderPath2FromWac1() throws Exception { + Map model = new HashMap<>(); + view1.setUrl(VIEW_PATH_2); + view1.render(model, request1, response1); + } +} diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/view/tiles3/TilesViewTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/view/tiles3/TilesViewTests.java index 2887e83f86df..6dce44c6ab92 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/view/tiles3/TilesViewTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/view/tiles3/TilesViewTests.java @@ -15,24 +15,30 @@ */ package org.springframework.web.servlet.view.tiles3; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.BDDMockito.eq; +import static org.mockito.BDDMockito.isA; +import static org.mockito.BDDMockito.mock; +import static org.mockito.BDDMockito.verify; + import java.util.HashMap; import java.util.Map; +import org.apache.tiles.access.TilesAccess; import org.apache.tiles.request.AbstractRequest; import org.apache.tiles.request.Request; import org.apache.tiles.request.render.Renderer; +import org.apache.tiles.request.render.StringRenderer; import org.junit.Before; import org.junit.Test; - import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.mock.web.test.MockHttpServletResponse; import org.springframework.mock.web.test.MockServletContext; import org.springframework.web.context.support.StaticWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; -import static org.junit.Assert.*; -import static org.mockito.BDDMockito.*; - /** * Test fixture for {@link TilesView}. * @@ -66,8 +72,16 @@ public void setUp() throws Exception { renderer = mock(Renderer.class); - view = new TilesView(); + TilesConfigurer tc = new TilesConfigurer(); + tc.setDefinitions("/org/springframework/web/servlet/view/tiles3/tiles-definitions.xml"); + tc.setCheckRefresh(true); + tc.setServletContext(servletContext); + tc.setApplicationContext(wac); + tc.afterPropertiesSet(); + + view = new TilesView(); view.setServletContext(servletContext); + view.setApplicationContext(wac); view.setRenderer(renderer); view.setUrl(VIEW_PATH); view.afterPropertiesSet(); diff --git a/spring-webmvc/src/test/resources/org/springframework/web/servlet/view/tiles3/tiles-definitions-2nd.xml b/spring-webmvc/src/test/resources/org/springframework/web/servlet/view/tiles3/tiles-definitions-2nd.xml new file mode 100644 index 000000000000..6b559450d7bf --- /dev/null +++ b/spring-webmvc/src/test/resources/org/springframework/web/servlet/view/tiles3/tiles-definitions-2nd.xml @@ -0,0 +1,10 @@ + + + + + + + +