Only apply non-null Groovy Template properties

Previously, properties were always applied even when they had a null
value. When using the property defaults, this would leave the
GroovyMarkupConfigurer bean with null values for autoIndentString,
locale, and newLineString. The null values could cause problems at
runtime, for example an NPE when Groovy Templates tries to call
toString on the null newLineString.

Closes gh-47139
This commit is contained in:
Andy Wilkinson
2025-09-10 10:53:19 +01:00
parent 3ca81e3227
commit 1b00d38fda
2 changed files with 43 additions and 2 deletions
@@ -115,7 +115,7 @@ public class GroovyTemplateAutoConfiguration {
GroovyMarkupConfigurer groovyMarkupConfigurer(ObjectProvider<MarkupTemplateEngine> templateEngine,
Environment environment) {
GroovyMarkupConfigurer configurer = new GroovyMarkupConfigurer();
PropertyMapper map = PropertyMapper.get();
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
map.from(this.properties::isAutoEscape).to(configurer::setAutoEscape);
map.from(this.properties::isAutoIndent).to(configurer::setAutoIndent);
map.from(this.properties::getAutoIndentString).to(configurer::setAutoIndentString);
@@ -25,6 +25,7 @@ import java.util.Locale;
import java.util.Map;
import groovy.text.markup.BaseTemplate;
import groovy.text.markup.DelegatingIndentWriter;
import groovy.text.markup.MarkupTemplateEngine;
import groovy.text.markup.TemplateConfiguration;
import jakarta.servlet.http.HttpServletRequest;
@@ -159,9 +160,16 @@ class GroovyTemplateAutoConfigurationTests {
assertThat(result).contains("suffixed");
}
@Test
void defaultResourceLoaderPath() throws Exception {
registerAndRefreshContext();
assertThat(this.context.getBean(GroovyMarkupConfigurer.class).getResourceLoaderPath())
.isEqualTo(GroovyTemplateProperties.DEFAULT_RESOURCE_LOADER_PATH);
}
@Test
@WithResource(name = "custom-templates/custom.tpl", content = "yield \"custom\"")
void customTemplateLoaderPath() throws Exception {
void customResourceLoaderPath() throws Exception {
registerAndRefreshContext("spring.groovy.template.resource-loader-path:classpath:/custom-templates/");
MockHttpServletResponse response = render("custom");
String result = response.getContentAsString();
@@ -206,6 +214,13 @@ class GroovyTemplateAutoConfigurationTests {
assertThat(this.context.getBean(GroovyMarkupConfigurer.class).isAutoIndent()).isTrue();
}
@Test
void defaultAutoIndentString() {
registerAndRefreshContext();
assertThat(this.context.getBean(GroovyMarkupConfigurer.class).getAutoIndentString())
.isEqualTo(DelegatingIndentWriter.SPACES);
}
@Test
void customAutoIndentString() {
registerAndRefreshContext("spring.groovy.template.auto-indent-string:\\t");
@@ -218,6 +233,13 @@ class GroovyTemplateAutoConfigurationTests {
assertThat(this.context.getBean(GroovyMarkupConfigurer.class).isAutoNewLine()).isTrue();
}
@Test
void defaultBaseTemplateClass() {
registerAndRefreshContext();
assertThat(this.context.getBean(GroovyMarkupConfigurer.class).getBaseTemplateClass())
.isEqualTo(BaseTemplate.class);
}
@Test
void customBaseTemplateClass() {
registerAndRefreshContext("spring.groovy.template.base-template-class:" + CustomBaseTemplate.class.getName());
@@ -225,6 +247,12 @@ class GroovyTemplateAutoConfigurationTests {
.isEqualTo(CustomBaseTemplate.class);
}
@Test
void defaultDeclarationEncoding() {
registerAndRefreshContext();
assertThat(this.context.getBean(GroovyMarkupConfigurer.class).getDeclarationEncoding()).isNull();
}
@Test
void customDeclarationEncoding() {
registerAndRefreshContext("spring.groovy.template.declaration-encoding:UTF-8");
@@ -237,12 +265,25 @@ class GroovyTemplateAutoConfigurationTests {
assertThat(this.context.getBean(GroovyMarkupConfigurer.class).isExpandEmptyElements()).isTrue();
}
@Test
void defaultLocale() {
registerAndRefreshContext();
assertThat(this.context.getBean(GroovyMarkupConfigurer.class).getLocale()).isEqualTo(Locale.getDefault());
}
@Test
void customLocale() {
registerAndRefreshContext("spring.groovy.template.locale:en_US");
assertThat(this.context.getBean(GroovyMarkupConfigurer.class).getLocale()).isEqualTo(Locale.US);
}
@Test
void defaultNewLineString() {
registerAndRefreshContext();
assertThat(this.context.getBean(GroovyMarkupConfigurer.class).getNewLineString())
.isEqualTo(System.lineSeparator());
}
@Test
void customNewLineString() {
registerAndRefreshContext("spring.groovy.template.new-line-string:\\r\\n");