Add spring-js-tiles3 module
Issue: SWF-1575
This commit is contained in:
80
build.gradle
80
build.gradle
@@ -10,16 +10,18 @@ buildscript {
|
||||
}
|
||||
|
||||
configure(allprojects) {
|
||||
apply plugin: "eclipse"
|
||||
apply plugin: "idea"
|
||||
apply plugin: "javadocHotfix"
|
||||
|
||||
group = "org.springframework.webflow"
|
||||
|
||||
apply plugin: "propdeps"
|
||||
apply plugin: "java"
|
||||
apply from: "${rootProject.projectDir}/ide.gradle"
|
||||
apply plugin: "javadocHotfix"
|
||||
}
|
||||
|
||||
configure(subprojects) { subproject ->
|
||||
configure(subprojects - project(":spring-build-src")) { subproject ->
|
||||
|
||||
apply plugin: "java"
|
||||
apply plugin: "propdeps"
|
||||
apply plugin: "merge"
|
||||
apply from: "${rootProject.projectDir}/publish-maven.gradle"
|
||||
|
||||
sourceCompatibility=1.6
|
||||
@@ -58,7 +60,7 @@ configure(subprojects.findAll {it.name != "spring-js-resources"}) { subproject -
|
||||
subproject.ext {
|
||||
springVersion = "4.0.1.RELEASE"
|
||||
springSecurityVersion = "3.2.0.RELEASE"
|
||||
slf4jVersion = "1.6.1"
|
||||
slf4jVersion = "1.7.5"
|
||||
log4jVersion = "1.2.15"
|
||||
}
|
||||
|
||||
@@ -89,6 +91,18 @@ configure(subprojects.findAll {it.name != "spring-js-resources"}) { subproject -
|
||||
}
|
||||
}
|
||||
|
||||
project("spring-build-src") {
|
||||
description = "Exposes gradle buildSrc for IDE support"
|
||||
apply plugin: "groovy"
|
||||
|
||||
dependencies {
|
||||
compile gradleApi()
|
||||
compile localGroovy()
|
||||
}
|
||||
|
||||
configurations.archives.artifacts.clear()
|
||||
}
|
||||
|
||||
project("spring-binding") {
|
||||
description = "Spring Binding"
|
||||
|
||||
@@ -133,10 +147,18 @@ project("spring-js") {
|
||||
compile("org.springframework:spring-webmvc:$springVersion")
|
||||
provided("javax.servlet:javax.servlet-api:3.0.1")
|
||||
optional("org.apache.tiles:tiles-api:2.2.2")
|
||||
optional("org.apache.tiles:tiles-core:2.2.2")
|
||||
optional("org.apache.tiles:tiles-jsp:2.2.2")
|
||||
optional("org.apache.tiles:tiles-servlet:2.2.2")
|
||||
testCompile("javax.servlet:jstl:1.2")
|
||||
optional("org.apache.tiles:tiles-core:2.2.2") {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
}
|
||||
optional("org.apache.tiles:tiles-jsp:2.2.2") {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
}
|
||||
optional("org.apache.tiles:tiles-servlet:2.2.2") {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
}
|
||||
testCompile("javax.servlet:jstl:1.2") {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
}
|
||||
testCompile("log4j:log4j:$log4jVersion") {
|
||||
exclude group: "javax.mail", module: "mail"
|
||||
exclude group: "javax.jms", module: "jms"
|
||||
@@ -149,6 +171,42 @@ project("spring-js") {
|
||||
}
|
||||
}
|
||||
|
||||
project("spring-js-tiles3") {
|
||||
description = "Spring JS Tiles 3 Integration"
|
||||
merge.into = project(":spring-js")
|
||||
|
||||
dependencies {
|
||||
compile("commons-logging:commons-logging:1.1.1")
|
||||
compile("org.springframework:spring-core:$springVersion")
|
||||
compile("org.springframework:spring-webmvc:$springVersion")
|
||||
optional("javax.el:javax.el-api:2.2.4")
|
||||
optional("javax.servlet:javax.servlet-api:3.0.1")
|
||||
optional("javax.servlet.jsp:jsp-api:2.2")
|
||||
optional("org.apache.tiles:tiles-request-api:1.0.1")
|
||||
optional("org.apache.tiles:tiles-api:3.0.1")
|
||||
optional("org.apache.tiles:tiles-core:3.0.1") {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
}
|
||||
optional("org.apache.tiles:tiles-servlet:3.0.1") {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
}
|
||||
optional("org.apache.tiles:tiles-jsp:3.0.1") {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
}
|
||||
optional("org.apache.tiles:tiles-el:3.0.1") {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
}
|
||||
optional("org.apache.tiles:tiles-extras:3.0.1") {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
exclude group: "org.springframework", module: "spring-web"
|
||||
}
|
||||
testCompile("javax.servlet:jstl:1.2")
|
||||
testCompile("org.slf4j:jcl-over-slf4j:$slf4jVersion")
|
||||
testCompile("org.slf4j:slf4j-api:$slf4jVersion")
|
||||
testCompile("org.springframework:spring-test:$springVersion")
|
||||
}
|
||||
}
|
||||
|
||||
project("spring-webflow") {
|
||||
description = "Spring Web Flow"
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
implementation-class=org.springframework.build.gradle.MergePlugin
|
||||
104
ide.gradle
Normal file
104
ide.gradle
Normal file
@@ -0,0 +1,104 @@
|
||||
import org.gradle.plugins.ide.eclipse.model.ProjectDependency
|
||||
import org.gradle.plugins.ide.eclipse.model.SourceFolder
|
||||
|
||||
|
||||
apply plugin: "propdeps-eclipse"
|
||||
apply plugin: "propdeps-idea"
|
||||
|
||||
eclipse.jdt {
|
||||
sourceCompatibility = 1.6
|
||||
targetCompatibility = 1.6
|
||||
}
|
||||
|
||||
// Replace classpath entries with project dependencies (GRADLE-1116)
|
||||
eclipse.classpath.file.whenMerged { classpath ->
|
||||
def regexp = /.*?\/([^\/]+)\/build\/[^\/]+\/(?:main|test)/ // only match those that end in main or test (avoids removing necessary entries like build/classes/jaxb)
|
||||
def projectOutputDependencies = classpath.entries.findAll { entry -> entry.path =~ regexp }
|
||||
projectOutputDependencies.each { entry ->
|
||||
def matcher = (entry.path =~ regexp)
|
||||
if(matcher) {
|
||||
def projectName = matcher[0][1]
|
||||
def path = "/${projectName}"
|
||||
if(!classpath.entries.find { e -> e instanceof ProjectDependency && e.path == path }) {
|
||||
def dependency = new ProjectDependency(path, project(":${projectName}").path)
|
||||
dependency.exported = true
|
||||
classpath.entries.add(dependency)
|
||||
}
|
||||
classpath.entries.remove(entry)
|
||||
}
|
||||
}
|
||||
classpath.entries.removeAll { entry -> (entry.path =~ /(?!.*?repack.*\.jar).*?\/([^\/]+)\/build\/libs\/[^\/]+\.jar/) }
|
||||
}
|
||||
|
||||
|
||||
// Use separate main/test outputs (prevents WTP from packaging test classes)
|
||||
eclipse.classpath.defaultOutputDir = file(project.name+"/bin/eclipse")
|
||||
eclipse.classpath.file.beforeMerged { classpath ->
|
||||
classpath.entries.findAll{ it instanceof SourceFolder }.each {
|
||||
if(it.output.startsWith("bin/")) {
|
||||
it.output = null
|
||||
}
|
||||
}
|
||||
}
|
||||
eclipse.classpath.file.whenMerged { classpath ->
|
||||
classpath.entries.findAll{ it instanceof SourceFolder }.each {
|
||||
it.output = "bin/" + it.path.split("/")[1]
|
||||
}
|
||||
}
|
||||
|
||||
// Allow projects to be used as WPT modules
|
||||
eclipse.project.natures "org.eclipse.wst.common.project.facet.core.nature"
|
||||
|
||||
|
||||
// Include project specific settings
|
||||
task eclipseSettings(type: Copy) {
|
||||
from rootProject.files(
|
||||
"src/eclipse/org.eclipse.jdt.ui.prefs",
|
||||
"src/eclipse/org.eclipse.wst.common.project.facet.core.xml")
|
||||
into project.file('.settings/')
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
||||
task eclipseWstComponent(type: Copy) {
|
||||
from rootProject.files(
|
||||
"src/eclipse/org.eclipse.wst.common.component")
|
||||
into project.file('.settings/')
|
||||
expand(deployname: project.name)
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
||||
task eclipseJdtPrepare(type: Copy) {
|
||||
from rootProject.file("src/eclipse/org.eclipse.jdt.core.prefs")
|
||||
into project.file(".settings/")
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
||||
task cleanEclipseJdtUi(type: Delete) {
|
||||
delete project.file(".settings/org.eclipse.jdt.ui.prefs")
|
||||
delete project.file("org.eclipse.jdt.core.prefs")
|
||||
delete project.file(".settings/org.eclipse.wst.common.component")
|
||||
delete project.file(".settings/org.eclipse.wst.common.project.facet.core.xml")
|
||||
}
|
||||
|
||||
tasks["eclipseJdt"].dependsOn(eclipseJdtPrepare)
|
||||
tasks["cleanEclipse"].dependsOn(cleanEclipseJdtUi)
|
||||
tasks["eclipse"].dependsOn(eclipseSettings, eclipseWstComponent)
|
||||
|
||||
|
||||
// Filter 'build' folder
|
||||
|
||||
eclipse.project.file.withXml {
|
||||
def node = it.asNode()
|
||||
|
||||
def filteredResources = node.get("filteredResources")
|
||||
if(filteredResources) {
|
||||
node.remove(filteredResources)
|
||||
}
|
||||
def filterNode = node.appendNode("filteredResources").appendNode("filter")
|
||||
filterNode.appendNode("id", "1359048889071")
|
||||
filterNode.appendNode("name", "")
|
||||
filterNode.appendNode("type", "30")
|
||||
def matcherNode = filterNode.appendNode("matcher")
|
||||
matcherNode.appendNode("id", "org.eclipse.ui.ide.multiFilter")
|
||||
matcherNode.appendNode("arguments", "1.0-projectRelativePath-matches-false-false-build")
|
||||
}
|
||||
@@ -3,6 +3,10 @@ rootProject.name = 'webflow'
|
||||
include 'spring-binding'
|
||||
include 'spring-faces'
|
||||
include 'spring-js'
|
||||
include 'spring-js-tiles3'
|
||||
include 'spring-js-resources'
|
||||
include 'spring-webflow'
|
||||
|
||||
// Exposes gradle buildSrc
|
||||
include "buildSrc"
|
||||
rootProject.children.find{ it.name == "buildSrc" }.name = "spring-build-src"
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* 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.js.ajax.tiles3;
|
||||
|
||||
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.js.ajax.AjaxHandler;
|
||||
import org.springframework.js.ajax.SpringJavascriptAjaxHandler;
|
||||
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.
|
||||
*
|
||||
* <p>This implementation uses the {@link SpringJavascriptAjaxHandler} 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 AjaxTilesView extends TilesView {
|
||||
|
||||
private static final String FRAGMENTS_PARAM = "fragments";
|
||||
|
||||
private AjaxHandler ajaxHandler = new SpringJavascriptAjaxHandler();
|
||||
|
||||
|
||||
public AjaxHandler getAjaxHandler() {
|
||||
return this.ajaxHandler;
|
||||
}
|
||||
|
||||
public void setAjaxHandler(AjaxHandler ajaxHandler) {
|
||||
this.ajaxHandler = ajaxHandler;
|
||||
}
|
||||
|
||||
|
||||
protected void renderMergedOutputModel(Map<String, Object> 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<String, Attribute> flattenedAttributeMap = new HashMap<String, Attribute>();
|
||||
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<String, Object> 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<String, Attribute> resultMap, Definition definition) {
|
||||
|
||||
Set<String> attributeNames = new HashSet<String>();
|
||||
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<String, Attribute> resultMap) {
|
||||
|
||||
AttributeContext attributeContext = container.getAttributeContext(tilesRequest);
|
||||
Set<String> attributeNames = new HashSet<String>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The Ajax integration between Spring.js and the Tiles3 layout system.
|
||||
*/
|
||||
package org.springframework.js.ajax.tiles3;
|
||||
|
||||
0
spring-js-tiles3/src/main/resources/.gitignore
vendored
Normal file
0
spring-js-tiles3/src/main/resources/.gitignore
vendored
Normal file
@@ -0,0 +1,185 @@
|
||||
package org.springframework.js.ajax.tiles3;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
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.springframework.js.ajax.SpringJavascriptAjaxHandler;
|
||||
import org.springframework.js.ajax.tiles3.AjaxTilesView;
|
||||
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 AjaxTilesViewTests extends TestCase {
|
||||
|
||||
private AjaxTilesView ajaxTilesView;
|
||||
|
||||
private MockHttpServletRequest request;
|
||||
|
||||
private MockHttpServletResponse response;
|
||||
|
||||
private MockServletContext servletContext;
|
||||
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
|
||||
servletContext = new MockServletContext("/org/springframework/js/ajax/tiles3/");
|
||||
request = new MockHttpServletRequest(servletContext);
|
||||
response = new MockHttpServletResponse();
|
||||
|
||||
TilesConfigurer tc = new TilesConfigurer();
|
||||
tc.setDefinitions(new String[] { "tiles-definitions.xml" });
|
||||
tc.setValidateDefinitions(true);
|
||||
tc.setServletContext(servletContext);
|
||||
tc.setUseMutableTilesContainer(false);
|
||||
tc.afterPropertiesSet();
|
||||
|
||||
ajaxTilesView = new AjaxTilesView();
|
||||
}
|
||||
|
||||
private void setupStaticWebApplicationContext() {
|
||||
StaticWebApplicationContext wac = new StaticWebApplicationContext();
|
||||
wac.setServletContext(servletContext);
|
||||
wac.refresh();
|
||||
request.setAttribute(RequestContext.WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
|
||||
ajaxTilesView.setApplicationContext(wac);
|
||||
}
|
||||
|
||||
public void testFullPageRendering() throws Exception {
|
||||
setupStaticWebApplicationContext();
|
||||
ajaxTilesView.setUrl("search");
|
||||
ajaxTilesView.afterPropertiesSet();
|
||||
ajaxTilesView.renderMergedOutputModel(new HashMap<String, Object>(), request, response);
|
||||
assertEquals("/WEB-INF/layout.jsp", response.getForwardedUrl());
|
||||
}
|
||||
|
||||
public void testAjaxRequestNoFragments() throws Exception {
|
||||
setupStaticWebApplicationContext();
|
||||
request.addHeader("Accept", SpringJavascriptAjaxHandler.AJAX_ACCEPT_CONTENT_TYPE);
|
||||
ajaxTilesView.setUrl("search");
|
||||
ajaxTilesView.afterPropertiesSet();
|
||||
ajaxTilesView.renderMergedOutputModel(new HashMap<String, Object>(), request, response);
|
||||
assertEquals("/WEB-INF/layout.jsp", response.getForwardedUrl());
|
||||
}
|
||||
|
||||
public void testRenderFragment_Template() throws Exception {
|
||||
setupStaticWebApplicationContext();
|
||||
request.addHeader("Accept", SpringJavascriptAjaxHandler.AJAX_ACCEPT_CONTENT_TYPE);
|
||||
request.addParameter("fragments", "searchResults");
|
||||
ajaxTilesView.setUrl("search");
|
||||
ajaxTilesView.afterPropertiesSet();
|
||||
ajaxTilesView.renderMergedOutputModel(new HashMap<String, Object>(), request, response);
|
||||
assertEquals("/WEB-INF/searchResults.jsp", response.getForwardedUrl());
|
||||
}
|
||||
|
||||
public void testRenderFragment_Definition() throws Exception {
|
||||
setupStaticWebApplicationContext();
|
||||
request.addHeader("Accept", SpringJavascriptAjaxHandler.AJAX_ACCEPT_CONTENT_TYPE);
|
||||
request.addParameter("fragments", "body");
|
||||
ajaxTilesView.setUrl("search");
|
||||
ajaxTilesView.afterPropertiesSet();
|
||||
ajaxTilesView.renderMergedOutputModel(new HashMap<String, Object>(), request, response);
|
||||
assertEquals("/WEB-INF/search.jsp", response.getForwardedUrl());
|
||||
}
|
||||
|
||||
public void testRenderFragment_CascadedAttribute() throws Exception {
|
||||
setupStaticWebApplicationContext();
|
||||
request.addHeader("Accept", SpringJavascriptAjaxHandler.AJAX_ACCEPT_CONTENT_TYPE);
|
||||
request.addParameter("fragments", "searchNavigation");
|
||||
ajaxTilesView.setUrl("search");
|
||||
ajaxTilesView.afterPropertiesSet();
|
||||
ajaxTilesView.renderMergedOutputModel(new HashMap<String, Object>(), request, response);
|
||||
assertEquals("/WEB-INF/searchNavigation.jsp", response.getForwardedUrl());
|
||||
}
|
||||
|
||||
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", SpringJavascriptAjaxHandler.AJAX_ACCEPT_CONTENT_TYPE);
|
||||
request.addParameter("fragments", "body");
|
||||
ajaxTilesView.setUrl("search");
|
||||
ajaxTilesView.afterPropertiesSet();
|
||||
ajaxTilesView.renderMergedOutputModel(new HashMap<String, Object>(), request, response);
|
||||
assertTrue(AttributeTestingPreparer.invoked);
|
||||
}
|
||||
|
||||
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<String, Attribute> resultMap = new HashMap<String, Attribute>();
|
||||
ajaxTilesView.addRuntimeAttributes(container, tilesRequest, resultMap);
|
||||
assertNotNull(resultMap.get("body"));
|
||||
assertEquals("/WEB-INF/dynamicTemplate.jsp", resultMap.get("body").toString());
|
||||
container.endContext(tilesRequest);
|
||||
}
|
||||
|
||||
public void testRenderFragment_Multiple() throws Exception {
|
||||
setupStaticWebApplicationContext();
|
||||
request.addHeader("Accept", SpringJavascriptAjaxHandler.AJAX_ACCEPT_CONTENT_TYPE);
|
||||
request.addParameter("fragments", "body,searchNavigation");
|
||||
ajaxTilesView.setUrl("search");
|
||||
ajaxTilesView.afterPropertiesSet();
|
||||
ajaxTilesView.renderMergedOutputModel(new HashMap<String, Object>(), request, response);
|
||||
assertTrue("Multiple fragments should result in include, not forward", response.getIncludedUrls().size() == 2);
|
||||
assertEquals("/WEB-INF/search.jsp", response.getIncludedUrls().get(0));
|
||||
assertEquals("/WEB-INF/searchNavigation.jsp", response.getIncludedUrls().get(1));
|
||||
}
|
||||
|
||||
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<String, Attribute> resultMap = new HashMap<String, Attribute>();
|
||||
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"));
|
||||
}
|
||||
|
||||
public void testGetRenderFragments() throws Exception {
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
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;
|
||||
Assert.assertTrue(attributeContext.getAttribute("searchNavigation") != null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE tiles-definitions PUBLIC
|
||||
"-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"
|
||||
"http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
|
||||
|
||||
<tiles-definitions>
|
||||
|
||||
<definition name="layout" template="/WEB-INF/layout.jsp"/>
|
||||
|
||||
<definition name="search" extends="layout">
|
||||
<put-attribute name="searchForm" value="Substituted Value" type="string" />
|
||||
<put-attribute name="body" value="search.body" />
|
||||
<put-attribute name="searchNavigation" value="/WEB-INF/searchNavigation.jsp" cascade="true" />
|
||||
</definition>
|
||||
|
||||
<definition name="search.body" template="/WEB-INF/search.jsp">
|
||||
<put-attribute name="searchForm" value="/WEB-INF/searchForm.jsp" />
|
||||
<put-attribute name="searchResults" value="/WEB-INF/searchResults.jsp" />
|
||||
</definition>
|
||||
|
||||
</tiles-definitions>
|
||||
48
spring-js-tiles3/src/test/resources/log4j.xml
Normal file
48
spring-js-tiles3/src/test/resources/log4j.xml
Normal file
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
|
||||
|
||||
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
|
||||
|
||||
<!-- Appenders -->
|
||||
<appender name="console" class="org.apache.log4j.ConsoleAppender">
|
||||
<param name="Target" value="System.out" />
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<param name="ConversionPattern" value="%-5p: %c - %m%n" />
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework.beans">
|
||||
<level value="warn" />
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework.binding">
|
||||
<level value="debug" />
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework.jdbc">
|
||||
<level value="warn" />
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework.transaction">
|
||||
<level value="warn" />
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework.orm">
|
||||
<level value="warn" />
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework.web">
|
||||
<level value="debug" />
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework.webflow">
|
||||
<level value="debug" />
|
||||
</logger>
|
||||
|
||||
<!-- Root Logger -->
|
||||
<root>
|
||||
<priority value="warn" />
|
||||
<appender-ref ref="console" />
|
||||
</root>
|
||||
|
||||
</log4j:configuration>
|
||||
@@ -44,13 +44,13 @@ import org.springframework.web.servlet.view.tiles2.TilesView;
|
||||
|
||||
/**
|
||||
* Tiles view implementation that is able to handle partial rendering for Spring Javascript Ajax requests.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* This implementation uses the {@link SpringJavascriptAjaxHandler} 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.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Jeremy Grelle
|
||||
* @author David Winterfeldt
|
||||
*/
|
||||
@@ -145,7 +145,7 @@ public class AjaxTilesView extends TilesView {
|
||||
* start with "/") or is a nested definition is added to a Map. The method class itself recursively to traverse
|
||||
* nested definitions.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @param container the TilesContainer
|
||||
* @param requestContext the TilesRequestContext
|
||||
* @param resultMap the output Map where attributes of interest are added to.
|
||||
@@ -180,7 +180,7 @@ public class AjaxTilesView extends TilesView {
|
||||
* Iterate over dynamically added Tiles attributes (see "Runtime Composition" in the Tiles documentation) and add
|
||||
* them to the output Map passed as input.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @param container the Tiles container
|
||||
* @param resultMap the output Map where attributes of interest are added to.
|
||||
* @param request the Servlet request
|
||||
|
||||
Reference in New Issue
Block a user