diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mobile/DeviceDelegatingViewResolverAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mobile/DeviceDelegatingViewResolverAutoConfiguration.java
index 9e88580395b..a5bf1bdf9c1 100644
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mobile/DeviceDelegatingViewResolverAutoConfiguration.java
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mobile/DeviceDelegatingViewResolverAutoConfiguration.java
@@ -28,7 +28,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat
import org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration;
import org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration;
import org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration;
-import org.springframework.boot.autoconfigure.mustache.web.MustacheViewResolver;
+import org.springframework.boot.autoconfigure.mustache.servlet.MustacheViewResolver;
import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
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 51a2547bf6f..e84c8f4c276 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
@@ -30,7 +30,7 @@ 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.condition.ConditionalOnWebApplication.Type;
-import org.springframework.boot.autoconfigure.mustache.web.MustacheViewResolver;
+import org.springframework.boot.autoconfigure.mustache.servlet.MustacheViewResolver;
import org.springframework.boot.autoconfigure.template.TemplateLocation;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
@@ -43,6 +43,7 @@ import org.springframework.core.env.Environment;
* {@link EnableAutoConfiguration Auto-configuration} for Mustache.
*
* @author Dave Syer
+ * @author Brian Clozel
* @since 1.2.2
*/
@Configuration
@@ -123,4 +124,34 @@ public class MustacheAutoConfiguration {
}
+ @Configuration
+ @ConditionalOnWebApplication(type = Type.REACTIVE)
+ protected static class MustacheReactiveWebConfiguration {
+
+ private final MustacheProperties mustache;
+
+ protected MustacheReactiveWebConfiguration(MustacheProperties mustache) {
+ this.mustache = mustache;
+ }
+
+ @Bean
+ @ConditionalOnMissingBean(org.springframework.boot.autoconfigure
+ .mustache.reactive.MustacheViewResolver.class)
+ public org.springframework.boot.autoconfigure
+ .mustache.reactive.MustacheViewResolver mustacheViewResolver(Compiler mustacheCompiler) {
+ org.springframework.boot.autoconfigure
+ .mustache.reactive.MustacheViewResolver resolver
+ = new org.springframework.boot.autoconfigure
+ .mustache.reactive.MustacheViewResolver(mustacheCompiler);
+ resolver.setPrefix(this.mustache.getPrefix());
+ resolver.setSuffix(this.mustache.getSuffix());
+ resolver.setViewNames(this.mustache.getViewNames());
+ resolver.setRequestContextAttribute(this.mustache.getRequestContextAttribute());
+ resolver.setCharset(this.mustache.getCharsetName());
+ resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 10);
+ return resolver;
+ }
+
+ }
+
}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/reactive/MustacheView.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/reactive/MustacheView.java
new file mode 100644
index 00000000000..d40f7fb5ddc
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/reactive/MustacheView.java
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ * 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.mustache.reactive;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Optional;
+
+import com.samskivert.mustache.Mustache;
+import com.samskivert.mustache.Template;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.http.MediaType;
+import org.springframework.web.reactive.result.view.AbstractUrlBasedView;
+import org.springframework.web.reactive.result.view.View;
+import org.springframework.web.server.ServerWebExchange;
+
+/**
+ * Spring WebFlux {@link View} using the Mustache template engine.
+ *
+ * @author Brian Clozel
+ * @since 2.0.0
+ */
+public class MustacheView extends AbstractUrlBasedView {
+
+ private Mustache.Compiler compiler;
+
+ private String charset;
+
+ /**
+ * Set the JMustache 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 void setCompiler(Mustache.Compiler compiler) {
+ this.compiler = compiler;
+ }
+
+ /**
+ * Set the charset used for reading Mustache template files.
+ * @param charset the charset to use for reading template files
+ */
+ public void setCharset(String charset) {
+ this.charset = charset;
+ }
+
+ @Override
+ public boolean checkResourceExists(Locale locale) throws Exception {
+ return resolveResource() != null;
+ }
+
+ private Resource resolveResource() {
+ Resource resource = getApplicationContext().getResource(getUrl());
+ if (resource == null || !resource.exists()) {
+ return null;
+ }
+ return resource;
+ }
+
+ @Override
+ protected Mono renderInternal(Map model,
+ MediaType contentType, ServerWebExchange exchange) {
+ Resource resource = resolveResource();
+ if (resource == null) {
+ return Mono.error(new IllegalStateException("Could not find Mustache template with URL ["
+ + getUrl() + "]"));
+ }
+ DataBuffer dataBuffer = exchange.getResponse().bufferFactory().allocateBuffer();
+ try (Reader reader = getReader(resource)) {
+ Template template = this.compiler.compile(reader);
+ Charset charset = getCharset(contentType).orElse(getDefaultCharset());
+ try (Writer writer = new OutputStreamWriter(dataBuffer.asOutputStream(), charset)) {
+ template.execute(model, writer);
+ writer.flush();
+ }
+ }
+ catch (Throwable exc) {
+ return Mono.error(exc);
+ }
+ return exchange.getResponse().writeWith(Flux.just(dataBuffer));
+ }
+
+ private Reader getReader(Resource resource) throws IOException {
+ if (this.charset != null) {
+ return new InputStreamReader(resource.getInputStream(), this.charset);
+ }
+ return new InputStreamReader(resource.getInputStream());
+ }
+
+ private Optional getCharset(MediaType mediaType) {
+ return (mediaType != null ? Optional.ofNullable(mediaType.getCharset()) : Optional.empty());
+ }
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/reactive/MustacheViewResolver.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/reactive/MustacheViewResolver.java
new file mode 100644
index 00000000000..2a60f8881b5
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/reactive/MustacheViewResolver.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ * 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.mustache.reactive;
+
+import com.samskivert.mustache.Mustache;
+
+import org.springframework.web.reactive.result.view.AbstractUrlBasedView;
+import org.springframework.web.reactive.result.view.UrlBasedViewResolver;
+import org.springframework.web.reactive.result.view.ViewResolver;
+
+/**
+ * Spring WebFlux {@link ViewResolver} for Mustache.
+ *
+ * @author Brian Clozel
+ * @since 2.0.0
+ */
+public class MustacheViewResolver extends UrlBasedViewResolver {
+
+ 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());
+ }
+
+ /**
+ * Set the charset.
+ * @param charset the charset
+ */
+ public void setCharset(String charset) {
+ this.charset = charset;
+ }
+
+ @Override
+ protected Class> requiredViewClass() {
+ return MustacheView.class;
+ }
+
+ @Override
+ protected AbstractUrlBasedView createUrlBasedView(String viewName) {
+ MustacheView view = (MustacheView) super.createUrlBasedView(viewName);
+ view.setCompiler(this.compiler);
+ view.setCharset(this.charset);
+ return view;
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/reactive/package-info.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/reactive/package-info.java
new file mode 100644
index 00000000000..e89db28df66
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/reactive/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ * 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.
+ */
+
+/**
+ * Auto-configuration for Mustache with Spring WebFlux.
+ */
+package org.springframework.boot.autoconfigure.mustache.reactive;
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/web/MustacheView.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheView.java
similarity index 93%
rename from spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/web/MustacheView.java
rename to spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheView.java
index c368941e6a8..f877b2bbb62 100644
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/web/MustacheView.java
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheView.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2015 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.autoconfigure.mustache.web;
+package org.springframework.boot.autoconfigure.mustache.servlet;
import java.util.Map;
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/web/MustacheViewResolver.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheViewResolver.java
similarity index 96%
rename from spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/web/MustacheViewResolver.java
rename to spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheViewResolver.java
index 6cc66e9b124..d513c655547 100644
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/web/MustacheViewResolver.java
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheViewResolver.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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.autoconfigure.mustache.web;
+package org.springframework.boot.autoconfigure.mustache.servlet;
import java.io.IOException;
import java.io.InputStreamReader;
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/web/package-info.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/servlet/package-info.java
similarity index 83%
rename from spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/web/package-info.java
rename to spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/servlet/package-info.java
index dafe21fc771..3d137e0afd2 100644
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/web/package-info.java
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/servlet/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2015 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.
@@ -17,4 +17,4 @@
/**
* Auto-configuration for Mustache with Spring MVC.
*/
-package org.springframework.boot.autoconfigure.mustache.web;
+package org.springframework.boot.autoconfigure.mustache.servlet;
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mobile/DeviceDelegatingViewResolverAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mobile/DeviceDelegatingViewResolverAutoConfigurationTests.java
index fe8c45ada1f..e6e4cb971e6 100644
--- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mobile/DeviceDelegatingViewResolverAutoConfigurationTests.java
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mobile/DeviceDelegatingViewResolverAutoConfigurationTests.java
@@ -34,7 +34,7 @@ import org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfigura
import org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration;
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
import org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration;
-import org.springframework.boot.autoconfigure.mustache.web.MustacheViewResolver;
+import org.springframework.boot.autoconfigure.mustache.servlet.MustacheViewResolver;
import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.boot.test.util.EnvironmentTestUtils;
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfigurationIntegrationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfigurationIntegrationTests.java
deleted file mode 100644
index 92531a58cf2..00000000000
--- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfigurationIntegrationTests.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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.
- * 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.mustache;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.util.Date;
-import java.util.Map;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
-import org.springframework.boot.test.web.client.TestRestTemplate;
-import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Import;
-import org.springframework.stereotype.Controller;
-import org.springframework.test.annotation.DirtiesContext;
-import org.springframework.test.context.junit4.SpringRunner;
-import org.springframework.web.bind.annotation.RequestMapping;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-/**
- * Integration tests for {@link MustacheAutoConfiguration}.
- *
- * @author Dave Syer
- */
-@RunWith(SpringRunner.class)
-@DirtiesContext
-@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = {
- "spring.mustache.prefix:classpath:/mustache-templates/" })
-public class MustacheAutoConfigurationIntegrationTests {
-
- @Autowired
- private ServletWebServerApplicationContext context;
-
- private int port;
-
- @Before
- public void init() {
- this.port = this.context.getWebServer().getPort();
- }
-
- @Test
- public void testHomePage() throws Exception {
- String body = new TestRestTemplate().getForObject("http://localhost:" + this.port,
- String.class);
- assertThat(body.contains("Hello World")).isTrue();
- }
-
- @Test
- public void testPartialPage() throws Exception {
- String body = new TestRestTemplate()
- .getForObject("http://localhost:" + this.port + "/partial", String.class);
- assertThat(body.contains("Hello World")).isTrue();
- }
-
- @Configuration
- @MinimalWebConfiguration
- @Controller
- public static class Application {
-
- @RequestMapping("/")
- public String home(Map model) {
- model.put("time", new Date());
- model.put("message", "Hello World");
- model.put("title", "Hello App");
- return "home";
- }
-
- @RequestMapping("/partial")
- public String layout(Map model) {
- model.put("time", new Date());
- model.put("message", "Hello World");
- model.put("title", "Hello App");
- return "partial";
- }
-
- public static void main(String[] args) {
- SpringApplication.run(Application.class, args);
- }
-
- }
-
- @Target(ElementType.TYPE)
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- @Import({ MustacheAutoConfiguration.class,
- ServletWebServerFactoryAutoConfiguration.class,
- DispatcherServletAutoConfiguration.class,
- PropertyPlaceholderAutoConfiguration.class })
- protected @interface MinimalWebConfiguration {
-
- }
-
-}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfigurationTests.java
new file mode 100644
index 00000000000..1e71ed027fd
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfigurationTests.java
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ * 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.mustache;
+
+import com.samskivert.mustache.Mustache;
+import org.junit.Test;
+
+import org.springframework.boot.autoconfigure.mustache.servlet.MustacheViewResolver;
+import org.springframework.boot.test.util.EnvironmentTestUtils;
+import org.springframework.boot.web.reactive.context.GenericReactiveWebApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link MustacheAutoConfiguration}.
+ *
+ * @author Brian Clozel
+ */
+public class MustacheAutoConfigurationTests {
+
+ private AnnotationConfigWebApplicationContext webContext;
+
+ private GenericReactiveWebApplicationContext reactiveWebContext;
+
+ @Test
+ public void registerBeansForServletApp() {
+ loadWithServlet(null);
+ assertThat(this.webContext.getBeansOfType(Mustache.Compiler.class)).hasSize(1);
+ assertThat(this.webContext.getBeansOfType(MustacheResourceTemplateLoader.class)).hasSize(1);
+ assertThat(this.webContext.getBeansOfType(MustacheViewResolver.class)).hasSize(1);
+ }
+
+ @Test
+ public void registerCompilerForServletApp() {
+ loadWithServlet(CustomCompilerConfiguration.class);
+ assertThat(this.webContext.getBeansOfType(MustacheResourceTemplateLoader.class)).hasSize(1);
+ assertThat(this.webContext.getBeansOfType(MustacheViewResolver.class)).hasSize(1);
+ assertThat(this.webContext.getBeansOfType(Mustache.Compiler.class)).hasSize(1);
+ assertThat(this.webContext.getBean(Mustache.Compiler.class).standardsMode).isTrue();
+ }
+
+ @Test
+ public void registerBeansForReactiveApp() {
+ loadWithReactive(null);
+ assertThat(this.reactiveWebContext.getBeansOfType(Mustache.Compiler.class)).hasSize(1);
+ assertThat(this.reactiveWebContext.getBeansOfType(MustacheResourceTemplateLoader.class)).hasSize(1);
+ assertThat(this.reactiveWebContext.getBeansOfType(MustacheViewResolver.class)).isEmpty();
+ assertThat(this.reactiveWebContext
+ .getBeansOfType(org.springframework.boot.autoconfigure.mustache.reactive.MustacheViewResolver.class)
+ ).hasSize(1);
+ }
+
+
+ @Test
+ public void registerCompilerForReactiveApp() {
+ loadWithReactive(CustomCompilerConfiguration.class);
+ assertThat(this.reactiveWebContext.getBeansOfType(Mustache.Compiler.class)).hasSize(1);
+ assertThat(this.reactiveWebContext.getBeansOfType(MustacheResourceTemplateLoader.class)).hasSize(1);
+ assertThat(this.reactiveWebContext.getBeansOfType(MustacheViewResolver.class)).isEmpty();
+ assertThat(this.reactiveWebContext
+ .getBeansOfType(org.springframework.boot.autoconfigure.mustache.reactive.MustacheViewResolver.class)
+ ).hasSize(1);
+ assertThat(this.reactiveWebContext.getBean(Mustache.Compiler.class).standardsMode).isTrue();
+ }
+
+ private void loadWithServlet(Class> config) {
+ this.webContext = new AnnotationConfigWebApplicationContext();
+ EnvironmentTestUtils.addEnvironment(this.webContext,
+ "spring.mustache.prefix=classpath:/mustache-templates/");
+ if (config != null) {
+ this.webContext.register(config);
+ }
+ this.webContext.register(BaseConfiguration.class);
+ this.webContext.refresh();
+ }
+
+ private void loadWithReactive(Class> config) {
+ this.reactiveWebContext = new GenericReactiveWebApplicationContext();
+ EnvironmentTestUtils.addEnvironment(this.reactiveWebContext,
+ "spring.mustache.prefix=classpath:/mustache-templates/");
+ if (config != null) {
+ this.reactiveWebContext.register(config);
+ }
+ this.reactiveWebContext.register(BaseConfiguration.class);
+ this.reactiveWebContext.refresh();
+ }
+
+ @Configuration
+ @Import({MustacheAutoConfiguration.class})
+ protected static class BaseConfiguration {
+
+ }
+
+ @Configuration
+ protected static class CustomCompilerConfiguration {
+
+ @Bean
+ public Mustache.Compiler compiler(Mustache.TemplateLoader mustacheTemplateLoader) {
+ return Mustache.compiler().standardsMode(true).withLoader(mustacheTemplateLoader);
+ }
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/reactive/MustacheViewResolverTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/reactive/MustacheViewResolverTests.java
new file mode 100644
index 00000000000..3f84133b1b6
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/reactive/MustacheViewResolverTests.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ * 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.mustache.reactive;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.springframework.context.support.GenericApplicationContext;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link org.springframework.boot.autoconfigure.mustache.reactive.MustacheViewResolver}.
+ *
+ * @author Brian Clozel
+ */
+public class MustacheViewResolverTests {
+
+ private MustacheViewResolver resolver = new MustacheViewResolver();
+
+ @Before
+ public void init() {
+ GenericApplicationContext applicationContext = new GenericApplicationContext();
+ applicationContext.refresh();
+ this.resolver.setApplicationContext(applicationContext);
+ this.resolver.setPrefix("classpath:/mustache-templates/");
+ this.resolver.setSuffix(".html");
+ }
+
+ @Test
+ public void resolveNonExistent() throws Exception {
+ assertThat(this.resolver.resolveViewName("bar", null).block()).isNull();
+ }
+
+ @Test
+ public void resolveExisting() throws Exception {
+ assertThat(this.resolver.resolveViewName("foo", null).block()).isNotNull();
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/reactive/MustacheViewTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/reactive/MustacheViewTests.java
new file mode 100644
index 00000000000..ebb05c81534
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/reactive/MustacheViewTests.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ * 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.mustache.reactive;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+
+import com.samskivert.mustache.Mustache;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.springframework.context.support.GenericApplicationContext;
+import org.springframework.http.MediaType;
+import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
+import org.springframework.mock.http.server.reactive.MockServerWebExchange;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link MustacheView}.
+ *
+ * @author Brian Clozel
+ */
+public class MustacheViewTests {
+
+ private GenericApplicationContext context = new GenericApplicationContext();
+
+ private MockServerWebExchange exchange;
+
+ @Before
+ public void init() {
+ this.context.refresh();
+ }
+
+ @Test
+ public void viewResolvesHandlebars() throws Exception {
+ this.exchange = MockServerHttpRequest.get("/test").toExchange();
+ MustacheView view = new MustacheView();
+ view.setCompiler(Mustache.compiler());
+ view.setUrl("classpath:/mustache-templates/foo.html");
+ view.setCharset(StandardCharsets.UTF_8.displayName());
+ view.setApplicationContext(this.context);
+ view.render(Collections.singletonMap("World", "Spring"), MediaType.TEXT_HTML, this.exchange).block();
+ assertThat(this.exchange.getResponse().getBodyAsString().block()).isEqualTo("Hello Spring");
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/reactive/MustacheWebIntegrationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/reactive/MustacheWebIntegrationTests.java
new file mode 100644
index 00000000000..34f2bddec72
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/reactive/MustacheWebIntegrationTests.java
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ * 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.mustache.reactive;
+
+import java.util.Date;
+
+import com.samskivert.mustache.Mustache;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
+import org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration;
+import org.springframework.boot.autoconfigure.mustache.MustacheResourceTemplateLoader;
+import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration;
+import org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerAutoConfiguration;
+import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.stereotype.Controller;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.reactive.server.WebTestClient;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Integration Tests for {@link MustacheAutoConfiguration}, {@link MustacheViewResolver}
+ * and {@link MustacheView}.
+ *
+ * @author Brian Clozel
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT,
+ properties = "spring.main.web-application-type=reactive")
+public class MustacheWebIntegrationTests {
+
+ @Autowired
+ private WebTestClient client;
+
+ @Test
+ public void testHomePage() throws Exception {
+ String result = (String) this.client.get().uri("/").exchange()
+ .expectStatus().isOk()
+ .expectBody(String.class).returnResult().getResponseBody();
+ assertThat(result).contains("Hello App").contains("Hello World");
+ }
+
+ @Test
+ public void testPartialPage() throws Exception {
+ String result = (String) this.client.get().uri("/partial").exchange()
+ .expectStatus().isOk()
+ .expectBody(String.class).returnResult().getResponseBody();
+ assertThat(result).contains("Hello App").contains("Hello World");
+ }
+
+ @Configuration
+ @Import({ReactiveWebServerAutoConfiguration.class,
+ WebFluxAutoConfiguration.class,
+ HttpHandlerAutoConfiguration.class,
+ PropertyPlaceholderAutoConfiguration.class})
+ @Controller
+ public static class Application {
+
+ @RequestMapping("/")
+ public String home(Model model) {
+ model.addAttribute("time", new Date());
+ model.addAttribute("message", "Hello World");
+ model.addAttribute("title", "Hello App");
+ return "home";
+ }
+
+ @RequestMapping("/partial")
+ public String layout(Model model) {
+ model.addAttribute("time", new Date());
+ model.addAttribute("message", "Hello World");
+ model.addAttribute("title", "Hello App");
+ return "partial";
+ }
+
+ @Bean
+ public MustacheViewResolver viewResolver() {
+ 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");
+ return resolver;
+ }
+
+ public static void main(String[] args) {
+ SpringApplication application = new SpringApplication(Application.class);
+ application.setWebApplicationType(WebApplicationType.REACTIVE);
+ application.run(args);
+ }
+
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/web/MustacheViewResolverTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheViewResolverTests.java
similarity index 98%
rename from spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/web/MustacheViewResolverTests.java
rename to spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheViewResolverTests.java
index dff2651272f..b15931873f7 100644
--- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/web/MustacheViewResolverTests.java
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheViewResolverTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.autoconfigure.mustache.web;
+package org.springframework.boot.autoconfigure.mustache.servlet;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/web/MustacheViewTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheViewTests.java
similarity index 97%
rename from spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/web/MustacheViewTests.java
rename to spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheViewTests.java
index 02db8318cff..c1e1d7f4b57 100644
--- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/web/MustacheViewTests.java
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheViewTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.autoconfigure.mustache.web;
+package org.springframework.boot.autoconfigure.mustache.servlet;
import java.util.Collections;
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/web/MustacheWebIntegrationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheWebIntegrationTests.java
similarity index 98%
rename from spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/web/MustacheWebIntegrationTests.java
rename to spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheWebIntegrationTests.java
index d9912f1cb90..cf8a5d28b95 100644
--- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/web/MustacheWebIntegrationTests.java
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/servlet/MustacheWebIntegrationTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.autoconfigure.mustache.web;
+package org.springframework.boot.autoconfigure.mustache.servlet;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
diff --git a/spring-boot-samples/spring-boot-sample-web-mustache/pom.xml b/spring-boot-samples/spring-boot-sample-web-mustache/pom.xml
index 3a3c37618f8..1fff694c84a 100644
--- a/spring-boot-samples/spring-boot-sample-web-mustache/pom.xml
+++ b/spring-boot-samples/spring-boot-sample-web-mustache/pom.xml
@@ -21,6 +21,10 @@
+
+ org.springframework.boot
+ spring-boot-starter-web
+
org.springframework.boot
spring-boot-starter-mustache
diff --git a/spring-boot-starters/spring-boot-starter-mustache/pom.xml b/spring-boot-starters/spring-boot-starter-mustache/pom.xml
index 387965dc16c..04e46985447 100644
--- a/spring-boot-starters/spring-boot-starter-mustache/pom.xml
+++ b/spring-boot-starters/spring-boot-starter-mustache/pom.xml
@@ -8,7 +8,7 @@
spring-boot-starter-mustache
Spring Boot Mustache Starter
- Starter for building MVC web applications using Mustache views
+ Starter for building web applications using Mustache views
http://projects.spring.io/spring-boot/
Pivotal Software, Inc.
@@ -22,10 +22,6 @@
org.springframework.boot
spring-boot-starter
-
- org.springframework.boot
- spring-boot-starter-web
-
com.samskivert
jmustache