diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfiguration.java
index e84c8f4c27..d7bc956638 100644
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfiguration.java
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfiguration.java
@@ -114,10 +114,9 @@ public class MustacheAutoConfiguration {
@Bean
@ConditionalOnMissingBean(MustacheViewResolver.class)
public MustacheViewResolver mustacheViewResolver(Compiler mustacheCompiler) {
- MustacheViewResolver resolver = new MustacheViewResolver();
+ MustacheViewResolver resolver = new MustacheViewResolver(mustacheCompiler);
this.mustache.applyToViewResolver(resolver);
resolver.setCharset(this.mustache.getCharsetName());
- resolver.setCompiler(mustacheCompiler);
resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 10);
return resolver;
}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheView.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheView.java
index f877b2bbb6..7fbe995aca 100644
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheView.java
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheView.java
@@ -16,58 +16,84 @@
package org.springframework.boot.autoconfigure.mustache.servlet;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.Locale;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import com.samskivert.mustache.Mustache;
import com.samskivert.mustache.Template;
+import org.springframework.core.io.Resource;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.view.AbstractTemplateView;
/**
* Spring MVC {@link View} using the Mustache template engine.
*
+ * @author Brian Clozel
* @author Dave Syer
* @author Phillip Webb
- * @since 1.2.2
+ * @since 2.0.0
*/
public class MustacheView extends AbstractTemplateView {
- private Template template;
+ private Mustache.Compiler compiler;
+
+ private String charset;
/**
- * Create a new {@link MustacheView} instance.
- * @since 1.2.5
- * @see #setTemplate(Template)
+ * Set the Mustache compiler to be used by this view.
+ *
Typically this property is not set directly. Instead a single
+ * {@link Mustache.Compiler} is expected in the Spring application context
+ * which is used to compile Mustache templates.
+ * @param compiler the Mustache compiler
*/
- public MustacheView() {
+ public void setCompiler(Mustache.Compiler compiler) {
+ this.compiler = compiler;
}
/**
- * Create a new {@link MustacheView} with the specified template.
- * @param template the source template
+ * Set the charset used for reading Mustache template files.
+ * @param charset the charset to use for reading template files
*/
- public MustacheView(Template template) {
- this.template = template;
- }
-
- /**
- * Set the Mustache template that should actually be rendered.
- * @param template the mustache template
- * @since 1.2.5
- */
- public void setTemplate(Template template) {
- this.template = template;
+ public void setCharset(String charset) {
+ this.charset = charset;
}
@Override
- protected void renderMergedTemplateModel(Map model,
- HttpServletRequest request, HttpServletResponse response) throws Exception {
- if (this.template != null) {
- this.template.execute(model, response.getWriter());
+ public boolean checkResource(Locale locale) throws Exception {
+ Resource resource = getApplicationContext().getResource(this.getUrl());
+ return (resource != null && resource.exists());
+ }
+
+ @Override
+ protected void renderMergedTemplateModel(Map model, HttpServletRequest request,
+ HttpServletResponse response) throws Exception {
+ Template template = createTemplate(getApplicationContext().getResource(this.getUrl()));
+ if (template != null) {
+ template.execute(model, response.getWriter());
}
}
+ private Template createTemplate(Resource resource) throws IOException {
+ Reader reader = getReader(resource);
+ try {
+ return this.compiler.compile(reader);
+ }
+ finally {
+ reader.close();
+ }
+ }
+
+ private Reader getReader(Resource resource) throws IOException {
+ if (this.charset != null) {
+ return new InputStreamReader(resource.getInputStream(), this.charset);
+ }
+ return new InputStreamReader(resource.getInputStream());
+ }
}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheViewResolver.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheViewResolver.java
index d513c65554..1c66279268 100644
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheViewResolver.java
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheViewResolver.java
@@ -16,36 +16,40 @@
package org.springframework.boot.autoconfigure.mustache.servlet;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.util.Locale;
-
import com.samskivert.mustache.Mustache;
-import com.samskivert.mustache.Mustache.Compiler;
-import com.samskivert.mustache.Template;
-import org.springframework.beans.propertyeditors.LocaleEditor;
-import org.springframework.core.io.Resource;
-import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.AbstractTemplateViewResolver;
+import org.springframework.web.servlet.view.AbstractUrlBasedView;
/**
* Spring MVC {@link ViewResolver} for Mustache.
*
- * @author Dave Syer
- * @author Andy Wilkinson
- * @author Phillip Webb
- * @since 1.2.2
+ * @author Brian Clozel
+ * @since 2.0.0
*/
public class MustacheViewResolver extends AbstractTemplateViewResolver {
- private Compiler compiler = Mustache.compiler();
+ private final Mustache.Compiler compiler;
private String charset;
+ /**
+ * Create a {@code MustacheViewResolver} backed by a default
+ * instance of a {@link Mustache.Compiler}.
+ */
public MustacheViewResolver() {
+ this.compiler = Mustache.compiler();
+ setViewClass(requiredViewClass());
+ }
+
+ /**
+ * Create a {@code MustacheViewResolver} backed by a custom
+ * instance of a {@link Mustache.Compiler}.
+ * @param compiler the Mustache compiler used to compile templates
+ */
+ public MustacheViewResolver(Mustache.Compiler compiler) {
+ this.compiler = compiler;
setViewClass(requiredViewClass());
}
@@ -54,14 +58,6 @@ public class MustacheViewResolver extends AbstractTemplateViewResolver {
return MustacheView.class;
}
- /**
- * Set the compiler.
- * @param compiler the compiler
- */
- public void setCompiler(Compiler compiler) {
- this.compiler = compiler;
- }
-
/**
* Set the charset.
* @param charset the charset
@@ -71,57 +67,11 @@ public class MustacheViewResolver extends AbstractTemplateViewResolver {
}
@Override
- protected View loadView(String viewName, Locale locale) throws Exception {
- Resource resource = resolveResource(viewName, locale);
- if (resource == null) {
- return null;
- }
- MustacheView mustacheView = (MustacheView) super.loadView(viewName, locale);
- mustacheView.setTemplate(createTemplate(resource));
- return mustacheView;
- }
-
- private Resource resolveResource(String viewName, Locale locale) {
- return resolveFromLocale(viewName, getLocale(locale));
- }
-
- 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;
- }
-
- private String getLocale(Locale locale) {
- if (locale == null) {
- return "";
- }
- LocaleEditor localeEditor = new LocaleEditor();
- localeEditor.setValue(locale);
- return "_" + localeEditor.getAsText();
- }
-
- private Template createTemplate(Resource resource) throws IOException {
- Reader reader = getReader(resource);
- try {
- return this.compiler.compile(reader);
- }
- finally {
- reader.close();
- }
- }
-
- private Reader getReader(Resource resource) throws IOException {
- if (this.charset != null) {
- return new InputStreamReader(resource.getInputStream(), this.charset);
- }
- return new InputStreamReader(resource.getInputStream());
+ protected AbstractUrlBasedView buildView(String viewName) throws Exception {
+ MustacheView view = (MustacheView) super.buildView(viewName);
+ view.setCompiler(this.compiler);
+ view.setCharset(this.charset);
+ return view;
}
}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheViewResolverTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheViewResolverTests.java
index b15931873f..36a4ad24e9 100644
--- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheViewResolverTests.java
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheViewResolverTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2016 the original author or authors.
+ * Copyright 2012-2017 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.
@@ -16,23 +16,14 @@
package org.springframework.boot.autoconfigure.mustache.servlet;
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.util.Locale;
-
import org.junit.Before;
import org.junit.Test;
-import org.springframework.core.io.Resource;
+import org.springframework.context.support.GenericApplicationContext;
import org.springframework.mock.web.MockServletContext;
-import org.springframework.web.context.support.StaticWebApplicationContext;
import org.springframework.web.servlet.View;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.BDDMockito.given;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
/**
* Tests for {@link MustacheViewResolver}.
@@ -46,7 +37,9 @@ public class MustacheViewResolverTests {
@Before
public void init() {
- this.resolver.setApplicationContext(new StaticWebApplicationContext());
+ GenericApplicationContext applicationContext = new GenericApplicationContext();
+ applicationContext.refresh();
+ this.resolver.setApplicationContext(applicationContext);
this.resolver.setServletContext(new MockServletContext());
this.resolver.setPrefix("classpath:/mustache-templates/");
this.resolver.setSuffix(".html");
@@ -58,32 +51,10 @@ public class MustacheViewResolverTests {
}
@Test
- public void resolveNullLocale() throws Exception {
+ public void resolveExisting() throws Exception {
assertThat(this.resolver.resolveViewName("foo", null)).isNotNull();
}
- @Test
- public void resolveDefaultLocale() throws Exception {
- assertThat(this.resolver.resolveViewName("foo", Locale.US)).isNotNull();
- }
-
- @Test
- public void resolveDoubleLocale() throws Exception {
- assertThat(this.resolver.resolveViewName("foo", Locale.CANADA_FRENCH))
- .isNotNull();
- }
-
- @Test
- public void resolveTripleLocale() throws Exception {
- assertThat(this.resolver.resolveViewName("foo", new Locale("en", "GB", "cy")))
- .isNotNull();
- }
-
- @Test
- public void resolveSpecificLocale() throws Exception {
- assertThat(this.resolver.resolveViewName("foo", new Locale("de"))).isNotNull();
- }
-
@Test
public void setsContentType() throws Exception {
this.resolver.setContentType("application/octet-stream");
@@ -92,24 +63,4 @@ public class MustacheViewResolverTests {
}
- @Test
- public void templateResourceInputStreamIsClosed() throws Exception {
- final Resource resource = mock(Resource.class);
- given(resource.exists()).willReturn(true);
- InputStream inputStream = new ByteArrayInputStream(new byte[0]);
- InputStream spyInputStream = spy(inputStream);
- given(resource.getInputStream()).willReturn(spyInputStream);
- this.resolver = new MustacheViewResolver();
- this.resolver.setApplicationContext(new StaticWebApplicationContext() {
-
- @Override
- public Resource getResource(String location) {
- return resource;
- }
-
- });
- this.resolver.loadView("foo", null);
- verify(spyInputStream).close();
- }
-
}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheViewTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheViewTests.java
index c1e1d7f4b5..a1801eb2cd 100644
--- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheViewTests.java
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheViewTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2016 the original author or authors.
+ * Copyright 2012-2017 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.
@@ -55,12 +55,12 @@ public class MustacheViewTests {
@Test
public void viewResolvesHandlebars() throws Exception {
- MustacheView view = new MustacheView(
- Mustache.compiler().compile("Hello {{msg}}"));
+ MustacheView view = new MustacheView();
+ view.setCompiler(Mustache.compiler());
+ view.setUrl("classpath:/mustache-templates/foo.html");
view.setApplicationContext(this.context);
- view.render(Collections.singletonMap("msg", "World"), this.request,
- this.response);
- assertThat(this.response.getContentAsString()).isEqualTo("Hello World");
+ view.render(Collections.singletonMap("World", "Spring"), this.request, this.response);
+ assertThat(this.response.getContentAsString()).isEqualTo("Hello Spring");
}
}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheWebIntegrationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheWebIntegrationTests.java
index cf8a5d28b9..7b0a45c425 100644
--- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheWebIntegrationTests.java
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheWebIntegrationTests.java
@@ -120,12 +120,12 @@ public class MustacheWebIntegrationTests {
@Bean
public MustacheViewResolver viewResolver() {
- MustacheViewResolver resolver = new MustacheViewResolver();
+ Mustache.Compiler compiler = Mustache.compiler()
+ .withLoader(new MustacheResourceTemplateLoader("classpath:/mustache-templates/",
+ ".html"));
+ MustacheViewResolver resolver = new MustacheViewResolver(compiler);
resolver.setPrefix("classpath:/mustache-templates/");
resolver.setSuffix(".html");
- resolver.setCompiler(
- Mustache.compiler().withLoader(new MustacheResourceTemplateLoader(
- "classpath:/mustache-templates/", ".html")));
return resolver;
}