Browse Source

Remove Velocity support

Issue: SPR-13795
pull/1099/head
Juergen Hoeller 10 years ago
parent
commit
ff6ead1fff
  1. 5
      spring-context-support/src/main/java/org/springframework/mail/MailPreparationException.java
  2. 4
      spring-context-support/src/main/java/org/springframework/mail/javamail/MimeMessagePreparator.java
  3. 128
      spring-context-support/src/main/java/org/springframework/ui/velocity/SpringResourceLoader.java
  4. 357
      spring-context-support/src/main/java/org/springframework/ui/velocity/VelocityEngineFactory.java
  5. 79
      spring-context-support/src/main/java/org/springframework/ui/velocity/VelocityEngineFactoryBean.java
  6. 118
      spring-context-support/src/main/java/org/springframework/ui/velocity/VelocityEngineUtils.java
  7. 6
      spring-context-support/src/main/java/org/springframework/ui/velocity/package-info.java
  8. 3
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/MvcNamespaceHandler.java
  9. 59
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/VelocityConfigurerBeanDefinitionParser.java
  10. 6
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/ViewResolversBeanDefinitionParser.java
  11. 29
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewResolverRegistry.java
  12. 2
      spring-webmvc/src/main/java/org/springframework/web/servlet/support/BindStatus.java
  13. 15
      spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContext.java
  14. 8
      spring-webmvc/src/main/java/org/springframework/web/servlet/view/AbstractCachingViewResolver.java
  15. 16
      spring-webmvc/src/main/java/org/springframework/web/servlet/view/AbstractTemplateView.java
  16. 11
      spring-webmvc/src/main/java/org/springframework/web/servlet/view/AbstractTemplateViewResolver.java
  17. 6
      spring-webmvc/src/main/java/org/springframework/web/servlet/view/UrlBasedViewResolver.java
  18. 2
      spring-webmvc/src/main/java/org/springframework/web/servlet/view/package-info.java
  19. 41
      spring-webmvc/src/main/java/org/springframework/web/servlet/view/velocity/VelocityConfig.java
  20. 151
      spring-webmvc/src/main/java/org/springframework/web/servlet/view/velocity/VelocityConfigurer.java
  21. 188
      spring-webmvc/src/main/java/org/springframework/web/servlet/view/velocity/VelocityLayoutView.java
  22. 110
      spring-webmvc/src/main/java/org/springframework/web/servlet/view/velocity/VelocityLayoutViewResolver.java
  23. 134
      spring-webmvc/src/main/java/org/springframework/web/servlet/view/velocity/VelocityToolboxView.java
  24. 578
      spring-webmvc/src/main/java/org/springframework/web/servlet/view/velocity/VelocityView.java
  25. 137
      spring-webmvc/src/main/java/org/springframework/web/servlet/view/velocity/VelocityViewResolver.java
  26. 7
      spring-webmvc/src/main/java/org/springframework/web/servlet/view/velocity/package-info.java
  27. 320
      spring-webmvc/src/main/resources/org/springframework/web/servlet/view/velocity/spring.vm
  28. 28
      spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java
  29. 38
      spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ViewResolutionIntegrationTests.java
  30. 19
      spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ViewResolverRegistryTests.java
  31. 10
      spring-webmvc/src/test/java/org/springframework/web/servlet/view/jasperreports/JasperReportViewResolverTests.java
  32. 56
      spring-webmvc/src/test/java/org/springframework/web/servlet/view/velocity/TestVelocityEngine.java
  33. 171
      spring-webmvc/src/test/java/org/springframework/web/servlet/view/velocity/VelocityConfigurerTests.java
  34. 266
      spring-webmvc/src/test/java/org/springframework/web/servlet/view/velocity/VelocityMacroTests.java
  35. 173
      spring-webmvc/src/test/java/org/springframework/web/servlet/view/velocity/VelocityRenderTests.java
  36. 83
      spring-webmvc/src/test/java/org/springframework/web/servlet/view/velocity/VelocityToolboxViewTests.java
  37. 145
      spring-webmvc/src/test/java/org/springframework/web/servlet/view/velocity/VelocityViewResolverTests.java
  38. 280
      spring-webmvc/src/test/java/org/springframework/web/servlet/view/velocity/VelocityViewTests.java
  39. 7
      spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-view-resolution-content-negotiation.xml
  40. 7
      spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-view-resolution.xml
  41. 4
      spring-webmvc/src/test/resources/org/springframework/web/servlet/view/velocity/error.vm
  42. 4
      spring-webmvc/src/test/resources/org/springframework/web/servlet/view/velocity/ioerror.vm
  43. 6
      spring-webmvc/src/test/resources/org/springframework/web/servlet/view/velocity/simple.vm
  44. 30
      spring-webmvc/src/test/resources/org/springframework/web/servlet/view/velocity/test-spr5172.vm
  45. 64
      spring-webmvc/src/test/resources/org/springframework/web/servlet/view/velocity/test.vm
  46. 23
      spring-webmvc/src/test/resources/org/springframework/web/servlet/view/velocity/toolbox.xml
  47. 4
      src/asciidoc/images/full.svg
  48. 2
      src/asciidoc/images/overview-full.graffle
  49. 6
      src/asciidoc/images/spring-overview.svg
  50. 123
      src/asciidoc/integration.adoc
  51. 36
      src/asciidoc/overview.adoc
  52. 16
      src/asciidoc/testing.adoc
  53. 32
      src/asciidoc/web-mvc.adoc
  54. 224
      src/asciidoc/web-view.adoc

5
spring-context-support/src/main/java/org/springframework/mail/MailPreparationException.java

@ -1,5 +1,5 @@ @@ -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; @@ -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")

4
spring-context-support/src/main/java/org/springframework/mail/javamail/MimeMessagePreparator.java

@ -1,5 +1,5 @@ @@ -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 { @@ -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;

128
spring-context-support/src/main/java/org/springframework/ui/velocity/SpringResourceLoader.java

@ -1,128 +0,0 @@ @@ -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;
}
}

357
spring-context-support/src/main/java/org/springframework/ui/velocity/VelocityEngineFactory.java

@ -1,357 +0,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 {
}
}

79
spring-context-support/src/main/java/org/springframework/ui/velocity/VelocityEngineFactoryBean.java

@ -1,79 +0,0 @@ @@ -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"> &lt;bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean"&gt;
* &lt;property name="resourceLoaderPath" value="/WEB-INF/velocity/"/&gt;
* &lt;/bean&gt;</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;
}
}

118
spring-context-support/src/main/java/org/springframework/ui/velocity/VelocityEngineUtils.java

@ -1,118 +0,0 @@ @@ -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();
}
}

6
spring-context-support/src/main/java/org/springframework/ui/velocity/package-info.java

@ -1,6 +0,0 @@ @@ -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;

3
spring-webmvc/src/main/java/org/springframework/web/servlet/config/MvcNamespaceHandler.java

@ -1,5 +1,5 @@ @@ -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 { @@ -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());

59
spring-webmvc/src/main/java/org/springframework/web/servlet/config/VelocityConfigurerBeanDefinitionParser.java

@ -1,59 +0,0 @@ @@ -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/");
}
}
}

6
spring-webmvc/src/main/java/org/springframework/web/servlet/config/ViewResolversBeanDefinitionParser.java

