Guide to Mustache with Spring Boot

1. Overview

In this article, we’ll focus on using Mustache templates for producing HTML content in Spring Boot applications.

It’s a logic-less template engine for creating dynamic content, which is popular due to its simplicity.

If you want to discover the basics, check our introduction to Mustache article.

2. Maven Dependency

To be able to use Mustache along with Spring Boot, we need to add the dedicated Spring Boot starter to our pom.xml:

<dependency>			
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mustache</artifactId>
</dependency>
<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-web</artifactId> 
</dependency>

In addition, we need the spring-boot-starter-web dependency.

3. Creating Templates

Let’s show an example and create a simple MVC application using Spring-Boot that will serve articles on a web page.

Let’s write the first template for the article contents:

<div class="starter-template">
    {{#articles}}
    <h1>{{title}}</h1>
    <h3>{{publishDate}}</h3>
    <h3>{{author}}</h3>
    <p>{{body}}</p>
    {{/articles}}
</div>

We’ll save this HTML file, say article.html, and refer it in our index.html:

<div class="container">
    {{>layout/article}}
</div>

Here, the layout is a sub-directory, and the article is the file name for the template file.

Note that the default mustache template file extension is now .mustache. We can override this configuration with a property:

spring.mustache.suffix:.html

4. Controller

Now let’s write the controller for serving articles:

@GetMapping("/article")
public ModelAndView displayArticle(Map<String, Object> model) {

    List<Article> articles = IntStream.range(0, 10)
      .mapToObj(i -> generateArticle("Article Title " + i))
      .collect(Collectors.toList());

    model.put("articles", articles);

    return new ModelAndView("index", model);
}

The controller returns a list of articles to be rendered on the page. In the article template, the tag articles starting with # and ending in /, takes care of the list.

This will iterate over the model passed and render each element separately just like in an HTML table:

{{#articles}}...{{/articles}}

The generateArticle() method creates an Article instance with some random data.

Note that the keys in the Article Model, returned by the controller, should be same as that of the article template tags.

Now, let’s test our application:

@Test
public void givenIndexPage_whenContainsArticle_thenTrue() {

    ResponseEntity<String> entity 
      = this.restTemplate.getForEntity("/article", String.class);
 
    assertTrue(entity.getStatusCode()
      .equals(HttpStatus.OK));
    assertTrue(entity.getBody()
      .contains("Article Title 0"));
}

We can also test the application by deploying it with:

mvn spring-boot:run

Once deployed, we can hit localhost:8080/article, and we’ll get our articles listed:

5. Handling Default Values

In a Mustache environment, if we do not provide a value for a placeholder, the MustacheException will be thrown with a message “No method or field with name ”variable-name …”.

In order to avoid such errors it’s better to provide a default global value to all placeholders:

@Bean
public Mustache.Compiler mustacheCompiler(
  Mustache.TemplateLoader templateLoader, 
  Environment environment) {

    MustacheEnvironmentCollector collector
      = new MustacheEnvironmentCollector();
    collector.setEnvironment(environment);

    return Mustache.compiler()
      .defaultValue("Some Default Value")
      .withLoader(templateLoader)
      .withCollector(collector);
}

6. Mustache With Spring MVC

Now, let’s discuss how to integrate with Spring MVC if we decide not to use Spring Boot. First, let’s add the dependency:

<dependency>
    <groupId>com.github.sps.mustache</groupId>
    <artifactId>mustache-spring-view</artifactId>
    <version>1.4</version>
</dependency>

The latest could be found here.

Next, we need to configure MustacheViewResolver instead of Spring’s InternalResourceViewResolver:

@Bean
public ViewResolver getViewResolver(ResourceLoader resourceLoader) {
    MustacheViewResolver mustacheViewResolver
      = new MustacheViewResolver();
    mustacheViewResolver.setPrefix("/WEB-INF/views/");
    mustacheViewResolver.setSuffix("..mustache");
    mustacheViewResolver.setCache(false);
    MustacheTemplateLoader mustacheTemplateLoader 
      = new MustacheTemplateLoader();
    mustacheTemplateLoader.setResourceLoader(resourceLoader);
    mustacheViewResolver.setTemplateLoader(mustacheTemplateLoader);
    return mustacheViewResolver;
}

We just need to configure the suffix, where our templates are stored, prefix the extension of our templates, and the templateLoader, which will be responsible for loading templates.

7. Conclusion

In this quick tutorial, we looked at using Mustache templates with Spring Boot, rendering a collection of elements in the UI and also providing default values to variables to avoid errors.

Finally, we discussed how to integrate it with Spring, using MustacheViewResolver.

As always the source code is available over on GitHub.

Related posts:

An Intro to Spring Cloud Task
Comparing getPath(), getAbsolutePath(), and getCanonicalPath() in Java
Sử dụng JDBC API thực thi câu lệnh truy vấn dữ liệu
Java Program to Implement the Checksum Method for Small String Messages and Detect
Java Program to Apply Above-Below-on Test to Find the Position of a Point with respect to a Line
The “final” Keyword in Java
Giới thiệu Google Guice – Aspect Oriented Programming (AOP)
Write/Read cookies using HTTP and Read a file from the internet
Quick Guide on Loading Initial Data with Spring Boot
Java – InputStream to Reader
Java Program to Implement Weight Balanced Tree
Java Program to Implement K Way Merge Algorithm
Java Program to Check whether Graph is a Bipartite using 2 Color Algorithm
Java Program to Find the Longest Subsequence Common to All Sequences in a Set of Sequences
Java Program to Decode a Message Encoded Using Playfair Cipher
Iterable to Stream in Java
Java Program to Implement Hash Tables
Java Program to Implement Euclid GCD Algorithm
Quản lý bộ nhớ trong Java với Heap Space vs Stack
Java Program to implement Array Deque
Setting the Java Version in Maven
Spring REST API + OAuth2 + Angular (using the Spring Security OAuth legacy stack)
Tạo chương trình Java đầu tiên sử dụng Eclipse
Documenting a Spring REST API Using OpenAPI 3.0
Java Program to Implement Gauss Jordan Elimination
Java Program to Find Nearest Neighbor Using Linear Search
Java Program to Find Median of Elements where Elements are Stored in 2 Different Arrays
Spring @RequestParam Annotation
Spring Cloud – Adding Angular
Programmatic Transaction Management in Spring
Java Program to Implement Knapsack Algorithm
Hướng dẫn Java Design Pattern – Interpreter