Implementing Mustache with Spring Boot

Spread the love

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.

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.

Below is the Spring Initializr for generating the project.

Spring Boot Mustache Initializr

3. Project Layout

This is how the project layout will look like for the Spring Boot Mustache application.

Spring Boot Mustache Project Layout

4. Creating Templates

Let’s create a simple HTML template using Mustache which we will use in our sample Spring Boot web application. We are using a modular approach to build our Spring Boot web application. The main template for this post is split into the following three parts.

4.1 Header (header.mustache)

Header parts contain the head and starting body for the HTML template.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Sample Spring Boot application with Mustache</title>
</head>
<body>

4.2 Footer (footer.mustache)

</body>
</html>

4.3 Main Template (book.mustache)

We will be adding the header and footer templates in this main template

{{>header}}
<h1>Mustache with Spring Boot</h1>
<div> <b>Book List </b></div>
{{#bookList}}
    <b> Book ID: </b>{{bookid}}
    <b> ISBN Number: </b>{{isbn}}
    <b> Book Title: </b>{{bookTitle}}
    <b> Author: </b>{{author}}
    <b> Price: </b>{{price}}
    <br>
    <hr>
{{/bookList}}
{{>footer}}

5. Spring Auto Configuration

We will add the Spring auto-configuration properties for mustache templates in the application.properties file.

spring.mustache.prefix = classpath:/templates/
spring.mustache.suffix = .mustache

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

spring.mustache.suffix:.html

6. Controller

We have a simple controller, our controller returns a list of Books.

@Controller
public class BookController {

    @GetMapping("/books")
    public String getProducts(final Model model){

        List bookList = IntStream.range(0,7)
                        .mapToObj(i->getBook(i))
                        .collect(Collectors.toList());
        
        model.addAttribute("bookList",bookList);
        return "book";
    }

    private Book getBook(int i){
        return new Book(Long.valueOf(i),
                "ISBN Number -" + i,
                "Book Name " + i,
                "Author " + i,
                Double.valueOf(100 * i));
    }
}

Our controller creating a dummy list of Books and set this book list in the Model class to be available during HTML rendering. Pay close attention to the  {{#bookList}}  and {{/bookList}} tags in our HTML, these tags iterate over the list of books filled in the controller and render each element of the list on the UI.

7. Run the Application

We can also test the application by deploying it with:

mvn spring-boot:run

Once deployed, we can hit localhost:8080/booksand we’ll get our result:

Spring Boot Mustache Output

7.1 Code Flow

8. 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:

@SpringBootApplication
public class SpringBootMustacheDemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringBootMustacheDemoApplication.class, args);
	}

	@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);
	}
}

Now, if we change any variable name and we forget to change the same in HTML or Model (vice-versa), it won’t throw the Mustache compiler exception. But for that variable, the default value will be populated and the UI will be rendered.

Spring Boot Mustache with Default variable

The price variable is changed with the default values from the Mustache compiler.

9. Mustache with Spring MVC

In case you can not use Spring Boot for your web application, integrating Mustache with your Spring MVC application is not complex. Let’s walk through the steps of integrating Mustache with your Spring MVC application.

9.1 Maven Dependencies

Spring Boot automatically takes care of adding required dependencies, For the non Spring Boot application, add Mustache maven dependencies.

<!-- https://mvnrepository.com/artifact/com.github.sps.mustache/mustache-spring-view -->
<dependency>
    <groupId>com.github.sps.mustache</groupId>
    <artifactId>mustache-spring-view</artifactId>
    <version>1.4</version>
</dependency>

In order for our Spring MVC application to work properly, we need to configure view resolver to use Mustache as a template engine.

@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.

10. Conclusion

In this post, we learned how to implement Mustache with Spring Boot application.  Mustache is really a powerful yet simple template engine. At the end of this post, we covered the steps for integrating Mustache in non Spring Boot application. 

Source Code

As always the source code is available over on GitHub.