Browse Source

Introduce Freemarker/Velocity/TilesWebMvcConfigurer

This change improves the support for auto-registration of FreeMarker,
Velocity, and Tiles configuration.

The configuration is now conditional not only based on the classpath
but also based on whether a FreeMarkerConfigurer for example is already
present in the configuration.

This change also introduces FreeMarker~, Velocity~, and
TilesWebMvcConfigurer interfaces for customizing each view technology.

The WebMvcConfigurer can still be used to configure all view resolvers
centrally (including FreeMarker, Velocity, and Tiles) without some
default conifguration, i.e. without the need to use the new
~WebMvcConfigurer interfaces until customizations are required.

Issue: SPR-7093
pull/589/merge
Rossen Stoyanchev 11 years ago
parent
commit
5bc793768c
  1. 1
      build.gradle
  2. 9
      spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/JavaConfigTests.java
  3. 67
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/BeanTypeNotPresentCondition.java
  4. 2
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/EnableWebMvc.java
  5. 59
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/FreeMarkerConfigurerConfigurationSupport.java
  6. 25
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/FreeMarkerRegistration.java
  7. 35
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/FreeMarkerWebMvcConfigurer.java
  8. 59
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/TilesConfigurerConfigurationSupport.java
  9. 41
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/TilesRegistration.java
  10. 35
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/TilesWebMvcConfigurer.java
  11. 59
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/VelocityConfigurerConfigurationSupport.java
  12. 17
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/VelocityRegistration.java
  13. 35
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/VelocityWebMvcConfigurer.java
  14. 64
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewConfigurationImportSelector.java
  15. 58
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewConfigurationsImportSelector.java
  16. 64
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewResolutionRegistry.java
  17. 5
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java
  18. 76
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcFreeMarkerConfiguration.java
  19. 94
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcTilesConfiguration.java
  20. 76
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcVelocityConfiguration.java
  21. 239
      spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ViewResolutionIntegrationTests.java
  22. 49
      spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ViewResolutionRegistryTests.java
  23. 1
      spring-webmvc/src/test/resources/org/springframework/web/servlet/config/annotation/WEB-INF/index.ftl
  24. 12
      spring-webmvc/src/test/resources/org/springframework/web/servlet/config/annotation/WEB-INF/index.jsp
  25. 1
      spring-webmvc/src/test/resources/org/springframework/web/servlet/config/annotation/WEB-INF/index.vm
  26. 7
      spring-webmvc/src/test/resources/org/springframework/web/servlet/config/annotation/WEB-INF/tiles.xml

1
build.gradle

@ -910,7 +910,6 @@ project("spring-test") { @@ -910,7 +910,6 @@ project("spring-test") {
optional("xmlunit:xmlunit:1.5")
testCompile(project(":spring-context-support"))
testCompile(project(":spring-oxm"))
testCompile(project(":spring-webmvc-tiles2"))
testCompile("javax.mail:javax.mail-api:1.5.2")
testCompile("javax.ejb:ejb-api:3.0")
testCompile("org.hibernate:hibernate-core:${hibernate4Version}")

9
spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/JavaConfigTests.java

@ -35,6 +35,7 @@ import org.springframework.test.web.servlet.samples.context.JavaConfigTests.WebC @@ -35,6 +35,7 @@ import org.springframework.test.web.servlet.samples.context.JavaConfigTests.WebC
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.config.annotation.*;
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
@ -99,7 +100,7 @@ public class JavaConfigTests { @@ -99,7 +100,7 @@ public class JavaConfigTests {
@Configuration
@EnableWebMvc
static class WebConfig extends WebMvcConfigurerAdapter {
static class WebConfig extends WebMvcConfigurerAdapter implements TilesWebMvcConfigurer {
@Autowired
private RootConfig rootConfig;
@ -126,9 +127,13 @@ public class JavaConfigTests { @@ -126,9 +127,13 @@ public class JavaConfigTests {
@Override
public void configureViewResolution(ViewResolutionRegistry registry) {
registry.tiles().definition("/WEB-INF/**/tiles.xml");
registry.tiles();
}
@Override
public void configureTiles(TilesConfigurer configurer) {
configurer.setDefinitions("/WEB-INF/**/tiles.xml");
}
}
}

67
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/BeanTypeNotPresentCondition.java

@ -0,0 +1,67 @@ @@ -0,0 +1,67 @@
/*
* 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.annotation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.ConfigurationCondition;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.ObjectUtils;
/**
* A simple configuration condition that checks for the absence of any beans
* of a given type.
*
* @author Rossen Stoyanchev
* @since 4.1
*/
class BeanTypeNotPresentCondition implements ConfigurationCondition {
private static final Log logger =
LogFactory.getLog("org.springframework.web.servlet.config.annotation.ViewResolution");
private final Class<?> beanType;
BeanTypeNotPresentCondition(Class<?> beanType) {
this.beanType = beanType;
}
@Override
public ConfigurationPhase getConfigurationPhase() {
return ConfigurationPhase.PARSE_CONFIGURATION;
}
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
ListableBeanFactory factory = context.getBeanFactory();
String[] names = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(factory, this.beanType, false, false);
if (ObjectUtils.isEmpty(names)) {
logger.debug("No bean of type [" + this.beanType + "]. Conditional configuration applies.");
return true;
}
else {
logger.debug("Found bean of type [" + this.beanType + "]. Conditional configuration does not apply.");
return false;
}
}
}

2
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/EnableWebMvc.java

@ -90,6 +90,6 @@ import org.springframework.context.annotation.Import; @@ -90,6 +90,6 @@ import org.springframework.context.annotation.Import;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import({DelegatingWebMvcConfiguration.class, ViewConfigurationsImportSelector.class})
@Import({DelegatingWebMvcConfiguration.class, ViewResolutionImportSelector.class})
public @interface EnableWebMvc {
}

59
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/FreeMarkerConfigurerConfigurationSupport.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.annotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import java.util.List;
/**
* This class creates a FreeMarkerConfigurer bean.
* It is typically imported by adding {@link EnableWebMvc @EnableWebMvc} to an
* application {@link Configuration @Configuration} class when FreeMarker is
* in the classpath.
*
* @author Sebastien Deleuze
* @since 4.1
* @see org.springframework.web.servlet.config.annotation.ViewConfigurationsImportSelector
*/
@Configuration
public class FreeMarkerConfigurerConfigurationSupport {
private List<WebMvcConfigurationSupport> webMvcConfigurationSupports;
@Autowired(required = false)
public void setWebMvcConfigurationSupports(List<WebMvcConfigurationSupport> webMvcConfigurationSupports) {
this.webMvcConfigurationSupports = webMvcConfigurationSupports;
}
@Bean
public FreeMarkerConfigurer freeMarkerConfigurer() {
FreeMarkerConfigurer configurer = null;
if(webMvcConfigurationSupports != null) {
for(WebMvcConfigurationSupport configurationSupport : webMvcConfigurationSupports) {
configurer = configurationSupport.getViewResolutionRegistry().getFreeMarkerConfigurer();
if(configurer != null) {
break;
}
}
}
return configurer;
}
}

25
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/FreeMarkerRegistration.java

@ -16,12 +16,8 @@ @@ -16,12 +16,8 @@
package org.springframework.web.servlet.config.annotation;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
import java.util.Arrays;
import java.util.List;
/**
* Encapsulates information required to create a
* {@link org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver} and a
@ -33,15 +29,11 @@ import java.util.List; @@ -33,15 +29,11 @@ import java.util.List;
*/
public class FreeMarkerRegistration extends ViewResolutionRegistration<FreeMarkerViewResolver> {
private final FreeMarkerConfigurer configurer;
private List<String> templateLoaderPaths;
public FreeMarkerRegistration(ViewResolutionRegistry registry) {
super(registry, new FreeMarkerViewResolver());
this.configurer = new FreeMarkerConfigurer();
this.prefix("");
this.suffix(".ftl");
this.templateLoaderPath("/WEB-INF/");
}
/**
@ -74,21 +66,4 @@ public class FreeMarkerRegistration extends ViewResolutionRegistration<FreeMarke @@ -74,21 +66,4 @@ public class FreeMarkerRegistration extends ViewResolutionRegistration<FreeMarke
return this;
}
/**
* Set a List of {@code TemplateLoader}s that will be used to search
* for templates.
*
* @see org.springframework.ui.freemarker.FreeMarkerConfigurationFactory#setTemplateLoaderPaths(String...)
*/
public FreeMarkerRegistration templateLoaderPath(String... templateLoaderPath) {
this.templateLoaderPaths= Arrays.asList(templateLoaderPath);
return this;
}
protected FreeMarkerConfigurer getConfigurer() {
if(this.templateLoaderPaths != null && !this.templateLoaderPaths.isEmpty()) {
this.configurer.setTemplateLoaderPaths(this.templateLoaderPaths.toArray(new String[0]));
}
return this.configurer;
}
}

35
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/FreeMarkerWebMvcConfigurer.java

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
/*
* 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.annotation;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
/**
* Defines a callback method to customize the
* {@link org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer
* FreeMarkerConfigurer} bean provided when using {@code @EnableWebMvc}.
*
* <p>An {@code @EnableWebMvc}-annotated configuration classes can implement
* this interface to customize the {@code FreeMarkerConfigurer}.
*
* @author Rossen Stoyanchev
* @since 4.1
*/
public interface FreeMarkerWebMvcConfigurer {
void configureFreeMarker(FreeMarkerConfigurer configurer);
}

59
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/TilesConfigurerConfigurationSupport.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.annotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
import java.util.List;
/**
* This class creates a TilesConfigurer bean.
* It is typically imported by adding {@link EnableWebMvc @EnableWebMvc} to an
* application {@link Configuration @Configuration} class when Tiles 3 is
* in the classpath.
*
* @author Sebastien Deleuze
* @since 4.1
* @see org.springframework.web.servlet.config.annotation.ViewConfigurationsImportSelector
*/
@Configuration
public class TilesConfigurerConfigurationSupport {
private List<WebMvcConfigurationSupport> webMvcConfigurationSupports;
@Autowired(required = false)
public void setWebMvcConfigurationSupports(List<WebMvcConfigurationSupport> webMvcConfigurationSupports) {
this.webMvcConfigurationSupports = webMvcConfigurationSupports;
}
@Bean
public TilesConfigurer tilesConfigurer() {
TilesConfigurer configurer = null;
if(webMvcConfigurationSupports != null) {
for(WebMvcConfigurationSupport configurationSupport : webMvcConfigurationSupports) {
configurer = configurationSupport.getViewResolutionRegistry().getTilesConfigurer();
if(configurer != null) {
break;
}
}
}
return configurer;
}
}

41
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/TilesRegistration.java

@ -16,13 +16,8 @@ @@ -16,13 +16,8 @@
package org.springframework.web.servlet.config.annotation;
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
import org.springframework.web.servlet.view.tiles3.TilesViewResolver;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Encapsulates information required to create a
* {@link org.springframework.web.servlet.view.tiles3.TilesViewResolver} and a
@ -35,8 +30,6 @@ import java.util.List; @@ -35,8 +30,6 @@ import java.util.List;
*/
public class TilesRegistration extends ViewResolutionRegistration<TilesViewResolver> {
private List<String> definitions;
private Boolean checkRefresh;
public TilesRegistration(ViewResolutionRegistry registry) {
super(registry, new TilesViewResolver());
@ -62,38 +55,4 @@ public class TilesRegistration extends ViewResolutionRegistration<TilesViewResol @@ -62,38 +55,4 @@ public class TilesRegistration extends ViewResolutionRegistration<TilesViewResol
return this;
}
/**
* Set the Tiles definitions, i.e. a single value or a list of files containing the definitions.
*
* @see TilesConfigurer#setDefinitions(String...)
*/
public TilesRegistration definition(String... definitions) {
if(this.definitions == null) {
this.definitions = new ArrayList<String>();
}
this.definitions.addAll(Arrays.asList(definitions));
return this;
}
/**
* Set whether to check Tiles definition files for a refresh at runtime.
*
* @see TilesConfigurer#setCheckRefresh(boolean)
*/
public TilesRegistration checkRefresh(boolean checkRefresh) {
this.checkRefresh = checkRefresh;
return this;
}
protected TilesConfigurer getTilesConfigurer() {
TilesConfigurer tilesConfigurer = new TilesConfigurer();
if(this.definitions != null && !this.definitions.isEmpty()) {
tilesConfigurer.setDefinitions(this.definitions.toArray(new String[0]));
}
if(this.checkRefresh != null) {
tilesConfigurer.setCheckRefresh(this.checkRefresh);
}
return tilesConfigurer;
}
}

35
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/TilesWebMvcConfigurer.java

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
/*
* 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.annotation;
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
/**
* Defines a callback method to customize the
* {@link org.springframework.web.servlet.view.tiles3.TilesConfigurer
* TilesConfigurer} bean provided when using {@code @EnableWebMvc}.
*
* <p>An {@code @EnableWebMvc}-annotated configuration classes can implement
* this interface to customize the {@code TilesConfigurer}.
*
* @author Rossen Stoyanchev
* @since 4.1
*/
public interface TilesWebMvcConfigurer {
void configureTiles(TilesConfigurer configurer);
}

59
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/VelocityConfigurerConfigurationSupport.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.annotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.view.velocity.VelocityConfigurer;
import java.util.List;
/**
* This class creates the VelocityConfigurer bean.
* It is typically imported by adding {@link EnableWebMvc @EnableWebMvc} to an
* application {@link Configuration @Configuration} class when Velocity in the classpath.
*
* @author Sebastien Deleuze
* @since 4.1
* @see org.springframework.web.servlet.config.annotation.ViewConfigurationsImportSelector
*/
@Configuration
public class VelocityConfigurerConfigurationSupport {
private List<WebMvcConfigurationSupport> webMvcConfigurationSupports;
@Autowired(required = false)
public void setWebMvcConfigurationSupports(List<WebMvcConfigurationSupport> webMvcConfigurationSupports) {
this.webMvcConfigurationSupports = webMvcConfigurationSupports;
}
@Bean
public VelocityConfigurer velocityConfigurer() {
VelocityConfigurer configurer = null;
if(webMvcConfigurationSupports != null) {
for(WebMvcConfigurationSupport configurationSupport : webMvcConfigurationSupports) {
configurer = configurationSupport.getViewResolutionRegistry().getVelocityConfigurer();
if(configurer != null) {
break;
}
}
}
return configurer;
}
}

17
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/VelocityRegistration.java

@ -16,7 +16,6 @@ @@ -16,7 +16,6 @@
package org.springframework.web.servlet.config.annotation;
import org.springframework.web.servlet.view.velocity.VelocityConfigurer;
import org.springframework.web.servlet.view.velocity.VelocityViewResolver;
/**
@ -30,24 +29,11 @@ import org.springframework.web.servlet.view.velocity.VelocityViewResolver; @@ -30,24 +29,11 @@ import org.springframework.web.servlet.view.velocity.VelocityViewResolver;
*/
public class VelocityRegistration extends ViewResolutionRegistration<VelocityViewResolver> {
private final VelocityConfigurer configurer;
public VelocityRegistration(ViewResolutionRegistry registry) {
super(registry, new VelocityViewResolver());
this.configurer = new VelocityConfigurer();
this.prefix("");
this.suffix(".vm");
this.resourceLoaderPath("/WEB-INF/");
}
/**
* Set the Velocity resource loader path via a Spring resource location.
*
* @see org.springframework.web.servlet.view.velocity.VelocityConfigurer#setResourceLoaderPath(String)
*/
public VelocityRegistration resourceLoaderPath(String resourceLoaderPath) {
this.configurer.setResourceLoaderPath(resourceLoaderPath);
return this;
}
/**
@ -80,7 +66,4 @@ public class VelocityRegistration extends ViewResolutionRegistration<VelocityVie @@ -80,7 +66,4 @@ public class VelocityRegistration extends ViewResolutionRegistration<VelocityVie
return this;
}
protected VelocityConfigurer getConfigurer() {
return this.configurer;
}
}

35
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/VelocityWebMvcConfigurer.java

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
/*
* 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.annotation;
import org.springframework.web.servlet.view.velocity.VelocityConfigurer;
/**
* Defines a callback method to customize the
* {@link org.springframework.web.servlet.view.velocity.VelocityConfigurer
* VelocityConfigurer} bean provided when using {@code @EnableWebMvc}.
*
* <p>An {@code @EnableWebMvc}-annotated configuration classes can implement
* this interface to customize the {@code VelocityConfigurer}.
*
* @author Rossen Stoyanchev
* @since 4.1
*/
public interface VelocityWebMvcConfigurer {
void configureVelocity(VelocityConfigurer configurer);
}

64
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewConfigurationImportSelector.java

@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
/*
* 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.annotation;
import org.springframework.context.annotation.DeferredImportSelector;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.ClassUtils;
import java.util.ArrayList;
import java.util.List;
/**
* Selectively imports configuration required to configure Tiles, Freemarker, or
* Velocity for view resolution depending on whether those 3rd party libraries
* are available on the classpath.
*
* @author Sebastien Deleuze
* @author Rossen Stoyanchev
* @since 4.1
*
* @see WebMvcFreeMarkerConfiguration
*/
public class ViewConfigurationImportSelector implements DeferredImportSelector {
private static final boolean tilesPresent = ClassUtils.isPresent(
"org.apache.tiles.startup.TilesInitializer", ViewConfigurationImportSelector.class.getClassLoader());
private static final boolean velocityPresent = ClassUtils.isPresent(
"org.apache.velocity.app.VelocityEngine", ViewConfigurationImportSelector.class.getClassLoader());
private static final boolean freeMarkerPresent = ClassUtils.isPresent(
"freemarker.template.Configuration", ViewConfigurationImportSelector.class.getClassLoader());
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
List<String> classes = new ArrayList<String>(3);
if (tilesPresent) {
classes.add(WebMvcTilesConfiguration.class.getName());
}
if (velocityPresent) {
classes.add(WebMvcVelocityConfiguration.class.getName());
}
if (freeMarkerPresent) {
classes.add(WebMvcFreeMarkerConfiguration.class.getName());
}
return classes.toArray(new String[0]);
}
}

58
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewConfigurationsImportSelector.java

@ -1,58 +0,0 @@ @@ -1,58 +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.annotation;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.ClassUtils;
import java.util.ArrayList;
import java.util.List;
/**
* This class imports @{@link org.springframework.context.annotation.Configuration}
* classes for view configurers based on a classpath criteria.
*
* @author Sebastien Deleuze
* @since 4.1
*/
public class ViewConfigurationsImportSelector implements ImportSelector {
private static final boolean tilesPresent =
ClassUtils.isPresent("org.apache.tiles.startup.TilesInitializer", ViewConfigurationsImportSelector.class.getClassLoader());
private static final boolean velocityPresent =
ClassUtils.isPresent("org.apache.velocity.app.VelocityEngine", ViewConfigurationsImportSelector.class.getClassLoader());
private static final boolean freeMarkerPresent =
ClassUtils.isPresent("freemarker.template.Configuration", ViewConfigurationsImportSelector.class.getClassLoader());
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
List<String> configurationClasses = new ArrayList<String>();
if(tilesPresent) {
configurationClasses.add(TilesConfigurerConfigurationSupport.class.getName());
}
if(velocityPresent) {
configurationClasses.add(VelocityConfigurerConfigurationSupport.class.getName());
}
if(freeMarkerPresent) {
configurationClasses.add(FreeMarkerConfigurerConfigurationSupport.class.getName());
}
return configurationClasses.toArray(new String[0]);
}
}

64
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewResolutionRegistry.java

@ -16,8 +16,13 @@ @@ -16,8 +16,13 @@
package org.springframework.web.servlet.config.annotation;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.context.ApplicationContext;
import org.springframework.util.ObjectUtils;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfig;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
import org.springframework.web.servlet.view.velocity.VelocityConfigurer;
@ -35,6 +40,14 @@ public class ViewResolutionRegistry { @@ -35,6 +40,14 @@ public class ViewResolutionRegistry {
private final List<ViewResolutionRegistration<?>> registrations = new ArrayList<ViewResolutionRegistration<?>>();
private final ApplicationContext applicationContext;
public ViewResolutionRegistry(ApplicationContext context) {
this.applicationContext = context;
}
/**
* Register a custom {@link ViewResolver} bean.
*/
@ -79,6 +92,12 @@ public class ViewResolutionRegistry { @@ -79,6 +92,12 @@ public class ViewResolutionRegistry {
* default "/WEB-INF/tiles.xml" definition and no Tiles definition check refresh.
*/
public TilesRegistration tiles() {
if (!hasBeanOfType(TilesConfigurer.class)) {
throw new BeanInitializationException(
"It looks like you're trying to configure Tiles view resolution. " +
"If not using @EnableWebMvc you must import WebMvcTilesConfiguration, " +
"or declare your own TilesConfigurer bean.");
}
TilesRegistration registration = new TilesRegistration(this);
addAndCheckViewResolution(registration);
return registration;
@ -90,6 +109,12 @@ public class ViewResolutionRegistry { @@ -90,6 +109,12 @@ public class ViewResolutionRegistry {
* default "" prefix, ".vm" suffix and "/WEB-INF/" resourceLoaderPath.
*/
public VelocityRegistration velocity() {
if (!hasBeanOfType(VelocityConfigurer.class)) {
throw new BeanInitializationException(
"It looks like you're trying to configure Velocity view resolution. " +
"If not using @EnableWebMvc you must import WebMvcVelocityConfiguration, " +
"or declare your own VelocityConfigurer bean.");
}
VelocityRegistration registration = new VelocityRegistration(this);
addAndCheckViewResolution(registration);
return registration;
@ -101,11 +126,22 @@ public class ViewResolutionRegistry { @@ -101,11 +126,22 @@ public class ViewResolutionRegistry {
* "" prefix, ".ftl" suffix and "/WEB-INF/" templateLoaderPath.
*/
public FreeMarkerRegistration freemarker() {
if (!hasBeanOfType(FreeMarkerConfigurer.class)) {
throw new BeanInitializationException(
"It looks like you're trying to configure FreeMarker view resolution. " +
"If not using @EnableWebMvc you must import WebMvcFreeMarkerConfiguration, " +
"or declare your own FreeMarkerConfigurer bean.");
}
FreeMarkerRegistration registration = new FreeMarkerRegistration(this);
addAndCheckViewResolution(registration);
return registration;
}
protected boolean hasBeanOfType(Class<?> beanType) {
return !ObjectUtils.isEmpty(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.applicationContext, beanType, false, false));
}
/**
* Register a {@link org.springframework.web.servlet.view.ContentNegotiatingViewResolver} bean.
*/
@ -118,40 +154,12 @@ public class ViewResolutionRegistry { @@ -118,40 +154,12 @@ public class ViewResolutionRegistry {
protected List<ViewResolver> getViewResolvers() {
List<ViewResolver> viewResolvers = new ArrayList<ViewResolver>();
for(ViewResolutionRegistration<?> registration : this.registrations) {
viewResolvers.add(registration.getViewResolver());
}
return viewResolvers;
}
protected TilesConfigurer getTilesConfigurer() {
for(ViewResolutionRegistration<?> registration : this.registrations) {
if(registration instanceof TilesRegistration) {
return ((TilesRegistration) registration).getTilesConfigurer();
}
}
return null;
}
protected FreeMarkerConfigurer getFreeMarkerConfigurer() {
for(ViewResolutionRegistration<?> registration : this.registrations) {
if(registration instanceof FreeMarkerRegistration) {
return ((FreeMarkerRegistration) registration).getConfigurer();
}
}
return null;
}
protected VelocityConfigurer getVelocityConfigurer() {
for(ViewResolutionRegistration<?> registration : this.registrations) {
if(registration instanceof VelocityRegistration) {
return ((VelocityRegistration) registration).getConfigurer();
}
}
return null;
}
private void addAndCheckViewResolution(ViewResolutionRegistration<?> registration) {
for(ViewResolutionRegistration<?> existingRegistration : this.registrations) {
if(existingRegistration.getClass().equals(registration.getClass())) {

5
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java

@ -152,8 +152,7 @@ import org.springframework.web.util.UrlPathHelper; @@ -152,8 +152,7 @@ import org.springframework.web.util.UrlPathHelper;
* <p>When extending directly from this class instead of using
* {@link EnableWebMvc @EnableWebMvc}, an extra step is needed if you want to use Tiles, FreeMarker
* or Velocity view resolution configuration. Since view configurer beans are registered in their own
* {@link org.springframework.web.servlet.config.annotation.TilesConfigurerConfigurationSupport},
* {@link org.springframework.web.servlet.config.annotation.FreeMarkerConfigurerConfigurationSupport}
* {@link org.springframework.web.servlet.config.annotation.TilesConfigurerConfigurationSupport}
* and {@link org.springframework.web.servlet.config.annotation.VelocityConfigurerConfigurationSupport}
* classes, you should also extend those configuration classes (only the ones
* related to the view technology you are using), or register your own
@ -825,7 +824,7 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv @@ -825,7 +824,7 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
protected ViewResolutionRegistry getViewResolutionRegistry() {
if(this.viewResolutionRegistry == null) {
this.viewResolutionRegistry = new ViewResolutionRegistry();
this.viewResolutionRegistry = new ViewResolutionRegistry(this.applicationContext);
configureViewResolution(this.viewResolutionRegistry);
}
return this.viewResolutionRegistry;

76
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcFreeMarkerConfiguration.java

@ -0,0 +1,76 @@ @@ -0,0 +1,76 @@
/*
* 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.annotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.util.CollectionUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import java.util.ArrayList;
import java.util.List;
/**
* Configuration class that declares a
* {@link org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer
* FreeMarkerConfigurer} bean. The configuration is conditional and applies
* only if there is no {@code FreeMarkerConfigurer} bean already declared.
*
* <p>This configuration is imported when using {@link EnableWebMvc} if
* FreeMarker is available on the classpath. It can be customized by
* implementing {@link FreeMarkerWebMvcConfigurer}.
*
* @author Rossen Stoyanchev
* @since 4.1
*/
@Configuration
@Conditional(WebMvcFreeMarkerConfiguration.FreeMarkerConfigurerNotPresentCondition.class)
public class WebMvcFreeMarkerConfiguration {
private final List<FreeMarkerWebMvcConfigurer> webMvcConfigurers = new ArrayList<FreeMarkerWebMvcConfigurer>(1);
@Autowired(required = false)
public void setWebMvcConfigurers(List<FreeMarkerWebMvcConfigurer> webMvcConfigurers) {
if (!CollectionUtils.isEmpty(webMvcConfigurers)) {
this.webMvcConfigurers.addAll(webMvcConfigurers);
}
}
@Bean
@Lazy
public FreeMarkerConfigurer freeMarkerConfigurer() {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.setTemplateLoaderPath("/WEB-INF/");
for (FreeMarkerWebMvcConfigurer webMvcConfigurer : this.webMvcConfigurers) {
webMvcConfigurer.configureFreeMarker(configurer);
}
return configurer;
}
static class FreeMarkerConfigurerNotPresentCondition extends BeanTypeNotPresentCondition {
private FreeMarkerConfigurerNotPresentCondition() {
super(FreeMarkerConfigurer.class);
}
}
}

94
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcTilesConfiguration.java

@ -0,0 +1,94 @@ @@ -0,0 +1,94 @@
/*
* 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.annotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.CollectionUtils;
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
import java.util.ArrayList;
import java.util.List;
/**
* Configuration class that declares a
* {@link org.springframework.web.servlet.view.tiles3.TilesConfigurer
* TilesConfigurer} bean. The configuration is conditional and applies
* only if there is no {@code TilesConfigurer} bean already declared.
*
* <p>This configuration is imported when using {@link EnableWebMvc} if Tiles 3
* is available on the classpath. It can be customized by implementing
* {@link TilesWebMvcConfigurer}.
*
* @author Rossen Stoyanchev
* @since 4.1
*/
@Configuration
@Conditional(WebMvcTilesConfiguration.TilesConfigurerNotPresentCondition.class)
public class WebMvcTilesConfiguration implements ResourceLoaderAware {
private final List<TilesWebMvcConfigurer> webMvcConfigurers = new ArrayList<TilesWebMvcConfigurer>(1);
private ResourceLoader resourceLoader;
@Autowired(required = false)
public void setWebMvcConfigurers(List<TilesWebMvcConfigurer> webMvcConfigurers) {
if (!CollectionUtils.isEmpty(webMvcConfigurers)) {
this.webMvcConfigurers.addAll(webMvcConfigurers);
}
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
@Bean
public TilesConfigurer tilesConfigurer() {
TilesConfigurer configurer = new TilesConfigurer();
if (!this.webMvcConfigurers.isEmpty()) {
for (TilesWebMvcConfigurer webMvcConfigurer : this.webMvcConfigurers) {
webMvcConfigurer.configureTiles(configurer);
}
}
else {
Resource resource = this.resourceLoader.getResource("/WEB-INF/tiles.xml");
if (!resource.exists()) {
String[] noTilesDefinitions = new String[0];
configurer.setDefinitions(noTilesDefinitions);
}
}
return configurer;
}
static class TilesConfigurerNotPresentCondition extends BeanTypeNotPresentCondition {
private TilesConfigurerNotPresentCondition() {
super(TilesConfigurer.class);
}
}
}

76
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcVelocityConfiguration.java

@ -0,0 +1,76 @@ @@ -0,0 +1,76 @@
/*
* 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.annotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.util.CollectionUtils;
import org.springframework.web.servlet.view.velocity.VelocityConfigurer;
import java.util.ArrayList;
import java.util.List;
/**
* Configuration class that declares a
* {@link org.springframework.web.servlet.view.velocity.VelocityConfigurer
* VelocityConfigurer} bean. The configuration is conditional and applies
* only if there is no {@code VelocityConfigurer} bean already declared.
*
* <p>This configuration is imported when using {@link EnableWebMvc} if
* Velocity is available on the classpath. It can be customized by
* implementing {@link VelocityWebMvcConfigurer}.
*
* @author Rossen Stoyanchev
* @since 4.1
*/
@Configuration
@Conditional(WebMvcVelocityConfiguration.VelocityConfigurerNotPresentCondition.class)
public class WebMvcVelocityConfiguration {
private final List<VelocityWebMvcConfigurer> webMvcConfigurers = new ArrayList<VelocityWebMvcConfigurer>(1);
@Autowired(required = false)
public void setWebMvcConfigurers(List<VelocityWebMvcConfigurer> webMvcConfigurers) {
if (!CollectionUtils.isEmpty(webMvcConfigurers)) {
this.webMvcConfigurers.addAll(webMvcConfigurers);
}
}
@Bean
@Lazy
public VelocityConfigurer velocityConfigurer() {
VelocityConfigurer configurer = new VelocityConfigurer();
configurer.setResourceLoaderPath("/WEB-INF/");
for (VelocityWebMvcConfigurer webMvcConfigurer : this.webMvcConfigurers) {
webMvcConfigurer.configureVelocity(configurer);
}
return configurer;
}
static class VelocityConfigurerNotPresentCondition extends BeanTypeNotPresentCondition {
private VelocityConfigurerNotPresentCondition() {
super(VelocityConfigurer.class);
}
}
}

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

@ -0,0 +1,239 @@ @@ -0,0 +1,239 @@
/*
* 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.annotation;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.mock.web.test.MockHttpServletResponse;
import org.springframework.mock.web.test.MockServletConfig;
import org.springframework.mock.web.test.MockServletContext;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
import org.springframework.web.servlet.view.velocity.VelocityConfigurer;
import javax.servlet.ServletException;
import java.io.IOException;
import static org.junit.Assert.assertEquals;
/**
* Integration tests for view resolution with {@code @EnableWebMvc}.
*
* @author Rossen Stoyanchev
* @since 4.1
*/
public class ViewResolutionIntegrationTests {
@Rule
public final ExpectedException thrown = ExpectedException.none();
@Test
public void minimalFreemarkerConfig() throws Exception {
MockHttpServletResponse response = runTest(MinimalFreeMarkerWebConfig.class);
assertEquals("<html><body>Hello World!</body></html>", response.getContentAsString());
}
@Test
public void minimalVelocityConfig() throws Exception {
MockHttpServletResponse response = runTest(MinimalVelocityWebConfig.class);
assertEquals("<html><body>Hello World!</body></html>", response.getContentAsString());
}
@Test
public void minimalTilesConfig() throws Exception {
MockHttpServletResponse response = runTest(MinimalTilesWebConfig.class);
assertEquals("/WEB-INF/index.jsp", response.getForwardedUrl());
}
@Test
public void freemarker() throws Exception {
MockHttpServletResponse response = runTest(FreeMarkerWebConfig.class);
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);
assertEquals("/WEB-INF/index.jsp", response.getForwardedUrl());
}
@Test
public void freemarkerInvalidConfig() throws Exception {
this.thrown.expectMessage("It looks like you're trying to configure FreeMarker view resolution.");
runTest(InvalidFreeMarkerWebConfig.class);
}
@Test
public void velocityInvalidConfig() throws Exception {
this.thrown.expectMessage("It looks like you're trying to configure Velocity view resolution.");
runTest(InvalidVelocityWebConfig.class);
}
@Test
public void tilesInvalidConfig() throws Exception {
this.thrown.expectMessage("It looks like you're trying to configure Tiles view resolution.");
runTest(InvalidTilesWebConfig.class);
}
private MockHttpServletResponse runTest(Class<?> configClass) throws ServletException, IOException {
String basePath = "org/springframework/web/servlet/config/annotation";
MockServletContext servletContext = new MockServletContext(basePath);
MockServletConfig servletConfig = new MockServletConfig(servletContext);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
MockHttpServletResponse response = new MockHttpServletResponse();
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(configClass);
context.setServletContext(servletContext);
context.refresh();
DispatcherServlet servlet = new DispatcherServlet(context);
servlet.init(servletConfig);
servlet.service(request, response);
return response;
}
@Controller
static class SampleController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public String tiles(@ModelAttribute("model") ModelMap model) {
model.addAttribute("hello", "Hello World!");
return "index";
}
}
@EnableWebMvc
static abstract class AbstractWebConfig extends WebMvcConfigurerAdapter {
@Bean
public SampleController sampleController() {
return new SampleController();
}
}
@Configuration
static class MinimalFreeMarkerWebConfig extends AbstractWebConfig {
@Override
public void configureViewResolution(ViewResolutionRegistry registry) {
registry.freemarker();
}
}
@Configuration
static class MinimalVelocityWebConfig extends AbstractWebConfig {
@Override
public void configureViewResolution(ViewResolutionRegistry registry) {
registry.velocity();
}
}
@Configuration
static class MinimalTilesWebConfig extends AbstractWebConfig {
@Override
public void configureViewResolution(ViewResolutionRegistry registry) {
registry.tiles();
}
}
@Configuration
static class FreeMarkerWebConfig extends AbstractWebConfig implements FreeMarkerWebMvcConfigurer {
@Override
public void configureViewResolution(ViewResolutionRegistry registry) {
registry.freemarker();
}
@Override
public void configureFreeMarker(FreeMarkerConfigurer configurer) {
configurer.setTemplateLoaderPath("/WEB-INF/");
}
}
@Configuration
static class VelocityWebConfig extends AbstractWebConfig implements VelocityWebMvcConfigurer {
@Override
public void configureViewResolution(ViewResolutionRegistry registry) {
registry.velocity();
}
@Override
public void configureVelocity(VelocityConfigurer configurer) {
configurer.setResourceLoaderPath("/WEB-INF/");
}
}
@Configuration
static class TilesWebConfig extends AbstractWebConfig implements TilesWebMvcConfigurer {
@Override
public void configureViewResolution(ViewResolutionRegistry registry) {
registry.tiles();
}
@Override
public void configureTiles(TilesConfigurer configurer) {
configurer.setDefinitions("/WEB-INF/tiles.xml");
}
}
@Configuration
static class InvalidFreeMarkerWebConfig extends WebMvcConfigurationSupport {
// No @EnableWebMvc and no FreeMarkerConfigurer bean
@Override
public void configureViewResolution(ViewResolutionRegistry registry) {
registry.freemarker();
}
}
@Configuration
static class InvalidVelocityWebConfig extends WebMvcConfigurationSupport {
// No @EnableWebMvc and no VelocityConfigurer bean
@Override
public void configureViewResolution(ViewResolutionRegistry registry) {
registry.velocity();
}
}
@Configuration
static class InvalidTilesWebConfig extends WebMvcConfigurationSupport {
// No @EnableWebMvc and no TilesConfigurer bean
@Override
public void configureViewResolution(ViewResolutionRegistry registry) {
registry.tiles();
}
}
}

49
spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ViewResolutionRegistryTests.java

@ -19,15 +19,13 @@ package org.springframework.web.servlet.config.annotation; @@ -19,15 +19,13 @@ package org.springframework.web.servlet.config.annotation;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.web.context.support.StaticWebApplicationContext;
import org.springframework.web.servlet.view.BeanNameViewResolver;
import org.springframework.web.servlet.view.ContentNegotiatingViewResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
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 static org.junit.Assert.*;
@ -44,7 +42,7 @@ public class ViewResolutionRegistryTests { @@ -44,7 +42,7 @@ public class ViewResolutionRegistryTests {
@Before
public void setUp() {
registry = new ViewResolutionRegistry();
registry = new ViewResolutionRegistry(new StaticWebApplicationContext());
}
@Test
@ -100,25 +98,15 @@ public class ViewResolutionRegistryTests { @@ -100,25 +98,15 @@ public class ViewResolutionRegistryTests {
@Test
public void tilesViewResolution() {
registry.tiles().checkRefresh(true).definition("def1").definition("def2");
assertNotNull(registry.getViewResolvers());
assertEquals(1, registry.getViewResolvers().size());
assertEquals(TilesViewResolver.class, registry.getViewResolvers().get(0).getClass());
assertNotNull(registry.getTilesConfigurer());
TilesConfigurer configurer = registry.getTilesConfigurer();
DirectFieldAccessor configurerDirectFieldAccessor = new DirectFieldAccessor(configurer);
assertTrue((boolean) configurerDirectFieldAccessor.getPropertyValue("checkRefresh"));
assertNotNull(configurerDirectFieldAccessor.getPropertyValue("definitions"));
String[] definitions = (String[])configurerDirectFieldAccessor.getPropertyValue("definitions");
assertEquals(2, definitions.length);
assertEquals("def1", definitions[0]);
assertEquals("def2", definitions[1]);
this.registry.tiles();
assertNotNull(this.registry.getViewResolvers());
assertEquals(1, this.registry.getViewResolvers().size());
assertEquals(TilesViewResolver.class, this.registry.getViewResolvers().get(0).getClass());
}
@Test
public void velocityViewResolution() {
registry.velocity().prefix("/").suffix(".vm").cache(true).resourceLoaderPath("testResourceLoaderPath");
registry.velocity().prefix("/").suffix(".vm").cache(true);
assertNotNull(registry.getViewResolvers());
assertEquals(1, registry.getViewResolvers().size());
assertEquals(VelocityViewResolver.class, registry.getViewResolvers().get(0).getClass());
@ -127,11 +115,6 @@ public class ViewResolutionRegistryTests { @@ -127,11 +115,6 @@ public class ViewResolutionRegistryTests {
assertEquals("/", resolverDirectFieldAccessor.getPropertyValue("prefix"));
assertEquals(".vm", resolverDirectFieldAccessor.getPropertyValue("suffix"));
assertEquals(1024, resolverDirectFieldAccessor.getPropertyValue("cacheLimit"));
assertNotNull(registry.getVelocityConfigurer());
VelocityConfigurer configurer = registry.getVelocityConfigurer();
DirectFieldAccessor configurerDirectFieldAccessor = new DirectFieldAccessor(configurer);
assertEquals("testResourceLoaderPath", configurerDirectFieldAccessor.getPropertyValue("resourceLoaderPath"));
}
@Test
@ -144,16 +127,11 @@ public class ViewResolutionRegistryTests { @@ -144,16 +127,11 @@ public class ViewResolutionRegistryTests {
DirectFieldAccessor resolverDirectFieldAccessor = new DirectFieldAccessor(resolver);
assertEquals("", resolverDirectFieldAccessor.getPropertyValue("prefix"));
assertEquals(".vm", resolverDirectFieldAccessor.getPropertyValue("suffix"));
assertNotNull(registry.getVelocityConfigurer());
VelocityConfigurer configurer = registry.getVelocityConfigurer();
DirectFieldAccessor configurerDirectFieldAccessor = new DirectFieldAccessor(configurer);
assertEquals("/WEB-INF/", configurerDirectFieldAccessor.getPropertyValue("resourceLoaderPath"));
}
@Test
public void freeMarkerViewResolution() {
registry.freemarker().prefix("/").suffix(".fmt").cache(false).templateLoaderPath("path1", "path2");
registry.freemarker().prefix("/").suffix(".fmt").cache(false);
assertNotNull(registry.getViewResolvers());
assertEquals(1, registry.getViewResolvers().size());
assertEquals(FreeMarkerViewResolver.class, registry.getViewResolvers().get(0).getClass());
@ -162,15 +140,6 @@ public class ViewResolutionRegistryTests { @@ -162,15 +140,6 @@ public class ViewResolutionRegistryTests {
assertEquals("/", resolverDirectFieldAccessor.getPropertyValue("prefix"));
assertEquals(".fmt", resolverDirectFieldAccessor.getPropertyValue("suffix"));
assertEquals(0, resolverDirectFieldAccessor.getPropertyValue("cacheLimit"));
assertNotNull(registry.getFreeMarkerConfigurer());
FreeMarkerConfigurer configurer = registry.getFreeMarkerConfigurer();
DirectFieldAccessor configurerDirectFieldAccessor = new DirectFieldAccessor(configurer);
assertNotNull(configurerDirectFieldAccessor.getPropertyValue("templateLoaderPaths"));
String[] templateLoaderPaths = (String[])configurerDirectFieldAccessor.getPropertyValue("templateLoaderPaths");
assertEquals(2, templateLoaderPaths.length);
assertEquals("path1", templateLoaderPaths[0]);
assertEquals("path2", templateLoaderPaths[1]);
}
@Test
@ -183,8 +152,6 @@ public class ViewResolutionRegistryTests { @@ -183,8 +152,6 @@ public class ViewResolutionRegistryTests {
DirectFieldAccessor resolverDirectFieldAccessor = new DirectFieldAccessor(resolver);
assertEquals("", resolverDirectFieldAccessor.getPropertyValue("prefix"));
assertEquals(".ftl", resolverDirectFieldAccessor.getPropertyValue("suffix"));
DirectFieldAccessor configurerDirectFieldAccessor = new DirectFieldAccessor(registry.getFreeMarkerConfigurer());
assertArrayEquals(new String[]{"/WEB-INF/"}, (String[])configurerDirectFieldAccessor.getPropertyValue("templateLoaderPaths"));
}
@Test

1
spring-webmvc/src/test/resources/org/springframework/web/servlet/config/annotation/WEB-INF/index.ftl

@ -0,0 +1 @@ @@ -0,0 +1 @@
<html><body>${model.hello}</body></html>

12
spring-webmvc/src/test/resources/org/springframework/web/servlet/config/annotation/WEB-INF/index.jsp

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>My First Web Application Using Spring MVC</title>
</head>
<body>
${model.hello}
</body>
</html>

1
spring-webmvc/src/test/resources/org/springframework/web/servlet/config/annotation/WEB-INF/index.vm

@ -0,0 +1 @@ @@ -0,0 +1 @@
<html><body>${model.hello}</body></html>

7
spring-webmvc/src/test/resources/org/springframework/web/servlet/config/annotation/WEB-INF/tiles.xml

@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
<!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN" "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
<tiles-definitions>
<definition name="index" template="/WEB-INF/index.jsp" />
</tiles-definitions>
Loading…
Cancel
Save