Spring MVC + Mustache JS template example


In this tutorial, we will show you a Spring MVC + Mustache JS template web application example.

Technologies used :

  1. Spring 4.2.4.RELEASE
  2. mustache.js
  3. JDK 1.8.0_66
  4. Jackson 2.7
  5. Eclipse 4.3
  6. Tomcat 8
  7. Maven 3
  8. Bootstrap 3
This solution is still working, but recommend this simple Spring Boot + JMustache solution.

In Spring, we can use ScriptTemplateConfigurer to integrate most of the JS templating library, for example Mustache, Handlebars or React. Refer to this official Spring script template documentation.

P.S ScriptTemplateConfigurer has been supported since Spring 4.2

This example will run “Mustache JS” on the server side, using the built in Java 8 Nashorn Javascript engine. An isomorphic javascript example.

1. Project Structure

A standard Maven folder structure.


2. pom.xml

A Maven pom.xml file to declare dependencies and some useful plugins.


<project xmlns="http://maven.apache.org/POM/4.0.0" 

	<name>spring mvc mustache</name>



		<!-- Spring and exclude commons log -->

		<!-- Add slf4j Logging -->


		<!-- compile only, deployed container will provide this -->
		<!--  no web.xml project need this to start app -->

		<!-- JSON -->









3. Integrate Spring + Mustache JS

To integrate Mustache script template as the Spring view template, configure both ScriptTemplateConfigurer and ViewResolver. See comment for self-explanatory.


package com.mkyong.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.script.ScriptTemplateConfigurer;
import org.springframework.web.servlet.view.script.ScriptTemplateViewResolver;

