Skip to content

Commit 95d65c2

Browse files
author
Dave Syer
committed
Add indirection to avoid runtime dependency on MVC in templates
Velocity and Freemarker share some common properties so the base class for configuring their properties makes some sense. Unfortunately the implementation pulls in Spring MVC at runtime because of the signature of one method (that would never be called). We can fix that in a number of ways, but the least disruptive is probably to change the signature of that method and only refer to the concrete template view resolver type if the method is called. Fixes gh-1437
1 parent f4dc090 commit 95d65c2

File tree

11 files changed

+183
-18
lines changed

11 files changed

+183
-18
lines changed

spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/freemarker/FreeMarkerProperties.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121

2222
import org.springframework.boot.autoconfigure.template.AbstractTemplateViewResolverProperties;
2323
import org.springframework.boot.context.properties.ConfigurationProperties;
24-
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
2524

2625
/**
2726
* {@link ConfigurationProperties} for configuring FreeMarker
@@ -63,11 +62,4 @@ public void setTemplateLoaderPath(String templateLoaderPath) {
6362
this.templateLoaderPath = templateLoaderPath;
6463
}
6564

66-
/**
67-
* Apply the given properties to a {@link FreeMarkerViewResolver}.
68-
* @param resolver the resolver to apply the properties to.
69-
*/
70-
public void applyToViewResolver(FreeMarkerViewResolver resolver) {
71-
super.applyToViewResolver(resolver);
72-
}
7365
}

spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/template/AbstractTemplateViewResolverProperties.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import org.springframework.boot.context.properties.ConfigurationProperties;
2020
import org.springframework.core.Ordered;
21+
import org.springframework.util.Assert;
2122
import org.springframework.web.servlet.view.AbstractTemplateViewResolver;
2223

2324
/**
@@ -158,10 +159,18 @@ public void setExposeSpringMacroHelpers(boolean exposeSpringMacroHelpers) {
158159
}
159160

160161
/**
161-
* Apply the given properties to a {@link AbstractTemplateViewResolver}.
162-
* @param resolver the resolver to apply the properties to.
162+
* Apply the given properties to a {@link AbstractTemplateViewResolver}. Use Object in
163+
* signature to avoid runtime dependency on MVC, which means that the template engine
164+
* can be used in a non-web application.
165+
*
166+
* @param viewResolver the resolver to apply the properties to.
163167
*/
164-
protected void applyToViewResolver(AbstractTemplateViewResolver resolver) {
168+
public void applyToViewResolver(Object viewResolver) {
169+
170+
Assert.isInstanceOf(AbstractTemplateViewResolver.class, viewResolver,
171+
"ViewResolver is not an instance of AbstractTemplateViewResolver :"
172+
+ viewResolver);
173+
AbstractTemplateViewResolver resolver = (AbstractTemplateViewResolver) viewResolver;
165174
resolver.setPrefix(getPrefix());
166175
resolver.setSuffix(getSuffix());
167176
resolver.setCache(isCache());
@@ -175,6 +184,7 @@ protected void applyToViewResolver(AbstractTemplateViewResolver resolver) {
175184
// The resolver usually acts as a fallback resolver (e.g. like a
176185
// InternalResourceViewResolver) so it needs to have low precedence
177186
resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 5);
187+
178188
}
179189

180190
}

spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/velocity/VelocityAutoConfiguration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ public VelocityConfigurer velocityConfigurer() {
118118
@Bean
119119
public VelocityEngine velocityEngine(VelocityConfigurer configurer)
120120
throws VelocityException, IOException {
121-
return configurer.createVelocityEngine();
121+
return configurer.getVelocityEngine();
122122
}
123123

124124
@Bean

spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/velocity/VelocityProperties.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,10 @@ public void setToolboxConfigLocation(String toolboxConfigLocation) {
9292
this.toolboxConfigLocation = toolboxConfigLocation;
9393
}
9494

95-
/**
96-
* Apply the given properties to a {@link VelocityViewResolver}.
97-
* @param resolver the resolver to apply the properties to.
98-
*/
99-
public void applyToViewResolver(VelocityViewResolver resolver) {
100-
super.applyToViewResolver(resolver);
95+
@Override
96+
public void applyToViewResolver(Object viewResolver) {
97+
super.applyToViewResolver(viewResolver);
98+
VelocityViewResolver resolver = (VelocityViewResolver) viewResolver;
10199
resolver.setToolboxConfigLocation(getToolboxConfigLocation());
102100
resolver.setDateToolAttribute(getDateToolAttribute());
103101
resolver.setNumberToolAttribute(getNumberToolAttribute());

spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ public void customize(Context context) {
275275
public void customize(Connector connector) {
276276
ProtocolHandler handler = connector.getProtocolHandler();
277277
if (handler instanceof AbstractProtocol) {
278+
@SuppressWarnings("rawtypes")
278279
AbstractProtocol protocol = (AbstractProtocol) handler;
279280
protocol.setMaxThreads(Tomcat.this.maxThreads);
280281
}
@@ -288,6 +289,7 @@ public void customize(Connector connector) {
288289
public void customize(Connector connector) {
289290
ProtocolHandler handler = connector.getProtocolHandler();
290291
if (handler instanceof AbstractHttp11Protocol) {
292+
@SuppressWarnings("rawtypes")
291293
AbstractHttp11Protocol protocol = (AbstractHttp11Protocol) handler;
292294
protocol.setMaxHttpHeaderSize(Tomcat.this.maxHttpHeaderSize);
293295
}

spring-boot-samples/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
<module>spring-boot-sample-tomcat-multi-connectors</module>
4949
<module>spring-boot-sample-tomcat8-jsp</module>
5050
<module>spring-boot-sample-traditional</module>
51+
<module>spring-boot-sample-velocity</module>
5152
<module>spring-boot-sample-web-freemarker</module>
5253
<module>spring-boot-sample-web-groovy-templates</module>
5354
<module>spring-boot-sample-web-method-security</module>
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<parent>
5+
<!-- Your own application should inherit from spring-boot-starter-parent -->
6+
<groupId>org.springframework.boot</groupId>
7+
<artifactId>spring-boot-samples</artifactId>
8+
<version>1.1.6.BUILD-SNAPSHOT</version>
9+
</parent>
10+
<artifactId>spring-boot-sample-velocity</artifactId>
11+
<name>spring-boot-sample-velocity</name>
12+
<description>Spring Boot Web Velocity Sample</description>
13+
<url>http://projects.spring.io/spring-boot/</url>
14+
<organization>
15+
<name>Pivotal Software, Inc.</name>
16+
<url>http://www.spring.io</url>
17+
</organization>
18+
<properties>
19+
<main.basedir>${basedir}/../..</main.basedir>
20+
<m2eclipse.wtp.contextRoot>/</m2eclipse.wtp.contextRoot>
21+
</properties>
22+
<dependencies>
23+
<dependency>
24+
<groupId>org.springframework.boot</groupId>
25+
<artifactId>spring-boot-starter</artifactId>
26+
</dependency>
27+
<dependency>
28+
<groupId>org.springframework</groupId>
29+
<artifactId>spring-context-support</artifactId>
30+
</dependency>
31+
<dependency>
32+
<groupId>org.apache.velocity</groupId>
33+
<artifactId>velocity</artifactId>
34+
</dependency>
35+
<dependency>
36+
<groupId>org.springframework.boot</groupId>
37+
<artifactId>spring-boot-starter-test</artifactId>
38+
<scope>test</scope>
39+
</dependency>
40+
</dependencies>
41+
<build>
42+
<plugins>
43+
<plugin>
44+
<groupId>org.springframework.boot</groupId>
45+
<artifactId>spring-boot-maven-plugin</artifactId>
46+
</plugin>
47+
<plugin>
48+
<groupId>org.apache.maven.plugins</groupId>
49+
<artifactId>maven-surefire-plugin</artifactId>
50+
<configuration>
51+
<useSystemClassLoader>false</useSystemClassLoader>
52+
</configuration>
53+
</plugin>
54+
</plugins>
55+
</build>
56+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2012-2014 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package sample.velocity;
18+
19+
import java.util.Date;
20+
import java.util.HashMap;
21+
import java.util.Map;
22+
23+
import org.apache.velocity.app.VelocityEngine;
24+
import org.springframework.beans.factory.annotation.Autowired;
25+
import org.springframework.beans.factory.annotation.Value;
26+
import org.springframework.boot.CommandLineRunner;
27+
import org.springframework.boot.SpringApplication;
28+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
29+
import org.springframework.context.annotation.ComponentScan;
30+
import org.springframework.context.annotation.Configuration;
31+
import org.springframework.ui.velocity.VelocityEngineUtils;
32+
33+
@Configuration
34+
@EnableAutoConfiguration
35+
@ComponentScan
36+
public class SampleVelocityApplication implements CommandLineRunner {
37+
38+
@Value("${application.message}")
39+
private String message;
40+
41+
@Autowired
42+
private VelocityEngine engine;
43+
44+
@Override
45+
public void run(String... args) throws Exception {
46+
Map<String, Object> model = new HashMap<String, Object>();
47+
model.put("time", new Date());
48+
model.put("message", this.message);
49+
System.out.println(VelocityEngineUtils.mergeTemplateIntoString(this.engine,
50+
"welcome.vm", "UTF-8", model));
51+
}
52+
53+
public static void main(String[] args) throws Exception {
54+
SpringApplication.run(SampleVelocityApplication.class, args);
55+
}
56+
57+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
application.message: Hello, Andy
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
From application: $time
2+
Message: $message

0 commit comments

Comments
 (0)