@ -58,7 +58,6 @@ import org.springframework.web.servlet.view.tiles3.TilesViewResolver; @@ -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 { @@ -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");

29
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewResolverRegistry.java

@ -190,26 +190,6 @@ public class ViewResolverRegistry { @@ -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 { @@ -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() {

2
spring-webmvc/src/main/java/org/springframework/web/servlet/support/BindStatus.java

@ -31,7 +31,7 @@ import org.springframework.web.util.HtmlUtils; @@ -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

15
spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContext.java

@ -1,5 +1,5 @@ @@ -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; @@ -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

8
spring-webmvc/src/main/java/org/springframework/web/servlet/view/AbstractCachingViewResolver.java

@ -1,5 +1,5 @@ @@ -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 @@ -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 @@ -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

16
spring-webmvc/src/main/java/org/springframework/web/servlet/view/AbstractTemplateView.java

@ -1,5 +1,5 @@ @@ -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; @@ -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; @@ -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 { @@ -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) {

11
spring-webmvc/src/main/java/org/springframework/web/servlet/view/AbstractTemplateViewResolver.java

@ -1,5 +1,5 @@ @@ -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 @@ @@ -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 {

6
spring-webmvc/src/main/java/org/springframework/web/servlet/view/UrlBasedViewResolver.java

@ -36,9 +36,8 @@ import org.springframework.web.servlet.View; @@ -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; @@ -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 {

2
spring-webmvc/src/main/java/org/springframework/web/servlet/view/package-info.java

@ -3,7 +3,7 @@ @@ -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.

41
spring-webmvc/src/main/java/org/springframework/web/servlet/view/velocity/VelocityConfig.java

@ -1,41 +0,0 @@ @@ -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();
}

151
spring-webmvc/src/main/java/org/springframework/web/servlet/view/velocity/VelocityConfigurer.java

@ -1,151 +0,0 @@ @@ -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">
* &lt;bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer"&gt;
* &lt;property name="resourceLoaderPath">&lt;value&gt;/WEB-INF/velocity/&lt;/value>&lt;/property&gt;
* &lt;/bean&gt;</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;
}
}

188
spring-webmvc/src/main/java/org/springframework/web/servlet/view/velocity/VelocityLayoutView.java

@ -1,188 +0,0 @@ @@ -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());
}
}

110
spring-webmvc/src/main/java/org/springframework/web/servlet/view/velocity/VelocityLayoutViewResolver.java

@ -1,110 +0,0 @@ @@ -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;
}
}

134
spring-webmvc/src/main/java/org/springframework/web/servlet/view/velocity/VelocityToolboxView.java

@ -1,134 +0,0 @@ @@ -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);
}
}
}

578
spring-webmvc/src/main/java/org/springframework/web/servlet/view/velocity/VelocityView.java

@ -1,578 +0,0 @@ @@ -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);
}
}
}

137
spring-webmvc/src/main/java/org/springframework/web/servlet/view/velocity/VelocityViewResolver.java

@ -1,137 +0,0 @@ @@ -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;
}
}

7
spring-webmvc/src/main/java/org/springframework/web/servlet/view/velocity/package-info.java

@ -1,7 +0,0 @@ @@ -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;

320
spring-webmvc/src/main/resources/org/springframework/web/servlet/view/velocity/spring.vm

@ -1,320 +0,0 @@ @@ -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 '&nbsp;' 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 '&nbsp;' 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

28
spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java

@ -1,5 +1,5 @@ @@ -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; @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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());

38
spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ViewResolutionIntegrationTests.java

@ -39,7 +39,6 @@ import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 {

19
spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ViewResolverRegistryTests.java

@ -38,8 +38,6 @@ import org.springframework.web.servlet.view.script.ScriptTemplateConfigurer; @@ -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 { @@ -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 { @@ -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 { @@ -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);

10
spring-webmvc/src/test/java/org/springframework/web/servlet/view/jasperreports/JasperReportViewResolverTests.java

@ -1,5 +1,5 @@ @@ -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; @@ -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 { @@ -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*");

56
spring-webmvc/src/test/java/org/springframework/web/servlet/view/velocity/TestVelocityEngine.java

@ -1,56 +0,0 @@ @@ -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;
}
}

171
spring-webmvc/src/test/java/org/springframework/web/servlet/view/velocity/VelocityConfigurerTests.java

@ -1,171 +0,0 @@ @@ -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()));
}
}

266
spring-webmvc/src/test/java/org/springframework/web/servlet/view/velocity/VelocityMacroTests.java

@ -1,266 +0,0 @@ @@ -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]);
}
}
}