@ComponentScan({ "com.mkyong.web.controller" })
public class SpringWebConfig extends WebMvcConfigurerAdapter {
    public ScriptTemplateConfigurer configurer() {
        ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer();
        //1. Nashorn jdk8 script engine.
        //2. Add mustache.min.js and custom render.js to Nashorn
        configurer.setScripts("/static/js/mustache.min.js", "/static/js/render.js");
        //3. Ask Nashorn to run this function "render()"
        return configurer;

    //Define where is Mustache template, in classpath level.
  	// If view "hello" is returned, Mustache temple will be '/static/templates/hello.html'
    public ViewResolver viewResolver() {
        ScriptTemplateViewResolver viewResolver = new ScriptTemplateViewResolver();
        return viewResolver;

	//add static resources like js or css
	public void addResourceHandlers(ResourceHandlerRegistry registry) {


4. Spring Controller + Mustache Template

4.1 A Spring controller to pass data to the Mustache template.


package com.mkyong.web.controller;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mkyong.web.model.User;

public class HelloController {

    private static final Logger logger = LoggerFactory.getLogger(HelloController.class);

    private static final ObjectMapper om = new ObjectMapper();

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public ModelAndView printWelcome(HttpServletRequest request) {

        ModelAndView result = new ModelAndView();
        result.addObject("resources", request.getContextPath() + "/resources");
        result.addObject("logo", "mkyong.com");
        result.addObject("title", "Spring MVC + Mustache template");
        result.addObject("jumbo-title", "Spring MVC + Mustache template");
        result.addObject("jumbo-desc", "Maven + Spring MVC + Mustache JS, ScriptTemplate example.");

        //1. Test data type
        result.addObject("id", 100);
        result.addObject("username", "mkyong");

        //2. Test List
        result.addObject("scriptTemplates", getScriptTemplate());

        //3. Test Object
        result.addObject("user", new User("abc@gmail.com", 0));

        //4. Test List<Object>
        List<User> list = new ArrayList<>();
        list.add(new User("aaa@gmail.com", 1));
        list.add(new User("bbb@yahoo.com", 2));
        list.add(new User("ccc@hotmail.com", 3));
        result.addObject("users_json", convertObjectToJson(list));

        result.addObject("users", list);

        return result;


    private List<String> getScriptTemplate() {

        List<String> scriptTemplates = new ArrayList<>();
        scriptTemplates.add("String templates");
        return scriptTemplates;


    //Jackson2 - Convert Java Object to JSON format
    public static String convertObjectToJson(Object obj) {
        String result = "";
        try {
            result = om.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            logger.error("Error In JSON conversion : {}", e);
        return result;


4.2 A Mustache template file to display the data from the above Spring controller.


<!DOCTYPE html>
<html lang="en">
    <link href="{{{resources}}}/core/css/bootstrap.min.css" rel="stylesheet">
    <link href="{{{resources}}}/core/css/bootstrap-theme.min.css" rel="stylesheet">
    <link href="{{{resources}}}/core/css/hello.css" rel="stylesheet">

<body role="document">

<nav class="navbar navbar-inverse navbar-fixed-top">
    <div class="container">
        <div class="navbar-header">
            <a class="navbar-brand" href="#">{{logo}}</a>

<div class="container theme-showcase" role="main">

    <div class="jumbotron">

    <div class="row">
        <div class="col-sm-6">
            <div class="page-header">
                <h1>1. Data Types</h1>
                Hello {{username}}, id : {{.}}
        <div class="col-sm-6">
            <div class="page-header">
                <h1>2. List</h1>

    <div class="row">
        <div class="col-sm-6">
            <div class="page-header">
                <h1>3. User Object</h1>
                    <li>email- {{user.email}}</li>
                    <li>loginFailed- {{user.loginFailed}}</li>
        <div class="col-sm-6">
            <div class="page-header">
                <h1>4. List of User Objects (JSON)</h1>
                <li>email- {{email}}</li>
                <li>loginFailed- {{loginFailed}}</li>


    <div class="row">
        <div class="col-sm-6">
            <div class="page-header">
                <h1>5. List of User Objects (RAW)</h1>
                No idea how to loop it...
                <li>email- {{email}}</li>
                <li>loginFailed- {{loginFailed}}</li>
        <div class="col-sm-6">
            <div class="page-header">

<div class="container">
        <p>© Mkyong.com 2016</p>

<script type="text/javascript" src="{{{resources}}}/core/js/hello.js"></script>
<script type="text/javascript" src="{{{resources}}}/core/js/jquery-1.12.0.min.js"></script>
<script type="text/javascript" src="{{{resources}}}/core/js/bootstrap.min.js"></script>


5. Javascript ‘render.js’

When a view is returned, Spring will run this function render(template, model, url). But, not all Java objects or data types are supported in Javascript, conversion is required, especially the List<Object>.

Summary :

  1. For primitive data type, there is no need for conversion.
  2. For java.lang.Iterable, convert it with Java.from().
  3. For List<User>, convert it into JSON formatted string with Jackson, and convert it to a JS object via JSON.parse. This trick should work in any Java object <--> JavaScript conversion.

 * Bindings to use mustache.js with Nashorn.

 * String templates: the Mustache template content. e.g hello.html
 * Map model: the model in controller
 * String url: the templates url (since 4.2.2)
function render(template, model, url) {
	return Mustache.render(template, toJsonObject(model));

// Some Java objects may not support in JS directly, need conversion.
function toJsonObject(model) {
    var o = {};
    for (var k in model) {

        //Convert Object String to Javascript JSON
        if (k.indexOf("_json") > -1) {
            o[k] = JSON.parse(model[k]);

        // Convert Iterable like List to real JSON array
        if (model[k] instanceof Java.type("java.lang.Iterable")) {
            o[k] = Java.from(model[k]);
        else {
            o[k] = model[k];
    return o;

6. Misc Classes

6.1 Create a WebInitializer class to create a no web.xml web application.


package com.mkyong.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

import com.mkyong.config.SpringWebConfig;

public class MyWebInitializer extends
		AbstractAnnotationConfigDispatcherServletInitializer {

	protected Class<?>[] getServletConfigClasses() {
		return new Class[] { SpringWebConfig.class };

	protected String[] getServletMappings() {
		return new String[] { "/" };

	protected Class<?>[] getRootConfigClasses() {
		return null;


6.2 User Object.


package com.mkyong.web.model;

public class User {

    String email;
    int loginFailed;

    public User(String email, int loginFailed) {
        this.email = email;
        this.loginFailed = loginFailed;

   //setters and getters

7. Demo

7.1 http://localhost:8080/spring/


7.2 http://localhost:8080/spring/


8. How to run this project?

8.1 Clone the source code from Github.

$ git clone https://github.com/mkyong/spring-mvc-mustache-js-template

8.2 Run the embedded Jetty container.

$ mvn jetty:run

8.3 Visit URL : http://localhost:8080/spring/

Download Source Code

Download – spring-mvc-mustache.zip (127 KB)


  1. Mustache – Logic-less templates
  2. Mustache – Javascript
  3. Spring IO – View Template
  4. Isomorphic templating with Spring Boot, Nashorn and React
  5. Java 8 Nashorn tutorial
  6. Spring React example
  7. Yet another Spring Mustache solution
  8. Isomorphic JavaScript

About the Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.


2 Comment threads
0 Thread replies
Most reacted comment
Hottest comment thread
2 Comment authors
Saurabh?? Recent comment authors
newest oldest most voted

How to get this folder structure in Eclipse-STS.