Thymeleaf dialects now handled as @Autowired collection

This fixed the immediate problem with Thymeleaf, but leaves open
the question of how we can prevent other race conditions developing.
As long as the container can start handling requests before the Spring
context is refreshed this will be a source of bugs.

[Fixes #53482411] [bs-235] Race condition in Thymeleaf
This commit is contained in:
Dave Syer 2013-07-17 12:00:58 +01:00
parent 4de64c7f6b
commit b02be6e6ec
7 changed files with 75 additions and 33 deletions

View File

@ -21,7 +21,6 @@ import java.io.InputStream;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import javax.annotation.PostConstruct;
import javax.servlet.Servlet; import javax.servlet.Servlet;
import nz.net.ultraq.thymeleaf.LayoutDialect; import nz.net.ultraq.thymeleaf.LayoutDialect;
@ -33,12 +32,12 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.bootstrap.context.condition.ConditionalOnClass; import org.springframework.bootstrap.context.condition.ConditionalOnClass;
import org.springframework.bootstrap.context.condition.ConditionalOnMissingBean; import org.springframework.bootstrap.context.condition.ConditionalOnMissingBean;
import org.springframework.bootstrap.context.condition.ConditionalOnMissingClass;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
import org.thymeleaf.TemplateProcessingParameters; import org.thymeleaf.TemplateProcessingParameters;
import org.thymeleaf.dialect.IDialect;
import org.thymeleaf.extras.springsecurity3.dialect.SpringSecurityDialect; import org.thymeleaf.extras.springsecurity3.dialect.SpringSecurityDialect;
import org.thymeleaf.resourceresolver.IResourceResolver; import org.thymeleaf.resourceresolver.IResourceResolver;
import org.thymeleaf.spring3.SpringTemplateEngine; import org.thymeleaf.spring3.SpringTemplateEngine;
@ -107,19 +106,24 @@ public class ThymeleafAutoConfiguration {
} }
@Configuration @Configuration
@ConditionalOnMissingClass("nz.net.ultraq.thymeleaf.LayoutDialect")
@ConditionalOnMissingBean(SpringTemplateEngine.class) @ConditionalOnMissingBean(SpringTemplateEngine.class)
protected static class ThymeleafDefaultConfiguration { protected static class ThymeleafDefaultConfiguration {
@Autowired @Autowired
private Collection<ITemplateResolver> templateResolvers = Collections.emptySet(); private Collection<ITemplateResolver> templateResolvers = Collections.emptySet();
@Autowired(required = false)
private Collection<IDialect> dialects = Collections.emptySet();
@Bean @Bean
public SpringTemplateEngine templateEngine() { public SpringTemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine(); SpringTemplateEngine engine = new SpringTemplateEngine();
for (ITemplateResolver templateResolver : this.templateResolvers) { for (ITemplateResolver templateResolver : this.templateResolvers) {
engine.addTemplateResolver(templateResolver); engine.addTemplateResolver(templateResolver);
} }
for (IDialect dialect : this.dialects) {
engine.addDialect(dialect);
}
return engine; return engine;
} }
@ -127,20 +131,11 @@ public class ThymeleafAutoConfiguration {
@Configuration @Configuration
@ConditionalOnClass(name = "nz.net.ultraq.thymeleaf.LayoutDialect") @ConditionalOnClass(name = "nz.net.ultraq.thymeleaf.LayoutDialect")
@ConditionalOnMissingBean(SpringTemplateEngine.class)
protected static class ThymeleafWebLayoutConfiguration { protected static class ThymeleafWebLayoutConfiguration {
@Autowired
private Collection<ITemplateResolver> templateResolvers = Collections.emptySet();
@Bean @Bean
public SpringTemplateEngine templateEngine() { public LayoutDialect layoutDialect() {
SpringTemplateEngine engine = new SpringTemplateEngine(); return new LayoutDialect();
for (ITemplateResolver templateResolver : this.templateResolvers) {
engine.addTemplateResolver(templateResolver);
}
engine.addDialect(new LayoutDialect());
return engine;
} }
} }
@ -167,12 +162,9 @@ public class ThymeleafAutoConfiguration {
@ConditionalOnClass({ SpringSecurityDialect.class }) @ConditionalOnClass({ SpringSecurityDialect.class })
protected static class ThymeleafSecurityDialectConfiguration { protected static class ThymeleafSecurityDialectConfiguration {
@Autowired @Bean
private SpringTemplateEngine templateEngine; public SpringSecurityDialect securityDialect() {
return new SpringSecurityDialect();
@PostConstruct
public void configureThymeleafSecurity() {
this.templateEngine.addDialect(new SpringSecurityDialect());
} }
} }

View File

@ -99,7 +99,7 @@
<plugin> <plugin>
<artifactId>maven-plugin-plugin</artifactId> <artifactId>maven-plugin-plugin</artifactId>
<configuration> <configuration>
<goalPrefix>spring</goalPrefix> <goalPrefix>spring-package</goalPrefix>
</configuration> </configuration>
<executions> <executions>
<execution> <execution>

View File

@ -18,9 +18,11 @@
<module>spring-starter-batch</module> <module>spring-starter-batch</module>
<module>spring-starter-data-jpa</module> <module>spring-starter-data-jpa</module>
<module>spring-starter-integration</module> <module>spring-starter-integration</module>
<module>spring-starter-jetty</module>
<module>spring-starter-logging</module> <module>spring-starter-logging</module>
<module>spring-starter-parent</module> <module>spring-starter-parent</module>
<module>spring-starter-security</module> <module>spring-starter-security</module>
<module>spring-starter-tomcat</module>
<module>spring-starter-web</module> <module>spring-starter-web</module>
</modules> </modules>
</project> </project>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.zero</groupId>
<artifactId>spring-starters</artifactId>
<version>0.5.0.BUILD-SNAPSHOT</version>
</parent>
<artifactId>spring-starter-jetty</artifactId>
<packaging>jar</packaging>
<properties>
<main.basedir>${basedir}/../..</main.basedir>
</properties>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jsp</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -56,6 +56,11 @@
<artifactId>spring-starter-tomcat</artifactId> <artifactId>spring-starter-tomcat</artifactId>
<version>${spring.zero.version}</version> <version>${spring.zero.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.zero</groupId>
<artifactId>spring-starter-jetty</artifactId>
<version>${spring.zero.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.zero</groupId> <groupId>org.springframework.zero</groupId>
<artifactId>spring-starter-data-jpa</artifactId> <artifactId>spring-starter-data-jpa</artifactId>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.zero</groupId>
<artifactId>spring-starters</artifactId>
<version>0.5.0.BUILD-SNAPSHOT</version>
</parent>
<artifactId>spring-starter-tomcat</artifactId>
<packaging>jar</packaging>
<properties>
<main.basedir>${basedir}/../..</main.basedir>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-logging-juli</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -18,22 +18,15 @@
<artifactId>spring-starter</artifactId> <artifactId>spring-starter</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>spring-starter-tomcat</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId> <artifactId>jackson-databind</artifactId>
</dependency> </dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-logging-juli</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId> <artifactId>spring-webmvc</artifactId>