Commit 18b89293 authored by Brian Clozel's avatar Brian Clozel Committed by Dave Syer

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
parent 7dd6ae76
...@@ -19,13 +19,13 @@ package org.springframework.boot.autoconfigure.groovy.template; ...@@ -19,13 +19,13 @@ package org.springframework.boot.autoconfigure.groovy.template;
import groovy.text.SimpleTemplateEngine; import groovy.text.SimpleTemplateEngine;
import groovy.text.TemplateEngine; import groovy.text.TemplateEngine;
import groovy.text.markup.MarkupTemplateEngine; import groovy.text.markup.MarkupTemplateEngine;
import groovy.text.markup.TemplateConfiguration;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.annotation.PostConstruct;
import javax.servlet.Servlet; import javax.servlet.Servlet;
import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.BeanClassLoaderAware;
...@@ -47,15 +47,21 @@ import org.springframework.core.Ordered; ...@@ -47,15 +47,21 @@ import org.springframework.core.Ordered;
import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
import org.springframework.util.Assert;
import org.springframework.web.servlet.view.UrlBasedViewResolver; 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 * Autoconfiguration support for Groovy templates in MVC. By default creates a
* {@link MarkupTemplateEngine} configured from {@link GroovyTemplateProperties}, but you * {@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 Dave Syer
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Brian Clozel
* @since 1.1.0 * @since 1.1.0
*/ */
@Configuration @Configuration
...@@ -64,13 +70,49 @@ import org.springframework.web.servlet.view.UrlBasedViewResolver; ...@@ -64,13 +70,49 @@ import org.springframework.web.servlet.view.UrlBasedViewResolver;
@EnableConfigurationProperties(GroovyTemplateProperties.class) @EnableConfigurationProperties(GroovyTemplateProperties.class)
public class GroovyTemplateAutoConfiguration { public class GroovyTemplateAutoConfiguration {
@Autowired @Configuration
private final ResourceLoader resourceLoader = new DefaultResourceLoader(); @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 @Bean
private GroovyTemplateProperties properties; @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 { BeanClassLoaderAware {
@Autowired @Autowired
...@@ -99,47 +141,12 @@ public class GroovyTemplateAutoConfiguration { ...@@ -99,47 +141,12 @@ public class GroovyTemplateAutoConfiguration {
return new URLClassLoader(urls.toArray(new URL[urls.size()]), return new URLClassLoader(urls.toArray(new URL[urls.size()]),
this.classLoader); 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 @Bean
@ConditionalOnMissingBean(TemplateEngine.class) @ConditionalOnMissingBean(TemplateEngine.class)
public TemplateEngine groovyTemplateEngine() throws Exception { public SimpleTemplateEngine groovyTemplateEngine() throws Exception {
return new SimpleTemplateEngine(createParentLoaderForTemplates()); return new SimpleTemplateEngine(createParentLoaderForTemplates());
} }
...@@ -154,22 +161,35 @@ public class GroovyTemplateAutoConfiguration { ...@@ -154,22 +161,35 @@ public class GroovyTemplateAutoConfiguration {
@Autowired @Autowired
private GroovyTemplateProperties properties; private GroovyTemplateProperties properties;
@Bean
@ConditionalOnMissingBean(name = "groovyMarkupViewResolver")
@ConditionalOnClass(MarkupTemplateEngine.class)
public GroovyMarkupViewResolver groovyMarkupViewResolver() {
GroovyMarkupViewResolver resolver = new GroovyMarkupViewResolver();
configureViewResolver(resolver);
return resolver;
}
@Bean @Bean
@ConditionalOnMissingBean(name = "groovyTemplateViewResolver") @ConditionalOnMissingBean(name = "groovyTemplateViewResolver")
@ConditionalOnMissingClass(MarkupTemplateEngine.class)
public GroovyTemplateViewResolver groovyTemplateViewResolver(TemplateEngine engine) { public GroovyTemplateViewResolver groovyTemplateViewResolver(TemplateEngine engine) {
GroovyTemplateViewResolver resolver = new GroovyTemplateViewResolver(); GroovyTemplateViewResolver resolver = new GroovyTemplateViewResolver();
configureViewResolver(resolver);
resolver.setPrefix(this.properties.getPrefix()); resolver.setPrefix(this.properties.getPrefix());
resolver.setTemplateEngine(engine);
return resolver;
}
private void configureViewResolver(UrlBasedViewResolver resolver) {
resolver.setSuffix(this.properties.getSuffix()); resolver.setSuffix(this.properties.getSuffix());
resolver.setCache(this.properties.isCache()); resolver.setCache(this.properties.isCache());
resolver.setContentType(this.properties.getContentType()); resolver.setContentType(this.properties.getContentType());
resolver.setViewNames(this.properties.getViewNames()); resolver.setViewNames(this.properties.getViewNames());
resolver.setTemplateEngine(engine); resolver.setRequestContextAttribute("spring");
// This resolver acts as a fallback resolver (e.g. like a // This resolver acts as a fallback resolver (e.g. like a
// InternalResourceViewResolver) so it needs to have low precedence // InternalResourceViewResolver) so it needs to have low precedence
resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 6); resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 6);
return resolver;
} }
} }
......
...@@ -23,6 +23,8 @@ import java.io.IOException; ...@@ -23,6 +23,8 @@ import java.io.IOException;
import java.net.URL; import java.net.URL;
import org.springframework.context.i18n.LocaleContextHolder; 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 * A custom {@link groovy.text.markup.TemplateResolver template resolver} which resolves
...@@ -31,8 +33,12 @@ import org.springframework.context.i18n.LocaleContextHolder; ...@@ -31,8 +33,12 @@ import org.springframework.context.i18n.LocaleContextHolder;
* *
* @author Cédric Champeau * @author Cédric Champeau
* @since 1.1.0 * @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 { public class GroovyTemplateResolver implements TemplateResolver {
private ClassLoader templateClassLoader; private ClassLoader templateClassLoader;
@Override @Override
...@@ -57,4 +63,5 @@ public class GroovyTemplateResolver implements TemplateResolver { ...@@ -57,4 +63,5 @@ public class GroovyTemplateResolver implements TemplateResolver {
} }
return resource; return resource;
} }
} }
...@@ -46,8 +46,6 @@ public class GroovyTemplateView extends AbstractUrlBasedView { ...@@ -46,8 +46,6 @@ public class GroovyTemplateView extends AbstractUrlBasedView {
protected void renderMergedOutputModel(Map<String, Object> model, protected void renderMergedOutputModel(Map<String, Object> model,
HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest request, HttpServletResponse response) throws Exception {
applyContentType(response); applyContentType(response);
model.put("spring", new RequestContext(request, response, getServletContext(),
model));
this.template.make(model).writeTo(new BufferedWriter(response.getWriter())); this.template.make(model).writeTo(new BufferedWriter(response.getWriter()));
} }
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
package org.springframework.boot.autoconfigure.groovy.template; package org.springframework.boot.autoconfigure.groovy.template;
import groovy.text.TemplateEngine; import groovy.text.markup.MarkupTemplateEngine;
import java.io.File; import java.io.File;
import java.io.StringWriter; import java.io.StringWriter;
...@@ -30,7 +30,6 @@ import javax.servlet.http.HttpServletRequest; ...@@ -30,7 +30,6 @@ import javax.servlet.http.HttpServletRequest;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.autoconfigure.groovy.template.web.GroovyTemplateViewResolver;
import org.springframework.boot.test.EnvironmentTestUtils; import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
...@@ -40,6 +39,8 @@ import org.springframework.mock.web.MockServletContext; ...@@ -40,6 +39,8 @@ import org.springframework.mock.web.MockServletContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.View; import org.springframework.web.servlet.View;
import org.springframework.web.servlet.support.RequestContext; 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.containsString;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
...@@ -47,7 +48,7 @@ import static org.hamcrest.Matchers.notNullValue; ...@@ -47,7 +48,7 @@ import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
/** /**
* Tests for GroovyTemplateAutoConfiguration. * Tests for {@link GroovyTemplateAutoConfiguration}.
* *
* @author Dave Syer * @author Dave Syer
*/ */
...@@ -71,7 +72,7 @@ public class GroovyTemplateAutoConfigurationTests { ...@@ -71,7 +72,7 @@ public class GroovyTemplateAutoConfigurationTests {
@Test @Test
public void defaultConfiguration() { public void defaultConfiguration() {
registerAndRefreshContext(); registerAndRefreshContext();
assertThat(this.context.getBean(GroovyTemplateViewResolver.class), notNullValue()); assertThat(this.context.getBean(GroovyMarkupViewResolver.class), notNullValue());
} }
@Test @Test
...@@ -101,7 +102,6 @@ public class GroovyTemplateAutoConfigurationTests { ...@@ -101,7 +102,6 @@ public class GroovyTemplateAutoConfigurationTests {
@Test @Test
public void localeViewResolution() throws Exception { public void localeViewResolution() throws Exception {
LocaleContextHolder.setLocale(Locale.FRENCH);
registerAndRefreshContext(); registerAndRefreshContext();
MockHttpServletResponse response = render("includes", Locale.FRENCH); MockHttpServletResponse response = render("includes", Locale.FRENCH);
String result = response.getContentAsString(); String result = response.getContentAsString();
...@@ -145,15 +145,15 @@ public class GroovyTemplateAutoConfigurationTests { ...@@ -145,15 +145,15 @@ public class GroovyTemplateAutoConfigurationTests {
@Test @Test
public void disableCache() { public void disableCache() {
registerAndRefreshContext("spring.groovy.template.cache:false"); registerAndRefreshContext("spring.groovy.template.cache:false");
assertThat( assertThat(this.context.getBean(GroovyMarkupViewResolver.class).getCacheLimit(),
this.context.getBean(GroovyTemplateViewResolver.class).getCacheLimit(),
equalTo(0)); equalTo(0));
} }
@Test @Test
public void renderTemplate() throws Exception { public void renderTemplate() throws Exception {
registerAndRefreshContext(); registerAndRefreshContext();
TemplateEngine engine = this.context.getBean(TemplateEngine.class); GroovyMarkupConfig config = this.context.getBean(GroovyMarkupConfig.class);
MarkupTemplateEngine engine = config.getTemplateEngine();
Writer writer = new StringWriter(); Writer writer = new StringWriter();
engine.createTemplate(new ClassPathResource("templates/message.tpl").getFile()) engine.createTemplate(new ClassPathResource("templates/message.tpl").getFile())
.make(new HashMap<String, Object>(Collections.singletonMap("greeting", .make(new HashMap<String, Object>(Collections.singletonMap("greeting",
...@@ -173,8 +173,9 @@ public class GroovyTemplateAutoConfigurationTests { ...@@ -173,8 +173,9 @@ public class GroovyTemplateAutoConfigurationTests {
private MockHttpServletResponse render(String viewName, Locale locale) private MockHttpServletResponse render(String viewName, Locale locale)
throws Exception { throws Exception {
GroovyTemplateViewResolver resolver = this.context LocaleContextHolder.setLocale(locale);
.getBean(GroovyTemplateViewResolver.class); GroovyMarkupViewResolver resolver = this.context
.getBean(GroovyMarkupViewResolver.class);
View view = resolver.resolveViewName(viewName, locale); View view = resolver.resolveViewName(viewName, locale);
assertThat(view, notNullValue()); assertThat(view, notNullValue());
HttpServletRequest request = new MockHttpServletRequest(); HttpServletRequest request = new MockHttpServletRequest();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment