diff --git a/spring-boot-autoconfigure/pom.xml b/spring-boot-autoconfigure/pom.xml
index 1b510bdf7d1..7b40548dfb8 100644
--- a/spring-boot-autoconfigure/pom.xml
+++ b/spring-boot-autoconfigure/pom.xml
@@ -66,6 +66,11 @@
tomcat-jdbc
true
+
+ org.codehaus.groovy
+ groovy-templates
+ true
+
com.zaxxer
HikariCP
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
new file mode 100644
index 00000000000..210dfea3a7b
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplateAutoConfiguration.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2012-2013 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.boot.autoconfigure.groovy.template;
+
+import groovy.text.TemplateEngine;
+import groovy.text.markup.BaseTemplate;
+import groovy.text.markup.MarkupTemplateEngine;
+import groovy.text.markup.TemplateConfiguration;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+
+import javax.annotation.PostConstruct;
+import javax.servlet.Servlet;
+
+import org.springframework.beans.factory.BeanClassLoaderAware;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
+import org.springframework.boot.autoconfigure.groovy.template.web.GroovyTemplateViewResolver;
+import org.springframework.boot.autoconfigure.groovy.template.web.LocaleAwareTemplate;
+import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.i18n.LocaleContextHolder;
+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;
+
+/**
+ * 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.
+ *
+ * @author Dave Syer
+ * @since 1.1.0
+ */
+@Configuration
+@ConditionalOnClass(TemplateEngine.class)
+@AutoConfigureAfter(WebMvcAutoConfiguration.class)
+@EnableConfigurationProperties(GroovyTemplateProperties.class)
+public class GroovyTemplateAutoConfiguration {
+
+ @Autowired
+ private final ResourceLoader resourceLoader = new DefaultResourceLoader();
+
+ @Autowired
+ private GroovyTemplateProperties properties;
+
+ @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 "
+ + "or check your FreeMarker configuration)");
+ }
+ }
+
+ @Configuration
+ @ConditionalOnClass({ Servlet.class, LocaleContextHolder.class })
+ @ConditionalOnWebApplication
+ public static class GroovyWebConfiguration implements BeanClassLoaderAware {
+
+ @Autowired
+ private final ResourceLoader resourceLoader = new DefaultResourceLoader();
+
+ @Autowired
+ private GroovyTemplateProperties properties;
+
+ private ClassLoader classLoader = GroovyWebConfiguration.class.getClassLoader();
+
+ @Override
+ public void setBeanClassLoader(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+
+ @Bean
+ @ConditionalOnMissingBean(TemplateEngine.class)
+ public TemplateEngine groovyTemplateEngine() throws Exception {
+ TemplateConfiguration configuration = this.properties.getConfiguration();
+ if (configuration.getBaseTemplateClass() == BaseTemplate.class) {
+ // Enable locale-dependent includes
+ configuration.setBaseTemplateClass(LocaleAwareTemplate.class);
+ }
+ return new MarkupTemplateEngine(createParentLoaderForTemplates(),
+ configuration);
+ }
+
+ private ClassLoader createParentLoaderForTemplates() throws Exception {
+ return new URLClassLoader(new URL[] { this.resourceLoader.getResource(
+ this.properties.getPrefix()).getURL() }, this.classLoader);
+ }
+
+ @Bean
+ @ConditionalOnMissingBean(name = "groovyTemplateViewResolver")
+ public GroovyTemplateViewResolver groovyTemplateViewResolver(TemplateEngine engine) {
+ GroovyTemplateViewResolver resolver = new GroovyTemplateViewResolver();
+ resolver.setPrefix(this.properties.getPrefix());
+ resolver.setSuffix(this.properties.getSuffix());
+ resolver.setCache(this.properties.isCache());
+ resolver.setContentType(this.properties.getContentType());
+ resolver.setCharSet(this.properties.getCharSet());
+ resolver.setViewNames(this.properties.getViewNames());
+ resolver.setTemplateEngine(engine);
+
+ // 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/GroovyTemplateAvailabilityProvider.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplateAvailabilityProvider.java
new file mode 100644
index 00000000000..b188d2dd351
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplateAvailabilityProvider.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2012-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.boot.autoconfigure.groovy.template;
+
+import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider;
+import org.springframework.core.env.Environment;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.util.ClassUtils;
+
+/**
+ * {@link TemplateAvailabilityProvider} that provides availability information for Groovy
+ * view templates
+ *
+ * @author Dave Syer
+ * @since 1.1.0
+ */
+public class GroovyTemplateAvailabilityProvider implements TemplateAvailabilityProvider {
+
+ @Override
+ public boolean isTemplateAvailable(String view, Environment environment,
+ ClassLoader classLoader, ResourceLoader resourceLoader) {
+ if (ClassUtils.isPresent("groovy.text.TemplateEngine", classLoader)) {
+ String prefix = environment.getProperty("spring.groovy.template.prefix",
+ GroovyTemplateProperties.DEFAULT_PREFIX);
+ String suffix = environment.getProperty("spring.groovy.template.suffix",
+ GroovyTemplateProperties.DEFAULT_SUFFIX);
+ return resourceLoader.getResource(prefix + view + suffix).exists();
+ }
+ return false;
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplateProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplateProperties.java
new file mode 100644
index 00000000000..b60031c84dd
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplateProperties.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2012-2013 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.boot.autoconfigure.groovy.template;
+
+import groovy.text.markup.TemplateConfiguration;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * @author Dave Syer
+ * @since 1.1.0
+ */
+@ConfigurationProperties(prefix = "spring.groovy.template")
+public class GroovyTemplateProperties {
+
+ public static final String DEFAULT_PREFIX = "classpath:/templates/";
+
+ public static final String DEFAULT_SUFFIX = ".tpl";
+
+ private String prefix = DEFAULT_PREFIX;
+
+ private String suffix = DEFAULT_SUFFIX;
+
+ private boolean cache;
+
+ private String contentType = "text/html";
+
+ private String charSet = "UTF-8";
+
+ private String[] viewNames;
+
+ private boolean checkTemplateLocation = true;
+
+ private TemplateConfiguration configuration = new TemplateConfiguration();
+
+ public void setCheckTemplateLocation(boolean checkTemplateLocation) {
+ this.checkTemplateLocation = checkTemplateLocation;
+ }
+
+ public boolean isCheckTemplateLocation() {
+ return this.checkTemplateLocation;
+ }
+
+ public String[] getViewNames() {
+ return this.viewNames;
+ }
+
+ public void setViewNames(String[] viewNames) {
+ this.viewNames = viewNames;
+ }
+
+ public boolean isCache() {
+ return this.cache;
+ }
+
+ public void setCache(boolean cache) {
+ this.cache = cache;
+ }
+
+ public String getContentType() {
+ return this.contentType
+ + (this.contentType.contains(";charset=") ? "" : ";charset="
+ + this.charSet);
+ }
+
+ public void setContentType(String contentType) {
+ this.contentType = contentType;
+ }
+
+ public String getCharSet() {
+ return this.charSet;
+ }
+
+ public void setCharSet(String charSet) {
+ this.charSet = charSet;
+ }
+
+ public String getPrefix() {
+ return this.prefix;
+ }
+
+ public void setPrefix(String prefix) {
+ this.prefix = prefix;
+ }
+
+ public String getSuffix() {
+ return this.suffix;
+ }
+
+ public void setSuffix(String suffix) {
+ this.suffix = suffix;
+ }
+
+ public void setConfiguration(TemplateConfiguration configuration) {
+ this.configuration = configuration;
+ }
+
+ public TemplateConfiguration getConfiguration() {
+ return this.configuration;
+ }
+
+}
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
new file mode 100644
index 00000000000..423834ebbd1
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/web/GroovyTemplateView.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2012-2013 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.boot.autoconfigure.groovy.template.web;
+
+import groovy.text.Template;
+
+import java.io.BufferedWriter;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.web.servlet.view.AbstractUrlBasedView;
+
+/**
+ * @author Dave Syer
+ *
+ * @since 1.1.0
+ */
+public class GroovyTemplateView extends AbstractUrlBasedView {
+
+ private final Template template;
+
+ public GroovyTemplateView(Template template) {
+ this.template = template;
+ }
+
+ @Override
+ protected void renderMergedOutputModel(Map model,
+ HttpServletRequest request, HttpServletResponse response) throws Exception {
+ applyContentType(response);
+ this.template.make(model).writeTo(new BufferedWriter(response.getWriter()));
+ }
+
+ /**
+ * Apply this view's content type as specified in the "contentType" bean property to
+ * the given response.
+ * @param response current HTTP response
+ * @see #setContentType
+ */
+ protected void applyContentType(HttpServletResponse response) {
+ if (response.getContentType() == null) {
+ response.setContentType(getContentType());
+ }
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/web/GroovyTemplateViewResolver.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/web/GroovyTemplateViewResolver.java
new file mode 100644
index 00000000000..3f2d07ff23e
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/web/GroovyTemplateViewResolver.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2012-2013 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.boot.autoconfigure.groovy.template.web;
+
+import groovy.text.SimpleTemplateEngine;
+import groovy.text.Template;
+import groovy.text.TemplateEngine;
+
+import java.io.InputStreamReader;
+import java.util.Locale;
+
+import org.springframework.beans.propertyeditors.LocaleEditor;
+import org.springframework.core.io.Resource;
+import org.springframework.web.servlet.View;
+import org.springframework.web.servlet.view.UrlBasedViewResolver;
+
+/**
+ * @author Dave Syer
+ * @since 1.1.0
+ */
+public class GroovyTemplateViewResolver extends UrlBasedViewResolver {
+
+ private TemplateEngine engine = new SimpleTemplateEngine();
+
+ private String charSet = "UTF-8";
+
+ public GroovyTemplateViewResolver() {
+ setViewClass(GroovyTemplateView.class);
+ }
+
+ /**
+ * @param engine the engine to set
+ */
+ public void setTemplateEngine(TemplateEngine engine) {
+ this.engine = engine;
+ }
+
+ /**
+ * @param charSet the charSet to set
+ */
+ public void setCharSet(String charSet) {
+ this.charSet = charSet;
+ }
+
+ @Override
+ protected View loadView(String viewName, Locale locale) throws Exception {
+ Resource resource = resolveResource(viewName, locale);
+ if (resource == null) {
+ return null;
+ }
+ Template template = this.engine.createTemplate(new InputStreamReader(resource
+ .getInputStream(), this.charSet));
+ GroovyTemplateView view = new GroovyTemplateView(template);
+ view.setApplicationContext(getApplicationContext());
+ view.setServletContext(getServletContext());
+ view.setContentType(getContentType());
+ return view;
+ }
+
+ private Resource resolveResource(String viewName, Locale locale) {
+ String l10n = "";
+ if (locale != null) {
+ LocaleEditor localeEditor = new LocaleEditor();
+ localeEditor.setValue(locale);
+ l10n = "_" + localeEditor.getAsText();
+ }
+ return resolveFromLocale(viewName, l10n);
+ }
+
+ private Resource resolveFromLocale(String viewName, String locale) {
+ Resource resource = getApplicationContext().getResource(
+ getPrefix() + viewName + locale + getSuffix());
+ if (resource == null || !resource.exists()) {
+ if (locale.isEmpty()) {
+ return null;
+ }
+ int index = locale.lastIndexOf("_");
+ return resolveFromLocale(viewName, locale.substring(0, index));
+ }
+ return resource;
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/web/LocaleAwareTemplate.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/web/LocaleAwareTemplate.java
new file mode 100644
index 00000000000..8a5d1e739e8
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/groovy/template/web/LocaleAwareTemplate.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012-2013 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.boot.autoconfigure.groovy.template.web;
+
+import groovy.text.markup.BaseTemplate;
+import groovy.text.markup.MarkupTemplateEngine;
+import groovy.text.markup.TemplateConfiguration;
+
+import java.util.Map;
+
+import org.springframework.context.i18n.LocaleContextHolder;
+
+/**
+ * @author Dave Syer
+ */
+public abstract class LocaleAwareTemplate extends BaseTemplate {
+
+ public LocaleAwareTemplate(MarkupTemplateEngine templateEngine, Map, ?> model,
+ Map modelTypes, TemplateConfiguration configuration) {
+ super(localize(templateEngine), model, modelTypes, localize(configuration));
+ }
+
+ private static MarkupTemplateEngine localize(MarkupTemplateEngine templateEngine) {
+ TemplateConfiguration templateConfiguration = templateEngine
+ .getTemplateConfiguration();
+ ClassLoader parent = templateEngine.getTemplateLoader().getParent();
+ return new MarkupTemplateEngine(parent, localize(templateConfiguration));
+ }
+
+ private static TemplateConfiguration localize(TemplateConfiguration configuration) {
+ TemplateConfiguration result = new TemplateConfiguration(configuration);
+ result.setLocale(LocaleContextHolder.getLocale());
+ return result;
+ }
+
+}
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
new file mode 100644
index 00000000000..d9d12304c71
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/groovy/template/GroovyTemplateAutoConfigurationTests.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2012-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.boot.autoconfigure.groovy.template;
+
+import groovy.text.TemplateEngine;
+
+import java.io.File;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Locale;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.beans.factory.BeanCreationException;
+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;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+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 static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Tests for GroovyTemplateAutoConfiguration.
+ *
+ * @author Dave Syer
+ */
+public class GroovyTemplateAutoConfigurationTests {
+
+ private AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
+
+ @Before
+ public void setupContext() {
+ this.context.setServletContext(new MockServletContext());
+ }
+
+ @After
+ public void close() {
+ LocaleContextHolder.resetLocaleContext();
+ if (this.context != null) {
+ this.context.close();
+ }
+ }
+
+ @Test
+ public void defaultConfiguration() {
+ registerAndRefreshContext();
+ assertThat(this.context.getBean(GroovyTemplateViewResolver.class), notNullValue());
+ }
+
+ @Test(expected = BeanCreationException.class)
+ public void nonExistentTemplateLocation() {
+ registerAndRefreshContext("spring.groovy.template.prefix:"
+ + "classpath:/does-not-exist/");
+ }
+
+ @Test
+ public void emptyTemplateLocation() {
+ new File("target/test-classes/templates/empty-directory").mkdir();
+ registerAndRefreshContext("spring.groovy.template.prefix:"
+ + "classpath:/templates/empty-directory/");
+ }
+
+ @Test
+ public void defaultViewResolution() throws Exception {
+ registerAndRefreshContext();
+ MockHttpServletResponse response = render("home");
+ String result = response.getContentAsString();
+ assertThat(result, containsString("home"));
+ assertThat(response.getContentType(), equalTo("text/html;charset=UTF-8"));
+ }
+
+ @Test
+ public void includesViewResolution() throws Exception {
+ registerAndRefreshContext();
+ MockHttpServletResponse response = render("includes");
+ String result = response.getContentAsString();
+ assertThat(result, containsString("here"));
+ assertThat(response.getContentType(), equalTo("text/html;charset=UTF-8"));
+ }
+
+ @Test
+ public void localeViewResolution() throws Exception {
+ LocaleContextHolder.setLocale(Locale.FRENCH);
+ registerAndRefreshContext();
+ MockHttpServletResponse response = render("includes", Locale.FRENCH);
+ String result = response.getContentAsString();
+ assertThat(result, containsString("voila"));
+ assertThat(response.getContentType(), equalTo("text/html;charset=UTF-8"));
+ }
+
+ @Test
+ public void customContentType() throws Exception {
+ registerAndRefreshContext("spring.groovy.template.contentType:application/json");
+ MockHttpServletResponse response = render("home");
+ String result = response.getContentAsString();
+ assertThat(result, containsString("home"));
+ assertThat(response.getContentType(), equalTo("application/json;charset=UTF-8"));
+ }
+
+ @Test
+ public void customPrefix() throws Exception {
+ registerAndRefreshContext("spring.groovy.template.prefix:classpath:/templates/prefix/");
+ MockHttpServletResponse response = render("prefixed");
+ String result = response.getContentAsString();
+ assertThat(result, containsString("prefixed"));
+ }
+
+ @Test
+ public void customSuffix() throws Exception {
+ registerAndRefreshContext("spring.groovy.template.suffix:.groovytemplate");
+ MockHttpServletResponse response = render("suffixed");
+ String result = response.getContentAsString();
+ assertThat(result, containsString("suffixed"));
+ }
+
+ @Test
+ public void customTemplateLoaderPath() throws Exception {
+ registerAndRefreshContext("spring.groovy.template.prefix:classpath:/custom-templates/");
+ MockHttpServletResponse response = render("custom");
+ String result = response.getContentAsString();
+ assertThat(result, containsString("custom"));
+ }
+
+ @Test
+ public void disableCache() {
+ registerAndRefreshContext("spring.groovy.template.cache:false");
+ assertThat(
+ this.context.getBean(GroovyTemplateViewResolver.class).getCacheLimit(),
+ equalTo(0));
+ }
+
+ @Test
+ public void renderTemplate() throws Exception {
+ registerAndRefreshContext();
+ TemplateEngine engine = this.context.getBean(TemplateEngine.class);
+ Writer writer = new StringWriter();
+ engine.createTemplate(new ClassPathResource("templates/message.tpl").getFile())
+ .make(new HashMap(Collections.singletonMap("greeting",
+ "Hello World"))).writeTo(writer);
+ assertThat(writer.toString(), containsString("Hello World"));
+ }
+
+ private void registerAndRefreshContext(String... env) {
+ EnvironmentTestUtils.addEnvironment(this.context, env);
+ this.context.register(GroovyTemplateAutoConfiguration.class);
+ this.context.refresh();
+ }
+
+ private MockHttpServletResponse render(String viewName) throws Exception {
+ return render(viewName, Locale.UK);
+ }
+
+ private MockHttpServletResponse render(String viewName, Locale locale)
+ throws Exception {
+ GroovyTemplateViewResolver resolver = this.context
+ .getBean(GroovyTemplateViewResolver.class);
+ View view = resolver.resolveViewName(viewName, locale);
+ assertThat(view, notNullValue());
+ HttpServletRequest request = new MockHttpServletRequest();
+ request.setAttribute(RequestContext.WEB_APPLICATION_CONTEXT_ATTRIBUTE,
+ this.context);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ view.render(null, request, response);
+ return response;
+ }
+}
diff --git a/spring-boot-autoconfigure/src/test/resources/custom-templates/custom.tpl b/spring-boot-autoconfigure/src/test/resources/custom-templates/custom.tpl
new file mode 100644
index 00000000000..06b9992513a
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/resources/custom-templates/custom.tpl
@@ -0,0 +1 @@
+yield "custom"
\ No newline at end of file
diff --git a/spring-boot-autoconfigure/src/test/resources/templates/home.tpl b/spring-boot-autoconfigure/src/test/resources/templates/home.tpl
new file mode 100644
index 00000000000..eb07ff6f939
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/resources/templates/home.tpl
@@ -0,0 +1 @@
+yield "home"
\ No newline at end of file
diff --git a/spring-boot-autoconfigure/src/test/resources/templates/included.tpl b/spring-boot-autoconfigure/src/test/resources/templates/included.tpl
new file mode 100644
index 00000000000..a1bbaa02e9a
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/resources/templates/included.tpl
@@ -0,0 +1 @@
+yield "here"
\ No newline at end of file
diff --git a/spring-boot-autoconfigure/src/test/resources/templates/included_fr.tpl b/spring-boot-autoconfigure/src/test/resources/templates/included_fr.tpl
new file mode 100644
index 00000000000..035e2e95759
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/resources/templates/included_fr.tpl
@@ -0,0 +1 @@
+yield "voila"
\ No newline at end of file
diff --git a/spring-boot-autoconfigure/src/test/resources/templates/includes.tpl b/spring-boot-autoconfigure/src/test/resources/templates/includes.tpl
new file mode 100644
index 00000000000..9ea4039123d
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/resources/templates/includes.tpl
@@ -0,0 +1,2 @@
+yield "include"
+include template: "included.tpl"
\ No newline at end of file
diff --git a/spring-boot-autoconfigure/src/test/resources/templates/message.tpl b/spring-boot-autoconfigure/src/test/resources/templates/message.tpl
new file mode 100644
index 00000000000..6a9df3b50d1
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/resources/templates/message.tpl
@@ -0,0 +1 @@
+yield "Message: ${greeting}"
\ No newline at end of file
diff --git a/spring-boot-autoconfigure/src/test/resources/templates/prefix/prefixed.tpl b/spring-boot-autoconfigure/src/test/resources/templates/prefix/prefixed.tpl
new file mode 100644
index 00000000000..c9c6c42d6c9
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/resources/templates/prefix/prefixed.tpl
@@ -0,0 +1 @@
+yield "prefixed"
\ No newline at end of file
diff --git a/spring-boot-autoconfigure/src/test/resources/templates/suffixed.groovytemplate b/spring-boot-autoconfigure/src/test/resources/templates/suffixed.groovytemplate
new file mode 100644
index 00000000000..3539f6d6f4a
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/resources/templates/suffixed.groovytemplate
@@ -0,0 +1,3 @@
+yield """
+suffixed
+"""
\ No newline at end of file
diff --git a/spring-boot-dependencies/pom.xml b/spring-boot-dependencies/pom.xml
index d9d2b382dc1..0b92ca8cdc8 100644
--- a/spring-boot-dependencies/pom.xml
+++ b/spring-boot-dependencies/pom.xml
@@ -106,8 +106,9 @@
1.1.0.RELEASE
1.3.2.RELEASE
1.1.1.RELEASE
+ 1.1.0.RELEASE
3.2.3.RELEASE
- 2.0.0.RC2
+ 2.0.0.RELEASE
1.0.2.RELEASE
2.1.3.RELEASE
2.1.1.RELEASE
@@ -994,6 +995,11 @@
spring-mobile-device
${spring-mobile.version}
+
+ org.springframework.retry
+ spring-retry
+ ${spring-retry.version}
+
org.springframework.security
spring-security-acl