From 18b8929335b3c14d190610a80bef58b2cf5095ca Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Thu, 18 Sep 2014 16:10:17 +0200 Subject: [PATCH] Migrate to groovy templates from Spring 4.1 Update `GroovyTemplateAutoConfiguration` to use Spring 4.1 Groovy Markup Template infrastructure instead of Boot's. Fixes gh-1552 --- .../GroovyTemplateAutoConfiguration.java | 116 ++++++++++-------- .../template/GroovyTemplateResolver.java | 7 ++ .../template/web/GroovyTemplateView.java | 2 - .../GroovyTemplateAutoConfigurationTests.java | 21 ++-- 4 files changed, 86 insertions(+), 60 deletions(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplateAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplateAutoConfiguration.java index 4a32921fc94..39f69a0e42c 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplateAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplateAutoConfiguration.java @@ -19,13 +19,13 @@ package org.springframework.boot.autoconfigure.groovy.template; import groovy.text.SimpleTemplateEngine; import groovy.text.TemplateEngine; import groovy.text.markup.MarkupTemplateEngine; -import groovy.text.markup.TemplateConfiguration; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.List; +import javax.annotation.PostConstruct; import javax.servlet.Servlet; import org.springframework.beans.factory.BeanClassLoaderAware; @@ -47,15 +47,21 @@ import org.springframework.core.Ordered; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; +import org.springframework.util.Assert; import org.springframework.web.servlet.view.UrlBasedViewResolver; +import org.springframework.web.servlet.view.groovy.GroovyMarkupConfig; +import org.springframework.web.servlet.view.groovy.GroovyMarkupConfigurer; +import org.springframework.web.servlet.view.groovy.GroovyMarkupViewResolver; /** * Autoconfiguration support for Groovy templates in MVC. By default creates a * {@link MarkupTemplateEngine} configured from {@link GroovyTemplateProperties}, but you - * can override that by providing a {@link TemplateEngine} of a different type. + * can override that by providing your own {@link GroovyMarkupConfig} or even a + * {@link MarkupTemplateEngine} of a different type. * * @author Dave Syer * @author Andy Wilkinson + * @author Brian Clozel * @since 1.1.0 */ @Configuration @@ -64,13 +70,49 @@ import org.springframework.web.servlet.view.UrlBasedViewResolver; @EnableConfigurationProperties(GroovyTemplateProperties.class) public class GroovyTemplateAutoConfiguration { - @Autowired - private final ResourceLoader resourceLoader = new DefaultResourceLoader(); + @Configuration + @ConditionalOnClass({ MarkupTemplateEngine.class, GroovyMarkupConfigurer.class }) + public static class GroovyMarkupConfiguration { + + @Autowired + private final ResourceLoader resourceLoader = new DefaultResourceLoader(); + + @Autowired + private GroovyTemplateProperties properties; + + @Autowired(required = false) + private MarkupTemplateEngine templateEngine; + + @PostConstruct + public void checkTemplateLocationExists() { + if (this.properties.isCheckTemplateLocation()) { + Resource resource = this.resourceLoader.getResource(this.properties + .getPrefix()); + Assert.state(resource.exists(), "Cannot find template location: " + + resource + " (please add some templates, " + + "check your Groovy configuration, or set " + + "spring.groovy.template.check-template-location=false)"); + } + } - @Autowired - private GroovyTemplateProperties properties; + @Bean + @ConditionalOnMissingBean(GroovyMarkupConfig.class) + @ConfigurationProperties(prefix = "spring.groovy.template.configuration") + public GroovyMarkupConfigurer groovyMarkupConfigurer() { + GroovyMarkupConfigurer configurer = new GroovyMarkupConfigurer(); + configurer.setResourceLoaderPath(this.properties.getPrefix()); + configurer.setCacheTemplates(this.properties.isCache()); + if (this.templateEngine != null) { + configurer.setTemplateEngine(this.templateEngine); + } + return configurer; + } - public abstract static class BaseGroovyTemplateConfiguration implements + } + + @Configuration + @ConditionalOnMissingClass(name = "groovy.text.markup.MarkupTemplateEngine") + public static class GroovySimpleTemplateEngineConfiguration implements BeanClassLoaderAware { @Autowired @@ -99,47 +141,12 @@ public class GroovyTemplateAutoConfiguration { return new URLClassLoader(urls.toArray(new URL[urls.size()]), this.classLoader); } - else { - return this.classLoader; - } + return this.classLoader; } - } - - @Configuration - @ConditionalOnClass(MarkupTemplateEngine.class) - public static class GroovyMarkupConfiguration extends BaseGroovyTemplateConfiguration { - - @Autowired - private GroovyTemplateProperties properties; - - @Bean - @ConfigurationProperties(prefix = "spring.groovy.template.configuration") - public TemplateConfiguration groovyTemplateConfiguration() { - return new TemplateConfiguration(); - } - - @Bean - @ConditionalOnMissingBean(TemplateEngine.class) - public TemplateEngine groovyTemplateEngine() throws Exception { - TemplateConfiguration configuration = groovyTemplateConfiguration(); - configuration.setCacheTemplates(this.properties.isCache()); - return new MarkupTemplateEngine(createParentLoaderForTemplates(), - configuration, new GroovyTemplateResolver()); - } - - } - - @Configuration - @ConditionalOnMissingClass(name = "groovy.text.markup.MarkupTemplateEngine") - public static class GroovySimpleConfiguration extends BaseGroovyTemplateConfiguration { - - @Autowired - private GroovyTemplateProperties properties; - @Bean @ConditionalOnMissingBean(TemplateEngine.class) - public TemplateEngine groovyTemplateEngine() throws Exception { + public SimpleTemplateEngine groovyTemplateEngine() throws Exception { return new SimpleTemplateEngine(createParentLoaderForTemplates()); } @@ -154,22 +161,35 @@ public class GroovyTemplateAutoConfiguration { @Autowired private GroovyTemplateProperties properties; + @Bean + @ConditionalOnMissingBean(name = "groovyMarkupViewResolver") + @ConditionalOnClass(MarkupTemplateEngine.class) + public GroovyMarkupViewResolver groovyMarkupViewResolver() { + GroovyMarkupViewResolver resolver = new GroovyMarkupViewResolver(); + configureViewResolver(resolver); + return resolver; + } + @Bean @ConditionalOnMissingBean(name = "groovyTemplateViewResolver") + @ConditionalOnMissingClass(MarkupTemplateEngine.class) public GroovyTemplateViewResolver groovyTemplateViewResolver(TemplateEngine engine) { GroovyTemplateViewResolver resolver = new GroovyTemplateViewResolver(); + configureViewResolver(resolver); resolver.setPrefix(this.properties.getPrefix()); + resolver.setTemplateEngine(engine); + return resolver; + } + + private void configureViewResolver(UrlBasedViewResolver resolver) { resolver.setSuffix(this.properties.getSuffix()); resolver.setCache(this.properties.isCache()); resolver.setContentType(this.properties.getContentType()); resolver.setViewNames(this.properties.getViewNames()); - resolver.setTemplateEngine(engine); - + resolver.setRequestContextAttribute("spring"); // This resolver acts as a fallback resolver (e.g. like a // InternalResourceViewResolver) so it needs to have low precedence resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 6); - - return resolver; } } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplateResolver.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplateResolver.java index 1c987638453..a724063860c 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplateResolver.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplateResolver.java @@ -23,6 +23,8 @@ import java.io.IOException; import java.net.URL; import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.web.servlet.view.groovy.GroovyMarkupConfigurer; +import org.springframework.web.servlet.view.groovy.GroovyMarkupViewResolver; /** * A custom {@link groovy.text.markup.TemplateResolver template resolver} which resolves @@ -31,8 +33,12 @@ import org.springframework.context.i18n.LocaleContextHolder; * * @author Cédric Champeau * @since 1.1.0 + * @deprecated since 1.2 in favor of Spring 4.1's {@link GroovyMarkupViewResolver} and + * {@link GroovyMarkupConfigurer}. */ +@Deprecated public class GroovyTemplateResolver implements TemplateResolver { + private ClassLoader templateClassLoader; @Override @@ -57,4 +63,5 @@ public class GroovyTemplateResolver implements TemplateResolver { } return resource; } + } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/web/GroovyTemplateView.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/web/GroovyTemplateView.java index f66d2a7c244..d9e2c8fe74a 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/web/GroovyTemplateView.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/web/GroovyTemplateView.java @@ -46,8 +46,6 @@ public class GroovyTemplateView extends AbstractUrlBasedView { protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception { applyContentType(response); - model.put("spring", new RequestContext(request, response, getServletContext(), - model)); this.template.make(model).writeTo(new BufferedWriter(response.getWriter())); } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplateAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplateAutoConfigurationTests.java index ea9563e690a..308dd6adf1a 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplateAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplateAutoConfigurationTests.java @@ -16,7 +16,7 @@ package org.springframework.boot.autoconfigure.groovy.template; -import groovy.text.TemplateEngine; +import groovy.text.markup.MarkupTemplateEngine; import java.io.File; import java.io.StringWriter; @@ -30,7 +30,6 @@ import javax.servlet.http.HttpServletRequest; import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.springframework.boot.autoconfigure.groovy.template.web.GroovyTemplateViewResolver; import org.springframework.boot.test.EnvironmentTestUtils; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.core.io.ClassPathResource; @@ -40,6 +39,8 @@ import org.springframework.mock.web.MockServletContext; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.View; import org.springframework.web.servlet.support.RequestContext; +import org.springframework.web.servlet.view.groovy.GroovyMarkupConfig; +import org.springframework.web.servlet.view.groovy.GroovyMarkupViewResolver; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; @@ -47,7 +48,7 @@ import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertThat; /** - * Tests for GroovyTemplateAutoConfiguration. + * Tests for {@link GroovyTemplateAutoConfiguration}. * * @author Dave Syer */ @@ -71,7 +72,7 @@ public class GroovyTemplateAutoConfigurationTests { @Test public void defaultConfiguration() { registerAndRefreshContext(); - assertThat(this.context.getBean(GroovyTemplateViewResolver.class), notNullValue()); + assertThat(this.context.getBean(GroovyMarkupViewResolver.class), notNullValue()); } @Test @@ -101,7 +102,6 @@ public class GroovyTemplateAutoConfigurationTests { @Test public void localeViewResolution() throws Exception { - LocaleContextHolder.setLocale(Locale.FRENCH); registerAndRefreshContext(); MockHttpServletResponse response = render("includes", Locale.FRENCH); String result = response.getContentAsString(); @@ -145,15 +145,15 @@ public class GroovyTemplateAutoConfigurationTests { @Test public void disableCache() { registerAndRefreshContext("spring.groovy.template.cache:false"); - assertThat( - this.context.getBean(GroovyTemplateViewResolver.class).getCacheLimit(), + assertThat(this.context.getBean(GroovyMarkupViewResolver.class).getCacheLimit(), equalTo(0)); } @Test public void renderTemplate() throws Exception { registerAndRefreshContext(); - TemplateEngine engine = this.context.getBean(TemplateEngine.class); + GroovyMarkupConfig config = this.context.getBean(GroovyMarkupConfig.class); + MarkupTemplateEngine engine = config.getTemplateEngine(); Writer writer = new StringWriter(); engine.createTemplate(new ClassPathResource("templates/message.tpl").getFile()) .make(new HashMap(Collections.singletonMap("greeting", @@ -173,8 +173,9 @@ public class GroovyTemplateAutoConfigurationTests { private MockHttpServletResponse render(String viewName, Locale locale) throws Exception { - GroovyTemplateViewResolver resolver = this.context - .getBean(GroovyTemplateViewResolver.class); + LocaleContextHolder.setLocale(locale); + GroovyMarkupViewResolver resolver = this.context + .getBean(GroovyMarkupViewResolver.class); View view = resolver.resolveViewName(viewName, locale); assertThat(view, notNullValue()); HttpServletRequest request = new MockHttpServletRequest();