Remove Velocity support
Issue: SPR-13795
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* 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.
|
||||
@@ -18,11 +18,10 @@ package org.springframework.mail;
|
||||
|
||||
/**
|
||||
* Exception to be thrown by user code if a mail cannot be prepared properly,
|
||||
* for example when a Velocity template cannot be rendered for the mail text.
|
||||
* for example when a FreeMarker template cannot be rendered for the mail text.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.1
|
||||
* @see org.springframework.ui.velocity.VelocityEngineUtils#mergeTemplateIntoString
|
||||
* @see org.springframework.ui.freemarker.FreeMarkerTemplateUtils#processTemplateIntoString
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* 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.
|
||||
@@ -46,7 +46,7 @@ public interface MimeMessagePreparator {
|
||||
* @throws java.io.IOException passing any exceptions thrown by MimeMessage methods
|
||||
* through for automatic conversion to the MailException hierarchy
|
||||
* @throws Exception if mail preparation failed, for example when a
|
||||
* Velocity template cannot be rendered for the mail text
|
||||
* FreeMarker template cannot be rendered for the mail text
|
||||
*/
|
||||
void prepare(MimeMessage mimeMessage) throws Exception;
|
||||
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.ui.velocity;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.commons.collections.ExtendedProperties;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.velocity.exception.ResourceNotFoundException;
|
||||
import org.apache.velocity.runtime.resource.Resource;
|
||||
import org.apache.velocity.runtime.resource.loader.ResourceLoader;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Velocity ResourceLoader adapter that loads via a Spring ResourceLoader.
|
||||
* Used by VelocityEngineFactory for any resource loader path that cannot
|
||||
* be resolved to a {@code java.io.File}.
|
||||
*
|
||||
* <p>Note that this loader does not allow for modification detection:
|
||||
* Use Velocity's default FileResourceLoader for {@code java.io.File}
|
||||
* resources.
|
||||
*
|
||||
* <p>Expects "spring.resource.loader" and "spring.resource.loader.path"
|
||||
* application attributes in the Velocity runtime: the former of type
|
||||
* {@code org.springframework.core.io.ResourceLoader}, the latter a String.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 14.03.2004
|
||||
* @see VelocityEngineFactory#setResourceLoaderPath
|
||||
* @see org.springframework.core.io.ResourceLoader
|
||||
* @see org.apache.velocity.runtime.resource.loader.FileResourceLoader
|
||||
*/
|
||||
public class SpringResourceLoader extends ResourceLoader {
|
||||
|
||||
public static final String NAME = "spring";
|
||||
|
||||
public static final String SPRING_RESOURCE_LOADER_CLASS = "spring.resource.loader.class";
|
||||
|
||||
public static final String SPRING_RESOURCE_LOADER_CACHE = "spring.resource.loader.cache";
|
||||
|
||||
public static final String SPRING_RESOURCE_LOADER = "spring.resource.loader";
|
||||
|
||||
public static final String SPRING_RESOURCE_LOADER_PATH = "spring.resource.loader.path";
|
||||
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private org.springframework.core.io.ResourceLoader resourceLoader;
|
||||
|
||||
private String[] resourceLoaderPaths;
|
||||
|
||||
|
||||
@Override
|
||||
public void init(ExtendedProperties configuration) {
|
||||
this.resourceLoader = (org.springframework.core.io.ResourceLoader)
|
||||
this.rsvc.getApplicationAttribute(SPRING_RESOURCE_LOADER);
|
||||
String resourceLoaderPath = (String) this.rsvc.getApplicationAttribute(SPRING_RESOURCE_LOADER_PATH);
|
||||
if (this.resourceLoader == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"'resourceLoader' application attribute must be present for SpringResourceLoader");
|
||||
}
|
||||
if (resourceLoaderPath == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"'resourceLoaderPath' application attribute must be present for SpringResourceLoader");
|
||||
}
|
||||
this.resourceLoaderPaths = StringUtils.commaDelimitedListToStringArray(resourceLoaderPath);
|
||||
for (int i = 0; i < this.resourceLoaderPaths.length; i++) {
|
||||
String path = this.resourceLoaderPaths[i];
|
||||
if (!path.endsWith("/")) {
|
||||
this.resourceLoaderPaths[i] = path + "/";
|
||||
}
|
||||
}
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("SpringResourceLoader for Velocity: using resource loader [" + this.resourceLoader +
|
||||
"] and resource loader paths " + Arrays.asList(this.resourceLoaderPaths));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getResourceStream(String source) throws ResourceNotFoundException {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Looking for Velocity resource with name [" + source + "]");
|
||||
}
|
||||
for (String resourceLoaderPath : this.resourceLoaderPaths) {
|
||||
org.springframework.core.io.Resource resource =
|
||||
this.resourceLoader.getResource(resourceLoaderPath + source);
|
||||
try {
|
||||
return resource.getInputStream();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Could not find Velocity resource: " + resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new ResourceNotFoundException(
|
||||
"Could not find resource [" + source + "] in Spring resource loader path");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSourceModified(Resource resource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastModified(Resource resource) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,357 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.ui.velocity;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.velocity.app.VelocityEngine;
|
||||
import org.apache.velocity.exception.VelocityException;
|
||||
import org.apache.velocity.runtime.RuntimeConstants;
|
||||
import org.apache.velocity.runtime.log.CommonsLogLogChute;
|
||||
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.PropertiesLoaderUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Factory that configures a VelocityEngine. Can be used standalone,
|
||||
* but typically you will either use {@link VelocityEngineFactoryBean}
|
||||
* for preparing a VelocityEngine as bean reference, or
|
||||
* {@link org.springframework.web.servlet.view.velocity.VelocityConfigurer}
|
||||
* for web views.
|
||||
*
|
||||
* <p>The optional "configLocation" property sets the location of the Velocity
|
||||
* properties file, within the current application. Velocity properties can be
|
||||
* overridden via "velocityProperties", or even completely specified locally,
|
||||
* avoiding the need for an external properties file.
|
||||
*
|
||||
* <p>The "resourceLoaderPath" property can be used to specify the Velocity
|
||||
* resource loader path via Spring's Resource abstraction, possibly relative
|
||||
* to the Spring application context.
|
||||
*
|
||||
* <p>If "overrideLogging" is true (the default), the VelocityEngine will be
|
||||
* configured to log via Commons Logging, that is, using
|
||||
* {@link CommonsLogLogChute} as log system.
|
||||
*
|
||||
* <p>The simplest way to use this class is to specify a
|
||||
* {@link #setResourceLoaderPath(String) "resourceLoaderPath"}; the
|
||||
* VelocityEngine typically then does not need any further configuration.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @see #setConfigLocation
|
||||
* @see #setVelocityProperties
|
||||
* @see #setResourceLoaderPath
|
||||
* @see #setOverrideLogging
|
||||
* @see #createVelocityEngine
|
||||
* @see VelocityEngineFactoryBean
|
||||
* @see org.springframework.web.servlet.view.velocity.VelocityConfigurer
|
||||
* @see org.apache.velocity.app.VelocityEngine
|
||||
* @deprecated as of Spring 4.3, in favor of FreeMarker
|
||||
*/
|
||||
@Deprecated
|
||||
public class VelocityEngineFactory {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private Resource configLocation;
|
||||
|
||||
private final Map<String, Object> velocityProperties = new HashMap<String, Object>();
|
||||
|
||||
private String resourceLoaderPath;
|
||||
|
||||
private ResourceLoader resourceLoader = new DefaultResourceLoader();
|
||||
|
||||
private boolean preferFileSystemAccess = true;
|
||||
|
||||
private boolean overrideLogging = true;
|
||||
|
||||
|
||||
/**
|
||||
* Set the location of the Velocity config file.
|
||||
* Alternatively, you can specify all properties locally.
|
||||
* @see #setVelocityProperties
|
||||
* @see #setResourceLoaderPath
|
||||
*/
|
||||
public void setConfigLocation(Resource configLocation) {
|
||||
this.configLocation = configLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Velocity properties, like "file.resource.loader.path".
|
||||
* Can be used to override values in a Velocity config file,
|
||||
* or to specify all necessary properties locally.
|
||||
* <p>Note that the Velocity resource loader path also be set to any
|
||||
* Spring resource location via the "resourceLoaderPath" property.
|
||||
* Setting it here is just necessary when using a non-file-based
|
||||
* resource loader.
|
||||
* @see #setVelocityPropertiesMap
|
||||
* @see #setConfigLocation
|
||||
* @see #setResourceLoaderPath
|
||||
*/
|
||||
public void setVelocityProperties(Properties velocityProperties) {
|
||||
CollectionUtils.mergePropertiesIntoMap(velocityProperties, this.velocityProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Velocity properties as Map, to allow for non-String values
|
||||
* like "ds.resource.loader.instance".
|
||||
* @see #setVelocityProperties
|
||||
*/
|
||||
public void setVelocityPropertiesMap(Map<String, Object> velocityPropertiesMap) {
|
||||
if (velocityPropertiesMap != null) {
|
||||
this.velocityProperties.putAll(velocityPropertiesMap);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Velocity resource loader path via a Spring resource location.
|
||||
* Accepts multiple locations in Velocity's comma-separated path style.
|
||||
* <p>When populated via a String, standard URLs like "file:" and "classpath:"
|
||||
* pseudo URLs are supported, as understood by ResourceLoader. Allows for
|
||||
* relative paths when running in an ApplicationContext.
|
||||
* <p>Will define a path for the default Velocity resource loader with the name
|
||||
* "file". If the specified resource cannot be resolved to a {@code java.io.File},
|
||||
* a generic SpringResourceLoader will be used under the name "spring", without
|
||||
* modification detection.
|
||||
* <p>Note that resource caching will be enabled in any case. With the file
|
||||
* resource loader, the last-modified timestamp will be checked on access to
|
||||
* detect changes. With SpringResourceLoader, the resource will be cached
|
||||
* forever (for example for class path resources).
|
||||
* <p>To specify a modification check interval for files, use Velocity's
|
||||
* standard "file.resource.loader.modificationCheckInterval" property. By default,
|
||||
* the file timestamp is checked on every access (which is surprisingly fast).
|
||||
* Of course, this just applies when loading resources from the file system.
|
||||
* <p>To enforce the use of SpringResourceLoader, i.e. to not resolve a path
|
||||
* as file system resource in any case, turn off the "preferFileSystemAccess"
|
||||
* flag. See the latter's javadoc for details.
|
||||
* @see #setResourceLoader
|
||||
* @see #setVelocityProperties
|
||||
* @see #setPreferFileSystemAccess
|
||||
* @see SpringResourceLoader
|
||||
* @see org.apache.velocity.runtime.resource.loader.FileResourceLoader
|
||||
*/
|
||||
public void setResourceLoaderPath(String resourceLoaderPath) {
|
||||
this.resourceLoaderPath = resourceLoaderPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Spring ResourceLoader to use for loading Velocity template files.
|
||||
* The default is DefaultResourceLoader. Will get overridden by the
|
||||
* ApplicationContext if running in a context.
|
||||
* @see org.springframework.core.io.DefaultResourceLoader
|
||||
* @see org.springframework.context.ApplicationContext
|
||||
*/
|
||||
public void setResourceLoader(ResourceLoader resourceLoader) {
|
||||
this.resourceLoader = resourceLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Spring ResourceLoader to use for loading Velocity template files.
|
||||
*/
|
||||
protected ResourceLoader getResourceLoader() {
|
||||
return this.resourceLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to prefer file system access for template loading.
|
||||
* File system access enables hot detection of template changes.
|
||||
* <p>If this is enabled, VelocityEngineFactory will try to resolve the
|
||||
* specified "resourceLoaderPath" as file system resource (which will work
|
||||
* for expanded class path resources and ServletContext resources too).
|
||||
* <p>Default is "true". Turn this off to always load via SpringResourceLoader
|
||||
* (i.e. as stream, without hot detection of template changes), which might
|
||||
* be necessary if some of your templates reside in an expanded classes
|
||||
* directory while others reside in jar files.
|
||||
* @see #setResourceLoaderPath
|
||||
*/
|
||||
public void setPreferFileSystemAccess(boolean preferFileSystemAccess) {
|
||||
this.preferFileSystemAccess = preferFileSystemAccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether to prefer file system access for template loading.
|
||||
*/
|
||||
protected boolean isPreferFileSystemAccess() {
|
||||
return this.preferFileSystemAccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether Velocity should log via Commons Logging, i.e. whether Velocity's
|
||||
* log system should be set to {@link CommonsLogLogChute}. Default is "true".
|
||||
*/
|
||||
public void setOverrideLogging(boolean overrideLogging) {
|
||||
this.overrideLogging = overrideLogging;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prepare the VelocityEngine instance and return it.
|
||||
* @return the VelocityEngine instance
|
||||
* @throws IOException if the config file wasn't found
|
||||
* @throws VelocityException on Velocity initialization failure
|
||||
*/
|
||||
public VelocityEngine createVelocityEngine() throws IOException, VelocityException {
|
||||
VelocityEngine velocityEngine = newVelocityEngine();
|
||||
Map<String, Object> props = new HashMap<String, Object>();
|
||||
|
||||
// Load config file if set.
|
||||
if (this.configLocation != null) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Loading Velocity config from [" + this.configLocation + "]");
|
||||
}
|
||||
CollectionUtils.mergePropertiesIntoMap(PropertiesLoaderUtils.loadProperties(this.configLocation), props);
|
||||
}
|
||||
|
||||
// Merge local properties if set.
|
||||
if (!this.velocityProperties.isEmpty()) {
|
||||
props.putAll(this.velocityProperties);
|
||||
}
|
||||
|
||||
// Set a resource loader path, if required.
|
||||
if (this.resourceLoaderPath != null) {
|
||||
initVelocityResourceLoader(velocityEngine, this.resourceLoaderPath);
|
||||
}
|
||||
|
||||
// Log via Commons Logging?
|
||||
if (this.overrideLogging) {
|
||||
velocityEngine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, new CommonsLogLogChute());
|
||||
}
|
||||
|
||||
// Apply properties to VelocityEngine.
|
||||
for (Map.Entry<String, Object> entry : props.entrySet()) {
|
||||
velocityEngine.setProperty(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
postProcessVelocityEngine(velocityEngine);
|
||||
|
||||
// Perform actual initialization.
|
||||
velocityEngine.init();
|
||||
|
||||
return velocityEngine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new VelocityEngine. Subclasses can override this for
|
||||
* custom initialization, or for using a mock object for testing.
|
||||
* <p>Called by {@code createVelocityEngine()}.
|
||||
* @return the VelocityEngine instance
|
||||
* @throws IOException if a config file wasn't found
|
||||
* @throws VelocityException on Velocity initialization failure
|
||||
* @see #createVelocityEngine()
|
||||
*/
|
||||
protected VelocityEngine newVelocityEngine() throws IOException, VelocityException {
|
||||
return new VelocityEngine();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a Velocity resource loader for the given VelocityEngine:
|
||||
* either a standard Velocity FileResourceLoader or a SpringResourceLoader.
|
||||
* <p>Called by {@code createVelocityEngine()}.
|
||||
* @param velocityEngine the VelocityEngine to configure
|
||||
* @param resourceLoaderPath the path to load Velocity resources from
|
||||
* @see org.apache.velocity.runtime.resource.loader.FileResourceLoader
|
||||
* @see SpringResourceLoader
|
||||
* @see #initSpringResourceLoader
|
||||
* @see #createVelocityEngine()
|
||||
*/
|
||||
protected void initVelocityResourceLoader(VelocityEngine velocityEngine, String resourceLoaderPath) {
|
||||
if (isPreferFileSystemAccess()) {
|
||||
// Try to load via the file system, fall back to SpringResourceLoader
|
||||
// (for hot detection of template changes, if possible).
|
||||
try {
|
||||
StringBuilder resolvedPath = new StringBuilder();
|
||||
String[] paths = StringUtils.commaDelimitedListToStringArray(resourceLoaderPath);
|
||||
for (int i = 0; i < paths.length; i++) {
|
||||
String path = paths[i];
|
||||
Resource resource = getResourceLoader().getResource(path);
|
||||
File file = resource.getFile(); // will fail if not resolvable in the file system
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Resource loader path [" + path + "] resolved to file [" + file.getAbsolutePath() + "]");
|
||||
}
|
||||
resolvedPath.append(file.getAbsolutePath());
|
||||
if (i < paths.length - 1) {
|
||||
resolvedPath.append(',');
|
||||
}
|
||||
}
|
||||
velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADER, "file");
|
||||
velocityEngine.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_CACHE, "true");
|
||||
velocityEngine.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, resolvedPath.toString());
|
||||
}
|
||||
catch (IOException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Cannot resolve resource loader path [" + resourceLoaderPath +
|
||||
"] to [java.io.File]: using SpringResourceLoader", ex);
|
||||
}
|
||||
initSpringResourceLoader(velocityEngine, resourceLoaderPath);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Always load via SpringResourceLoader
|
||||
// (without hot detection of template changes).
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("File system access not preferred: using SpringResourceLoader");
|
||||
}
|
||||
initSpringResourceLoader(velocityEngine, resourceLoaderPath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a SpringResourceLoader for the given VelocityEngine.
|
||||
* <p>Called by {@code initVelocityResourceLoader}.
|
||||
* @param velocityEngine the VelocityEngine to configure
|
||||
* @param resourceLoaderPath the path to load Velocity resources from
|
||||
* @see SpringResourceLoader
|
||||
* @see #initVelocityResourceLoader
|
||||
*/
|
||||
protected void initSpringResourceLoader(VelocityEngine velocityEngine, String resourceLoaderPath) {
|
||||
velocityEngine.setProperty(
|
||||
RuntimeConstants.RESOURCE_LOADER, SpringResourceLoader.NAME);
|
||||
velocityEngine.setProperty(
|
||||
SpringResourceLoader.SPRING_RESOURCE_LOADER_CLASS, SpringResourceLoader.class.getName());
|
||||
velocityEngine.setProperty(
|
||||
SpringResourceLoader.SPRING_RESOURCE_LOADER_CACHE, "true");
|
||||
velocityEngine.setApplicationAttribute(
|
||||
SpringResourceLoader.SPRING_RESOURCE_LOADER, getResourceLoader());
|
||||
velocityEngine.setApplicationAttribute(
|
||||
SpringResourceLoader.SPRING_RESOURCE_LOADER_PATH, resourceLoaderPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* To be implemented by subclasses that want to perform custom
|
||||
* post-processing of the VelocityEngine after this FactoryBean
|
||||
* performed its default configuration (but before VelocityEngine.init).
|
||||
* <p>Called by {@code createVelocityEngine()}.
|
||||
* @param velocityEngine the current VelocityEngine
|
||||
* @throws IOException if a config file wasn't found
|
||||
* @throws VelocityException on Velocity initialization failure
|
||||
* @see #createVelocityEngine()
|
||||
* @see org.apache.velocity.app.VelocityEngine#init
|
||||
*/
|
||||
protected void postProcessVelocityEngine(VelocityEngine velocityEngine)
|
||||
throws IOException, VelocityException {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.ui.velocity;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.velocity.app.VelocityEngine;
|
||||
import org.apache.velocity.exception.VelocityException;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
|
||||
/**
|
||||
* Factory bean that configures a VelocityEngine and provides it as bean
|
||||
* reference. This bean is intended for any kind of usage of Velocity in
|
||||
* application code, e.g. for generating email content. For web views,
|
||||
* VelocityConfigurer is used to set up a VelocityEngine for views.
|
||||
*
|
||||
* <p>The simplest way to use this class is to specify a "resourceLoaderPath";
|
||||
* you do not need any further configuration then. For example, in a web
|
||||
* application context:
|
||||
*
|
||||
* <pre class="code"> <bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
|
||||
* <property name="resourceLoaderPath" value="/WEB-INF/velocity/"/>
|
||||
* </bean></pre>
|
||||
*
|
||||
* See the base class VelocityEngineFactory for configuration details.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @see #setConfigLocation
|
||||
* @see #setVelocityProperties
|
||||
* @see #setResourceLoaderPath
|
||||
* @see org.springframework.web.servlet.view.velocity.VelocityConfigurer
|
||||
* @deprecated as of Spring 4.3, in favor of FreeMarker
|
||||
*/
|
||||
@Deprecated
|
||||
public class VelocityEngineFactoryBean extends VelocityEngineFactory
|
||||
implements FactoryBean<VelocityEngine>, InitializingBean, ResourceLoaderAware {
|
||||
|
||||
private VelocityEngine velocityEngine;
|
||||
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws IOException, VelocityException {
|
||||
this.velocityEngine = createVelocityEngine();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public VelocityEngine getObject() {
|
||||
return this.velocityEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends VelocityEngine> getObjectType() {
|
||||
return VelocityEngine.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.ui.velocity;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.velocity.VelocityContext;
|
||||
import org.apache.velocity.app.VelocityEngine;
|
||||
import org.apache.velocity.exception.VelocityException;
|
||||
|
||||
/**
|
||||
* Utility class for working with a VelocityEngine.
|
||||
* Provides convenience methods to merge a Velocity template with a model.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 22.01.2004
|
||||
* @deprecated as of Spring 4.3, in favor of FreeMarker
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class VelocityEngineUtils {
|
||||
|
||||
/**
|
||||
* Merge the specified Velocity template with the given model and write
|
||||
* the result to the given Writer.
|
||||
* @param velocityEngine VelocityEngine to work with
|
||||
* @param templateLocation the location of template, relative to Velocity's resource loader path
|
||||
* @param model the Map that contains model names as keys and model objects as values
|
||||
* @param writer the Writer to write the result to
|
||||
* @throws VelocityException if the template wasn't found or rendering failed
|
||||
* @deprecated Use {@link #mergeTemplate(VelocityEngine, String, String, Map, Writer)}
|
||||
* instead, following Velocity 1.6's corresponding deprecation in its own API.
|
||||
*/
|
||||
@Deprecated
|
||||
public static void mergeTemplate(
|
||||
VelocityEngine velocityEngine, String templateLocation, Map<String, Object> model, Writer writer)
|
||||
throws VelocityException {
|
||||
|
||||
VelocityContext velocityContext = new VelocityContext(model);
|
||||
velocityEngine.mergeTemplate(templateLocation, velocityContext, writer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the specified Velocity template with the given model and write the result
|
||||
* to the given Writer.
|
||||
* @param velocityEngine VelocityEngine to work with
|
||||
* @param templateLocation the location of template, relative to Velocity's resource loader path
|
||||
* @param encoding the encoding of the template file
|
||||
* @param model the Map that contains model names as keys and model objects as values
|
||||
* @param writer the Writer to write the result to
|
||||
* @throws VelocityException if the template wasn't found or rendering failed
|
||||
*/
|
||||
public static void mergeTemplate(
|
||||
VelocityEngine velocityEngine, String templateLocation, String encoding,
|
||||
Map<String, Object> model, Writer writer) throws VelocityException {
|
||||
|
||||
VelocityContext velocityContext = new VelocityContext(model);
|
||||
velocityEngine.mergeTemplate(templateLocation, encoding, velocityContext, writer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the specified Velocity template with the given model into a String.
|
||||
* <p>When using this method to prepare a text for a mail to be sent with Spring's
|
||||
* mail support, consider wrapping VelocityException in MailPreparationException.
|
||||
* @param velocityEngine VelocityEngine to work with
|
||||
* @param templateLocation the location of template, relative to Velocity's resource loader path
|
||||
* @param model the Map that contains model names as keys and model objects as values
|
||||
* @return the result as String
|
||||
* @throws VelocityException if the template wasn't found or rendering failed
|
||||
* @see org.springframework.mail.MailPreparationException
|
||||
* @deprecated Use {@link #mergeTemplateIntoString(VelocityEngine, String, String, Map)}
|
||||
* instead, following Velocity 1.6's corresponding deprecation in its own API.
|
||||
*/
|
||||
@Deprecated
|
||||
public static String mergeTemplateIntoString(VelocityEngine velocityEngine, String templateLocation,
|
||||
Map<String, Object> model) throws VelocityException {
|
||||
|
||||
StringWriter result = new StringWriter();
|
||||
mergeTemplate(velocityEngine, templateLocation, model, result);
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the specified Velocity template with the given model into a String.
|
||||
* <p>When using this method to prepare a text for a mail to be sent with Spring's
|
||||
* mail support, consider wrapping VelocityException in MailPreparationException.
|
||||
* @param velocityEngine VelocityEngine to work with
|
||||
* @param templateLocation the location of template, relative to Velocity's resource loader path
|
||||
* @param encoding the encoding of the template file
|
||||
* @param model the Map that contains model names as keys and model objects as values
|
||||
* @return the result as String
|
||||
* @throws VelocityException if the template wasn't found or rendering failed
|
||||
* @see org.springframework.mail.MailPreparationException
|
||||
*/
|
||||
public static String mergeTemplateIntoString(VelocityEngine velocityEngine, String templateLocation,
|
||||
String encoding, Map<String, Object> model) throws VelocityException {
|
||||
|
||||
StringWriter result = new StringWriter();
|
||||
mergeTemplate(velocityEngine, templateLocation, encoding, model, result);
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
/**
|
||||
* Support classes for setting up
|
||||
* <a href="http://velocity.apache.org">Velocity</a>
|
||||
* within a Spring application context.
|
||||
*/
|
||||
package org.springframework.ui.velocity;
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* 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.
|
||||
@@ -41,7 +41,6 @@ public class MvcNamespaceHandler extends NamespaceHandlerSupport {
|
||||
registerBeanDefinitionParser("view-resolvers", new ViewResolversBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("tiles-configurer", new TilesConfigurerBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("freemarker-configurer", new FreeMarkerConfigurerBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("velocity-configurer", new VelocityConfigurerBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("groovy-configurer", new GroovyMarkupConfigurerBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("script-template-configurer", new ScriptTemplateConfigurerBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("cors", new CorsBeanDefinitionParser());
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-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.web.servlet.config;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
|
||||
|
||||
/**
|
||||
* Parse the <mvc:velocity-configurer> MVC namespace element and register an
|
||||
* VelocityConfigurer bean
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.1
|
||||
*/
|
||||
public class VelocityConfigurerBeanDefinitionParser extends AbstractSimpleBeanDefinitionParser {
|
||||
|
||||
public static final String BEAN_NAME = "mvcVelocityConfigurer";
|
||||
|
||||
@Override
|
||||
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) {
|
||||
return BEAN_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getBeanClassName(Element element) {
|
||||
return "org.springframework.web.servlet.view.velocity.VelocityConfigurer";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEligibleAttribute(String attributeName) {
|
||||
return attributeName.equals("resource-loader-path");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postProcess(BeanDefinitionBuilder builder, Element element) {
|
||||
if (!builder.getBeanDefinition().hasAttribute("resourceLoaderPath")) {
|
||||
builder.getBeanDefinition().setAttribute("resourceLoaderPath", "/WEB-INF/");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,7 +58,6 @@ import org.springframework.web.servlet.view.tiles3.TilesViewResolver;
|
||||
* @since 4.1
|
||||
* @see TilesConfigurerBeanDefinitionParser
|
||||
* @see FreeMarkerConfigurerBeanDefinitionParser
|
||||
* @see VelocityConfigurerBeanDefinitionParser
|
||||
* @see GroovyMarkupConfigurerBeanDefinitionParser
|
||||
* @see ScriptTemplateConfigurerBeanDefinitionParser
|
||||
*/
|
||||
@@ -98,11 +97,6 @@ public class ViewResolversBeanDefinitionParser implements BeanDefinitionParser {
|
||||
resolverBeanDef.getPropertyValues().add("suffix", ".ftl");
|
||||
addUrlBasedViewResolverProperties(resolverElement, resolverBeanDef);
|
||||
}
|
||||
else if ("velocity".equals(name)) {
|
||||
resolverBeanDef = new RootBeanDefinition(org.springframework.web.servlet.view.velocity.VelocityViewResolver.class);
|
||||
resolverBeanDef.getPropertyValues().add("suffix", ".vm");
|
||||
addUrlBasedViewResolverProperties(resolverElement, resolverBeanDef);
|
||||
}
|
||||
else if ("groovy".equals(name)) {
|
||||
resolverBeanDef = new RootBeanDefinition(GroovyMarkupViewResolver.class);
|
||||
resolverBeanDef.getPropertyValues().add("suffix", ".tpl");
|
||||
|
||||
@@ -190,26 +190,6 @@ public class ViewResolverRegistry {
|
||||
return registration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register Velocity view resolver with an empty default view name
|
||||
* prefix and a default suffix of ".vm".
|
||||
* <p><strong>Note</strong> that you must also configure Velocity by adding a
|
||||
* {@link org.springframework.web.servlet.view.velocity.VelocityConfigurer} bean.
|
||||
* @deprecated as of Spring 4.3, in favor of FreeMarker
|
||||
*/
|
||||
@Deprecated
|
||||
public UrlBasedViewResolverRegistration velocity() {
|
||||
if (this.applicationContext != null && !hasBeanOfType(org.springframework.web.servlet.view.velocity.VelocityConfigurer.class)) {
|
||||
throw new BeanInitializationException("In addition to a Velocity view resolver " +
|
||||
"there must also be a single VelocityConfig bean in this web application context " +
|
||||
"(or its parent): VelocityConfigurer is the usual implementation. " +
|
||||
"This bean may be given any name.");
|
||||
}
|
||||
VelocityRegistration registration = new VelocityRegistration();
|
||||
this.viewResolvers.add(registration.getViewResolver());
|
||||
return registration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a Groovy markup view resolver with an empty default view name
|
||||
* prefix and a default suffix of ".tpl".
|
||||
@@ -309,15 +289,6 @@ public class ViewResolverRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
private static class VelocityRegistration extends UrlBasedViewResolverRegistration {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public VelocityRegistration() {
|
||||
super(new org.springframework.web.servlet.view.velocity.VelocityViewResolver());
|
||||
getViewResolver().setSuffix(".vm");
|
||||
}
|
||||
}
|
||||
|
||||
private static class FreeMarkerRegistration extends UrlBasedViewResolverRegistration {
|
||||
|
||||
public FreeMarkerRegistration() {
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.springframework.web.util.HtmlUtils;
|
||||
|
||||
/**
|
||||
* Simple adapter to expose the bind status of a field or object.
|
||||
* Set as a variable both by the JSP bind tag and Velocity/FreeMarker macros.
|
||||
* Set as a variable both by the JSP bind tag and FreeMarker macros.
|
||||
*
|
||||
* <p>Obviously, object status representations (i.e. errors at the object level
|
||||
* rather than the field level) do not have an expression and a value but only
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* 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.
|
||||
@@ -53,17 +53,18 @@ import org.springframework.web.util.UrlPathHelper;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
/**
|
||||
* Context holder for request-specific state, like current web application context, current locale, current theme,
|
||||
* and potential binding errors. Provides easy access to localized messages and Errors instances.
|
||||
* Context holder for request-specific state, like current web application context, current locale,
|
||||
* current theme, and potential binding errors. Provides easy access to localized messages and
|
||||
* Errors instances.
|
||||
*
|
||||
* <p>Suitable for exposition to views, and usage within JSP's "useBean" tag, JSP scriptlets, JSTL EL, Velocity
|
||||
* templates, etc. Necessary for views that do not have access to the servlet request, like Velocity templates.
|
||||
* <p>Suitable for exposition to views, and usage within JSP's "useBean" tag, JSP scriptlets, JSTL EL,
|
||||
* etc. Necessary for views that do not have access to the servlet request, like FreeMarker templates.
|
||||
*
|
||||
* <p>Can be instantiated manually, or automatically exposed to views as model attribute via AbstractView's
|
||||
* "requestContextAttribute" property.
|
||||
*
|
||||
* <p>Will also work outside of DispatcherServlet requests, accessing the root WebApplicationContext and using
|
||||
* an appropriate fallback for the locale (the HttpServletRequest's primary locale).
|
||||
* <p>Will also work outside of DispatcherServlet requests, accessing the root WebApplicationContext
|
||||
* and using an appropriate fallback for the locale (the HttpServletRequest's primary locale).
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Rossen Stoyanchev
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* 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.
|
||||
@@ -123,8 +123,8 @@ public abstract class AbstractCachingViewResolver extends WebApplicationObjectSu
|
||||
* Note that this flag only applies if the general {@link #setCache "cache"}
|
||||
* flag is kept at its default of "true" as well.
|
||||
* <p>Of specific interest is the ability for some AbstractUrlBasedView
|
||||
* implementations (FreeMarker, Velocity, Tiles) to check if an underlying
|
||||
* resource exists via {@link AbstractUrlBasedView#checkResource(Locale)}.
|
||||
* implementations (FreeMarker, Tiles) to check if an underlying resource
|
||||
* exists via {@link AbstractUrlBasedView#checkResource(Locale)}.
|
||||
* With this flag set to "false", an underlying resource that re-appears
|
||||
* is noticed and used. With the flag set to "true", one check is made only.
|
||||
*/
|
||||
@@ -185,7 +185,7 @@ public abstract class AbstractCachingViewResolver extends WebApplicationObjectSu
|
||||
/**
|
||||
* Provides functionality to clear the cache for a certain view.
|
||||
* <p>This can be handy in case developer are able to modify views
|
||||
* (e.g. Velocity templates) at runtime after which you'd need to
|
||||
* (e.g. FreeMarker templates) at runtime after which you'd need to
|
||||
* clear the cache for the specified view.
|
||||
* @param viewName the view name for which the cached view object
|
||||
* (if any) needs to be removed
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* 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.
|
||||
@@ -26,10 +26,9 @@ import javax.servlet.http.HttpSession;
|
||||
import org.springframework.web.servlet.support.RequestContext;
|
||||
|
||||
/**
|
||||
* Adapter base class for template-based view technologies such as
|
||||
* Velocity and FreeMarker, with the ability to use request and session
|
||||
* attributes in their model and the option to expose helper objects
|
||||
* for Spring's Velocity/FreeMarker macro library.
|
||||
* Adapter base class for template-based view technologies such as FreeMarker,
|
||||
* with the ability to use request and session attributes in their model and
|
||||
* the option to expose helper objects for Spring's FreeMarker macro library.
|
||||
*
|
||||
* <p>JSP/JSTL and other view technologies automatically have access to the
|
||||
* HttpServletRequest object and thereby the request/session attributes
|
||||
@@ -40,7 +39,6 @@ import org.springframework.web.servlet.support.RequestContext;
|
||||
* @author Darren Davison
|
||||
* @since 1.0.2
|
||||
* @see AbstractTemplateViewResolver
|
||||
* @see org.springframework.web.servlet.view.velocity.VelocityView
|
||||
* @see org.springframework.web.servlet.view.freemarker.FreeMarkerView
|
||||
*/
|
||||
public abstract class AbstractTemplateView extends AbstractUrlBasedView {
|
||||
@@ -102,9 +100,9 @@ public abstract class AbstractTemplateView extends AbstractUrlBasedView {
|
||||
/**
|
||||
* Set whether to expose a RequestContext for use by Spring's macro library,
|
||||
* under the name "springMacroRequestContext". Default is "true".
|
||||
* <p>Currently needed for Spring's Velocity and FreeMarker default macros.
|
||||
* Note that this is <i>not</i> required for templates that use HTML
|
||||
* forms <i>unless</i> you wish to take advantage of the Spring helper macros.
|
||||
* <p>Currently needed for Spring's FreeMarker default macros.
|
||||
* Note that this is <i>not</i> required for templates that use HTML forms
|
||||
* <i>unless</i> you wish to take advantage of the Spring helper macros.
|
||||
* @see #SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE
|
||||
*/
|
||||
public void setExposeSpringMacroHelpers(boolean exposeSpringMacroHelpers) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* 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.
|
||||
@@ -17,17 +17,14 @@
|
||||
package org.springframework.web.servlet.view;
|
||||
|
||||
/**
|
||||
* Abstract base class for template view resolvers,
|
||||
* in particular for Velocity and FreeMarker views.
|
||||
* Abstract base class for template view resolvers, in particular for FreeMarker views.
|
||||
*
|
||||
* <p>Provides a convenient way to specify {@link AbstractTemplateView}'s
|
||||
* exposure flags for request attributes, session attributes,
|
||||
* and Spring's macro helpers.
|
||||
* <p>Provides a convenient way to specify {@link AbstractTemplateView}'s exposure
|
||||
* flags for request attributes, session attributes, and Spring's macro helpers.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.1
|
||||
* @see AbstractTemplateView
|
||||
* @see org.springframework.web.servlet.view.velocity.VelocityViewResolver
|
||||
* @see org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver
|
||||
*/
|
||||
public class AbstractTemplateViewResolver extends UrlBasedViewResolver {
|
||||
|
||||
@@ -36,9 +36,8 @@ import org.springframework.web.servlet.View;
|
||||
* (i.e. the symbolic name is the unique part of the resource's filename),
|
||||
* without the need for a dedicated mapping to be defined for each view.
|
||||
*
|
||||
* <p>Supports {@link AbstractUrlBasedView} subclasses like {@link InternalResourceView},
|
||||
* {@link org.springframework.web.servlet.view.velocity.VelocityView} and
|
||||
* {@link org.springframework.web.servlet.view.freemarker.FreeMarkerView}.
|
||||
* <p>Supports {@link AbstractUrlBasedView} subclasses like {@link InternalResourceView}
|
||||
* and {@link org.springframework.web.servlet.view.freemarker.FreeMarkerView}.
|
||||
* The view class for all views generated by this resolver can be specified
|
||||
* via the "viewClass" property.
|
||||
*
|
||||
@@ -79,7 +78,6 @@ import org.springframework.web.servlet.View;
|
||||
* @see #REDIRECT_URL_PREFIX
|
||||
* @see AbstractUrlBasedView
|
||||
* @see InternalResourceView
|
||||
* @see org.springframework.web.servlet.view.velocity.VelocityView
|
||||
* @see org.springframework.web.servlet.view.freemarker.FreeMarkerView
|
||||
*/
|
||||
public class UrlBasedViewResolver extends AbstractCachingViewResolver implements Ordered {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* including abstract base classes for custom implementations.
|
||||
*
|
||||
* <p>Application developers don't usually need to implement views,
|
||||
* as the framework provides standard views for JSPs, Velocity,
|
||||
* as the framework provides standard views for JSPs, FreeMarker,
|
||||
* XSLT, etc. However, the ability to implement custom views easily
|
||||
* by subclassing the AbstractView class in this package can be
|
||||
* very helpful if an application has unusual view requirements.
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.velocity;
|
||||
|
||||
import org.apache.velocity.app.VelocityEngine;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by objects that configure and manage a
|
||||
* VelocityEngine for automatic lookup in a web environment. Detected
|
||||
* and used by VelocityView.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @see VelocityConfigurer
|
||||
* @see VelocityView
|
||||
* @deprecated as of Spring 4.3, in favor of FreeMarker
|
||||
*/
|
||||
@Deprecated
|
||||
public interface VelocityConfig {
|
||||
|
||||
/**
|
||||
* Return the VelocityEngine for the current web application context.
|
||||
* May be unique to one servlet, or shared in the root context.
|
||||
* @return the VelocityEngine
|
||||
*/
|
||||
VelocityEngine getVelocityEngine();
|
||||
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.velocity;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.apache.velocity.app.VelocityEngine;
|
||||
import org.apache.velocity.exception.VelocityException;
|
||||
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.web.context.ServletContextAware;
|
||||
|
||||
/**
|
||||
* JavaBean to configure Velocity for web usage, via the "configLocation"
|
||||
* and/or "velocityProperties" and/or "resourceLoaderPath" bean properties.
|
||||
* The simplest way to use this class is to specify just a "resourceLoaderPath";
|
||||
* you do not need any further configuration then.
|
||||
*
|
||||
* <pre class="code">
|
||||
* <bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
|
||||
* <property name="resourceLoaderPath"><value>/WEB-INF/velocity/</value></property>
|
||||
* </bean></pre>
|
||||
*
|
||||
* This bean must be included in the application context of any application
|
||||
* using Spring's {@link VelocityView} for web MVC. It exists purely to configure
|
||||
* Velocity; it is not meant to be referenced by application components (just
|
||||
* internally by VelocityView). This class implements {@link VelocityConfig}
|
||||
* in order to be found by VelocityView without depending on the bean name of
|
||||
* this configurer. Each DispatcherServlet may define its own VelocityConfigurer
|
||||
* if desired, potentially with different template loader paths.
|
||||
*
|
||||
* <p>Note that you can also refer to a pre-configured VelocityEngine
|
||||
* instance via the "velocityEngine" property, e.g. set up by
|
||||
* {@link org.springframework.ui.velocity.VelocityEngineFactoryBean},
|
||||
* This allows to share a VelocityEngine for web and email usage, for example.
|
||||
*
|
||||
* <p>This configurer registers the "spring.vm" Velocimacro library for web views
|
||||
* (contained in this package and thus in {@code spring.jar}), which makes
|
||||
* all of Spring's default Velocity macros available to the views.
|
||||
* This allows for using the Spring-provided macros such as follows:
|
||||
*
|
||||
* <pre class="code">
|
||||
* #springBind("person.age")
|
||||
* age is ${status.value}</pre>
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Darren Davison
|
||||
* @see #setConfigLocation
|
||||
* @see #setVelocityProperties
|
||||
* @see #setResourceLoaderPath
|
||||
* @see #setVelocityEngine
|
||||
* @see VelocityView
|
||||
* @deprecated as of Spring 4.3, in favor of FreeMarker
|
||||
*/
|
||||
@Deprecated
|
||||
public class VelocityConfigurer extends org.springframework.ui.velocity.VelocityEngineFactory
|
||||
implements VelocityConfig, InitializingBean, ResourceLoaderAware, ServletContextAware {
|
||||
|
||||
/** the name of the resource loader for Spring's bind macros */
|
||||
private static final String SPRING_MACRO_RESOURCE_LOADER_NAME = "springMacro";
|
||||
|
||||
/** the key for the class of Spring's bind macro resource loader */
|
||||
private static final String SPRING_MACRO_RESOURCE_LOADER_CLASS = "springMacro.resource.loader.class";
|
||||
|
||||
/** the name of Spring's default bind macro library */
|
||||
private static final String SPRING_MACRO_LIBRARY = "org/springframework/web/servlet/view/velocity/spring.vm";
|
||||
|
||||
|
||||
private VelocityEngine velocityEngine;
|
||||
|
||||
private ServletContext servletContext;
|
||||
|
||||
|
||||
/**
|
||||
* Set a pre-configured VelocityEngine to use for the Velocity web
|
||||
* configuration: e.g. a shared one for web and email usage, set up via
|
||||
* {@link org.springframework.ui.velocity.VelocityEngineFactoryBean}.
|
||||
* <p>Note that the Spring macros will <i>not</i> be enabled automatically in
|
||||
* case of an external VelocityEngine passed in here. Make sure to include
|
||||
* {@code spring.vm} in your template loader path in such a scenario
|
||||
* (if there is an actual need to use those macros).
|
||||
* <p>If this is not set, VelocityEngineFactory's properties
|
||||
* (inherited by this class) have to be specified.
|
||||
*/
|
||||
public void setVelocityEngine(VelocityEngine velocityEngine) {
|
||||
this.velocityEngine = velocityEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setServletContext(ServletContext servletContext) {
|
||||
this.servletContext = servletContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize VelocityEngineFactory's VelocityEngine
|
||||
* if not overridden by a pre-configured VelocityEngine.
|
||||
* @see #createVelocityEngine
|
||||
* @see #setVelocityEngine
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws IOException, VelocityException {
|
||||
if (this.velocityEngine == null) {
|
||||
this.velocityEngine = createVelocityEngine();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a ClasspathResourceLoader in addition to any default or user-defined
|
||||
* loader in order to load the spring Velocity macros from the class path.
|
||||
* @see org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
|
||||
*/
|
||||
@Override
|
||||
protected void postProcessVelocityEngine(VelocityEngine velocityEngine) {
|
||||
velocityEngine.setApplicationAttribute(ServletContext.class.getName(), this.servletContext);
|
||||
velocityEngine.setProperty(
|
||||
SPRING_MACRO_RESOURCE_LOADER_CLASS, ClasspathResourceLoader.class.getName());
|
||||
velocityEngine.addProperty(
|
||||
VelocityEngine.RESOURCE_LOADER, SPRING_MACRO_RESOURCE_LOADER_NAME);
|
||||
velocityEngine.addProperty(
|
||||
VelocityEngine.VM_LIBRARY, SPRING_MACRO_LIBRARY);
|
||||
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("ClasspathResourceLoader with name '" + SPRING_MACRO_RESOURCE_LOADER_NAME +
|
||||
"' added to configured VelocityEngine");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public VelocityEngine getVelocityEngine() {
|
||||
return this.velocityEngine;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,188 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.velocity;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import java.util.Locale;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.velocity.Template;
|
||||
import org.apache.velocity.context.Context;
|
||||
import org.apache.velocity.exception.ResourceNotFoundException;
|
||||
|
||||
import org.springframework.core.NestedIOException;
|
||||
|
||||
/**
|
||||
* VelocityLayoutView emulates the functionality offered by Velocity's
|
||||
* VelocityLayoutServlet to ease page composition from different templates.
|
||||
*
|
||||
* <p>The {@code url} property should be set to the content template
|
||||
* for the view, and the layout template location should be specified as
|
||||
* {@code layoutUrl} property. A view can override the configured
|
||||
* layout template location by setting the appropriate key (the default
|
||||
* is "layout") in the content template.
|
||||
*
|
||||
* <p>When the view is rendered, the VelocityContext is first merged with
|
||||
* the content template (specified by the {@code url} property) and
|
||||
* then merged with the layout template to produce the final output.
|
||||
*
|
||||
* <p>The layout template can include the screen content through a
|
||||
* VelocityContext variable (the default is "screen_content").
|
||||
* At runtime, this variable will contain the rendered content template.
|
||||
*
|
||||
* @author Darren Davison
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see #setLayoutUrl
|
||||
* @see #setLayoutKey
|
||||
* @see #setScreenContentKey
|
||||
* @deprecated as of Spring 4.3, in favor of FreeMarker
|
||||
*/
|
||||
@Deprecated
|
||||
public class VelocityLayoutView extends VelocityToolboxView {
|
||||
|
||||
/**
|
||||
* The default {@link #setLayoutUrl(String) layout url}.
|
||||
*/
|
||||
public static final String DEFAULT_LAYOUT_URL = "layout.vm";
|
||||
|
||||
/**
|
||||
* The default {@link #setLayoutKey(String) layout key}.
|
||||
*/
|
||||
public static final String DEFAULT_LAYOUT_KEY = "layout";
|
||||
|
||||
/**
|
||||
* The default {@link #setScreenContentKey(String) screen content key}.
|
||||
*/
|
||||
public static final String DEFAULT_SCREEN_CONTENT_KEY = "screen_content";
|
||||
|
||||
|
||||
private String layoutUrl = DEFAULT_LAYOUT_URL;
|
||||
|
||||
private String layoutKey = DEFAULT_LAYOUT_KEY;
|
||||
|
||||
private String screenContentKey = DEFAULT_SCREEN_CONTENT_KEY;
|
||||
|
||||
|
||||
/**
|
||||
* Set the layout template to use. Default is {@link #DEFAULT_LAYOUT_URL "layout.vm"}.
|
||||
* @param layoutUrl the template location (relative to the template
|
||||
* root directory)
|
||||
*/
|
||||
public void setLayoutUrl(String layoutUrl) {
|
||||
this.layoutUrl = layoutUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the context key used to specify an alternate layout to be used instead
|
||||
* of the default layout. Screen content templates can override the layout
|
||||
* template that they wish to be wrapped with by setting this value in the
|
||||
* template, for example:<br>
|
||||
* {@code #set($layout = "MyLayout.vm" )}
|
||||
* <p>Default key is {@link #DEFAULT_LAYOUT_KEY "layout"}, as illustrated above.
|
||||
* @param layoutKey the name of the key you wish to use in your
|
||||
* screen content templates to override the layout template
|
||||
*/
|
||||
public void setLayoutKey(String layoutKey) {
|
||||
this.layoutKey = layoutKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the context key that will hold the content of
|
||||
* the screen within the layout template. This key must be present
|
||||
* in the layout template for the current screen to be rendered.
|
||||
* <p>Default is {@link #DEFAULT_SCREEN_CONTENT_KEY "screen_content"}:
|
||||
* accessed in VTL as {@code $screen_content}.
|
||||
* @param screenContentKey the name of the screen content key to use
|
||||
*/
|
||||
public void setScreenContentKey(String screenContentKey) {
|
||||
this.screenContentKey = screenContentKey;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overrides {@code VelocityView.checkTemplate()} to additionally check
|
||||
* that both the layout template and the screen content template can be loaded.
|
||||
* Note that during rendering of the screen content, the layout template
|
||||
* can be changed which may invalidate any early checking done here.
|
||||
*/
|
||||
@Override
|
||||
public boolean checkResource(Locale locale) throws Exception {
|
||||
if (!super.checkResource(locale)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// Check that we can get the template, even if we might subsequently get it again.
|
||||
getTemplate(this.layoutUrl);
|
||||
return true;
|
||||
}
|
||||
catch (ResourceNotFoundException ex) {
|
||||
throw new NestedIOException("Cannot find Velocity template for URL [" + this.layoutUrl +
|
||||
"]: Did you specify the correct resource loader path?", ex);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new NestedIOException(
|
||||
"Could not load Velocity template for URL [" + this.layoutUrl + "]", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the normal rendering process in order to pre-process the Context,
|
||||
* merging it with the screen template into a single value (identified by the
|
||||
* value of screenContentKey). The layout template is then merged with the
|
||||
* modified Context in the super class.
|
||||
*/
|
||||
@Override
|
||||
protected void doRender(Context context, HttpServletResponse response) throws Exception {
|
||||
renderScreenContent(context);
|
||||
|
||||
// Velocity context now includes any mappings that were defined
|
||||
// (via #set) in screen content template.
|
||||
// The screen template can overrule the layout by doing
|
||||
// #set( $layout = "MyLayout.vm" )
|
||||
String layoutUrlToUse = (String) context.get(this.layoutKey);
|
||||
if (layoutUrlToUse != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Screen content template has requested layout [" + layoutUrlToUse + "]");
|
||||
}
|
||||
}
|
||||
else {
|
||||
// No explicit layout URL given -> use default layout of this view.
|
||||
layoutUrlToUse = this.layoutUrl;
|
||||
}
|
||||
|
||||
mergeTemplate(getTemplate(layoutUrlToUse), context, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* The resulting context contains any mappings from render, plus screen content.
|
||||
*/
|
||||
private void renderScreenContent(Context velocityContext) throws Exception {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Rendering screen content template [" + getUrl() + "]");
|
||||
}
|
||||
|
||||
StringWriter sw = new StringWriter();
|
||||
Template screenContentTemplate = getTemplate(getUrl());
|
||||
screenContentTemplate.merge(velocityContext, sw);
|
||||
|
||||
// Put rendered content into Velocity context.
|
||||
velocityContext.put(this.screenContentKey, sw.toString());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.velocity;
|
||||
|
||||
import org.springframework.web.servlet.view.AbstractUrlBasedView;
|
||||
|
||||
/**
|
||||
* Convenience subclass of VelocityViewResolver, adding support
|
||||
* for VelocityLayoutView and its properties.
|
||||
*
|
||||
* <p>See VelocityViewResolver's javadoc for general usage info.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2.7
|
||||
* @see VelocityViewResolver
|
||||
* @see VelocityLayoutView
|
||||
* @see #setLayoutUrl
|
||||
* @see #setLayoutKey
|
||||
* @see #setScreenContentKey
|
||||
* @deprecated as of Spring 4.3, in favor of FreeMarker
|
||||
*/
|
||||
@Deprecated
|
||||
public class VelocityLayoutViewResolver extends VelocityViewResolver {
|
||||
|
||||
private String layoutUrl;
|
||||
|
||||
private String layoutKey;
|
||||
|
||||
private String screenContentKey;
|
||||
|
||||
|
||||
/**
|
||||
* Requires VelocityLayoutView.
|
||||
* @see VelocityLayoutView
|
||||
*/
|
||||
@Override
|
||||
protected Class<?> requiredViewClass() {
|
||||
return VelocityLayoutView.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the layout template to use. Default is "layout.vm".
|
||||
* @param layoutUrl the template location (relative to the template
|
||||
* root directory)
|
||||
* @see VelocityLayoutView#setLayoutUrl
|
||||
*/
|
||||
public void setLayoutUrl(String layoutUrl) {
|
||||
this.layoutUrl = layoutUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the context key used to specify an alternate layout to be used instead
|
||||
* of the default layout. Screen content templates can override the layout
|
||||
* template that they wish to be wrapped with by setting this value in the
|
||||
* template, for example:<br>
|
||||
* {@code #set($layout = "MyLayout.vm" )}
|
||||
* <p>The default key is "layout", as illustrated above.
|
||||
* @param layoutKey the name of the key you wish to use in your
|
||||
* screen content templates to override the layout template
|
||||
* @see VelocityLayoutView#setLayoutKey
|
||||
*/
|
||||
public void setLayoutKey(String layoutKey) {
|
||||
this.layoutKey = layoutKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the context key that will hold the content of
|
||||
* the screen within the layout template. This key must be present
|
||||
* in the layout template for the current screen to be rendered.
|
||||
* <p>Default is "screen_content": accessed in VTL as
|
||||
* {@code $screen_content}.
|
||||
* @param screenContentKey the name of the screen content key to use
|
||||
* @see VelocityLayoutView#setScreenContentKey
|
||||
*/
|
||||
public void setScreenContentKey(String screenContentKey) {
|
||||
this.screenContentKey = screenContentKey;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected AbstractUrlBasedView buildView(String viewName) throws Exception {
|
||||
VelocityLayoutView view = (VelocityLayoutView) super.buildView(viewName);
|
||||
// Use not-null checks to preserve VelocityLayoutView's defaults.
|
||||
if (this.layoutUrl != null) {
|
||||
view.setLayoutUrl(this.layoutUrl);
|
||||
}
|
||||
if (this.layoutKey != null) {
|
||||
view.setLayoutKey(this.layoutKey);
|
||||
}
|
||||
if (this.screenContentKey != null) {
|
||||
view.setScreenContentKey(this.screenContentKey);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.velocity;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.velocity.VelocityContext;
|
||||
import org.apache.velocity.context.Context;
|
||||
import org.apache.velocity.tools.view.ToolboxManager;
|
||||
import org.apache.velocity.tools.view.context.ChainedContext;
|
||||
import org.apache.velocity.tools.view.servlet.ServletToolboxManager;
|
||||
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* {@link VelocityView} subclass which adds support for Velocity Tools toolboxes
|
||||
* and Velocity Tools ViewTool callbacks / Velocity Tools 1.3 init methods.
|
||||
*
|
||||
* <p>Specify a "toolboxConfigLocation", for example "/WEB-INF/toolbox.xml",
|
||||
* to automatically load a Velocity Tools toolbox definition file and expose
|
||||
* all defined tools in the specified scopes. If no config location is
|
||||
* specified, no toolbox will be loaded and exposed.
|
||||
*
|
||||
* <p>This view will always create a special Velocity context, namely an
|
||||
* instance of the ChainedContext class which is part of the view package
|
||||
* of Velocity tools. This allows to use tools from the view package of
|
||||
* Velocity Tools, like LinkTool, which need to be initialized with a special
|
||||
* context that implements the ViewContext interface (i.e. a ChainedContext).
|
||||
*
|
||||
* <p>This view also checks tools that are specified as "toolAttributes":
|
||||
* If they implement the ViewTool interface, they will get initialized with
|
||||
* the Velocity context. This allows tools from the view package of Velocity
|
||||
* Tools, such as LinkTool, to be defined as
|
||||
* {@link #setToolAttributes "toolAttributes"} on a VelocityToolboxView,
|
||||
* instead of in a separate toolbox XML file.
|
||||
*
|
||||
* <p>This is a separate class mainly to avoid a required dependency on
|
||||
* the view package of Velocity Tools in {@link VelocityView} itself.
|
||||
* As of Spring 3.0, this class requires Velocity Tools 1.3 or higher.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.1.3
|
||||
* @see #setToolboxConfigLocation
|
||||
* @see #initTool
|
||||
* @see org.apache.velocity.tools.view.context.ViewContext
|
||||
* @see org.apache.velocity.tools.view.context.ChainedContext
|
||||
* @deprecated as of Spring 4.3, in favor of FreeMarker
|
||||
*/
|
||||
@Deprecated
|
||||
public class VelocityToolboxView extends VelocityView {
|
||||
|
||||
private String toolboxConfigLocation;
|
||||
|
||||
|
||||
/**
|
||||
* Set a Velocity Toolbox config location, for example "/WEB-INF/toolbox.xml",
|
||||
* to automatically load a Velocity Tools toolbox definition file and expose
|
||||
* all defined tools in the specified scopes. If no config location is
|
||||
* specified, no toolbox will be loaded and exposed.
|
||||
* <p>The specified location string needs to refer to a ServletContext
|
||||
* resource, as expected by ServletToolboxManager which is part of
|
||||
* the view package of Velocity Tools.
|
||||
* @see org.apache.velocity.tools.view.servlet.ServletToolboxManager#getInstance
|
||||
*/
|
||||
public void setToolboxConfigLocation(String toolboxConfigLocation) {
|
||||
this.toolboxConfigLocation = toolboxConfigLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Velocity Toolbox config location, if any.
|
||||
*/
|
||||
protected String getToolboxConfigLocation() {
|
||||
return this.toolboxConfigLocation;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overridden to create a ChainedContext, which is part of the view package
|
||||
* of Velocity Tools, as special context. ChainedContext is needed for
|
||||
* initialization of ViewTool instances.
|
||||
* @see #initTool
|
||||
*/
|
||||
@Override
|
||||
protected Context createVelocityContext(
|
||||
Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||
|
||||
// Create a ChainedContext instance.
|
||||
ChainedContext velocityContext = new ChainedContext(
|
||||
new VelocityContext(model), getVelocityEngine(), request, response, getServletContext());
|
||||
|
||||
// Load a Velocity Tools toolbox, if necessary.
|
||||
if (getToolboxConfigLocation() != null) {
|
||||
ToolboxManager toolboxManager = ServletToolboxManager.getInstance(
|
||||
getServletContext(), getToolboxConfigLocation());
|
||||
Map<?, ?> toolboxContext = toolboxManager.getToolbox(velocityContext);
|
||||
velocityContext.setToolbox(toolboxContext);
|
||||
}
|
||||
|
||||
return velocityContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overridden to check for the ViewContext interface which is part of the
|
||||
* view package of Velocity Tools. This requires a special Velocity context,
|
||||
* like ChainedContext as set up by {@link #createVelocityContext} in this class.
|
||||
*/
|
||||
@Override
|
||||
protected void initTool(Object tool, Context velocityContext) throws Exception {
|
||||
// Velocity Tools 1.3: a class-level "init(Object)" method.
|
||||
Method initMethod = ClassUtils.getMethodIfAvailable(tool.getClass(), "init", Object.class);
|
||||
if (initMethod != null) {
|
||||
ReflectionUtils.invokeMethod(initMethod, tool, velocityContext);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,578 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.velocity;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.velocity.Template;
|
||||
import org.apache.velocity.VelocityContext;
|
||||
import org.apache.velocity.app.VelocityEngine;
|
||||
import org.apache.velocity.context.Context;
|
||||
import org.apache.velocity.exception.MethodInvocationException;
|
||||
import org.apache.velocity.exception.ResourceNotFoundException;
|
||||
import org.apache.velocity.tools.generic.DateTool;
|
||||
import org.apache.velocity.tools.generic.NumberTool;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.context.ApplicationContextException;
|
||||
import org.springframework.core.NestedIOException;
|
||||
import org.springframework.web.servlet.support.RequestContextUtils;
|
||||
import org.springframework.web.servlet.view.AbstractTemplateView;
|
||||
import org.springframework.web.util.NestedServletException;
|
||||
|
||||
/**
|
||||
* View using the Velocity template engine.
|
||||
*
|
||||
* <p>Exposes the following JavaBean properties:
|
||||
* <ul>
|
||||
* <li><b>url</b>: the location of the Velocity template to be wrapped,
|
||||
* relative to the Velocity resource loader path (see VelocityConfigurer).
|
||||
* <li><b>encoding</b> (optional, default is determined by Velocity configuration):
|
||||
* the encoding of the Velocity template file
|
||||
* <li><b>velocityFormatterAttribute</b> (optional, default=null): the name of
|
||||
* the VelocityFormatter helper object to expose in the Velocity context of this
|
||||
* view, or {@code null} if not needed. VelocityFormatter is part of standard Velocity.
|
||||
* <li><b>dateToolAttribute</b> (optional, default=null): the name of the
|
||||
* DateTool helper object to expose in the Velocity context of this view,
|
||||
* or {@code null} if not needed. DateTool is part of Velocity Tools.
|
||||
* <li><b>numberToolAttribute</b> (optional, default=null): the name of the
|
||||
* NumberTool helper object to expose in the Velocity context of this view,
|
||||
* or {@code null} if not needed. NumberTool is part of Velocity Tools.
|
||||
* <li><b>cacheTemplate</b> (optional, default=false): whether or not the Velocity
|
||||
* template should be cached. It should normally be true in production, but setting
|
||||
* this to false enables us to modify Velocity templates without restarting the
|
||||
* application (similar to JSPs). Note that this is a minor optimization only,
|
||||
* as Velocity itself caches templates in a modification-aware fashion.
|
||||
* </ul>
|
||||
*
|
||||
* <p>Depends on a VelocityConfig object such as VelocityConfigurer being
|
||||
* accessible in the current web application context, with any bean name.
|
||||
* Alternatively, you can set the VelocityEngine object as bean property.
|
||||
*
|
||||
* <p>Note: Spring 3.0's VelocityView requires Velocity 1.4 or higher, and optionally
|
||||
* Velocity Tools 1.1 or higher (depending on the use of DateTool and/or NumberTool).
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Dave Syer
|
||||
* @see VelocityConfig
|
||||
* @see VelocityConfigurer
|
||||
* @see #setUrl
|
||||
* @see #setExposeSpringMacroHelpers
|
||||
* @see #setEncoding
|
||||
* @see #setVelocityEngine
|
||||
* @see VelocityConfig
|
||||
* @see VelocityConfigurer
|
||||
* @deprecated as of Spring 4.3, in favor of FreeMarker
|
||||
*/
|
||||
@Deprecated
|
||||
public class VelocityView extends AbstractTemplateView {
|
||||
|
||||
private Map<String, Class<?>> toolAttributes;
|
||||
|
||||
private String dateToolAttribute;
|
||||
|
||||
private String numberToolAttribute;
|
||||
|
||||
private String encoding;
|
||||
|
||||
private boolean cacheTemplate = false;
|
||||
|
||||
private VelocityEngine velocityEngine;
|
||||
|
||||
private Template template;
|
||||
|
||||
|
||||
/**
|
||||
* Set tool attributes to expose to the view, as attribute name / class name pairs.
|
||||
* An instance of the given class will be added to the Velocity context for each
|
||||
* rendering operation, under the given attribute name.
|
||||
* <p>For example, an instance of MathTool, which is part of the generic package
|
||||
* of Velocity Tools, can be bound under the attribute name "math", specifying the
|
||||
* fully qualified class name "org.apache.velocity.tools.generic.MathTool" as value.
|
||||
* <p>Note that VelocityView can only create simple generic tools or values, that is,
|
||||
* classes with a public default constructor and no further initialization needs.
|
||||
* This class does not do any further checks, to not introduce a required dependency
|
||||
* on a specific tools package.
|
||||
* <p>For tools that are part of the view package of Velocity Tools, a special
|
||||
* Velocity context and a special init callback are needed. Use VelocityToolboxView
|
||||
* in such a case, or override {@code createVelocityContext} and
|
||||
* {@code initTool} accordingly.
|
||||
* <p>For a simple VelocityFormatter instance or special locale-aware instances
|
||||
* of DateTool/NumberTool, which are part of the generic package of Velocity Tools,
|
||||
* specify the "velocityFormatterAttribute", "dateToolAttribute" or
|
||||
* "numberToolAttribute" properties, respectively.
|
||||
* @param toolAttributes attribute names as keys, and tool class names as values
|
||||
* @see org.apache.velocity.tools.generic.MathTool
|
||||
* @see VelocityToolboxView
|
||||
* @see #createVelocityContext
|
||||
* @see #initTool
|
||||
* @see #setDateToolAttribute
|
||||
* @see #setNumberToolAttribute
|
||||
*/
|
||||
public void setToolAttributes(Map<String, Class<?>> toolAttributes) {
|
||||
this.toolAttributes = toolAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the DateTool helper object to expose in the Velocity context
|
||||
* of this view, or {@code null} if not needed. The exposed DateTool will be aware of
|
||||
* the current locale, as determined by Spring's LocaleResolver.
|
||||
* <p>DateTool is part of the generic package of Velocity Tools 1.0.
|
||||
* Spring uses a special locale-aware subclass of DateTool.
|
||||
* @see org.apache.velocity.tools.generic.DateTool
|
||||
* @see org.springframework.web.servlet.support.RequestContextUtils#getLocale
|
||||
* @see org.springframework.web.servlet.LocaleResolver
|
||||
*/
|
||||
public void setDateToolAttribute(String dateToolAttribute) {
|
||||
this.dateToolAttribute = dateToolAttribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the NumberTool helper object to expose in the Velocity context
|
||||
* of this view, or {@code null} if not needed. The exposed NumberTool will be aware of
|
||||
* the current locale, as determined by Spring's LocaleResolver.
|
||||
* <p>NumberTool is part of the generic package of Velocity Tools 1.1.
|
||||
* Spring uses a special locale-aware subclass of NumberTool.
|
||||
* @see org.apache.velocity.tools.generic.NumberTool
|
||||
* @see org.springframework.web.servlet.support.RequestContextUtils#getLocale
|
||||
* @see org.springframework.web.servlet.LocaleResolver
|
||||
*/
|
||||
public void setNumberToolAttribute(String numberToolAttribute) {
|
||||
this.numberToolAttribute = numberToolAttribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the encoding of the Velocity template file. Default is determined
|
||||
* by the VelocityEngine: "ISO-8859-1" if not specified otherwise.
|
||||
* <p>Specify the encoding in the VelocityEngine rather than per template
|
||||
* if all your templates share a common encoding.
|
||||
*/
|
||||
public void setEncoding(String encoding) {
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the encoding for the Velocity template.
|
||||
*/
|
||||
protected String getEncoding() {
|
||||
return this.encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the Velocity template should be cached. Default is "false".
|
||||
* It should normally be true in production, but setting this to false enables us to
|
||||
* modify Velocity templates without restarting the application (similar to JSPs).
|
||||
* <p>Note that this is a minor optimization only, as Velocity itself caches
|
||||
* templates in a modification-aware fashion.
|
||||
*/
|
||||
public void setCacheTemplate(boolean cacheTemplate) {
|
||||
this.cacheTemplate = cacheTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the Velocity template should be cached.
|
||||
*/
|
||||
protected boolean isCacheTemplate() {
|
||||
return this.cacheTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the VelocityEngine to be used by this view.
|
||||
* <p>If this is not set, the default lookup will occur: A single VelocityConfig
|
||||
* is expected in the current web application context, with any bean name.
|
||||
* @see VelocityConfig
|
||||
*/
|
||||
public void setVelocityEngine(VelocityEngine velocityEngine) {
|
||||
this.velocityEngine = velocityEngine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the VelocityEngine used by this view.
|
||||
*/
|
||||
protected VelocityEngine getVelocityEngine() {
|
||||
return this.velocityEngine;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Invoked on startup. Looks for a single VelocityConfig bean to
|
||||
* find the relevant VelocityEngine for this factory.
|
||||
*/
|
||||
@Override
|
||||
protected void initApplicationContext() throws BeansException {
|
||||
super.initApplicationContext();
|
||||
|
||||
if (getVelocityEngine() == null) {
|
||||
// No explicit VelocityEngine: try to autodetect one.
|
||||
setVelocityEngine(autodetectVelocityEngine());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Autodetect a VelocityEngine via the ApplicationContext.
|
||||
* Called if no explicit VelocityEngine has been specified.
|
||||
* @return the VelocityEngine to use for VelocityViews
|
||||
* @throws BeansException if no VelocityEngine could be found
|
||||
* @see #getApplicationContext
|
||||
* @see #setVelocityEngine
|
||||
*/
|
||||
protected VelocityEngine autodetectVelocityEngine() throws BeansException {
|
||||
try {
|
||||
VelocityConfig velocityConfig = BeanFactoryUtils.beanOfTypeIncludingAncestors(
|
||||
getApplicationContext(), VelocityConfig.class, true, false);
|
||||
return velocityConfig.getVelocityEngine();
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
throw new ApplicationContextException(
|
||||
"Must define a single VelocityConfig bean in this web application context " +
|
||||
"(may be inherited): VelocityConfigurer is the usual implementation. " +
|
||||
"This bean may be given any name.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the Velocity template used for this view exists and is valid.
|
||||
* <p>Can be overridden to customize the behavior, for example in case of
|
||||
* multiple templates to be rendered into a single view.
|
||||
*/
|
||||
@Override
|
||||
public boolean checkResource(Locale locale) throws Exception {
|
||||
try {
|
||||
// Check that we can get the template, even if we might subsequently get it again.
|
||||
this.template = getTemplate(getUrl());
|
||||
return true;
|
||||
}
|
||||
catch (ResourceNotFoundException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("No Velocity view found for URL: " + getUrl());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new NestedIOException(
|
||||
"Could not load Velocity template for URL [" + getUrl() + "]", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process the model map by merging it with the Velocity template.
|
||||
* Output is directed to the servlet response.
|
||||
* <p>This method can be overridden if custom behavior is needed.
|
||||
*/
|
||||
@Override
|
||||
protected void renderMergedTemplateModel(
|
||||
Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||
|
||||
exposeHelpers(model, request);
|
||||
|
||||
Context velocityContext = createVelocityContext(model, request, response);
|
||||
exposeHelpers(velocityContext, request, response);
|
||||
exposeToolAttributes(velocityContext, request);
|
||||
|
||||
doRender(velocityContext, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose helpers unique to each rendering operation. This is necessary so that
|
||||
* different rendering operations can't overwrite each other's formats etc.
|
||||
* <p>Called by {@code renderMergedTemplateModel}. The default implementation
|
||||
* is empty. This method can be overridden to add custom helpers to the model.
|
||||
* @param model the model that will be passed to the template for merging
|
||||
* @param request current HTTP request
|
||||
* @throws Exception if there's a fatal error while we're adding model attributes
|
||||
* @see #renderMergedTemplateModel
|
||||
*/
|
||||
protected void exposeHelpers(Map<String, Object> model, HttpServletRequest request) throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Velocity Context instance for the given model,
|
||||
* to be passed to the template for merging.
|
||||
* <p>The default implementation delegates to {@link #createVelocityContext(Map)}.
|
||||
* Can be overridden for a special context class, for example ChainedContext which
|
||||
* is part of the view package of Velocity Tools. ChainedContext is needed for
|
||||
* initialization of ViewTool instances.
|
||||
* <p>Have a look at {@link VelocityToolboxView}, which pre-implements
|
||||
* ChainedContext support. This is not part of the standard VelocityView class
|
||||
* in order to avoid a required dependency on the view package of Velocity Tools.
|
||||
* @param model the model Map, containing the model attributes to be exposed to the view
|
||||
* @param request current HTTP request
|
||||
* @param response current HTTP response
|
||||
* @return the Velocity Context
|
||||
* @throws Exception if there's a fatal error while creating the context
|
||||
* @see #createVelocityContext(Map)
|
||||
* @see #initTool
|
||||
* @see org.apache.velocity.tools.view.context.ChainedContext
|
||||
* @see VelocityToolboxView
|
||||
*/
|
||||
protected Context createVelocityContext(
|
||||
Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||
|
||||
return createVelocityContext(model);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Velocity Context instance for the given model,
|
||||
* to be passed to the template for merging.
|
||||
* <p>Default implementation creates an instance of Velocity's
|
||||
* VelocityContext implementation class.
|
||||
* @param model the model Map, containing the model attributes
|
||||
* to be exposed to the view
|
||||
* @return the Velocity Context
|
||||
* @throws Exception if there's a fatal error while creating the context
|
||||
* @see org.apache.velocity.VelocityContext
|
||||
*/
|
||||
protected Context createVelocityContext(Map<String, Object> model) throws Exception {
|
||||
return new VelocityContext(model);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose helpers unique to each rendering operation. This is necessary so that
|
||||
* different rendering operations can't overwrite each other's formats etc.
|
||||
* <p>Called by {@code renderMergedTemplateModel}. Default implementation
|
||||
* delegates to {@code exposeHelpers(velocityContext, request)}. This method
|
||||
* can be overridden to add special tools to the context, needing the servlet response
|
||||
* to initialize (see Velocity Tools, for example LinkTool and ViewTool/ChainedContext).
|
||||
* @param velocityContext Velocity context that will be passed to the template
|
||||
* @param request current HTTP request
|
||||
* @param response current HTTP response
|
||||
* @throws Exception if there's a fatal error while we're adding model attributes
|
||||
* @see #exposeHelpers(org.apache.velocity.context.Context, HttpServletRequest)
|
||||
*/
|
||||
protected void exposeHelpers(
|
||||
Context velocityContext, HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||
|
||||
exposeHelpers(velocityContext, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose helpers unique to each rendering operation. This is necessary so that
|
||||
* different rendering operations can't overwrite each other's formats etc.
|
||||
* <p>Default implementation is empty. This method can be overridden to add
|
||||
* custom helpers to the Velocity context.
|
||||
* @param velocityContext Velocity context that will be passed to the template
|
||||
* @param request current HTTP request
|
||||
* @throws Exception if there's a fatal error while we're adding model attributes
|
||||
* @see #exposeHelpers(Map, HttpServletRequest)
|
||||
*/
|
||||
protected void exposeHelpers(Context velocityContext, HttpServletRequest request) throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose the tool attributes, according to corresponding bean property settings.
|
||||
* <p>Do not override this method unless for further tools driven by bean properties.
|
||||
* Override one of the {@code exposeHelpers} methods to add custom helpers.
|
||||
* @param velocityContext Velocity context that will be passed to the template
|
||||
* @param request current HTTP request
|
||||
* @throws Exception if there's a fatal error while we're adding model attributes
|
||||
* @see #setDateToolAttribute
|
||||
* @see #setNumberToolAttribute
|
||||
* @see #exposeHelpers(Map, HttpServletRequest)
|
||||
* @see #exposeHelpers(org.apache.velocity.context.Context, HttpServletRequest, HttpServletResponse)
|
||||
*/
|
||||
protected void exposeToolAttributes(Context velocityContext, HttpServletRequest request) throws Exception {
|
||||
// Expose generic attributes.
|
||||
if (this.toolAttributes != null) {
|
||||
for (Map.Entry<String, Class<?>> entry : this.toolAttributes.entrySet()) {
|
||||
String attributeName = entry.getKey();
|
||||
Class<?> toolClass = entry.getValue();
|
||||
try {
|
||||
Object tool = toolClass.newInstance();
|
||||
initTool(tool, velocityContext);
|
||||
velocityContext.put(attributeName, tool);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new NestedServletException("Could not instantiate Velocity tool '" + attributeName + "'", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Expose locale-aware DateTool/NumberTool attributes.
|
||||
if (this.dateToolAttribute != null || this.numberToolAttribute != null) {
|
||||
if (this.dateToolAttribute != null) {
|
||||
velocityContext.put(this.dateToolAttribute, new LocaleAwareDateTool(request));
|
||||
}
|
||||
if (this.numberToolAttribute != null) {
|
||||
velocityContext.put(this.numberToolAttribute, new LocaleAwareNumberTool(request));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the given tool instance. The default implementation is empty.
|
||||
* <p>Can be overridden to check for special callback interfaces, for example
|
||||
* the ViewContext interface which is part of the view package of Velocity Tools.
|
||||
* In the particular case of ViewContext, you'll usually also need a special
|
||||
* Velocity context, like ChainedContext which is part of Velocity Tools too.
|
||||
* <p>Have a look at {@link VelocityToolboxView}, which pre-implements such a
|
||||
* ViewTool check. This is not part of the standard VelocityView class in order
|
||||
* to avoid a required dependency on the view package of Velocity Tools.
|
||||
* @param tool the tool instance to initialize
|
||||
* @param velocityContext the Velocity context
|
||||
* @throws Exception if initializion of the tool failed
|
||||
* @see #createVelocityContext
|
||||
* @see org.apache.velocity.tools.view.context.ViewContext
|
||||
* @see org.apache.velocity.tools.view.context.ChainedContext
|
||||
* @see VelocityToolboxView
|
||||
*/
|
||||
protected void initTool(Object tool, Context velocityContext) throws Exception {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render the Velocity view to the given response, using the given Velocity
|
||||
* context which contains the complete template model to use.
|
||||
* <p>The default implementation renders the template specified by the "url"
|
||||
* bean property, retrieved via {@code getTemplate}. It delegates to the
|
||||
* {@code mergeTemplate} method to merge the template instance with the
|
||||
* given Velocity context.
|
||||
* <p>Can be overridden to customize the behavior, for example to render
|
||||
* multiple templates into a single view.
|
||||
* @param context the Velocity context to use for rendering
|
||||
* @param response servlet response (use this to get the OutputStream or Writer)
|
||||
* @throws Exception if thrown by Velocity
|
||||
* @see #setUrl
|
||||
* @see #getTemplate()
|
||||
* @see #mergeTemplate
|
||||
*/
|
||||
protected void doRender(Context context, HttpServletResponse response) throws Exception {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Rendering Velocity template [" + getUrl() + "] in VelocityView '" + getBeanName() + "'");
|
||||
}
|
||||
mergeTemplate(getTemplate(), context, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Velocity template to be rendered by this view.
|
||||
* <p>By default, the template specified by the "url" bean property will be
|
||||
* retrieved: either returning a cached template instance or loading a fresh
|
||||
* instance (according to the "cacheTemplate" bean property)
|
||||
* @return the Velocity template to render
|
||||
* @throws Exception if thrown by Velocity
|
||||
* @see #setUrl
|
||||
* @see #setCacheTemplate
|
||||
* @see #getTemplate(String)
|
||||
*/
|
||||
protected Template getTemplate() throws Exception {
|
||||
// We already hold a reference to the template, but we might want to load it
|
||||
// if not caching. Velocity itself caches templates, so our ability to
|
||||
// cache templates in this class is a minor optimization only.
|
||||
if (isCacheTemplate() && this.template != null) {
|
||||
return this.template;
|
||||
}
|
||||
else {
|
||||
return getTemplate(getUrl());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Velocity template specified by the given name,
|
||||
* using the encoding specified by the "encoding" bean property.
|
||||
* <p>Can be called by subclasses to retrieve a specific template,
|
||||
* for example to render multiple templates into a single view.
|
||||
* @param name the file name of the desired template
|
||||
* @return the Velocity template
|
||||
* @throws Exception if thrown by Velocity
|
||||
* @see org.apache.velocity.app.VelocityEngine#getTemplate
|
||||
*/
|
||||
protected Template getTemplate(String name) throws Exception {
|
||||
return (getEncoding() != null ?
|
||||
getVelocityEngine().getTemplate(name, getEncoding()) :
|
||||
getVelocityEngine().getTemplate(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the template with the context.
|
||||
* Can be overridden to customize the behavior.
|
||||
* @param template the template to merge
|
||||
* @param context the Velocity context to use for rendering
|
||||
* @param response servlet response (use this to get the OutputStream or Writer)
|
||||
* @throws Exception if thrown by Velocity
|
||||
* @see org.apache.velocity.Template#merge
|
||||
*/
|
||||
protected void mergeTemplate(
|
||||
Template template, Context context, HttpServletResponse response) throws Exception {
|
||||
|
||||
try {
|
||||
template.merge(context, response.getWriter());
|
||||
}
|
||||
catch (MethodInvocationException ex) {
|
||||
Throwable cause = ex.getWrappedThrowable();
|
||||
throw new NestedServletException(
|
||||
"Method invocation failed during rendering of Velocity view with name '" +
|
||||
getBeanName() + "': " + ex.getMessage() + "; reference [" + ex.getReferenceName() +
|
||||
"], method '" + ex.getMethodName() + "'",
|
||||
cause==null ? ex : cause);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of DateTool from Velocity Tools, using a Spring-resolved
|
||||
* Locale and TimeZone instead of the default Locale.
|
||||
* @see org.springframework.web.servlet.support.RequestContextUtils#getLocale
|
||||
* @see org.springframework.web.servlet.support.RequestContextUtils#getTimeZone
|
||||
*/
|
||||
private static class LocaleAwareDateTool extends DateTool {
|
||||
|
||||
private final HttpServletRequest request;
|
||||
|
||||
public LocaleAwareDateTool(HttpServletRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return RequestContextUtils.getLocale(this.request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimeZone getTimeZone() {
|
||||
TimeZone timeZone = RequestContextUtils.getTimeZone(this.request);
|
||||
return (timeZone != null ? timeZone : super.getTimeZone());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of NumberTool from Velocity Tools, using a Spring-resolved
|
||||
* Locale instead of the default Locale.
|
||||
* @see org.springframework.web.servlet.support.RequestContextUtils#getLocale
|
||||
*/
|
||||
private static class LocaleAwareNumberTool extends NumberTool {
|
||||
|
||||
private final HttpServletRequest request;
|
||||
|
||||
public LocaleAwareNumberTool(HttpServletRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return RequestContextUtils.getLocale(this.request);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.velocity;
|
||||
|
||||
import org.springframework.web.servlet.view.AbstractTemplateViewResolver;
|
||||
import org.springframework.web.servlet.view.AbstractUrlBasedView;
|
||||
|
||||
/**
|
||||
* Convenience subclass of {@link org.springframework.web.servlet.view.UrlBasedViewResolver}
|
||||
* that supports {@link VelocityView} (i.e. Velocity templates) and custom subclasses of it.
|
||||
*
|
||||
* <p>The view class for all views generated by this resolver can be specified
|
||||
* via the "viewClass" property. See UrlBasedViewResolver's javadoc for details.
|
||||
*
|
||||
* <p><b>Note:</b> When chaining ViewResolvers, a VelocityViewResolver will
|
||||
* check for the existence of the specified template resources and only return
|
||||
* a non-null View object if the template was actually found.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 13.12.2003
|
||||
* @see #setViewClass
|
||||
* @see #setPrefix
|
||||
* @see #setSuffix
|
||||
* @see #setRequestContextAttribute
|
||||
* @see #setExposeSpringMacroHelpers
|
||||
* @see #setDateToolAttribute
|
||||
* @see #setNumberToolAttribute
|
||||
* @see VelocityView
|
||||
* @deprecated as of Spring 4.3, in favor of FreeMarker
|
||||
*/
|
||||
@Deprecated
|
||||
public class VelocityViewResolver extends AbstractTemplateViewResolver {
|
||||
|
||||
private String dateToolAttribute;
|
||||
|
||||
private String numberToolAttribute;
|
||||
|
||||
private String toolboxConfigLocation;
|
||||
|
||||
|
||||
public VelocityViewResolver() {
|
||||
setViewClass(requiredViewClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Requires {@link VelocityView}.
|
||||
*/
|
||||
@Override
|
||||
protected Class<?> requiredViewClass() {
|
||||
return VelocityView.class;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the name of the DateTool helper object to expose in the Velocity context
|
||||
* of this view, or {@code null} if not needed. DateTool is part of Velocity Tools 1.0.
|
||||
* @see org.apache.velocity.tools.generic.DateTool
|
||||
* @see VelocityView#setDateToolAttribute
|
||||
*/
|
||||
public void setDateToolAttribute(String dateToolAttribute) {
|
||||
this.dateToolAttribute = dateToolAttribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the NumberTool helper object to expose in the Velocity context
|
||||
* of this view, or {@code null} if not needed. NumberTool is part of Velocity Tools 1.1.
|
||||
* @see org.apache.velocity.tools.generic.NumberTool
|
||||
* @see VelocityView#setNumberToolAttribute
|
||||
*/
|
||||
public void setNumberToolAttribute(String numberToolAttribute) {
|
||||
this.numberToolAttribute = numberToolAttribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a Velocity Toolbox config location, for example "/WEB-INF/toolbox.xml",
|
||||
* to automatically load a Velocity Tools toolbox definition file and expose
|
||||
* all defined tools in the specified scopes. If no config location is
|
||||
* specified, no toolbox will be loaded and exposed.
|
||||
* <p>The specified location string needs to refer to a ServletContext
|
||||
* resource, as expected by ServletToolboxManager which is part of
|
||||
* the view package of Velocity Tools.
|
||||
* <p><b>Note:</b> Specifying a toolbox config location will lead to
|
||||
* VelocityToolboxView instances being created.
|
||||
* @see org.apache.velocity.tools.view.servlet.ServletToolboxManager#getInstance
|
||||
* @see VelocityToolboxView#setToolboxConfigLocation
|
||||
*/
|
||||
public void setToolboxConfigLocation(String toolboxConfigLocation) {
|
||||
this.toolboxConfigLocation = toolboxConfigLocation;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void initApplicationContext() {
|
||||
super.initApplicationContext();
|
||||
|
||||
if (this.toolboxConfigLocation != null) {
|
||||
if (VelocityView.class == getViewClass()) {
|
||||
logger.info("Using VelocityToolboxView instead of default VelocityView " +
|
||||
"due to specified toolboxConfigLocation");
|
||||
setViewClass(VelocityToolboxView.class);
|
||||
}
|
||||
else if (!VelocityToolboxView.class.isAssignableFrom(getViewClass())) {
|
||||
throw new IllegalArgumentException(
|
||||
"Given view class [" + getViewClass().getName() +
|
||||
"] is not of type [" + VelocityToolboxView.class.getName() +
|
||||
"], which it needs to be in case of a specified toolboxConfigLocation");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected AbstractUrlBasedView buildView(String viewName) throws Exception {
|
||||
VelocityView view = (VelocityView) super.buildView(viewName);
|
||||
view.setDateToolAttribute(this.dateToolAttribute);
|
||||
view.setNumberToolAttribute(this.numberToolAttribute);
|
||||
if (this.toolboxConfigLocation != null) {
|
||||
((VelocityToolboxView) view).setToolboxConfigLocation(this.toolboxConfigLocation);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
/**
|
||||
* Support classes for the integration of
|
||||
* <a href="http://velocity.apache.org">Velocity</a>
|
||||
* as Spring web view technology.
|
||||
* Contains a View implementation for Velocity templates.
|
||||
*/
|
||||
package org.springframework.web.servlet.view.velocity;
|
||||
@@ -1,320 +0,0 @@
|
||||
#**
|
||||
* spring.vm
|
||||
*
|
||||
* This file consists of a collection of Velocity macros aimed at easing
|
||||
* some of the common requirements of web applications - in particular
|
||||
* handling of forms.
|
||||
*
|
||||
* Spring's Velocity support will automatically make this file and therefore
|
||||
* all macros within it available to any application using Spring's
|
||||
* VelocityConfigurer.
|
||||
*
|
||||
* To take advantage of these macros, the "exposeSpringMacroHelpers" property
|
||||
* of the VelocityView class needs to be set to "true". This will expose a
|
||||
* RequestContext under the name "springMacroRequestContext", as needed by
|
||||
* the macros in this library.
|
||||
*
|
||||
* @author Darren Davison
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.1
|
||||
*#
|
||||
|
||||
#**
|
||||
* springMessage
|
||||
*
|
||||
* Macro to translate a message code into a message.
|
||||
*#
|
||||
#macro( springMessage $code )$springMacroRequestContext.getMessage($code)#end
|
||||
|
||||
#**
|
||||
* springMessageText
|
||||
*
|
||||
* Macro to translate a message code into a message,
|
||||
* using the given default text if no message found.
|
||||
*#
|
||||
#macro( springMessageText $code $text )$springMacroRequestContext.getMessage($code, $text)#end
|
||||
|
||||
#**
|
||||
* springTheme
|
||||
*
|
||||
* Macro to translate a theme message code into a string.
|
||||
*#
|
||||
#macro( springTheme $code )$springMacroRequestContext.getThemeMessage($code)#end
|
||||
|
||||
#**
|
||||
* springThemeText
|
||||
*
|
||||
* Macro to translate a theme message code into a string,
|
||||
* using the given default text if no message found.
|
||||
*#
|
||||
#macro( springThemeText $code $text )$springMacroRequestContext.getThemeMessage($code, $text)#end
|
||||
|
||||
#**
|
||||
* springUrl
|
||||
*
|
||||
* Takes a relative URL and makes it absolute from the server root by
|
||||
* adding the context root for the web application.
|
||||
*#
|
||||
#macro( springUrl $relativeUrl )$springMacroRequestContext.getContextUrl(${relativeUrl})#end
|
||||
|
||||
#**
|
||||
* springBind
|
||||
*
|
||||
* Exposes a BindStatus object for the given bind path, which can be
|
||||
* a bean (e.g. "person") to get global errors, or a bean property
|
||||
* (e.g. "person.name") to get field errors. Can be called multiple times
|
||||
* within a form to bind to multiple command objects and/or field names.
|
||||
*
|
||||
* This macro will participate in the default HTML escape setting for the given
|
||||
* RequestContext. This can be customized by calling "setDefaultHtmlEscape"
|
||||
* on the "springMacroRequestContext" context variable, or via the
|
||||
* "defaultHtmlEscape" context-param in web.xml (same as for the JSP bind tag).
|
||||
* Also regards a "springHtmlEscape" variable in the template context.
|
||||
*
|
||||
* Producing no output, the following context variable will be available
|
||||
* each time this macro is referenced:
|
||||
*
|
||||
* $status : a BindStatus instance holding the command object name,
|
||||
* expression, value, and error codes and messages for the path supplied
|
||||
*
|
||||
* @param $path : the path (string value) of the value required to bind to.
|
||||
* Spring defaults to a command name of "command" but this can be overridden
|
||||
* by user config.
|
||||
*#
|
||||
#macro( springBind $path )
|
||||
#if("$!springHtmlEscape"!="")
|
||||
#set( $status = $springMacroRequestContext.getBindStatus($path, $springHtmlEscape) )
|
||||
#else
|
||||
#set( $status = $springMacroRequestContext.getBindStatus($path) )
|
||||
#end
|
||||
#end
|
||||
|
||||
#**
|
||||
* springBindEscaped
|
||||
*
|
||||
* Similar to springBind, but takes an explicit HTML escape flag rather
|
||||
* than relying on the default HTML escape setting.
|
||||
*#
|
||||
#macro( springBindEscaped $path $htmlEscape )
|
||||
#set( $status = $springMacroRequestContext.getBindStatus($path, $htmlEscape) )
|
||||
#end
|
||||
|
||||
#**
|
||||
* springFormInput
|
||||
*
|
||||
* Display a form input field of type 'text' and bind it to an attribute
|
||||
* of a command or bean.
|
||||
*
|
||||
* @param path the name of the field to bind to
|
||||
* @param attributes any additional attributes for the element (such as class
|
||||
* or CSS styles or size)
|
||||
*
|
||||
*#
|
||||
#macro( springFormInput $path $attributes )
|
||||
#springBind($path)
|
||||
<input type="text" id="#springXmlId(${status.expression})" name="${status.expression}" value="$!status.value" ${attributes}#springCloseTag()
|
||||
#end
|
||||
|
||||
#**
|
||||
* springFormPasswordInput
|
||||
*
|
||||
* Display a form input field of type 'password' and bind it to an attribute
|
||||
* of a command or bean. No value will ever be specified for this field regardless
|
||||
* of whether one exists or not. For hopefully obvious reasons!
|
||||
*
|
||||
* @param path the name of the field to bind to
|
||||
* @param attributes any additional attributes for the element (such as class
|
||||
* or CSS styles or size)
|
||||
*
|
||||
*#
|
||||
#macro( springFormPasswordInput $path $attributes )
|
||||
#springBind($path)
|
||||
<input type="password" id="#springXmlId(${status.expression})" name="${status.expression}" value="" ${attributes}#springCloseTag()
|
||||
#end
|
||||
|
||||
#**
|
||||
* springFormHiddenInput
|
||||
*
|
||||
* Generate a form input field of type 'hidden' and bind it to an attribute
|
||||
* of a command or bean.
|
||||
*
|
||||
* @param path the name of the field to bind to
|
||||
* @param attributes any additional attributes for the element (such as class
|
||||
* or CSS styles or size)
|
||||
*
|
||||
*#
|
||||
#macro( springFormHiddenInput $path $attributes )
|
||||
#springBind($path)
|
||||
<input type="hidden" id="#springXmlId(${status.expression})" name="${status.expression}" value="$!status.value" ${attributes}#springCloseTag()
|
||||
#end
|
||||
|
||||
#**
|
||||
* formTextArea
|
||||
*
|
||||
* display a text area and bind it to an attribute
|
||||
* of a command or bean
|
||||
*
|
||||
* @param path the name of the field to bind to
|
||||
* @param attributes any additional attributes for the element (such as class
|
||||
* or CSS styles or size)
|
||||
*
|
||||
*#
|
||||
#macro( springFormTextarea $path $attributes )
|
||||
#springBind($path)
|
||||
<textarea id="#springXmlId(${status.expression})" name="${status.expression}" ${attributes}>
|
||||
$!status.value</textarea>
|
||||
#end
|
||||
|
||||
#**
|
||||
* springFormSingleSelect
|
||||
*
|
||||
* Show a selectbox (dropdown) input element allowing a single value to be chosen
|
||||
* from a list of options.
|
||||
*
|
||||
* The null check for $status.value leverages Velocity's 'quiet' notation rather
|
||||
* than the more common #if($status.value) since this method evaluates to the
|
||||
* boolean 'false' if the content of $status.value is the String "false" - not
|
||||
* what we want.
|
||||
*
|
||||
* @param path the name of the field to bind to
|
||||
* @param options a map (value=label) of all the available options
|
||||
* @param attributes any additional attributes for the element (such as class
|
||||
* or CSS styles or size)
|
||||
*#
|
||||
#macro( springFormSingleSelect $path $options $attributes )
|
||||
#springBind($path)
|
||||
<select id="#springXmlId(${status.expression})" name="${status.expression}" ${attributes}>
|
||||
#foreach($option in $options.keySet())
|
||||
<option value="${option}"
|
||||
#if("$!status.value"=="$option") selected="selected" #end>
|
||||
${options.get($option)}</option>
|
||||
#end
|
||||
</select>
|
||||
#end
|
||||
|
||||
#**
|
||||
* springFormMultiSelect
|
||||
*
|
||||
* Show a listbox of options allowing the user to make 0 or more choices from
|
||||
* the list of options.
|
||||
*
|
||||
* @param path the name of the field to bind to
|
||||
* @param options a map (value=label) of all the available options
|
||||
* @param attributes any additional attributes for the element (such as class
|
||||
* or CSS styles or size)
|
||||
*#
|
||||
#macro( springFormMultiSelect $path $options $attributes )
|
||||
#springBind($path)
|
||||
<select multiple="multiple" id="#springXmlId(${status.expression})" name="${status.expression}" ${attributes}>
|
||||
#foreach($option in $options.keySet())
|
||||
<option value="${option}"
|
||||
#foreach($item in $status.actualValue)
|
||||
#if($item==$option) selected="selected" #end
|
||||
#end
|
||||
>${options.get($option)}</option>
|
||||
#end
|
||||
</select>
|
||||
#end
|
||||
|
||||
#**
|
||||
* springFormRadioButtons
|
||||
*
|
||||
* Show radio buttons.
|
||||
*
|
||||
* @param path the name of the field to bind to
|
||||
* @param options a map (value=label) of all the available options
|
||||
* @param separator the html tag or other character list that should be used to
|
||||
* separate each option. Typically ' ' or '<br>'
|
||||
* @param attributes any additional attributes for the element (such as class
|
||||
* or CSS styles or size)
|
||||
*#
|
||||
#macro( springFormRadioButtons $path $options $separator $attributes )
|
||||
#springBind($path)
|
||||
#foreach($option in $options.keySet())
|
||||
<input type="radio" name="${status.expression}" value="${option}"
|
||||
#if("$!status.value"=="$option") checked="checked" #end
|
||||
${attributes}
|
||||
#springCloseTag()
|
||||
${options.get($option)} ${separator}
|
||||
#end
|
||||
#end
|
||||
|
||||
#**
|
||||
* springFormCheckboxes
|
||||
*
|
||||
* Show checkboxes.
|
||||
*
|
||||
* @param path the name of the field to bind to
|
||||
* @param options a map (value=label) of all the available options
|
||||
* @param separator the html tag or other character list that should be used to
|
||||
* separate each option. Typically ' ' or '<br>'.
|
||||
* @param attributes any additional attributes for the element (such as class
|
||||
* or CSS styles or size)
|
||||
*#
|
||||
#macro( springFormCheckboxes $path $options $separator $attributes )
|
||||
#springBind($path)
|
||||
#foreach($option in $options.keySet())
|
||||
<input type="checkbox" name="${status.expression}" value="${option}"
|
||||
#foreach($item in $status.actualValue)
|
||||
#if($item==$option) checked="checked" #end
|
||||
#end
|
||||
${attributes} #springCloseTag()
|
||||
${options.get($option)} ${separator}
|
||||
#end
|
||||
<input type="hidden" name="_${status.expression}" value="on"/>
|
||||
#end
|
||||
|
||||
#**
|
||||
* springFormCheckbox
|
||||
*
|
||||
* Show a single checkbox.
|
||||
*
|
||||
* @param path the name of the field to bind to
|
||||
* @param attributes any additional attributes for the element (such as class
|
||||
* or CSS styles or size)
|
||||
*#
|
||||
#macro( springFormCheckbox $path $attributes )
|
||||
#springBind($path)
|
||||
<input type="hidden" name="_#springXmlId(${status.expression})" value="on"/>
|
||||
<input type="checkbox" id="#springXmlId(${status.expression})" name="${status.expression}"#if("$!{status.value}"=="true") checked="checked"#end ${attributes}/>
|
||||
#end
|
||||
|
||||
#**
|
||||
* springShowErrors
|
||||
*
|
||||
* Show validation errors for the currently bound field, with
|
||||
* optional style attributes.
|
||||
*
|
||||
* @param separator the html tag or other character list that should be used to
|
||||
* separate each option. Typically '<br>'.
|
||||
* @param classOrStyle either the name of a CSS class element (which is defined in
|
||||
* the template or an external CSS file) or an inline style. If the value passed in here
|
||||
* contains a colon (:) then a 'style=' attribute will be used, else a 'class=' attribute
|
||||
* will be used.
|
||||
*#
|
||||
#macro( springShowErrors $separator $classOrStyle )
|
||||
#foreach($error in $status.errorMessages)
|
||||
#if($classOrStyle=="")
|
||||
<b>${error}</b>
|
||||
#else
|
||||
#if($classOrStyle.indexOf(":")==-1)
|
||||
#set($attr="class")
|
||||
#else
|
||||
#set($attr="style")
|
||||
#end
|
||||
<span ${attr}="${classOrStyle}">${error}</span>
|
||||
#end
|
||||
${separator}
|
||||
#end
|
||||
#end
|
||||
|
||||
#**
|
||||
* springCloseTag
|
||||
*
|
||||
* Simple macro to close an HTML tag that has no body with '>' or '/>',
|
||||
* depending on the value of a 'springXhtmlCompliant' variable in the
|
||||
* template context.
|
||||
*#
|
||||
#macro( springCloseTag )#if($springXhtmlCompliant)/>#else>#end#end
|
||||
|
||||
#macro( springXmlId $id)#if($id)$id.replaceAll("\[","").replaceAll("\]","")#else$id#end#end
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* 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.
|
||||
@@ -141,8 +141,6 @@ import org.springframework.web.servlet.view.script.ScriptTemplateViewResolver;
|
||||
import org.springframework.web.servlet.view.tiles3.SpringBeanPreparerFactory;
|
||||
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
|
||||
import org.springframework.web.servlet.view.tiles3.TilesViewResolver;
|
||||
import org.springframework.web.servlet.view.velocity.VelocityConfigurer;
|
||||
import org.springframework.web.servlet.view.velocity.VelocityViewResolver;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
@@ -742,11 +740,11 @@ public class MvcNamespaceTests {
|
||||
|
||||
@Test
|
||||
public void testViewResolution() throws Exception {
|
||||
loadBeanDefinitions("mvc-config-view-resolution.xml", 7);
|
||||
loadBeanDefinitions("mvc-config-view-resolution.xml", 6);
|
||||
|
||||
ViewResolverComposite compositeResolver = this.appContext.getBean(ViewResolverComposite.class);
|
||||
assertNotNull(compositeResolver);
|
||||
assertEquals("Actual: " + compositeResolver.getViewResolvers(), 9, compositeResolver.getViewResolvers().size());
|
||||
assertEquals("Actual: " + compositeResolver.getViewResolvers(), 8, compositeResolver.getViewResolvers().size());
|
||||
assertEquals(Ordered.LOWEST_PRECEDENCE, compositeResolver.getOrder());
|
||||
|
||||
List<ViewResolver> resolvers = compositeResolver.getViewResolvers();
|
||||
@@ -768,28 +766,21 @@ public class MvcNamespaceTests {
|
||||
assertEquals(1024, accessor.getPropertyValue("cacheLimit"));
|
||||
|
||||
resolver = resolvers.get(4);
|
||||
assertThat(resolver, instanceOf(VelocityViewResolver.class));
|
||||
accessor = new DirectFieldAccessor(resolver);
|
||||
assertEquals("", accessor.getPropertyValue("prefix"));
|
||||
assertEquals(".vm", accessor.getPropertyValue("suffix"));
|
||||
assertEquals(0, accessor.getPropertyValue("cacheLimit"));
|
||||
|
||||
resolver = resolvers.get(5);
|
||||
assertThat(resolver, instanceOf(GroovyMarkupViewResolver.class));
|
||||
accessor = new DirectFieldAccessor(resolver);
|
||||
assertEquals("", accessor.getPropertyValue("prefix"));
|
||||
assertEquals(".tpl", accessor.getPropertyValue("suffix"));
|
||||
assertEquals(1024, accessor.getPropertyValue("cacheLimit"));
|
||||
|
||||
resolver = resolvers.get(6);
|
||||
resolver = resolvers.get(5);
|
||||
assertThat(resolver, instanceOf(ScriptTemplateViewResolver.class));
|
||||
accessor = new DirectFieldAccessor(resolver);
|
||||
assertEquals("", accessor.getPropertyValue("prefix"));
|
||||
assertEquals("", accessor.getPropertyValue("suffix"));
|
||||
assertEquals(1024, accessor.getPropertyValue("cacheLimit"));
|
||||
|
||||
assertEquals(InternalResourceViewResolver.class, resolvers.get(6).getClass());
|
||||
assertEquals(InternalResourceViewResolver.class, resolvers.get(7).getClass());
|
||||
assertEquals(InternalResourceViewResolver.class, resolvers.get(8).getClass());
|
||||
|
||||
TilesConfigurer tilesConfigurer = appContext.getBean(TilesConfigurer.class);
|
||||
assertNotNull(tilesConfigurer);
|
||||
@@ -808,11 +799,6 @@ public class MvcNamespaceTests {
|
||||
accessor = new DirectFieldAccessor(freeMarkerConfigurer);
|
||||
assertArrayEquals(new String[] {"/", "/test"}, (String[]) accessor.getPropertyValue("templateLoaderPaths"));
|
||||
|
||||
VelocityConfigurer velocityConfigurer = appContext.getBean(VelocityConfigurer.class);
|
||||
assertNotNull(velocityConfigurer);
|
||||
accessor = new DirectFieldAccessor(velocityConfigurer);
|
||||
assertEquals("/test", accessor.getPropertyValue("resourceLoaderPath"));
|
||||
|
||||
GroovyMarkupConfigurer groovyMarkupConfigurer = appContext.getBean(GroovyMarkupConfigurer.class);
|
||||
assertNotNull(groovyMarkupConfigurer);
|
||||
assertEquals("/test", groovyMarkupConfigurer.getResourceLoaderPath());
|
||||
@@ -833,7 +819,7 @@ public class MvcNamespaceTests {
|
||||
|
||||
@Test
|
||||
public void testViewResolutionWithContentNegotiation() throws Exception {
|
||||
loadBeanDefinitions("mvc-config-view-resolution-content-negotiation.xml", 7);
|
||||
loadBeanDefinitions("mvc-config-view-resolution-content-negotiation.xml", 6);
|
||||
|
||||
ViewResolverComposite compositeResolver = this.appContext.getBean(ViewResolverComposite.class);
|
||||
assertNotNull(compositeResolver);
|
||||
@@ -843,7 +829,7 @@ public class MvcNamespaceTests {
|
||||
List<ViewResolver> resolvers = compositeResolver.getViewResolvers();
|
||||
assertEquals(ContentNegotiatingViewResolver.class, resolvers.get(0).getClass());
|
||||
ContentNegotiatingViewResolver cnvr = (ContentNegotiatingViewResolver) resolvers.get(0);
|
||||
assertEquals(7, cnvr.getViewResolvers().size());
|
||||
assertEquals(6, cnvr.getViewResolvers().size());
|
||||
assertEquals(1, cnvr.getDefaultViews().size());
|
||||
assertTrue(cnvr.isUseNotAcceptableStatusCode());
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@ import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
|
||||
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
|
||||
import org.springframework.web.servlet.view.groovy.GroovyMarkupConfigurer;
|
||||
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
|
||||
import org.springframework.web.servlet.view.velocity.VelocityConfigurer;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@@ -61,12 +60,6 @@ public class ViewResolutionIntegrationTests {
|
||||
assertEquals("<html><body>Hello World!</body></html>", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void velocity() throws Exception {
|
||||
MockHttpServletResponse response = runTest(VelocityWebConfig.class);
|
||||
assertEquals("<html><body>Hello World!</body></html>", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tiles() throws Exception {
|
||||
MockHttpServletResponse response = runTest(TilesWebConfig.class);
|
||||
@@ -85,12 +78,6 @@ public class ViewResolutionIntegrationTests {
|
||||
runTest(InvalidFreeMarkerWebConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void velocityInvalidConfig() throws Exception {
|
||||
this.thrown.expectMessage("In addition to a Velocity view resolver ");
|
||||
runTest(InvalidVelocityWebConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tilesInvalidConfig() throws Exception {
|
||||
this.thrown.expectMessage("In addition to a Tiles view resolver ");
|
||||
@@ -165,22 +152,6 @@ public class ViewResolutionIntegrationTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class VelocityWebConfig extends AbstractWebConfig {
|
||||
|
||||
@Override
|
||||
public void configureViewResolvers(ViewResolverRegistry registry) {
|
||||
registry.velocity();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public VelocityConfigurer velocityConfigurer() {
|
||||
VelocityConfigurer configurer = new VelocityConfigurer();
|
||||
configurer.setResourceLoaderPath("/WEB-INF/");
|
||||
return configurer;
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class TilesWebConfig extends AbstractWebConfig {
|
||||
|
||||
@@ -222,15 +193,6 @@ public class ViewResolutionIntegrationTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class InvalidVelocityWebConfig extends WebMvcConfigurationSupport {
|
||||
|
||||
@Override
|
||||
public void configureViewResolvers(ViewResolverRegistry registry) {
|
||||
registry.velocity();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class InvalidTilesWebConfig extends WebMvcConfigurationSupport {
|
||||
|
||||
|
||||
@@ -38,8 +38,6 @@ import org.springframework.web.servlet.view.script.ScriptTemplateConfigurer;
|
||||
import org.springframework.web.servlet.view.script.ScriptTemplateViewResolver;
|
||||
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
|
||||
import org.springframework.web.servlet.view.tiles3.TilesViewResolver;
|
||||
import org.springframework.web.servlet.view.velocity.VelocityConfigurer;
|
||||
import org.springframework.web.servlet.view.velocity.VelocityViewResolver;
|
||||
import org.springframework.web.servlet.view.xml.MarshallingView;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
@@ -59,7 +57,6 @@ public class ViewResolverRegistryTests {
|
||||
public void setUp() {
|
||||
StaticWebApplicationContext context = new StaticWebApplicationContext();
|
||||
context.registerSingleton("freeMarkerConfigurer", FreeMarkerConfigurer.class);
|
||||
context.registerSingleton("velocityConfigurer", VelocityConfigurer.class);
|
||||
context.registerSingleton("tilesConfigurer", TilesConfigurer.class);
|
||||
context.registerSingleton("groovyMarkupConfigurer", GroovyMarkupConfigurer.class);
|
||||
context.registerSingleton("scriptTemplateConfigurer", ScriptTemplateConfigurer.class);
|
||||
@@ -79,7 +76,7 @@ public class ViewResolverRegistryTests {
|
||||
@Test
|
||||
public void hasRegistrations() {
|
||||
assertFalse(this.registry.hasRegistrations());
|
||||
this.registry.velocity();
|
||||
this.registry.freeMarker();
|
||||
assertTrue(this.registry.hasRegistrations());
|
||||
}
|
||||
|
||||
@@ -141,20 +138,6 @@ public class ViewResolverRegistryTests {
|
||||
checkAndGetResolver(TilesViewResolver.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void velocity() {
|
||||
this.registry.velocity().prefix("/").suffix(".vm").cache(true);
|
||||
VelocityViewResolver resolver = checkAndGetResolver(VelocityViewResolver.class);
|
||||
checkPropertyValues(resolver, "prefix", "/", "suffix", ".vm", "cacheLimit", 1024);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void velocityDefaultValues() {
|
||||
this.registry.velocity();
|
||||
VelocityViewResolver resolver = checkAndGetResolver(VelocityViewResolver.class);
|
||||
checkPropertyValues(resolver, "prefix", "", "suffix", ".vm");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void freeMarker() {
|
||||
this.registry.freeMarker().prefix("/").suffix(".fmt").cache(false);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* 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.
|
||||
@@ -21,7 +21,6 @@ import java.util.Locale;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.web.servlet.view.velocity.VelocityView;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@@ -50,13 +49,6 @@ public class JasperReportViewResolverTests {
|
||||
assertEquals("Incorrect URL", prefix + viewName + suffix, view.getUrl());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void setIncorrectViewClass() {
|
||||
// Should not be able to set view class to a class that does not extend
|
||||
// AbstractJasperReportsView.
|
||||
new JasperReportsViewResolver().setViewClass(VelocityView.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withViewNamesAndEndsWithPattern() throws Exception {
|
||||
doViewNamesTest("DataSource*");
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2015 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.velocity;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.velocity.Template;
|
||||
import org.apache.velocity.app.VelocityEngine;
|
||||
import org.apache.velocity.exception.ResourceNotFoundException;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @since 09.10.2004
|
||||
*/
|
||||
class TestVelocityEngine extends VelocityEngine {
|
||||
|
||||
private final Map<String, Template> templates = new HashMap<>();
|
||||
|
||||
|
||||
public TestVelocityEngine() {
|
||||
}
|
||||
|
||||
public TestVelocityEngine(String expectedName, Template template) {
|
||||
addTemplate(expectedName, template);
|
||||
}
|
||||
|
||||
public void addTemplate(String expectedName, Template template) {
|
||||
this.templates.put(expectedName, template);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Template getTemplate(String name) throws ResourceNotFoundException {
|
||||
Template template = this.templates.get(name);
|
||||
if (template == null) {
|
||||
throw new ResourceNotFoundException("No template registered for name [" + name + "]");
|
||||
}
|
||||
return template;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2015 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.velocity;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.apache.velocity.app.VelocityEngine;
|
||||
import org.apache.velocity.exception.VelocityException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.core.io.DescriptiveResource;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.UrlResource;
|
||||
import org.springframework.ui.velocity.VelocityEngineFactoryBean;
|
||||
import org.springframework.ui.velocity.VelocityEngineUtils;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class VelocityConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void velocityEngineFactoryBeanWithConfigLocation() throws VelocityException {
|
||||
VelocityEngineFactoryBean vefb = new VelocityEngineFactoryBean();
|
||||
vefb.setConfigLocation(new FileSystemResource("myprops.properties"));
|
||||
Properties props = new Properties();
|
||||
props.setProperty("myprop", "/mydir");
|
||||
vefb.setVelocityProperties(props);
|
||||
try {
|
||||
vefb.afterPropertiesSet();
|
||||
fail("Should have thrown IOException");
|
||||
}
|
||||
catch (IOException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void velocityEngineFactoryBeanWithVelocityProperties() throws VelocityException, IOException {
|
||||
VelocityEngineFactoryBean vefb = new VelocityEngineFactoryBean();
|
||||
Properties props = new Properties();
|
||||
props.setProperty("myprop", "/mydir");
|
||||
vefb.setVelocityProperties(props);
|
||||
Object value = new Object();
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("myentry", value);
|
||||
vefb.setVelocityPropertiesMap(map);
|
||||
vefb.afterPropertiesSet();
|
||||
assertThat(vefb.getObject(), instanceOf(VelocityEngine.class));
|
||||
VelocityEngine ve = vefb.getObject();
|
||||
assertEquals("/mydir", ve.getProperty("myprop"));
|
||||
assertEquals(value, ve.getProperty("myentry"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void velocityEngineFactoryBeanWithResourceLoaderPath() throws IOException, VelocityException {
|
||||
VelocityEngineFactoryBean vefb = new VelocityEngineFactoryBean();
|
||||
vefb.setResourceLoaderPath("file:/mydir");
|
||||
vefb.afterPropertiesSet();
|
||||
assertThat(vefb.getObject(), instanceOf(VelocityEngine.class));
|
||||
VelocityEngine ve = vefb.getObject();
|
||||
assertEquals(new File("/mydir").getAbsolutePath(), ve.getProperty(VelocityEngine.FILE_RESOURCE_LOADER_PATH));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
public void velocityEngineFactoryBeanWithNonFileResourceLoaderPath() throws Exception {
|
||||
VelocityEngineFactoryBean vefb = new VelocityEngineFactoryBean();
|
||||
vefb.setResourceLoaderPath("file:/mydir");
|
||||
vefb.setResourceLoader(new ResourceLoader() {
|
||||
@Override
|
||||
public Resource getResource(String location) {
|
||||
if (location.equals("file:/mydir") || location.equals("file:/mydir/test")) {
|
||||
return new ByteArrayResource("test".getBytes(), "test");
|
||||
}
|
||||
try {
|
||||
return new UrlResource(location);
|
||||
}
|
||||
catch (MalformedURLException ex) {
|
||||
throw new IllegalArgumentException(ex.toString());
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public ClassLoader getClassLoader() {
|
||||
return getClass().getClassLoader();
|
||||
}
|
||||
});
|
||||
vefb.afterPropertiesSet();
|
||||
assertThat(vefb.getObject(), instanceOf(VelocityEngine.class));
|
||||
VelocityEngine ve = vefb.getObject();
|
||||
assertEquals("test", VelocityEngineUtils.mergeTemplateIntoString(ve, "test", Collections.emptyMap()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void velocityConfigurer() throws IOException, VelocityException {
|
||||
VelocityConfigurer vc = new VelocityConfigurer();
|
||||
vc.setResourceLoaderPath("file:/mydir");
|
||||
vc.afterPropertiesSet();
|
||||
assertThat(vc.createVelocityEngine(), instanceOf(VelocityEngine.class));
|
||||
VelocityEngine ve = vc.createVelocityEngine();
|
||||
assertEquals(new File("/mydir").getAbsolutePath(), ve.getProperty(VelocityEngine.FILE_RESOURCE_LOADER_PATH));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void velocityConfigurerWithCsvPath() throws IOException, VelocityException {
|
||||
VelocityConfigurer vc = new VelocityConfigurer();
|
||||
vc.setResourceLoaderPath("file:/mydir,file:/yourdir");
|
||||
vc.afterPropertiesSet();
|
||||
assertThat(vc.createVelocityEngine(), instanceOf(VelocityEngine.class));
|
||||
VelocityEngine ve = vc.createVelocityEngine();
|
||||
Vector<String> paths = new Vector<>();
|
||||
paths.add(new File("/mydir").getAbsolutePath());
|
||||
paths.add(new File("/yourdir").getAbsolutePath());
|
||||
assertEquals(paths, ve.getProperty(VelocityEngine.FILE_RESOURCE_LOADER_PATH));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
public void velocityConfigurerWithCsvPathAndNonFileAccess() throws IOException, VelocityException {
|
||||
VelocityConfigurer vc = new VelocityConfigurer();
|
||||
vc.setResourceLoaderPath("file:/mydir,file:/yourdir");
|
||||
vc.setResourceLoader(new ResourceLoader() {
|
||||
@Override
|
||||
public Resource getResource(String location) {
|
||||
if ("file:/yourdir/test".equals(location)) {
|
||||
return new DescriptiveResource("");
|
||||
}
|
||||
return new ByteArrayResource("test".getBytes(), "test");
|
||||
}
|
||||
@Override
|
||||
public ClassLoader getClassLoader() {
|
||||
return getClass().getClassLoader();
|
||||
}
|
||||
});
|
||||
vc.setPreferFileSystemAccess(false);
|
||||
vc.afterPropertiesSet();
|
||||
assertThat(vc.createVelocityEngine(), instanceOf(VelocityEngine.class));
|
||||
VelocityEngine ve = vc.createVelocityEngine();
|
||||
assertEquals("test", VelocityEngineUtils.mergeTemplateIntoString(ve, "test", Collections.emptyMap()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,266 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2015 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.velocity;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.velocity.Template;
|
||||
import org.apache.velocity.app.VelocityEngine;
|
||||
import org.apache.velocity.context.Context;
|
||||
|
||||
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.tests.sample.beans.TestBean;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.context.support.StaticWebApplicationContext;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
|
||||
import org.springframework.web.servlet.support.BindStatus;
|
||||
import org.springframework.web.servlet.support.RequestContext;
|
||||
import org.springframework.web.servlet.theme.FixedThemeResolver;
|
||||
import org.springframework.web.servlet.view.DummyMacroRequestContext;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Darren Davison
|
||||
* @author Juergen Hoeller
|
||||
* @since 18.06.2004
|
||||
*/
|
||||
public class VelocityMacroTests {
|
||||
|
||||
private static final String TEMPLATE_FILE = "test.vm";
|
||||
|
||||
private StaticWebApplicationContext wac;
|
||||
|
||||
private MockHttpServletRequest request;
|
||||
|
||||
private MockHttpServletResponse response;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
wac = new StaticWebApplicationContext();
|
||||
wac.setServletContext(new MockServletContext());
|
||||
|
||||
final Template expectedTemplate = new Template();
|
||||
VelocityConfig vc = new VelocityConfig() {
|
||||
@Override
|
||||
public VelocityEngine getVelocityEngine() {
|
||||
return new TestVelocityEngine(TEMPLATE_FILE, expectedTemplate);
|
||||
}
|
||||
};
|
||||
wac.getDefaultListableBeanFactory().registerSingleton("velocityConfigurer", vc);
|
||||
wac.refresh();
|
||||
|
||||
request = new MockHttpServletRequest();
|
||||
request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
|
||||
request.setAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE, new AcceptHeaderLocaleResolver());
|
||||
request.setAttribute(DispatcherServlet.THEME_RESOLVER_ATTRIBUTE, new FixedThemeResolver());
|
||||
response = new MockHttpServletResponse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exposeSpringMacroHelpers() throws Exception {
|
||||
VelocityView vv = new VelocityView() {
|
||||
@Override
|
||||
protected void mergeTemplate(Template template, Context context, HttpServletResponse response) {
|
||||
assertTrue(context.get(VelocityView.SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE) instanceof RequestContext);
|
||||
RequestContext rc = (RequestContext) context.get(VelocityView.SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE);
|
||||
BindStatus status = rc.getBindStatus("tb.name");
|
||||
assertEquals("name", status.getExpression());
|
||||
assertEquals("juergen", status.getValue());
|
||||
}
|
||||
};
|
||||
vv.setUrl(TEMPLATE_FILE);
|
||||
vv.setApplicationContext(wac);
|
||||
vv.setExposeSpringMacroHelpers(true);
|
||||
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
model.put("tb", new TestBean("juergen", 99));
|
||||
vv.render(model, request, response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void springMacroRequestContextAttributeUsed() {
|
||||
final String helperTool = "wrongType";
|
||||
|
||||
VelocityView vv = new VelocityView() {
|
||||
@Override
|
||||
protected void mergeTemplate(Template template, Context context, HttpServletResponse response) {
|
||||
fail();
|
||||
}
|
||||
};
|
||||
vv.setUrl(TEMPLATE_FILE);
|
||||
vv.setApplicationContext(wac);
|
||||
vv.setExposeSpringMacroHelpers(true);
|
||||
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
model.put(VelocityView.SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE, helperTool);
|
||||
|
||||
try {
|
||||
vv.render(model, request, response);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
assertTrue(ex instanceof ServletException);
|
||||
assertTrue(ex.getMessage().contains(VelocityView.SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allMacros() throws Exception {
|
||||
DummyMacroRequestContext rc = new DummyMacroRequestContext(request);
|
||||
Map<String, String> msgMap = new HashMap<String, String>();
|
||||
msgMap.put("hello", "Howdy");
|
||||
msgMap.put("world", "Mundo");
|
||||
rc.setMessageMap(msgMap);
|
||||
Map<String, String> themeMsgMap = new HashMap<String, String>();
|
||||
themeMsgMap.put("hello", "Howdy!");
|
||||
themeMsgMap.put("world", "Mundo!");
|
||||
rc.setThemeMessageMap(themeMsgMap);
|
||||
rc.setContextPath("/springtest");
|
||||
|
||||
TestBean tb = new TestBean("Darren", 99);
|
||||
tb.setJedi(true);
|
||||
tb.setStringArray(new String[] {"John", "Fred"});
|
||||
request.setAttribute("command", tb);
|
||||
|
||||
Map<String, String> names = new HashMap<String, String>();
|
||||
names.put("Darren", "Darren Davison");
|
||||
names.put("John", "John Doe");
|
||||
names.put("Fred", "Fred Bloggs");
|
||||
|
||||
VelocityConfigurer vc = new VelocityConfigurer();
|
||||
vc.setPreferFileSystemAccess(false);
|
||||
VelocityEngine ve = vc.createVelocityEngine();
|
||||
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
model.put("command", tb);
|
||||
model.put("springMacroRequestContext", rc);
|
||||
model.put("nameOptionMap", names);
|
||||
|
||||
VelocityView view = new VelocityView();
|
||||
view.setBeanName("myView");
|
||||
view.setUrl("org/springframework/web/servlet/view/velocity/test.vm");
|
||||
view.setEncoding("UTF-8");
|
||||
view.setExposeSpringMacroHelpers(false);
|
||||
view.setVelocityEngine(ve);
|
||||
|
||||
view.render(model, request, response);
|
||||
|
||||
// tokenize output and ignore whitespace
|
||||
String output = response.getContentAsString();
|
||||
System.out.println(output);
|
||||
String[] tokens = StringUtils.tokenizeToStringArray(output, "\t\n");
|
||||
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
if (tokens[i].equals("NAME")) assertEquals("Darren", tokens[i + 1]);
|
||||
if (tokens[i].equals("AGE")) assertEquals("99", tokens[i + 1]);
|
||||
if (tokens[i].equals("MESSAGE")) assertEquals("Howdy Mundo", tokens[i + 1]);
|
||||
if (tokens[i].equals("DEFAULTMESSAGE")) assertEquals("hi planet", tokens[i + 1]);
|
||||
if (tokens[i].equals("THEME")) assertEquals("Howdy! Mundo!", tokens[i + 1]);
|
||||
if (tokens[i].equals("DEFAULTTHEME")) assertEquals("hi! planet!", tokens[i + 1]);
|
||||
if (tokens[i].equals("URL")) assertEquals("/springtest/aftercontext.html", tokens[i + 1]);
|
||||
if (tokens[i].equals("FORM1")) assertEquals("<input type=\"text\" id=\"name\" name=\"name\" value=\"Darren\" >", tokens[i + 1]);
|
||||
if (tokens[i].equals("FORM2")) assertEquals("<input type=\"text\" id=\"name\" name=\"name\" value=\"Darren\" class=\"myCssClass\">", tokens[i + 1]);
|
||||
if (tokens[i].equals("FORM3")) assertEquals("<textarea id=\"name\" name=\"name\" >", tokens[i + 1]);
|
||||
if (tokens[i].equals("FORM3")) assertEquals("Darren</textarea>", tokens[i + 2]);
|
||||
if (tokens[i].equals("FORM4")) assertEquals("<textarea id=\"name\" name=\"name\" rows=10 cols=30>", tokens[i + 1]);
|
||||
if (tokens[i].equals("FORM4")) assertEquals("Darren</textarea>", tokens[i + 2]);
|
||||
//TODO verify remaining output (fix whitespace)
|
||||
if (tokens[i].equals("FORM9")) assertEquals("<input type=\"password\" id=\"name\" name=\"name\" value=\"\" >", tokens[i + 1]);
|
||||
if (tokens[i].equals("FORM10")) assertEquals("<input type=\"hidden\" id=\"name\" name=\"name\" value=\"Darren\" >", tokens[i + 1]);
|
||||
if (tokens[i].equals("FORM15")) assertEquals("<input type=\"hidden\" name=\"_name\" value=\"on\"/>", tokens[i + 1]);
|
||||
if (tokens[i].equals("FORM15")) assertEquals("<input type=\"checkbox\" id=\"name\" name=\"name\" />", tokens[i + 2]);
|
||||
if (tokens[i].equals("FORM16")) assertEquals("<input type=\"hidden\" name=\"_jedi\" value=\"on\"/>", tokens[i + 1]);
|
||||
if (tokens[i].equals("FORM16")) assertEquals("<input type=\"checkbox\" id=\"jedi\" name=\"jedi\" checked=\"checked\" />", tokens[i + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
// SPR-5172
|
||||
|
||||
@Test
|
||||
public void idContainsBraces() throws Exception {
|
||||
DummyMacroRequestContext rc = new DummyMacroRequestContext(request);
|
||||
Map<String, String> msgMap = new HashMap<String, String>();
|
||||
msgMap.put("hello", "Howdy");
|
||||
msgMap.put("world", "Mundo");
|
||||
rc.setMessageMap(msgMap);
|
||||
Map<String, String> themeMsgMap = new HashMap<String, String>();
|
||||
themeMsgMap.put("hello", "Howdy!");
|
||||
themeMsgMap.put("world", "Mundo!");
|
||||
rc.setThemeMessageMap(themeMsgMap);
|
||||
rc.setContextPath("/springtest");
|
||||
|
||||
TestBean darren = new TestBean("Darren", 99);
|
||||
TestBean fred = new TestBean("Fred");
|
||||
fred.setJedi(true);
|
||||
darren.setSpouse(fred);
|
||||
darren.setJedi(true);
|
||||
darren.setStringArray(new String[] {"John", "Fred"});
|
||||
request.setAttribute("command", darren);
|
||||
|
||||
Map<String, String> names = new HashMap<String, String>();
|
||||
names.put("Darren", "Darren Davison");
|
||||
names.put("John", "John Doe");
|
||||
names.put("Fred", "Fred Bloggs");
|
||||
|
||||
VelocityConfigurer vc = new VelocityConfigurer();
|
||||
vc.setPreferFileSystemAccess(false);
|
||||
VelocityEngine ve = vc.createVelocityEngine();
|
||||
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
model.put("command", darren);
|
||||
model.put("springMacroRequestContext", rc);
|
||||
model.put("nameOptionMap", names);
|
||||
|
||||
VelocityView view = new VelocityView();
|
||||
view.setBeanName("myView");
|
||||
view.setUrl("org/springframework/web/servlet/view/velocity/test-spr5172.vm");
|
||||
view.setEncoding("UTF-8");
|
||||
view.setExposeSpringMacroHelpers(false);
|
||||
view.setVelocityEngine(ve);
|
||||
|
||||
view.render(model, request, response);
|
||||
|
||||
// tokenize output and ignore whitespace
|
||||
String output = response.getContentAsString();
|
||||
String[] tokens = StringUtils.tokenizeToStringArray(output, "\t\n");
|
||||
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
if (tokens[i].equals("FORM1")) assertEquals("<input type=\"text\" id=\"spouses0.name\" name=\"spouses[0].name\" value=\"Fred\" >", tokens[i + 1]); //
|
||||
if (tokens[i].equals("FORM2")) assertEquals("<textarea id=\"spouses0.name\" name=\"spouses[0].name\" >", tokens[i + 1]);
|
||||
if (tokens[i].equals("FORM2")) assertEquals("Fred</textarea>", tokens[i + 2]);
|
||||
if (tokens[i].equals("FORM3")) assertEquals("<select id=\"spouses0.name\" name=\"spouses[0].name\" >", tokens[i + 1]);
|
||||
if (tokens[i].equals("FORM4")) assertEquals("<select multiple=\"multiple\" id=\"spouses\" name=\"spouses\" >", tokens[i + 1]);
|
||||
if (tokens[i].equals("FORM5")) assertEquals("<input type=\"radio\" name=\"spouses[0].name\" value=\"Darren\"", tokens[i + 1]);
|
||||
if (tokens[i].equals("FORM6")) assertEquals("<input type=\"password\" id=\"spouses0.name\" name=\"spouses[0].name\" value=\"\" >", tokens[i + 1]);
|
||||
if (tokens[i].equals("FORM7")) assertEquals("<input type=\"hidden\" id=\"spouses0.name\" name=\"spouses[0].name\" value=\"Fred\" >", tokens[i + 1]);
|
||||
if (tokens[i].equals("FORM8")) assertEquals("<input type=\"hidden\" name=\"_spouses0.name\" value=\"on\"/>", tokens[i + 1]);
|
||||
if (tokens[i].equals("FORM8")) assertEquals("<input type=\"checkbox\" id=\"spouses0.name\" name=\"spouses[0].name\" />", tokens[i + 2]);
|
||||
if (tokens[i].equals("FORM9")) assertEquals("<input type=\"hidden\" name=\"_spouses0.jedi\" value=\"on\"/>", tokens[i + 1]);
|
||||
if (tokens[i].equals("FORM9")) assertEquals("<input type=\"checkbox\" id=\"spouses0.jedi\" name=\"spouses[0].jedi\" checked=\"checked\" />", tokens[i + 2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.velocity;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.velocity.Template;
|
||||
import org.apache.velocity.app.VelocityEngine;
|
||||
import org.apache.velocity.exception.MethodInvocationException;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.TypeSafeMatcher;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.test.MockServletContext;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
import org.springframework.web.context.support.StaticWebApplicationContext;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
|
||||
import org.springframework.web.servlet.theme.FixedThemeResolver;
|
||||
import org.springframework.web.util.NestedServletException;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class VelocityRenderTests {
|
||||
|
||||
private StaticWebApplicationContext wac;
|
||||
|
||||
private MockHttpServletRequest request;
|
||||
|
||||
private MockHttpServletResponse response;
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
wac = new StaticWebApplicationContext();
|
||||
wac.setServletContext(new MockServletContext());
|
||||
|
||||
final Template expectedTemplate = new Template();
|
||||
VelocityConfig vc = new VelocityConfig() {
|
||||
@Override
|
||||
public VelocityEngine getVelocityEngine() {
|
||||
return new TestVelocityEngine("test.vm", expectedTemplate);
|
||||
}
|
||||
};
|
||||
wac.getDefaultListableBeanFactory().registerSingleton("velocityConfigurer", vc);
|
||||
wac.refresh();
|
||||
|
||||
request = new MockHttpServletRequest();
|
||||
request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
|
||||
request.setAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE, new AcceptHeaderLocaleResolver());
|
||||
request.setAttribute(DispatcherServlet.THEME_RESOLVER_ATTRIBUTE, new FixedThemeResolver());
|
||||
response = new MockHttpServletResponse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleRender() throws Exception {
|
||||
|
||||
VelocityConfigurer vc = new VelocityConfigurer();
|
||||
vc.setPreferFileSystemAccess(false);
|
||||
VelocityEngine ve = vc.createVelocityEngine();
|
||||
|
||||
VelocityView view = new VelocityView();
|
||||
view.setBeanName("myView");
|
||||
view.setUrl("org/springframework/web/servlet/view/velocity/simple.vm");
|
||||
view.setVelocityEngine(ve);
|
||||
view.setApplicationContext(wac);
|
||||
|
||||
|
||||
Map<String,Object> model = new HashMap<String,Object>();
|
||||
model.put("command", new TestBean("juergen", 99));
|
||||
view.render(model, request, response);
|
||||
assertEquals("\nNAME\njuergen\n", response.getContentAsString().replace("\r\n", "\n"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore // This works with Velocity 1.6.2
|
||||
public void testSimpleRenderWithError() throws Exception {
|
||||
|
||||
thrown.expect(NestedServletException.class);
|
||||
|
||||
thrown.expect(new TypeSafeMatcher<Exception>() {
|
||||
@Override
|
||||
public boolean matchesSafely(Exception item) {
|
||||
return item.getCause() instanceof MethodInvocationException;
|
||||
}
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("exception has cause of MethodInvocationException");
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
VelocityConfigurer vc = new VelocityConfigurer();
|
||||
vc.setPreferFileSystemAccess(false);
|
||||
vc.setVelocityPropertiesMap(Collections.<String,Object>singletonMap("runtime.references.strict", "true"));
|
||||
VelocityEngine ve = vc.createVelocityEngine();
|
||||
|
||||
VelocityView view = new VelocityView();
|
||||
view.setBeanName("myView");
|
||||
view.setUrl("org/springframework/web/servlet/view/velocity/error.vm");
|
||||
view.setVelocityEngine(ve);
|
||||
view.setApplicationContext(wac);
|
||||
|
||||
Map<String,Object> model = new HashMap<String,Object>();
|
||||
model.put("command", new TestBean("juergen", 99));
|
||||
view.render(model, request, response);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleRenderWithIOError() throws Exception {
|
||||
|
||||
thrown.expect(NestedServletException.class);
|
||||
|
||||
thrown.expect(new TypeSafeMatcher<Exception>() {
|
||||
@Override
|
||||
public boolean matchesSafely(Exception item) {
|
||||
return item.getCause() instanceof IOException;
|
||||
}
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("exception has cause of IOException");
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
VelocityConfigurer vc = new VelocityConfigurer();
|
||||
vc.setPreferFileSystemAccess(false);
|
||||
vc.setVelocityPropertiesMap(Collections.<String,Object>singletonMap("runtime.references.strict", "true"));
|
||||
VelocityEngine ve = vc.createVelocityEngine();
|
||||
|
||||
VelocityView view = new VelocityView();
|
||||
view.setBeanName("myView");
|
||||
view.setUrl("org/springframework/web/servlet/view/velocity/ioerror.vm");
|
||||
view.setVelocityEngine(ve);
|
||||
view.setApplicationContext(wac);
|
||||
|
||||
Map<String,Object> model = new HashMap<String,Object>();
|
||||
model.put("command", new TestBean("juergen", 99));
|
||||
view.render(model, request, response);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
package org.springframework.web.servlet.view.velocity;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.velocity.Template;
|
||||
import org.apache.velocity.app.VelocityEngine;
|
||||
import org.apache.velocity.context.Context;
|
||||
import org.apache.velocity.tools.generic.DateTool;
|
||||
import org.apache.velocity.tools.generic.MathTool;
|
||||
import org.apache.velocity.tools.view.context.ChainedContext;
|
||||
import org.apache.velocity.tools.view.tools.LinkTool;
|
||||
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 static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class VelocityToolboxViewTests {
|
||||
|
||||
@Test
|
||||
public void testVelocityToolboxView() throws Exception {
|
||||
final String templateName = "test.vm";
|
||||
|
||||
StaticWebApplicationContext wac = new StaticWebApplicationContext();
|
||||
wac.setServletContext(new MockServletContext());
|
||||
final Template expectedTemplate = new Template();
|
||||
VelocityConfig vc = new VelocityConfig() {
|
||||
@Override
|
||||
public VelocityEngine getVelocityEngine() {
|
||||
return new TestVelocityEngine(templateName, expectedTemplate);
|
||||
}
|
||||
};
|
||||
wac.getDefaultListableBeanFactory().registerSingleton("velocityConfigurer", vc);
|
||||
|
||||
final HttpServletRequest expectedRequest = new MockHttpServletRequest();
|
||||
final HttpServletResponse expectedResponse = new MockHttpServletResponse();
|
||||
|
||||
VelocityToolboxView vv = new VelocityToolboxView() {
|
||||
@Override
|
||||
protected void mergeTemplate(Template template, Context context, HttpServletResponse response) throws Exception {
|
||||
assertTrue(template == expectedTemplate);
|
||||
assertTrue(response == expectedResponse);
|
||||
assertTrue(context instanceof ChainedContext);
|
||||
|
||||
assertEquals("this is foo.", context.get("foo"));
|
||||
assertTrue(context.get("map") instanceof HashMap<?,?>);
|
||||
assertTrue(context.get("date") instanceof DateTool);
|
||||
assertTrue(context.get("math") instanceof MathTool);
|
||||
|
||||
assertTrue(context.get("link") instanceof LinkTool);
|
||||
LinkTool linkTool = (LinkTool) context.get("link");
|
||||
assertNotNull(linkTool.getContextURL());
|
||||
|
||||
assertTrue(context.get("link2") instanceof LinkTool);
|
||||
LinkTool linkTool2 = (LinkTool) context.get("link2");
|
||||
assertNotNull(linkTool2.getContextURL());
|
||||
}
|
||||
};
|
||||
|
||||
vv.setUrl(templateName);
|
||||
vv.setApplicationContext(wac);
|
||||
Map<String, Class<?>> toolAttributes = new HashMap<String, Class<?>>();
|
||||
toolAttributes.put("math", MathTool.class);
|
||||
toolAttributes.put("link2", LinkTool.class);
|
||||
vv.setToolAttributes(toolAttributes);
|
||||
vv.setToolboxConfigLocation("org/springframework/web/servlet/view/velocity/toolbox.xml");
|
||||
vv.setExposeSpringMacroHelpers(false);
|
||||
|
||||
vv.render(new HashMap<String,Object>(), expectedRequest, expectedResponse);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
package org.springframework.web.servlet.view.velocity;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.velocity.Template;
|
||||
import org.apache.velocity.app.VelocityEngine;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.web.context.support.StaticWebApplicationContext;
|
||||
import org.springframework.web.servlet.View;
|
||||
import org.springframework.web.servlet.view.InternalResourceView;
|
||||
import org.springframework.web.servlet.view.RedirectView;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class VelocityViewResolverTests {
|
||||
|
||||
@Test
|
||||
public void testVelocityViewResolver() throws Exception {
|
||||
VelocityConfig vc = new VelocityConfig() {
|
||||
@Override
|
||||
public VelocityEngine getVelocityEngine() {
|
||||
return new TestVelocityEngine("prefix_test_suffix", new Template());
|
||||
}
|
||||
};
|
||||
|
||||
StaticWebApplicationContext wac = new StaticWebApplicationContext();
|
||||
wac.getBeanFactory().registerSingleton("configurer", vc);
|
||||
wac.refresh();
|
||||
|
||||
VelocityViewResolver vr = new VelocityViewResolver();
|
||||
vr.setPrefix("prefix_");
|
||||
vr.setSuffix("_suffix");
|
||||
vr.setApplicationContext(wac);
|
||||
|
||||
View view = vr.resolveViewName("test", Locale.CANADA);
|
||||
assertEquals("Correct view class", VelocityView.class, view.getClass());
|
||||
assertEquals("Correct URL", "prefix_test_suffix", ((VelocityView) view).getUrl());
|
||||
|
||||
view = vr.resolveViewName("non-existing", Locale.CANADA);
|
||||
assertNull(view);
|
||||
|
||||
view = vr.resolveViewName("redirect:myUrl", Locale.getDefault());
|
||||
assertEquals("Correct view class", RedirectView.class, view.getClass());
|
||||
assertEquals("Correct URL", "myUrl", ((RedirectView) view).getUrl());
|
||||
|
||||
view = vr.resolveViewName("forward:myUrl", Locale.getDefault());
|
||||
assertEquals("Correct view class", InternalResourceView.class, view.getClass());
|
||||
assertEquals("Correct URL", "myUrl", ((InternalResourceView) view).getUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVelocityViewResolverWithToolbox() throws Exception {
|
||||
VelocityConfig vc = new VelocityConfig() {
|
||||
@Override
|
||||
public VelocityEngine getVelocityEngine() {
|
||||
return new TestVelocityEngine("prefix_test_suffix", new Template());
|
||||
}
|
||||
};
|
||||
|
||||
StaticWebApplicationContext wac = new StaticWebApplicationContext();
|
||||
wac.getBeanFactory().registerSingleton("configurer", vc);
|
||||
wac.refresh();
|
||||
|
||||
String toolbox = "org/springframework/web/servlet/view/velocity/toolbox.xml";
|
||||
|
||||
VelocityViewResolver vr = new VelocityViewResolver();
|
||||
vr.setPrefix("prefix_");
|
||||
vr.setSuffix("_suffix");
|
||||
vr.setToolboxConfigLocation(toolbox);
|
||||
vr.setApplicationContext(wac);
|
||||
|
||||
View view = vr.resolveViewName("test", Locale.CANADA);
|
||||
assertEquals("Correct view class", VelocityToolboxView.class, view.getClass());
|
||||
assertEquals("Correct URL", "prefix_test_suffix", ((VelocityView) view).getUrl());
|
||||
assertEquals("Correct toolbox", toolbox, ((VelocityToolboxView) view).getToolboxConfigLocation());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVelocityViewResolverWithToolboxSubclass() throws Exception {
|
||||
VelocityConfig vc = new VelocityConfig() {
|
||||
@Override
|
||||
public VelocityEngine getVelocityEngine() {
|
||||
TestVelocityEngine ve = new TestVelocityEngine();
|
||||
ve.addTemplate("prefix_test_suffix", new Template());
|
||||
ve.addTemplate(VelocityLayoutView.DEFAULT_LAYOUT_URL, new Template());
|
||||
return ve;
|
||||
}
|
||||
};
|
||||
|
||||
StaticWebApplicationContext wac = new StaticWebApplicationContext();
|
||||
wac.getBeanFactory().registerSingleton("configurer", vc);
|
||||
wac.refresh();
|
||||
|
||||
String toolbox = "org/springframework/web/servlet/view/velocity/toolbox.xml";
|
||||
|
||||
VelocityViewResolver vr = new VelocityViewResolver();
|
||||
vr.setViewClass(VelocityLayoutView.class);
|
||||
vr.setPrefix("prefix_");
|
||||
vr.setSuffix("_suffix");
|
||||
vr.setToolboxConfigLocation(toolbox);
|
||||
vr.setApplicationContext(wac);
|
||||
|
||||
View view = vr.resolveViewName("test", Locale.CANADA);
|
||||
assertEquals("Correct view class", VelocityLayoutView.class, view.getClass());
|
||||
assertEquals("Correct URL", "prefix_test_suffix", ((VelocityView) view).getUrl());
|
||||
assertEquals("Correct toolbox", toolbox, ((VelocityToolboxView) view).getToolboxConfigLocation());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVelocityLayoutViewResolver() throws Exception {
|
||||
VelocityConfig vc = new VelocityConfig() {
|
||||
@Override
|
||||
public VelocityEngine getVelocityEngine() {
|
||||
TestVelocityEngine ve = new TestVelocityEngine();
|
||||
ve.addTemplate("prefix_test_suffix", new Template());
|
||||
ve.addTemplate("myLayoutUrl", new Template());
|
||||
return ve;
|
||||
}
|
||||
};
|
||||
|
||||
StaticWebApplicationContext wac = new StaticWebApplicationContext();
|
||||
wac.getBeanFactory().registerSingleton("configurer", vc);
|
||||
wac.refresh();
|
||||
|
||||
VelocityLayoutViewResolver vr = new VelocityLayoutViewResolver();
|
||||
vr.setPrefix("prefix_");
|
||||
vr.setSuffix("_suffix");
|
||||
vr.setLayoutUrl("myLayoutUrl");
|
||||
vr.setLayoutKey("myLayoutKey");
|
||||
vr.setScreenContentKey("myScreenContentKey");
|
||||
vr.setApplicationContext(wac);
|
||||
|
||||
View view = vr.resolveViewName("test", Locale.CANADA);
|
||||
assertEquals("Correct view class", VelocityLayoutView.class, view.getClass());
|
||||
assertEquals("Correct URL", "prefix_test_suffix", ((VelocityView) view).getUrl());
|
||||
// TODO: Need to test actual VelocityLayoutView properties and their functionality!
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,280 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.velocity;
|
||||
|
||||
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;
|
||||
|
||||
import org.apache.velocity.Template;
|
||||
import org.apache.velocity.app.VelocityEngine;
|
||||
import org.apache.velocity.context.Context;
|
||||
import org.apache.velocity.exception.MethodInvocationException;
|
||||
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.junit.Test;
|
||||
|
||||
import org.springframework.context.ApplicationContextException;
|
||||
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.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.support.RequestDataValueProcessor;
|
||||
import org.springframework.web.servlet.view.AbstractView;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.BDDMockito.*;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class VelocityViewTests {
|
||||
|
||||
@Test
|
||||
public void testNoVelocityConfig() throws Exception {
|
||||
VelocityView vv = new VelocityView();
|
||||
WebApplicationContext wac = mock(WebApplicationContext.class);
|
||||
given(wac.getBeansOfType(VelocityConfig.class, true, false)).willReturn(new HashMap<String, VelocityConfig>());
|
||||
|
||||
vv.setUrl("anythingButNull");
|
||||
try {
|
||||
vv.setApplicationContext(wac);
|
||||
fail();
|
||||
}
|
||||
catch (ApplicationContextException ex) {
|
||||
// Check there's a helpful error message
|
||||
assertTrue(ex.getMessage().contains("VelocityConfig"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoTemplateName() throws Exception {
|
||||
VelocityView vv = new VelocityView();
|
||||
try {
|
||||
vv.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// Check there's a helpful error message
|
||||
assertTrue(ex.getMessage().indexOf("url") != -1);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergeTemplateSucceeds() throws Exception {
|
||||
testValidTemplateName(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergeTemplateFailureWithIOException() throws Exception {
|
||||
testValidTemplateName(new IOException());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergeTemplateFailureWithParseErrorException() throws Exception {
|
||||
testValidTemplateName(new ParseErrorException(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergeTemplateFailureWithUnspecifiedException() throws Exception {
|
||||
testValidTemplateName(new Exception(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergeTemplateFailureWithMethodInvocationException() throws Exception {
|
||||
testValidTemplateName(new MethodInvocationException("Bad template", null, "none", "foo.vm", 1, 100));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mergeTemplateFailureException may be null in which case mergeTemplate override will succeed.
|
||||
* If it's non null it will be checked
|
||||
*/
|
||||
private void testValidTemplateName(final Exception mergeTemplateFailureException) throws Exception {
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
model.put("foo", "bar");
|
||||
|
||||
final String templateName = "test.vm";
|
||||
|
||||
WebApplicationContext wac = mock(WebApplicationContext.class);
|
||||
MockServletContext sc = new MockServletContext();
|
||||
sc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
|
||||
|
||||
final Template expectedTemplate = new Template();
|
||||
VelocityConfig vc = new VelocityConfig() {
|
||||
@Override
|
||||
public VelocityEngine getVelocityEngine() {
|
||||
return new TestVelocityEngine(templateName, expectedTemplate);
|
||||
}
|
||||
};
|
||||
Map<String, VelocityConfig> configurers = new HashMap<String, VelocityConfig>();
|
||||
configurers.put("velocityConfigurer", vc);
|
||||
given(wac.getBeansOfType(VelocityConfig.class, true, false)).willReturn(configurers);
|
||||
given(wac.getServletContext()).willReturn(sc);
|
||||
given(wac.getBean("requestDataValueProcessor",
|
||||
RequestDataValueProcessor.class)).willReturn(null);
|
||||
|
||||
HttpServletRequest request = new MockHttpServletRequest();
|
||||
final HttpServletResponse expectedResponse = new MockHttpServletResponse();
|
||||
|
||||
VelocityView vv = new VelocityView() {
|
||||
@Override
|
||||
protected void mergeTemplate(Template template, Context context, HttpServletResponse response) throws Exception {
|
||||
assertTrue(template == expectedTemplate);
|
||||
assertTrue(context.getKeys().length >= 1);
|
||||
assertTrue(context.get("foo").equals("bar"));
|
||||
assertTrue(response == expectedResponse);
|
||||
if (mergeTemplateFailureException != null) {
|
||||
throw mergeTemplateFailureException;
|
||||
}
|
||||
}
|
||||
};
|
||||
vv.setUrl(templateName);
|
||||
vv.setApplicationContext(wac);
|
||||
|
||||
try {
|
||||
vv.render(model, request, expectedResponse);
|
||||
if (mergeTemplateFailureException != null) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
assertNotNull(mergeTemplateFailureException);
|
||||
assertEquals(ex, mergeTemplateFailureException);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeepExistingContentType() throws Exception {
|
||||
final String templateName = "test.vm";
|
||||
|
||||
WebApplicationContext wac = mock(WebApplicationContext.class);
|
||||
MockServletContext sc = new MockServletContext();
|
||||
sc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
|
||||
|
||||
final Template expectedTemplate = new Template();
|
||||
VelocityConfig vc = new VelocityConfig() {
|
||||
@Override
|
||||
public VelocityEngine getVelocityEngine() {
|
||||
return new TestVelocityEngine(templateName, expectedTemplate);
|
||||
}
|
||||
};
|
||||
Map<String, VelocityConfig> configurers = new HashMap<String, VelocityConfig>();
|
||||
configurers.put("velocityConfigurer", vc);
|
||||
given(wac.getBeansOfType(VelocityConfig.class, true, false)).willReturn(configurers);
|
||||
given(wac.getServletContext()).willReturn(sc);
|
||||
given(wac.getBean("requestDataValueProcessor",
|
||||
RequestDataValueProcessor.class)).willReturn(null);
|
||||
|
||||
HttpServletRequest request = new MockHttpServletRequest();
|
||||
final HttpServletResponse expectedResponse = new MockHttpServletResponse();
|
||||
expectedResponse.setContentType("myContentType");
|
||||
|
||||
VelocityView vv = new VelocityView() {
|
||||
@Override
|
||||
protected void mergeTemplate(Template template, Context context, HttpServletResponse response) {
|
||||
assertTrue(template == expectedTemplate);
|
||||
assertTrue(response == expectedResponse);
|
||||
}
|
||||
@Override
|
||||
protected void exposeHelpers(Map<String, Object> model, HttpServletRequest request) throws Exception {
|
||||
model.put("myHelper", "myValue");
|
||||
}
|
||||
};
|
||||
|
||||
vv.setUrl(templateName);
|
||||
vv.setApplicationContext(wac);
|
||||
vv.render(new HashMap<String, Object>(), request, expectedResponse);
|
||||
|
||||
assertEquals("myContentType", expectedResponse.getContentType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExposeHelpers() throws Exception {
|
||||
final String templateName = "test.vm";
|
||||
|
||||
WebApplicationContext wac = mock(WebApplicationContext.class);
|
||||
given(wac.getServletContext()).willReturn(new MockServletContext());
|
||||
|
||||
final Template expectedTemplate = new Template();
|
||||
VelocityConfig vc = new VelocityConfig() {
|
||||
@Override
|
||||
public VelocityEngine getVelocityEngine() {
|
||||
return new TestVelocityEngine(templateName, expectedTemplate);
|
||||
}
|
||||
};
|
||||
Map<String, VelocityConfig> configurers = new HashMap<String, VelocityConfig>();
|
||||
configurers.put("velocityConfigurer", vc);
|
||||
given(wac.getBeansOfType(VelocityConfig.class, true, false)).willReturn(configurers);
|
||||
|
||||
|
||||
// let it ask for locale
|
||||
HttpServletRequest req = mock(HttpServletRequest.class);
|
||||
given(req.getAttribute(View.PATH_VARIABLES)).willReturn(null);
|
||||
given(req.getAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE)).willReturn(new AcceptHeaderLocaleResolver());
|
||||
given(req.getLocale()).willReturn(Locale.CANADA);
|
||||
|
||||
final HttpServletResponse expectedResponse = new MockHttpServletResponse();
|
||||
|
||||
VelocityView vv = new VelocityView() {
|
||||
@Override
|
||||
protected void mergeTemplate(Template template, Context context, HttpServletResponse response) throws Exception {
|
||||
assertTrue(template == expectedTemplate);
|
||||
assertTrue(response == expectedResponse);
|
||||
|
||||
assertEquals("myValue", context.get("myHelper"));
|
||||
assertTrue(context.get("math") instanceof MathTool);
|
||||
|
||||
assertTrue(context.get("dateTool") instanceof DateTool);
|
||||
DateTool dateTool = (DateTool) context.get("dateTool");
|
||||
assertTrue(dateTool.getLocale().equals(Locale.CANADA));
|
||||
|
||||
assertTrue(context.get("numberTool") instanceof NumberTool);
|
||||
NumberTool numberTool = (NumberTool) context.get("numberTool");
|
||||
assertTrue(numberTool.getLocale().equals(Locale.CANADA));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void exposeHelpers(Map<String, Object> model, HttpServletRequest request) throws Exception {
|
||||
model.put("myHelper", "myValue");
|
||||
}
|
||||
};
|
||||
|
||||
vv.setUrl(templateName);
|
||||
vv.setApplicationContext(wac);
|
||||
Map<String, Class<?>> toolAttributes = new HashMap<String, Class<?>>();
|
||||
toolAttributes.put("math", MathTool.class);
|
||||
vv.setToolAttributes(toolAttributes);
|
||||
vv.setDateToolAttribute("dateTool");
|
||||
vv.setNumberToolAttribute("numberTool");
|
||||
vv.setExposeSpringMacroHelpers(false);
|
||||
|
||||
vv.render(new HashMap<String, Object>(), req, expectedResponse);
|
||||
|
||||
assertEquals(AbstractView.DEFAULT_CONTENT_TYPE, expectedResponse.getContentType());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,8 +3,8 @@
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
|
||||
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
|
||||
|
||||
<!--
|
||||
View resolution finds the ContentNegotiationManager created by or
|
||||
@@ -23,7 +23,6 @@
|
||||
<mvc:jsp/>
|
||||
<mvc:tiles/>
|
||||
<mvc:freemarker/>
|
||||
<mvc:velocity/>
|
||||
<mvc:groovy/>
|
||||
<mvc:script-template/>
|
||||
</mvc:view-resolvers>
|
||||
@@ -36,8 +35,6 @@
|
||||
<mvc:template-loader-path location="/org/springframework/web/servlet/view"/>
|
||||
</mvc:freemarker-configurer>
|
||||
|
||||
<mvc:velocity-configurer resource-loader-path="/org/springframework/web/servlet/view"/>
|
||||
|
||||
<mvc:groovy-configurer/>
|
||||
|
||||
<mvc:script-template-configurer engine-name="nashorn" render-function="render"/>
|
||||
|
||||
@@ -2,15 +2,14 @@
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
|
||||
|
||||
<mvc:view-resolvers>
|
||||
<mvc:bean-name/>
|
||||
<mvc:jsp view-class="org.springframework.web.servlet.view.InternalResourceView"/>
|
||||
<mvc:tiles/>
|
||||
<mvc:freemarker prefix="freemarker-" suffix=".freemarker" view-names="my*,*Report"/>
|
||||
<mvc:velocity cache-views="false"/>
|
||||
<mvc:groovy/>
|
||||
<mvc:script-template/>
|
||||
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"/>
|
||||
@@ -31,8 +30,6 @@
|
||||
<mvc:template-loader-path location="/test"/>
|
||||
</mvc:freemarker-configurer>
|
||||
|
||||
<mvc:velocity-configurer resource-loader-path="/test"/>
|
||||
|
||||
<mvc:groovy-configurer resource-loader-path="/test" cache-templates="false" auto-indent="true"/>
|
||||
|
||||
<mvc:script-template-configurer engine-name="nashorn" render-function="render" content-type="text/plain"
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
##
|
||||
## test template for Velocity view with missing method
|
||||
##
|
||||
$command.nonexistent()
|
||||
@@ -1,4 +0,0 @@
|
||||
##
|
||||
## test template for Velocity view with exception
|
||||
##
|
||||
$command.unreliableFileOperation()
|
||||
@@ -1,6 +0,0 @@
|
||||
##
|
||||
## test template for Velocity view
|
||||
##
|
||||
|
||||
NAME
|
||||
$command.name
|
||||
@@ -1,30 +0,0 @@
|
||||
##
|
||||
## test template for Velocity macro test class
|
||||
##
|
||||
|
||||
FORM1
|
||||
#springFormInput("command.spouses[0].name" "")
|
||||
|
||||
FORM2
|
||||
#springFormTextarea("command.spouses[0].name" "")
|
||||
|
||||
FORM3
|
||||
#springFormSingleSelect("command.spouses[0].name" $nameOptionMap "")
|
||||
|
||||
FORM4
|
||||
#springFormMultiSelect("command.spouses" $nameOptionMap "")
|
||||
|
||||
FORM5
|
||||
#springFormRadioButtons("command.spouses[0].name" $nameOptionMap " " "")
|
||||
|
||||
FORM6
|
||||
#springFormPasswordInput("command.spouses[0].name" "")
|
||||
|
||||
FORM7
|
||||
#springFormHiddenInput("command.spouses[0].name" "")
|
||||
|
||||
FORM8
|
||||
#springFormCheckbox("command.spouses[0].name" "")
|
||||
|
||||
FORM9
|
||||
#springFormCheckbox("command.spouses[0].jedi" "")
|
||||
@@ -1,64 +0,0 @@
|
||||
##
|
||||
## test template for Velocity macro test class
|
||||
##
|
||||
|
||||
NAME
|
||||
$command.name
|
||||
|
||||
AGE
|
||||
$command.age
|
||||
|
||||
MESSAGE
|
||||
#springMessage("hello") #springMessage("world")
|
||||
|
||||
DEFAULTMESSAGE
|
||||
#springMessageText("no.such.code" "hi") #springMessageText("no.such.code" "planet")
|
||||
|
||||
THEME
|
||||
#springTheme("hello") #springTheme("world")
|
||||
|
||||
DEFAULTTHEME
|
||||
#springThemeText("no.such.code" "hi!") #springThemeText("no.such.code" "planet!")
|
||||
|
||||
URL
|
||||
#springUrl("/aftercontext.html")
|
||||
|
||||
FORM1
|
||||
#springFormInput("command.name" "")
|
||||
|
||||
FORM2
|
||||
#springFormInput("command.name" 'class="myCssClass"')
|
||||
|
||||
FORM3
|
||||
#springFormTextarea("command.name" "")
|
||||
|
||||
FORM4
|
||||
#springFormTextarea("command.name" "rows=10 cols=30")
|
||||
|
||||
FORM5
|
||||
#springFormSingleSelect("command.name" $nameOptionMap "")
|
||||
|
||||
FORM6
|
||||
#springFormMultiSelect("command.spouses" $nameOptionMap "")
|
||||
|
||||
FORM7
|
||||
#springFormRadioButtons("command.name" $nameOptionMap " " "")
|
||||
|
||||
FORM8
|
||||
#springFormCheckboxes("command.stringArray" $nameOptionMap " " "")
|
||||
|
||||
FORM9
|
||||
#springFormPasswordInput("command.name" "")
|
||||
|
||||
FORM10
|
||||
#springFormHiddenInput("command.name" "")
|
||||
|
||||
FORM15
|
||||
#springFormCheckbox("command.name" "")
|
||||
|
||||
FORM16
|
||||
#springFormCheckbox("command.jedi" "")
|
||||
|
||||
|
||||
ERRORS
|
||||
#springShowErrors(" " "")
|
||||
@@ -1,23 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<toolbox>
|
||||
<xhtml>true</xhtml>
|
||||
<data type="string">
|
||||
<key>foo</key>
|
||||
<value>this is foo.</value>
|
||||
</data>
|
||||
<tool>
|
||||
<key>map</key>
|
||||
<class>java.util.HashMap</class>
|
||||
</tool>
|
||||
<tool>
|
||||
<key>date</key>
|
||||
<scope>application</scope>
|
||||
<class>org.apache.velocity.tools.generic.DateTool</class>
|
||||
</tool>
|
||||
<tool>
|
||||
<key>link</key>
|
||||
<scope>request</scope>
|
||||
<class>org.apache.velocity.tools.view.tools.LinkTool</class>
|
||||
</tool>
|
||||
</toolbox>
|
||||
@@ -154,7 +154,7 @@
|
||||
x="11.15" dy="1.2em" class="st8">data to the domain </tspan><tspan x="27.83" dy="1.2em" class="st8">model</tspan></text> </g>
|
||||
<g id="shape13-48" v:mID="13" v:groupContext="shape" transform="translate(263.76,-211.679)">
|
||||
<title>Box.13</title>
|
||||
<desc>Integration with JSP, Velocity, XSLT, PDF, Excel</desc>
|
||||
<desc>Integration with JSP, FreeMarker, XSLT, PDF, Excel</desc>
|
||||
<v:userDefs>
|
||||
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
|
||||
</v:userDefs>
|
||||
@@ -166,7 +166,7 @@
|
||||
</g>
|
||||
<rect x="0" y="214.421" width="72" height="44.7771" class="st6"/>
|
||||
<text x="8.49" y="231.41" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Integration with JSP, <tspan
|
||||
x="7.83" dy="1.2em" class="st8">Velocity</tspan>, XSLT, PDF, <tspan x="28.66" dy="1.2em" class="st8">Excel</tspan></text> </g>
|
||||
x="7.83" dy="1.2em" class="st8">FreeMarker</tspan>, XSLT, PDF, <tspan x="28.66" dy="1.2em" class="st8">Excel</tspan></text> </g>
|
||||
<g id="shape15-55" v:mID="15" v:groupContext="shape" transform="translate(16.44,-112.319)">
|
||||
<title>Box.15</title>
|
||||
<desc>Spring Context</desc>
|
||||
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@@ -128,7 +128,7 @@
|
||||
{\colortbl;\red255\green255\blue255;}
|
||||
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
|
||||
|
||||
\f0\i\b\fs28 \cf0 Integration with JSP, Velocity, SLT. PDF, Excel}</string>
|
||||
\f0\i\b\fs28 \cf0 Integration with JSP, FreeMarker, XSLT, PDF, Excel}</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
|
||||
@@ -160,7 +160,7 @@
|
||||
x="-78.63" dy="1.2em" class="st4">WebWork<v:newlineChar/></tspan><tspan x="-76.14" dy="1.2em"
|
||||
class="st4">Tapestry<v:newlineChar/></tspan><tspan x="-65.57" dy="1.2em" class="st4">JSF<v:newlineChar/></tspan><tspan
|
||||
x="-97.82" dy="1.2em" class="st4">Rich View Support<v:newlineChar/></tspan><tspan x="-68.36" dy="1.2em"
|
||||
class="st4">JSPs<v:newlineChar/></tspan><tspan x="-74.19" dy="1.2em" class="st4">Velocity<v:newlineChar/></tspan><tspan
|
||||
class="st4">JSPs<v:newlineChar/></tspan><tspan x="-74.19" dy="1.2em" class="st4">FreeMarker<v:newlineChar/></tspan><tspan
|
||||
x="-82.52" dy="1.2em" class="st4">FreeMarker<v:newlineChar/></tspan><tspan x="-66.69" dy="1.2em"
|
||||
class="st4">PDF<v:newlineChar/></tspan><tspan x="-90.59" dy="1.2em" class="st4">Jasper Reports<v:newlineChar/></tspan><tspan
|
||||
x="-68.91" dy="1.2em" class="st4">Excel<v:newlineChar/></tspan><tspan x="-99.48" dy="1.2em" class="st4">Spring Portlet MVC</tspan></text> </g>
|
||||
@@ -190,9 +190,7 @@
|
||||
<v:textRect cx="53.8583" cy="749.764" width="107.72" height="184.252"/>
|
||||
<text x="-88.86" y="717.96" transform="scale(-1,1)" class="st3" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>ORM<v:newlineChar/><v:newlineChar/><tspan
|
||||
x="-75.55" dy="2.76em" class="st4">Hibernate<v:newlineChar/></tspan><tspan x="-63.04" dy="1.2em"
|
||||
class="st4">JPA<v:newlineChar/></tspan><tspan x="-71.65" dy="1.2em" class="st4">TopLink<v:newlineChar/></tspan><tspan
|
||||
x="-63.87" dy="1.2em" class="st4">JDO<v:newlineChar/></tspan><tspan x="-63.59" dy="1.2em" class="st4">OJB<v:newlineChar/></tspan><tspan
|
||||
x="-66.09" dy="1.2em" class="st4">iBatis</tspan></text> </g>
|
||||
class="st4">JPA<v:newlineChar/></tspan></g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 11 KiB |
@@ -6043,124 +6043,11 @@ of your emails using the above approach for a number of reasons.
|
||||
recompiling, redeploying...
|
||||
|
||||
Typically the approach taken to address these issues is to use a template library such
|
||||
as FreeMarker or Velocity to define the display structure of email content. This leaves
|
||||
your code tasked only with creating the data that is to be rendered in the email
|
||||
template and sending the email. It is definitely a best practice for when the content of
|
||||
your emails becomes even moderately complex, and with the Spring Framework's support
|
||||
classes for FreeMarker and Velocity becomes quite easy to do. Find below an example of
|
||||
using the Velocity template library to create email content.
|
||||
|
||||
|
||||
[[mail-templates-example]]
|
||||
===== A Velocity-based example
|
||||
To use http://velocity.apache.org[Velocity] to create your email template(s), you will
|
||||
need to have the Velocity libraries available on your classpath. You will also need to
|
||||
create one or more Velocity templates for the email content that your application needs.
|
||||
Find below the Velocity template that this example will be using. As you can see it is
|
||||
HTML-based, and since it is plain text it can be created using your favorite HTML or
|
||||
text editor.
|
||||
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
# in the com/foo/package
|
||||
<html>
|
||||
<body>
|
||||
<h3>Hi ${user.userName}, welcome to the Chipping Sodbury On-the-Hill message boards!</h3>
|
||||
|
||||
<div>
|
||||
Your email address is <a href="mailto:${user.emailAddress}">${user.emailAddress}</a>.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
----
|
||||
|
||||
Find below some simple code and Spring XML configuration that makes use of the above
|
||||
Velocity template to create email content and send email(s).
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
package com.foo;
|
||||
|
||||
import org.apache.velocity.app.VelocityEngine;
|
||||
import org.springframework.mail.javamail.JavaMailSender;
|
||||
import org.springframework.mail.javamail.MimeMessageHelper;
|
||||
import org.springframework.mail.javamail.MimeMessagePreparator;
|
||||
import org.springframework.ui.velocity.VelocityEngineUtils;
|
||||
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class SimpleRegistrationService implements RegistrationService {
|
||||
|
||||
private JavaMailSender mailSender;
|
||||
private VelocityEngine velocityEngine;
|
||||
|
||||
public void setMailSender(JavaMailSender mailSender) {
|
||||
this.mailSender = mailSender;
|
||||
}
|
||||
|
||||
public void setVelocityEngine(VelocityEngine velocityEngine) {
|
||||
this.velocityEngine = velocityEngine;
|
||||
}
|
||||
|
||||
public void register(User user) {
|
||||
|
||||
// Do the registration logic...
|
||||
|
||||
sendConfirmationEmail(user);
|
||||
}
|
||||
|
||||
private void sendConfirmationEmail(final User user) {
|
||||
MimeMessagePreparator preparator = new MimeMessagePreparator() {
|
||||
public void prepare(MimeMessage mimeMessage) throws Exception {
|
||||
MimeMessageHelper message = new MimeMessageHelper(mimeMessage);
|
||||
message.setTo(user.getEmailAddress());
|
||||
message.setFrom("webmaster@csonth.gov.uk"); // could be parameterized...
|
||||
Map model = new HashMap();
|
||||
model.put("user", user);
|
||||
String text = VelocityEngineUtils.mergeTemplateIntoString(
|
||||
velocityEngine, "com/dns/registration-confirmation.vm", model);
|
||||
message.setText(text, true);
|
||||
}
|
||||
};
|
||||
this.mailSender.send(preparator);
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
|
||||
<property name="host" value="mail.csonth.gov.uk"/>
|
||||
</bean>
|
||||
|
||||
<bean id="registrationService" class="com.foo.SimpleRegistrationService">
|
||||
<property name="mailSender" ref="mailSender"/>
|
||||
<property name="velocityEngine" ref="velocityEngine"/>
|
||||
</bean>
|
||||
|
||||
<bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
|
||||
<property name="velocityProperties">
|
||||
<value>
|
||||
resource.loader=class
|
||||
class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
----
|
||||
as FreeMarker to define the display structure of email content. This leaves your code
|
||||
tasked only with creating the data that is to be rendered in the email template and
|
||||
sending the email. It is definitely a best practice for when the content of your emails
|
||||
becomes even moderately complex, and with the Spring Framework's support classes for
|
||||
FreeMarker becomes quite easy to do.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -145,8 +145,7 @@ The Context module also supports Java EE features such as EJB, JMX, and basic re
|
||||
The `ApplicationContext` interface is the focal point of the Context module.
|
||||
`spring-context-support` provides support for integrating common third-party libraries
|
||||
into a Spring application context for caching (EhCache, Guava, JCache), mailing
|
||||
(JavaMail), scheduling (CommonJ, Quartz) and template engines (FreeMarker, JasperReports,
|
||||
Velocity).
|
||||
(JavaMail), scheduling (CommonJ, Quartz) and template engines (FreeMarker, JasperReports).
|
||||
|
||||
|
||||
The `spring-expression` module provides a powerful <<expressions,__Expression
|
||||
@@ -198,14 +197,13 @@ management for classes that implement special interfaces and for __all your POJO
|
||||
Old Java Objects)__.
|
||||
|
||||
The `spring-orm` module provides integration layers for popular
|
||||
<<orm-introduction,object-relational mapping>> APIs, including <<orm-jpa,JPA>>,
|
||||
<<orm-jdo,JDO>>, and <<orm-hibernate,Hibernate>>. Using the `spring-orm` module you can
|
||||
use all of these O/R-mapping frameworks in combination with all of the other features
|
||||
Spring offers, such as the simple declarative transaction management feature mentioned
|
||||
previously.
|
||||
<<orm-introduction,object-relational mapping>> APIs, including <<orm-jpa,JPA>> and
|
||||
<<orm-hibernate,Hibernate>>. Using the `spring-orm` module you can use these
|
||||
O/R-mapping frameworks in combination with all of the other features Spring offers,
|
||||
such as the simple declarative transaction management feature mentioned previously.
|
||||
|
||||
The `spring-oxm` module provides an abstraction layer that supports <<oxm,Object/XML
|
||||
mapping>> implementations such as JAXB, Castor, XMLBeans, JiBX and XStream.
|
||||
mapping>> implementations such as JAXB, Castor, JiBX and XStream.
|
||||
|
||||
The `spring-jms` module (<<jms,Java Messaging Service>>) contains features for producing and
|
||||
consuming messages. Since Spring Framework 4.1, it provides integration with the
|
||||
@@ -214,8 +212,8 @@ consuming messages. Since Spring Framework 4.1, it provides integration with the
|
||||
|
||||
[[overview-web]]
|
||||
==== Web
|
||||
The __Web__ layer consists of the `spring-web`, `spring-webmvc`, `spring-websocket`, and
|
||||
`spring-webmvc-portlet` modules.
|
||||
The __Web__ layer consists of the `spring-web`, `spring-webmvc` and `spring-websocket`
|
||||
modules.
|
||||
|
||||
The `spring-web` module provides basic web-oriented integration features such as
|
||||
multipart file upload functionality and the initialization of the IoC container using
|
||||
@@ -228,10 +226,6 @@ for web applications. Spring's MVC framework provides a clean separation between
|
||||
model code and web forms and integrates with all of the other features of the Spring
|
||||
Framework.
|
||||
|
||||
The `spring-webmvc-portlet` module (also known as the __Web-Portlet__ module) provides
|
||||
the MVC implementation to be used in a Portlet environment and mirrors the functionality
|
||||
of the `spring-webmvc` module.
|
||||
|
||||
|
||||
[[overview-testing]]
|
||||
==== Test
|
||||
@@ -259,11 +253,11 @@ the web application fully transactional, just as it would be if you used EJB
|
||||
container-managed transactions. All your custom business logic can be implemented with
|
||||
simple POJOs and managed by Spring's IoC container. Additional services include support
|
||||
for sending email and validation that is independent of the web layer, which lets you
|
||||
choose where to execute validation rules. Spring's ORM support is integrated with JPA,
|
||||
Hibernate and JDO; for example, when using Hibernate, you can continue to use
|
||||
your existing mapping files and standard Hibernate `SessionFactory` configuration. Form
|
||||
controllers seamlessly integrate the web-layer with the domain model, removing the need
|
||||
for `ActionForms` or other classes that transform HTTP parameters to values for your
|
||||
choose where to execute validation rules. Spring's ORM support is integrated with JPA
|
||||
and Hibernate; for example, when using Hibernate, you can continue to use your existing
|
||||
mapping files and standard Hibernate `SessionFactory` configuration. Form controllers
|
||||
seamlessly integrate the web-layer with the domain model, removing the need for
|
||||
`ActionForms` or other classes that transform HTTP parameters to values for your
|
||||
domain model.
|
||||
|
||||
.Spring middle-tier using a third-party web framework
|
||||
@@ -416,10 +410,6 @@ modules, see <<overview-modules>>.
|
||||
|spring-webmvc
|
||||
|REST Web Services and model-view-controller implementation for web applications
|
||||
|
||||
|org.springframework
|
||||
|spring-webmvc-portlet
|
||||
|MVC implementation to be used in a Portlet environment
|
||||
|
||||
|org.springframework
|
||||
|spring-websocket
|
||||
|WebSocket and SockJS implementations, including STOMP support
|
||||
|
||||
@@ -84,12 +84,6 @@ conjunction with your `WebApplicationContext` configuration for Spring MVC, see
|
||||
<<spring-mvc-test-framework,_Spring MVC Test Framework_>>.
|
||||
|
||||
|
||||
[[mock-objects-portlet]]
|
||||
==== Portlet API
|
||||
The `org.springframework.mock.web.portlet` package contains a set of Portlet API mock
|
||||
objects, targeted at usage with Spring's Portlet MVC framework.
|
||||
|
||||
|
||||
|
||||
[[unit-testing-support-classes]]
|
||||
=== Unit Testing support Classes
|
||||
@@ -4091,9 +4085,9 @@ expectations.
|
||||
This means if you are using JSPs you can verify the JSP page to which the request was
|
||||
forwarded, but there won't be any HTML rendered. In other words, the JSP will not be
|
||||
_invoked_. Note however that all other rendering technologies which don't rely on
|
||||
forwarding such as Thymeleaf, Freemarker, and Velocity will render HTML to the response
|
||||
body as expected. The same is true for rendering JSON, XML, and other formats via
|
||||
`@ResponseBody` methods.
|
||||
forwarding such as Thymeleaf and Freemarker will render HTML to the response body as
|
||||
expected. The same is true for rendering JSON, XML, and other formats via `@ResponseBody`
|
||||
methods.
|
||||
|
||||
Alternatively you may consider the full end-to-end integration testing support from
|
||||
Spring Boot via `@WebIntegrationTest`. See the
|
||||
@@ -4149,8 +4143,8 @@ need to deploy to a Servlet container
|
||||
[NOTE]
|
||||
====
|
||||
`MockMvc` works with templating technologies that do not rely on a Servlet Container (e.g.,
|
||||
Thymeleaf, Freemarker, Velocity, etc.), but it does not work with JSPs since they rely on
|
||||
the Servlet Container.
|
||||
Thymeleaf, FreeMarker, etc.), but it does not work with JSPs since they rely on the Servlet
|
||||
container.
|
||||
====
|
||||
|
||||
[[spring-mvc-test-server-htmlunit-why]]
|
||||
|
||||
@@ -49,9 +49,9 @@ configurable through file extension or Accept header content type negotiation, t
|
||||
bean names, a properties file, or even a custom `ViewResolver` implementation. The model
|
||||
(the M in MVC) is a `Map` interface, which allows for the complete abstraction of the
|
||||
view technology. You can integrate directly with template based rendering technologies
|
||||
such as JSP, Velocity and Freemarker, or directly generate XML, JSON, Atom, and many
|
||||
other types of content. The model `Map` is simply transformed into an appropriate
|
||||
format, such as JSP request attributes, a Velocity template model.
|
||||
such as JSP and FreeMarker, or directly generate XML, JSON, Atom, and many other types
|
||||
of content. The model `Map` is simply transformed into an appropriate format, such as
|
||||
JSP request attributes or a FreeMarker template model.
|
||||
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ Spring's web module includes many unique web support features:
|
||||
* __Flexible model transfer__. Model transfer with a name/value `Map` supports easy
|
||||
integration with any view technology.
|
||||
* __Customizable locale, time zone and theme resolution, support for JSPs with or without
|
||||
Spring tag library, support for JSTL, support for Velocity without the need for extra
|
||||
Spring tag library, support for JSTL, support for FreeMarker without the need for extra
|
||||
bridges, and so on.__
|
||||
* __A simple yet powerful JSP tag library known as the Spring tag library that provides
|
||||
support for features such as data binding and themes__. The custom tags allow for
|
||||
@@ -2772,7 +2772,7 @@ directly on `RequestMappingHandlerAdapter`.
|
||||
== Resolving views
|
||||
All MVC frameworks for web applications provide a way to address views. Spring provides
|
||||
view resolvers, which enable you to render models in a browser without tying you to a
|
||||
specific view technology. Out of the box, Spring enables you to use JSPs, Velocity
|
||||
specific view technology. Out of the box, Spring enables you to use JSPs, FreeMarker
|
||||
templates and XSLT views, for example. See <<view>> for a discussion of how to integrate
|
||||
and use a number of disparate view technologies.
|
||||
|
||||
@@ -2824,9 +2824,9 @@ examples follow.
|
||||
specify the view class for all views generated by this resolver by using
|
||||
`setViewClass(..)`. See the `UrlBasedViewResolver` javadocs for details.
|
||||
|
||||
| `VelocityViewResolver` / `FreeMarkerViewResolver`
|
||||
| Convenient subclass of `UrlBasedViewResolver` that supports `VelocityView` (in effect,
|
||||
Velocity templates) or `FreeMarkerView` ,respectively, and custom subclasses of them.
|
||||
| `FreeMarkerViewResolver`
|
||||
| Convenient subclass of `UrlBasedViewResolver` that supports `FreeMarkerView` and
|
||||
custom subclasses of them.
|
||||
|
||||
| `ContentNegotiatingViewResolver`
|
||||
| Implementation of the `ViewResolver` interface that resolves a view based on the
|
||||
@@ -2876,7 +2876,7 @@ file "extend". This way you can specify a default view class, for example.
|
||||
Subclasses of `AbstractCachingViewResolver` cache view instances that they resolve.
|
||||
Caching improves performance of certain view technologies. It's possible to turn off the
|
||||
cache by setting the `cache` property to `false`. Furthermore, if you must refresh a
|
||||
certain view at runtime (for example when a Velocity template is modified), you can use
|
||||
certain view at runtime (for example when a FreeMarker template is modified), you can use
|
||||
the `removeFromCache(String viewName, Locale loc)` method.
|
||||
====
|
||||
|
||||
@@ -2926,7 +2926,7 @@ indicate the view could not be found. Not all view resolvers do this, however, b
|
||||
in some cases, the resolver simply cannot detect whether or not the view exists. For
|
||||
example, the `InternalResourceViewResolver` uses the `RequestDispatcher` internally, and
|
||||
dispatching is the only way to figure out if a JSP exists, but this action can only
|
||||
execute once. The same holds for the `VelocityViewResolver` and some others. Check the
|
||||
execute once. The same holds for the `FreeMarkerViewResolver` and some others. Check the
|
||||
javadocs of the specific view resolver to see whether it reports non-existing views.
|
||||
Thus, putting an `InternalResourceViewResolver` in the chain in a place other than
|
||||
the last results in the chain not being fully inspected, because the
|
||||
@@ -2942,7 +2942,7 @@ JSPs that are processed through the Servlet or JSP engine, this resolution is us
|
||||
handled through the combination of `InternalResourceViewResolver` and
|
||||
`InternalResourceView`, which issues an internal forward or include via the Servlet
|
||||
API's `RequestDispatcher.forward(..)` method or `RequestDispatcher.include()` method.
|
||||
For other view technologies, such as Velocity, XSLT, and so on, the view itself writes
|
||||
For other view technologies, such as FreeMarker, XSLT, and so on, the view itself writes
|
||||
the content directly to the response stream.
|
||||
|
||||
It is sometimes desirable to issue an HTTP redirect back to the client, before the view
|
||||
@@ -5228,7 +5228,7 @@ And the same in XML:
|
||||
</mvc:view-resolvers>
|
||||
----
|
||||
|
||||
Note however that FreeMarker, Velocity, Tiles, Groovy Markup and script templates also require
|
||||
Note however that FreeMarker, Tiles, Groovy Markup and script templates also require
|
||||
configuration of the underlying view technology.
|
||||
|
||||
The MVC namespace provides dedicated elements. For example with FreeMarker:
|
||||
@@ -5438,10 +5438,10 @@ XML example:
|
||||
In order for the above to work the application must also
|
||||
render URLs with versions. The easiest way to do that is to configure the
|
||||
`ResourceUrlEncodingFilter` which wraps the response and overrides its `encodeURL` method.
|
||||
This will work in JSPs, FreeMarker, Velocity, and any other view technology that calls
|
||||
the response `encodeURL` method. Alternatively, an application can also inject and
|
||||
use directly the `ResourceUrlProvider` bean, which is automatically declared with the MVC
|
||||
Java config and the MVC namespace.
|
||||
This will work in JSPs, FreeMarker, and any other view technology that calls the response
|
||||
`encodeURL` method. Alternatively, an application can also inject and use directly the
|
||||
`ResourceUrlProvider` bean, which is automatically declared with the MVC Java config and
|
||||
the MVC namespace.
|
||||
|
||||
Webjars are also supported with `WebJarsResourceResolver`, which is automatically registered
|
||||
when the `"org.webjars:webjars-locator"` library is on classpath. This resolver allows
|
||||
|
||||
@@ -36,6 +36,7 @@ text based content.
|
||||
|
||||
This requires Groovy 2.3.1+ on the classpath.
|
||||
|
||||
|
||||
[[view-groovymarkup-configuration]]
|
||||
=== Configuration
|
||||
|
||||
@@ -76,6 +77,7 @@ The XML counterpart using the MVC namespace is:
|
||||
<mvc:groovy-configurer resource-loader-path="/WEB-INF/"/>
|
||||
----
|
||||
|
||||
|
||||
[[view-groovymarkup-example]]
|
||||
=== Example
|
||||
|
||||
@@ -98,57 +100,27 @@ Here is a sample template for an HTML page:
|
||||
----
|
||||
|
||||
|
||||
[[view-velocity]]
|
||||
== Velocity & FreeMarker
|
||||
http://velocity.apache.org[Velocity] and http://www.freemarker.org[FreeMarker] are two
|
||||
templating languages that can be used as view technologies within Spring MVC
|
||||
applications. The languages are quite similar and serve similar needs and so are
|
||||
considered together in this section. For semantic and syntactic differences between the
|
||||
two languages, see the http://www.freemarker.org[FreeMarker] web site.
|
||||
[[view-freemarker]]
|
||||
== FreeMarker
|
||||
http://www.freemarker.org[FreeMarker] is a templating language that can be used as a
|
||||
view technology within Spring MVC applications. For details on the template language,
|
||||
see the http://www.freemarker.org[FreeMarker] web site.
|
||||
|
||||
|
||||
|
||||
[[view-velocity-dependencies]]
|
||||
[[view-freemarker-dependencies]]
|
||||
=== Dependencies
|
||||
Your web application will need to include `velocity-1.x.x.jar` or `freemarker-2.x.jar`
|
||||
in order to work with Velocity or FreeMarker respectively and `commons-collections.jar`
|
||||
is required for Velocity. Typically they are included in the `WEB-INF/lib` folder where
|
||||
they are guaranteed to be found by a Java EE server and added to the classpath for your
|
||||
Your web application will need to include `freemarker-2.x.jar` in order to work with
|
||||
FreeMarker. Typically this is included in the `WEB-INF/lib` folder where the jars are
|
||||
guaranteed to be found by a Java EE server and added to the classpath for your
|
||||
application. It is of course assumed that you already have the `spring-webmvc.jar` in
|
||||
your `'WEB-INF/lib'` directory too! If you make use of Spring's 'dateToolAttribute' or
|
||||
'numberToolAttribute' in your Velocity views, you will also need to include the
|
||||
`velocity-tools-generic-1.x.jar`
|
||||
your `'WEB-INF/lib'` directory too!
|
||||
|
||||
|
||||
|
||||
[[view-velocity-contextconfig]]
|
||||
[[view-freemarker-contextconfig]]
|
||||
=== Context configuration
|
||||
A suitable configuration is initialized by adding the relevant configurer bean
|
||||
definition to your `'{asterisk}-servlet.xml'` as shown below:
|
||||
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
<!--
|
||||
This bean sets up the Velocity environment for us based on a root path for templates.
|
||||
Optionally, a properties file can be specified for more control over the Velocity
|
||||
environment, but the defaults are pretty sane for file based template loading.
|
||||
-->
|
||||
<bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
|
||||
<property name="resourceLoaderPath" value="/WEB-INF/velocity/"/>
|
||||
</bean>
|
||||
|
||||
<!--
|
||||
View resolvers can also be configured with ResourceBundles or XML files. If you need
|
||||
different view resolving based on Locale, you have to use the resource bundle resolver.
|
||||
-->
|
||||
<bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
|
||||
<property name="cache" value="true"/>
|
||||
<property name="prefix" value=""/>
|
||||
<property name="suffix" value=".vm"/>
|
||||
</bean>
|
||||
----
|
||||
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -170,76 +142,22 @@ definition to your `'{asterisk}-servlet.xml'` as shown below:
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
For non web-apps add a `VelocityConfigurationFactoryBean` or a
|
||||
`FreeMarkerConfigurationFactoryBean` to your application context definition file.
|
||||
For non web-apps add a `FreeMarkerConfigurationFactoryBean` to your application context
|
||||
definition file.
|
||||
====
|
||||
|
||||
|
||||
|
||||
[[view-velocity-createtemplates]]
|
||||
[[view-freemarker-createtemplates]]
|
||||
=== Creating templates
|
||||
Your templates need to be stored in the directory specified by the `{asterisk}Configurer` bean
|
||||
shown above. This document does not cover details of creating templates for the two
|
||||
languages - please see their relevant websites for information. If you use the view
|
||||
resolvers highlighted, then the logical view names relate to the template file names in
|
||||
similar fashion to `InternalResourceViewResolver` for JSP's. So if your controller
|
||||
returns a ModelAndView object containing a view name of "welcome" then the resolvers
|
||||
will look for the `/WEB-INF/freemarker/welcome.ftl` or `/WEB-INF/velocity/welcome.vm`
|
||||
template as appropriate.
|
||||
|
||||
|
||||
|
||||
[[view-velocity-advancedconfig]]
|
||||
=== Advanced configuration
|
||||
The basic configurations highlighted above will be suitable for most application
|
||||
requirements, however additional configuration options are available for when unusual or
|
||||
advanced requirements dictate.
|
||||
|
||||
|
||||
[[view-velocity-example-velocityproperties]]
|
||||
==== velocity.properties
|
||||
This file is completely optional, but if specified, contains the values that are passed
|
||||
to the Velocity runtime in order to configure velocity itself. Only required for
|
||||
advanced configurations, if you need this file, specify its location on the
|
||||
`VelocityConfigurer` bean definition above.
|
||||
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
<bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
|
||||
<property name="configLocation" value="/WEB-INF/velocity.properties"/>
|
||||
</bean>
|
||||
----
|
||||
|
||||
Alternatively, you can specify velocity properties directly in the bean definition for
|
||||
the Velocity config bean by replacing the "configLocation" property with the following
|
||||
inline properties.
|
||||
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
<bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
|
||||
<property name="velocityProperties">
|
||||
<props>
|
||||
<prop key="resource.loader">file</prop>
|
||||
<prop key="file.resource.loader.class">
|
||||
org.apache.velocity.runtime.resource.loader.FileResourceLoader
|
||||
</prop>
|
||||
<prop key="file.resource.loader.path">${webapp.root}/WEB-INF/velocity</prop>
|
||||
<prop key="file.resource.loader.cache">false</prop>
|
||||
</props>
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
|
||||
Refer to the
|
||||
{api-spring-framework}/ui/velocity/VelocityEngineFactory.html[API
|
||||
documentation] for Spring configuration of Velocity, or the Velocity documentation for
|
||||
examples and definitions of the `'velocity.properties'` file itself.
|
||||
Your templates need to be stored in the directory specified by the `FreeMarkerConfigurer`
|
||||
shown above. If you use the view resolvers highlighted, then the logical view names
|
||||
relate to the template file names in similar fashion to `InternalResourceViewResolver`
|
||||
for JSP's. So if your controller returns a ModelAndView object containing a view name of
|
||||
"welcome" then the resolver will look for the `/WEB-INF/freemarker/welcome.ftl` template.
|
||||
|
||||
|
||||
[[views-freemarker]]
|
||||
==== FreeMarker
|
||||
=== Advanced FreeMarker configuration
|
||||
FreeMarker 'Settings' and 'SharedVariables' can be passed directly to the FreeMarker
|
||||
`Configuration` object managed by Spring by setting the appropriate bean properties on
|
||||
the `FreeMarkerConfigurer` bean. The `freemarkerSettings` property requires a
|
||||
@@ -266,14 +184,13 @@ the `Configuration` object.
|
||||
|
||||
|
||||
|
||||
[[view-velocity-forms]]
|
||||
[[view-freemarker-forms]]
|
||||
=== Bind support and form handling
|
||||
Spring provides a tag library for use in JSP's that contains (amongst other things) a
|
||||
`<spring:bind/>` tag. This tag primarily enables forms to display values from form
|
||||
backing objects and to show the results of failed validations from a `Validator` in the
|
||||
web or business tier. From version 1.1, Spring now has support for the same
|
||||
functionality in both Velocity and FreeMarker, with additional convenience macros for
|
||||
generating form input elements themselves.
|
||||
web or business tier. Spring also has support for the same functionality in FreeMarker,
|
||||
with additional convenience macros for generating form input elements themselves.
|
||||
|
||||
|
||||
[[view-bind-macros]]
|
||||
@@ -285,9 +202,8 @@ Some of the macros defined in the Spring libraries are considered internal (priv
|
||||
no such scoping exists in the macro definitions making all macros visible to calling
|
||||
code and user templates. The following sections concentrate only on the macros you need
|
||||
to be directly calling from within your templates. If you wish to view the macro code
|
||||
directly, the files are called spring.vm / spring.ftl and are in the packages
|
||||
`org.springframework.web.servlet.view.velocity` or
|
||||
`org.springframework.web.servlet.view.freemarker` respectively.
|
||||
directly, the file is called `spring.ftl` in the package
|
||||
`org.springframework.web.servlet.view.freemarker`.
|
||||
|
||||
|
||||
[[view-simple-binding]]
|
||||
@@ -295,28 +211,7 @@ directly, the files are called spring.vm / spring.ftl and are in the packages
|
||||
In your HTML forms (vm / ftl templates) which act as a form view for a Spring MVC
|
||||
controller, you can use code similar to the following to bind to field values and
|
||||
display error messages for each input field in similar fashion to the JSP equivalent.
|
||||
Example code is shown below for the `personFormV`/`personFormF` views configured earlier:
|
||||
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
<!-- velocity macros are automatically available -->
|
||||
<html>
|
||||
...
|
||||
<form action="" method="POST">
|
||||
Name:
|
||||
#springBind("myModelObject.name")
|
||||
<input type="text"
|
||||
name="${status.expression}"
|
||||
value="$!status.value"/><br>
|
||||
#foreach($error in $status.errorMessages) <b>$error</b> <br> #end
|
||||
<br>
|
||||
...
|
||||
<input type="submit" value="submit"/>
|
||||
</form>
|
||||
...
|
||||
</html>
|
||||
----
|
||||
Example code is shown below for the `personForm` view configured earlier:
|
||||
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
@@ -341,18 +236,18 @@ Example code is shown below for the `personFormV`/`personFormF` views configured
|
||||
</html>
|
||||
----
|
||||
|
||||
`#springBind` / `<@spring.bind>` requires a 'path' argument which consists of the name
|
||||
of your command object (it will be 'command' unless you changed it in your
|
||||
FormController properties) followed by a period and the name of the field on the command
|
||||
object you wish to bind to. Nested fields can be used too such as
|
||||
"command.address.street". The `bind` macro assumes the default HTML escaping behavior
|
||||
specified by the ServletContext parameter `defaultHtmlEscape` in web.xml
|
||||
`<@spring.bind>` requires a 'path' argument which consists of the name of your command
|
||||
object (it will be 'command' unless you changed it in your FormController properties)
|
||||
followed by a period and the name of the field on the command object you wish to bind to.
|
||||
Nested fields can be used too such as "command.address.street". The `bind` macro assumes
|
||||
the default HTML escaping behavior specified by the ServletContext parameter
|
||||
`defaultHtmlEscape` in `web.xml`.
|
||||
|
||||
The optional form of the macro called `#springBindEscaped` / `<@spring.bindEscaped>`
|
||||
takes a second argument and explicitly specifies whether HTML escaping should be used in
|
||||
the status error messages or values. Set to true or false as required. Additional form
|
||||
handling macros simplify the use of HTML escaping and these macros should be used
|
||||
wherever possible. They are explained in the next section.
|
||||
The optional form of the macro called `<@spring.bindEscaped>` takes a second argument
|
||||
and explicitly specifies whether HTML escaping should be used in the status error
|
||||
messages or values. Set to true or false as required. Additional form handling macros
|
||||
simplify the use of HTML escaping and these macros should be used wherever possible.
|
||||
They are explained in the next section.
|
||||
|
||||
|
||||
[[views-form-macros]]
|
||||
@@ -369,62 +264,49 @@ parameter list that each takes.
|
||||
.Table of macro definitions
|
||||
[cols="3,1,1"]
|
||||
|===
|
||||
| macro| VTL definition| FTL definition
|
||||
| macro| FTL definition
|
||||
|
||||
| **message** (output a string from a resource bundle based on the code parameter)
|
||||
| #springMessage($code)
|
||||
| <@spring.message code/>
|
||||
|
||||
| **messageText** (output a string from a resource bundle based on the code parameter,
|
||||
falling back to the value of the default parameter)
|
||||
| #springMessageText($code $text)
|
||||
| <@spring.messageText code, text/>
|
||||
|
||||
| **url** (prefix a relative URL with the application's context root)
|
||||
| #springUrl($relativeUrl)
|
||||
| <@spring.url relativeUrl/>
|
||||
|
||||
| **formInput** (standard input field for gathering user input)
|
||||
| #springFormInput($path $attributes)
|
||||
| <@spring.formInput path, attributes, fieldType/>
|
||||
|
||||
| **formHiddenInput *** (hidden input field for submitting non-user input)
|
||||
| #springFormHiddenInput($path $attributes)
|
||||
| <@spring.formHiddenInput path, attributes/>
|
||||
|
||||
| **formPasswordInput** * (standard input field for gathering passwords. Note that no
|
||||
value will ever be populated in fields of this type)
|
||||
| #springFormPasswordInput($path $attributes)
|
||||
| <@spring.formPasswordInput path, attributes/>
|
||||
|
||||
| **formTextarea** (large text field for gathering long, freeform text input)
|
||||
| #springFormTextarea($path $attributes)
|
||||
| <@spring.formTextarea path, attributes/>
|
||||
|
||||
| **formSingleSelect** (drop down box of options allowing a single required value to be
|
||||
selected)
|
||||
| #springFormSingleSelect( $path $options $attributes)
|
||||
| <@spring.formSingleSelect path, options, attributes/>
|
||||
|
||||
| **formMultiSelect** (a list box of options allowing the user to select 0 or more values)
|
||||
| #springFormMultiSelect($path $options $attributes)
|
||||
| <@spring.formMultiSelect path, options, attributes/>
|
||||
|
||||
| **formRadioButtons** (a set of radio buttons allowing a single selection to be made
|
||||
from the available choices)
|
||||
| #springFormRadioButtons($path $options $separator $attributes)
|
||||
| <@spring.formRadioButtons path, options separator, attributes/>
|
||||
|
||||
| **formCheckboxes** (a set of checkboxes allowing 0 or more values to be selected)
|
||||
| #springFormCheckboxes($path $options $separator $attributes)
|
||||
| <@spring.formCheckboxes path, options, separator, attributes/>
|
||||
|
||||
| **formCheckbox** (a single checkbox)
|
||||
| #springFormCheckbox($path $attributes)
|
||||
| <@spring.formCheckbox path, attributes/>
|
||||
|
||||
| **showErrors** (simplify display of validation errors for the bound field)
|
||||
| #springShowErrors($separator $classOrStyle)
|
||||
| <@spring.showErrors separator, classOrStyle/>
|
||||
|===
|
||||
|
||||
@@ -460,16 +342,6 @@ differences exist between the two languages, they are explained in the notes.
|
||||
|
||||
[[views-form-macros-input]]
|
||||
===== Input Fields
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
<!-- the Name field example from above using form macros in VTL -->
|
||||
...
|
||||
Name:
|
||||
#springFormInput("command.name" "")<br>
|
||||
#springShowErrors("<br>" "")<br>
|
||||
----
|
||||
|
||||
The formInput macro takes the path parameter (command.name) and an additional attributes
|
||||
parameter which is empty in the example above. The macro, along with all other form
|
||||
generation macros, performs an implicit spring bind on the path parameter. The binding
|
||||
@@ -479,8 +351,7 @@ path parameter again - it simply operates on whichever field a bind was last cre
|
||||
The showErrors macro takes a separator parameter (the characters that will be used to
|
||||
separate multiple errors on a given field) and also accepts a second parameter, this
|
||||
time a class name or style attribute. Note that FreeMarker is able to specify default
|
||||
values for the attributes parameter, unlike Velocity, and the two macro calls above
|
||||
could be expressed as follows in FTL:
|
||||
values for the attributes parameter.
|
||||
|
||||
[source,xml,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
@@ -559,15 +430,15 @@ codes would be created with suitable keys like the example below.
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
protected Map referenceData(HttpServletRequest request) throws Exception {
|
||||
Map cityMap = new LinkedHashMap();
|
||||
protected Map<String, String> referenceData(HttpServletRequest request) throws Exception {
|
||||
Map<String, String> cityMap = new LinkedHashMap<>();
|
||||
cityMap.put("LDN", "London");
|
||||
cityMap.put("PRS", "Paris");
|
||||
cityMap.put("NYC", "New York");
|
||||
|
||||
Map m = new HashMap();
|
||||
m.put("cityMap", cityMap);
|
||||
return m;
|
||||
Map<String, String> model = new HashMap<>();
|
||||
model.put("cityMap", cityMap);
|
||||
return model;
|
||||
}
|
||||
----
|
||||
|
||||
@@ -600,9 +471,6 @@ model/context variable named xhtmlCompliant:
|
||||
[source,jsp,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
## for Velocity..
|
||||
#set($springXhtmlCompliant = true)
|
||||
|
||||
<#-- for FreeMarker -->
|
||||
<#assign xhtmlCompliant = true in spring>
|
||||
----
|
||||
|
||||
Reference in New Issue
Block a user