173
spring-webmvc/src/test/java/org/springframework/web/servlet/view/velocity/VelocityRenderTests.java

@ -1,173 +0,0 @@ @@ -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);
}
}

83
spring-webmvc/src/test/java/org/springframework/web/servlet/view/velocity/VelocityToolboxViewTests.java

@ -1,83 +0,0 @@ @@ -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);
}
}

145
spring-webmvc/src/test/java/org/springframework/web/servlet/view/velocity/VelocityViewResolverTests.java

@ -1,145 +0,0 @@ @@ -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!
}
}

280
spring-webmvc/src/test/java/org/springframework/web/servlet/view/velocity/VelocityViewTests.java

@ -1,280 +0,0 @@ @@ -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());
}
}

7
spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-view-resolution-content-negotiation.xml

@ -3,8 +3,8 @@ @@ -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 @@ @@ -23,7 +23,6 @@
<mvc:jsp/>
<mvc:tiles/>
<mvc:freemarker/>
<mvc:velocity/>
<mvc:groovy/>
<mvc:script-template/>
</mvc:view-resolvers>
@ -36,8 +35,6 @@ @@ -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"/>

7
spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-view-resolution.xml

@ -2,15 +2,14 @@ @@ -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 @@ @@ -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"

4
spring-webmvc/src/test/resources/org/springframework/web/servlet/view/velocity/error.vm

@ -1,4 +0,0 @@ @@ -1,4 +0,0 @@
##
## test template for Velocity view with missing method
##
$command.nonexistent()

4
spring-webmvc/src/test/resources/org/springframework/web/servlet/view/velocity/ioerror.vm

@ -1,4 +0,0 @@ @@ -1,4 +0,0 @@
##
## test template for Velocity view with exception
##
$command.unreliableFileOperation()

6
spring-webmvc/src/test/resources/org/springframework/web/servlet/view/velocity/simple.vm

@ -1,6 +0,0 @@ @@ -1,6 +0,0 @@
##
## test template for Velocity view
##
NAME
$command.name

30
spring-webmvc/src/test/resources/org/springframework/web/servlet/view/velocity/test-spr5172.vm

@ -1,30 +0,0 @@ @@ -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" "")

64
spring-webmvc/src/test/resources/org/springframework/web/servlet/view/velocity/test.vm

@ -1,64 +0,0 @@ @@ -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(" " "")

23
spring-webmvc/src/test/resources/org/springframework/web/servlet/view/velocity/toolbox.xml

@ -1,23 +0,0 @@ @@ -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>

4
src/asciidoc/images/full.svg

@ -154,7 +154,7 @@ @@ -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 @@ @@ -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

2
src/asciidoc/images/overview-full.graffle

@ -128,7 +128,7 @@ @@ -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>

6
src/asciidoc/images/spring-overview.svg

@ -160,7 +160,7 @@ @@ -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 @@ @@ -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

123
src/asciidoc/integration.adoc

@ -6043,124 +6043,11 @@ of your emails using the above approach for a number of reasons. @@ -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.

36
src/asciidoc/overview.adoc

@ -145,8 +145,7 @@ The Context module also supports Java EE features such as EJB, JMX, and basic re @@ -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 @@ -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 @@ -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 @@ -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 @@ -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>>. @@ -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

16
src/asciidoc/testing.adoc

@ -84,12 +84,6 @@ conjunction with your `WebApplicationContext` configuration for Spring MVC, see @@ -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. @@ -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 @@ -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]]

32
src/asciidoc/web-mvc.adoc

@ -49,9 +49,9 @@ configurable through file extension or Accept header content type negotiation, t @@ -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: @@ -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`. @@ -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. @@ -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. @@ -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 @@ -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 @@ -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: @@ -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: @@ -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

224
src/asciidoc/web-view.adoc

@ -36,6 +36,7 @@ text based content. @@ -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: @@ -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: @@ -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: @@ -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. @@ -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 @@ -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 @@ -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 @@ -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. @@ -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. @@ -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 @@ -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. @@ -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: @@ -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>
----

Loading…
Cancel
Save