From 9207f961eba79345cac164d3e7c0ebf14ae332f8 Mon Sep 17 00:00:00 2001 From: Ian Young Date: Thu, 5 May 2022 15:47:35 +0100 Subject: [PATCH] Remove support for Tiles 3 This is no longer supported by Spring Framework 6. --- build.gradle | 10 - spring-webflow/spring-webflow.gradle | 6 - .../webflow/mvc/view/AjaxTiles3View.java | 194 ----------------- .../webflow/mvc/view/FlowAjaxTiles3View.java | 59 ------ .../webflow/mvc/view/AjaxTiles3ViewTests.java | 197 ------------------ 5 files changed, 466 deletions(-) delete mode 100644 spring-webflow/src/main/java/org/springframework/webflow/mvc/view/AjaxTiles3View.java delete mode 100644 spring-webflow/src/main/java/org/springframework/webflow/mvc/view/FlowAjaxTiles3View.java delete mode 100644 spring-webflow/src/test/java/org/springframework/webflow/mvc/view/AjaxTiles3ViewTests.java diff --git a/build.gradle b/build.gradle index 9aa0ebeb..f8fdf226 100644 --- a/build.gradle +++ b/build.gradle @@ -49,16 +49,6 @@ allprojects { entry 'jsf-api' entry 'jsf-impl' } - dependencySet(group: 'org.apache.tiles', version: '3.0.8') { - entry 'tiles-api' - entry('tiles-core', withoutJclOverSlf4j) - entry('tiles-servlet', withoutJclOverSlf4j) - entry('tiles-jsp', withoutJclOverSlf4j) - entry('tiles-el', withoutJclOverSlf4j) - entry('tiles-extras') { - exclude group: "org.springframework", name: "spring-web" - } - } dependency "org.apache.myfaces.core:myfaces-impl:2.2.14" dependency "com.sun.facelets:jsf-facelets:1.1.14" dependency "org.hsqldb:hsqldb:2.5.0" diff --git a/spring-webflow/spring-webflow.gradle b/spring-webflow/spring-webflow.gradle index 7c2ce936..1ae32547 100644 --- a/spring-webflow/spring-webflow.gradle +++ b/spring-webflow/spring-webflow.gradle @@ -13,12 +13,6 @@ dependencies { optional("org.springframework.security:spring-security-core") optional("org.springframework:spring-orm") optional("org.springframework:spring-tx") - optional("org.apache.tiles:tiles-api") - optional("org.apache.tiles:tiles-core") - optional("org.apache.tiles:tiles-servlet") - optional("org.apache.tiles:tiles-jsp") - optional("org.apache.tiles:tiles-el") - optional("org.apache.tiles:tiles-extras") testImplementation("junit:junit") testImplementation("org.junit.jupiter:junit-jupiter") diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/AjaxTiles3View.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/AjaxTiles3View.java deleted file mode 100644 index c78d65df..00000000 --- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/AjaxTiles3View.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright 2014 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 - * - * https://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.webflow.mvc.view; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.tiles.Attribute; -import org.apache.tiles.AttributeContext; -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.springframework.webflow.context.servlet.AjaxHandler; -import org.springframework.webflow.context.servlet.DefaultAjaxHandler; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; -import org.springframework.web.servlet.support.JstlUtils; -import org.springframework.web.servlet.support.RequestContext; -import org.springframework.web.servlet.view.tiles3.TilesView; - -/** - * Tiles 3 view implementation that is able to handle partial rendering for Spring - * Javascript Ajax requests. - * - *

This implementation uses the {@link DefaultAjaxHandler} by default - * to determine whether the current request is an Ajax request. On an Ajax request, - * a "fragments" parameter will be extracted from the request in order to - * determine which attributes to render from the current tiles view. - * - * @author Rossen Stoyanchev - * @since 2.4 - */ -public class AjaxTiles3View extends TilesView { - - private static final String FRAGMENTS_PARAM = "fragments"; - - private AjaxHandler ajaxHandler = new DefaultAjaxHandler(); - - - public AjaxHandler getAjaxHandler() { - return this.ajaxHandler; - } - - public void setAjaxHandler(AjaxHandler ajaxHandler) { - this.ajaxHandler = ajaxHandler; - } - - - protected void renderMergedOutputModel(Map model, HttpServletRequest request, - HttpServletResponse response) throws Exception { - - ServletContext servletContext = getServletContext(); - if (ajaxHandler.isAjaxRequest(request, response)) { - - String[] fragmentsToRender = getRenderFragments(model, request, response); - if (fragmentsToRender.length == 0) { - logger.warn("An Ajax request was detected, but no fragments were specified to be re-rendered. " - + "Falling back to full page render. This can cause unpredictable results when processing " - + "the ajax response on the client."); - super.renderMergedOutputModel(model, request, response); - return; - } - - Request tilesRequest = createTilesRequest(request, response); - ApplicationContext tilesAppContext = tilesRequest.getApplicationContext(); - BasicTilesContainer container = (BasicTilesContainer) TilesAccess.getContainer(tilesAppContext); - - if (container == null) { - throw new ServletException("Tiles container is not initialized. " - + "Have you added a TilesConfigurer to your web application context?"); - } - - exposeModelAsRequestAttributes(model, request); - JstlUtils.exposeLocalizationContext(new RequestContext(request, servletContext)); - - Definition compositeDefinition = container.getDefinitionsFactory().getDefinition(getUrl(), tilesRequest); - - Map flattenedAttributeMap = new HashMap<>(); - flattenAttributeMap(container, tilesRequest, flattenedAttributeMap, compositeDefinition); - addRuntimeAttributes(container, tilesRequest, flattenedAttributeMap); - - if (fragmentsToRender.length > 1) { - tilesRequest.getContext("request").put(ServletRequest.FORCE_INCLUDE_ATTRIBUTE_NAME, true); - } - - for (String element : fragmentsToRender) { - Attribute attributeToRender = flattenedAttributeMap.get(element); - if (attributeToRender == null) { - throw new ServletException("No tiles attribute with a name of '" + element - + "' could be found for the current view: " + this); - } - container.startContext(tilesRequest).inheritCascadedAttributes(compositeDefinition); - container.render(attributeToRender, tilesRequest); - container.endContext(tilesRequest); - } - } else { - super.renderMergedOutputModel(model, request, response); - } - } - - protected String[] getRenderFragments(Map model, HttpServletRequest request, - HttpServletResponse response) { - - String attrName = request.getParameter(FRAGMENTS_PARAM); - String[] renderFragments = StringUtils.commaDelimitedListToStringArray(attrName); - return StringUtils.trimArrayElements(renderFragments); - } - - /** - * Iterate over all attributes in the given Tiles definition. Every attribute - * value that represents a template (i.e. start with "/") or is a nested - * definition is added to a Map. The method class itself recursively to traverse - * nested definitions. - * - * @param container the TilesContainer - * @param tilesRequest the Tiles Request - * @param resultMap the output Map where attributes of interest are added to. - * @param definition the definition to search for attributes of interest. - */ - protected void flattenAttributeMap(BasicTilesContainer container, Request tilesRequest, - Map resultMap, Definition definition) { - - Set attributeNames = new HashSet<>(); - if (definition.getLocalAttributeNames() != null) { - attributeNames.addAll(definition.getLocalAttributeNames()); - } - if (definition.getCascadedAttributeNames() != null) { - attributeNames.addAll(definition.getCascadedAttributeNames()); - } - for (String attributeName : attributeNames) { - Attribute attribute = definition.getAttribute(attributeName); - if (attribute.getValue() == null || !(attribute.getValue() instanceof String)) { - continue; - } - String value = attribute.getValue().toString(); - if (value.startsWith("/")) { - resultMap.put(attributeName, attribute); - } else if (container.isValidDefinition(value, tilesRequest)) { - resultMap.put(attributeName, attribute); - Definition nestedDefinition = container.getDefinitionsFactory().getDefinition(value, tilesRequest); - Assert.isTrue(nestedDefinition != definition, "Circular nested definition: " + value); - flattenAttributeMap(container, tilesRequest, resultMap, nestedDefinition); - } - } - } - - /** - * Iterate over dynamically added Tiles attributes (see "Runtime Composition" - * in the Tiles documentation) and add them to the output Map passed as input. - * - * @param container the Tiles container - * @param tilesRequest the Tiles request - * @param resultMap the output Map where attributes of interest are added to. - */ - protected void addRuntimeAttributes(BasicTilesContainer container, - Request tilesRequest, Map resultMap) { - - AttributeContext attributeContext = container.getAttributeContext(tilesRequest); - Set attributeNames = new HashSet<>(); - if (attributeContext.getLocalAttributeNames() != null) { - attributeNames.addAll(attributeContext.getLocalAttributeNames()); - } - if (attributeContext.getCascadedAttributeNames() != null) { - attributeNames.addAll(attributeContext.getCascadedAttributeNames()); - } - for (String name : attributeNames) { - Attribute attr = attributeContext.getAttribute(name); - resultMap.put(name, attr); - } - } -} diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/FlowAjaxTiles3View.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/FlowAjaxTiles3View.java deleted file mode 100644 index b82aa60a..00000000 --- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/view/FlowAjaxTiles3View.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2014 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 - * - * https://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.webflow.mvc.view; - -import java.util.Map; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.springframework.webflow.context.servlet.DefaultAjaxHandler; -import org.springframework.webflow.execution.RequestContext; -import org.springframework.webflow.execution.RequestContextHolder; -import org.springframework.webflow.execution.View; - -/** - * Tiles view implementation that is able to handle partial rendering for Spring - * Javascript Ajax requests. - * - *

This implementation uses the {@link DefaultAjaxHandler} - * by default to determine whether the current request is an Ajax request. On an - * Ajax request for an active flow execution, the fragments set by a {@code } - * action will be respected, otherwise the parent {@link AjaxTiles3View}'s resolution algorithm - * will be applied. - * - * @author Rossen Stoyanchev - * @since 2.4 - */ -public class FlowAjaxTiles3View extends AjaxTiles3View { - - - protected String[] getRenderFragments(Map model, HttpServletRequest request, - HttpServletResponse response) { - - RequestContext context = RequestContextHolder.getRequestContext(); - if (context == null) { - return super.getRenderFragments(model, request, response); - } - - String[] fragments = (String[]) context.getFlashScope().get(View.RENDER_FRAGMENTS_ATTRIBUTE); - if (fragments == null) { - return super.getRenderFragments(model, request, response); - } - - return fragments; - } - -} diff --git a/spring-webflow/src/test/java/org/springframework/webflow/mvc/view/AjaxTiles3ViewTests.java b/spring-webflow/src/test/java/org/springframework/webflow/mvc/view/AjaxTiles3ViewTests.java deleted file mode 100644 index 8fcffc69..00000000 --- a/spring-webflow/src/test/java/org/springframework/webflow/mvc/view/AjaxTiles3ViewTests.java +++ /dev/null @@ -1,197 +0,0 @@ -package org.springframework.webflow.mvc.view; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.tiles.Attribute; -import org.apache.tiles.AttributeContext; -import org.apache.tiles.Definition; -import org.apache.tiles.access.TilesAccess; -import org.apache.tiles.impl.BasicTilesContainer; -import org.apache.tiles.preparer.ViewPreparer; -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.wildcard.WildcardServletApplicationContext; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.webflow.context.servlet.DefaultAjaxHandler; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.mock.web.MockServletContext; -import org.springframework.web.context.support.StaticWebApplicationContext; -import org.springframework.web.servlet.support.RequestContext; -import org.springframework.web.servlet.view.tiles3.TilesConfigurer; - -public class AjaxTiles3ViewTests { - - private AjaxTiles3View ajaxTilesView; - - private MockHttpServletRequest request; - - private MockHttpServletResponse response; - - private MockServletContext servletContext; - - - @BeforeEach - public void setUp() throws Exception { - - servletContext = new MockServletContext("/org/springframework/webflow/mvc/view/"); - request = new MockHttpServletRequest(servletContext); - response = new MockHttpServletResponse(); - - TilesConfigurer tc = new TilesConfigurer(); - tc.setDefinitions("tiles-definitions.xml"); - tc.setValidateDefinitions(true); - tc.setServletContext(servletContext); - tc.setUseMutableTilesContainer(false); - tc.afterPropertiesSet(); - - ajaxTilesView = new AjaxTiles3View(); - } - - private void setupStaticWebApplicationContext() { - StaticWebApplicationContext wac = new StaticWebApplicationContext(); - wac.setServletContext(servletContext); - wac.refresh(); - request.setAttribute(RequestContext.WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac); - ajaxTilesView.setApplicationContext(wac); - } - - @Test - public void testFullPageRendering() throws Exception { - setupStaticWebApplicationContext(); - ajaxTilesView.setUrl("search"); - ajaxTilesView.afterPropertiesSet(); - ajaxTilesView.renderMergedOutputModel(new HashMap<>(), request, response); - assertEquals("/WEB-INF/layout.jsp", response.getForwardedUrl()); - } - - @Test - public void testAjaxRequestNoFragments() throws Exception { - setupStaticWebApplicationContext(); - request.addHeader("Accept", DefaultAjaxHandler.AJAX_ACCEPT_CONTENT_TYPE); - ajaxTilesView.setUrl("search"); - ajaxTilesView.afterPropertiesSet(); - ajaxTilesView.renderMergedOutputModel(new HashMap<>(), request, response); - assertEquals("/WEB-INF/layout.jsp", response.getForwardedUrl()); - } - - @Test - public void testRenderFragment_Template() throws Exception { - setupStaticWebApplicationContext(); - request.addHeader("Accept", DefaultAjaxHandler.AJAX_ACCEPT_CONTENT_TYPE); - request.addParameter("fragments", "searchResults"); - ajaxTilesView.setUrl("search"); - ajaxTilesView.afterPropertiesSet(); - ajaxTilesView.renderMergedOutputModel(new HashMap<>(), request, response); - assertEquals("/WEB-INF/searchResults.jsp", response.getForwardedUrl()); - } - - @Test - public void testRenderFragment_Definition() throws Exception { - setupStaticWebApplicationContext(); - request.addHeader("Accept", DefaultAjaxHandler.AJAX_ACCEPT_CONTENT_TYPE); - request.addParameter("fragments", "body"); - ajaxTilesView.setUrl("search"); - ajaxTilesView.afterPropertiesSet(); - ajaxTilesView.renderMergedOutputModel(new HashMap<>(), request, response); - assertEquals("/WEB-INF/search.jsp", response.getForwardedUrl()); - } - - @Test - public void testRenderFragment_CascadedAttribute() throws Exception { - setupStaticWebApplicationContext(); - request.addHeader("Accept", DefaultAjaxHandler.AJAX_ACCEPT_CONTENT_TYPE); - request.addParameter("fragments", "searchNavigation"); - ajaxTilesView.setUrl("search"); - ajaxTilesView.afterPropertiesSet(); - ajaxTilesView.renderMergedOutputModel(new HashMap<>(), request, response); - assertEquals("/WEB-INF/searchNavigation.jsp", response.getForwardedUrl()); - } - - @Test - public void testRenderFragment_InheritCascadedAttribute() throws Exception { - ApplicationContext tilesAppContext = new WildcardServletApplicationContext(servletContext); - Request tilesRequest = new ServletRequest(tilesAppContext, request, response); - BasicTilesContainer container = (BasicTilesContainer) TilesAccess.getContainer(tilesAppContext); - Definition definition = container.getDefinitionsFactory().getDefinition("search.body", tilesRequest); - definition.setPreparer(AttributeTestingPreparer.class.getName()); - setupStaticWebApplicationContext(); - request.addHeader("Accept", DefaultAjaxHandler.AJAX_ACCEPT_CONTENT_TYPE); - request.addParameter("fragments", "body"); - ajaxTilesView.setUrl("search"); - ajaxTilesView.afterPropertiesSet(); - ajaxTilesView.renderMergedOutputModel(new HashMap<>(), request, response); - assertTrue(AttributeTestingPreparer.invoked); - } - - @Test - public void testRenderFragment_DynamicAttribute() throws Exception { - ApplicationContext tilesAppContext = new WildcardServletApplicationContext(servletContext); - Request tilesRequest = new ServletRequest(tilesAppContext, request, response); - BasicTilesContainer container = (BasicTilesContainer) TilesAccess.getContainer(tilesAppContext); - AttributeContext attributeContext = container.startContext(tilesRequest); - attributeContext.putAttribute("body", new Attribute("/WEB-INF/dynamicTemplate.jsp")); - Map resultMap = new HashMap<>(); - ajaxTilesView.addRuntimeAttributes(container, tilesRequest, resultMap); - assertNotNull(resultMap.get("body")); - assertEquals("/WEB-INF/dynamicTemplate.jsp", resultMap.get("body").toString()); - container.endContext(tilesRequest); - } - - @Test - public void testRenderFragment_Multiple() throws Exception { - setupStaticWebApplicationContext(); - request.addHeader("Accept", DefaultAjaxHandler.AJAX_ACCEPT_CONTENT_TYPE); - request.addParameter("fragments", "body,searchNavigation"); - ajaxTilesView.setUrl("search"); - ajaxTilesView.afterPropertiesSet(); - ajaxTilesView.renderMergedOutputModel(new HashMap<>(), request, response); - assertTrue(response.getIncludedUrls().size() == 2, "Multiple fragments should result in include, not forward"); - assertEquals("/WEB-INF/search.jsp", response.getIncludedUrls().get(0)); - assertEquals("/WEB-INF/searchNavigation.jsp", response.getIncludedUrls().get(1)); - } - - @Test - public void testFlattenAttributeMap() throws Exception { - ApplicationContext tilesAppContext = new WildcardServletApplicationContext(servletContext); - Request tilesRequest = new ServletRequest(tilesAppContext, request, response); - BasicTilesContainer container = (BasicTilesContainer) TilesAccess.getContainer(tilesAppContext); - Definition compositeDefinition = container.getDefinitionsFactory().getDefinition("search", tilesRequest); - Map resultMap = new HashMap<>(); - ajaxTilesView.flattenAttributeMap(container, tilesRequest, resultMap, compositeDefinition); - assertNotNull(resultMap.get("body")); - assertNotNull(resultMap.get("searchForm")); - assertEquals("/WEB-INF/searchForm.jsp", resultMap.get("searchForm").toString()); - assertNotNull(resultMap.get("searchResults")); - } - - @Test - public void testGetRenderFragments() throws Exception { - Map model = new HashMap<>(); - request.setParameter("fragments", "f1,f2, f3"); - String[] fragments = ajaxTilesView.getRenderFragments(model, request, response); - assertEquals("f1", fragments[0]); - assertEquals("f2", fragments[1]); - assertEquals("f3", fragments[2]); - } - - - public static class AttributeTestingPreparer implements ViewPreparer { - - public static boolean invoked; - - public void execute(Request tilesContext, AttributeContext attributeContext) { - invoked = true; - assertTrue(attributeContext.getAttribute("searchNavigation") != null); - } - - } - -}