Mustaches in the World of Java
Join the DZone community and get the full member experience.
Join For FreeMustache has simple idea of "logic-less" system because it lacks any explicit control statements, like if, else or goto and also it does not have for statement however looping and conditional calculation can be achieved using custom tags that work with lists and lambdas.
The name unfortunately has less to do with Tom Selleck but more with the heavy use of curly braces that look like mustache. The similarity is more than comparable.
Mustache has implementation for most of the widely used languages like: Java, Javascript, Ruby,Net and many more.
The client side template's in JavaScript
Let say that you have some REST service and you have created a book view object that has an additional function that appends amazon associates id to the book url:var book = { id : 12, title : "A Game of Thrones", url : "http://www.amazon.com/gp/product/0553573403/", amazonId : "myAwesomeness", associateUrl : function() { return this.url + '?tag=' + this.amazonId; }, author : { name : 'George R. R. Martin', imdbUrl : 'http://www.imdb.com/name/nm0552333/', wikiUrl : 'https://en.wikipedia.org/wiki/George_R._R._Martin' }, haveInStock : true, similarBooks : [{ id : 13, title : "Decision Points" }, { id : 13, title : "Spoken from the Heart" }], comments : [] };
The standard way of rendering data without using templates would be create an output variable and just append everything inside and at the end just place the data where it should be.
jQuery(document).ready(function() { var out = '<div class="book-box"><h3>' + book.title + '</h3><span> is awesome book get it on <a href="' + book.associateUrl() + '">Amazon</a></span></div>'; jQuery('#content-jquery').html(out); });
This is fairly simple but if you for example want to change the span element with div it takes a little bit of time to figure where it should be closed and often you can miss if the element should be in single quotes or double quotes. The bigger issue here is that the content is peaces of strings that need to be easy to styled via CSS and JavaScript. As the code gets bigger this becomes unmanageable and changes to anything become slower especially if you add on top of this jQuery's manipulation functions like appendTo() or prependTo(). This direct use of out+= type of creating the content reminds me a lot of HttpServlet style of using print writer and doing out.print() and for the same reason why this was almost abandoned we should not do this in JavaScript.
To simplify work we can add template engine like Mustache that is one of
many client side tempting engines. So how does a template in mustache
looks like, well for the example above with the book it would look like :
<script id="book-template" type="text/x-mustache-template"> <div class="book-box"> <h3>{{title}}</h3> <span> is awesome book get it on <a href="{{associateUrl}}">Amazon</a> </span> </div>
So this template can be placed anywhere on the page and then selected and rendered when you need it:
jQuery(document).ready(function() { var template = jQuery('#book-template').html(); var renderedData = Mustache.render(template, book); jQuery('#content-mustache').html(renderedData); });
nder method accepts the content of the template and the view object book, what is great here is that the template looks almost the same as html thus make it easy to style, change and maintain.
Also you can use section like : {{#conditon}} code or data here{{/condition}} where if it evaluates to true, the section is rendered,
otherwise the whole block is ignored.
If the conditions returns nonempty list this can be iterated using the same construct. Inverted condition is done using {^conditon}} code or data here{{/condition}}.
Dot notation can be used to access subelements (not in every implementation), for example if you wanted to render the authors imdb page from the previous example it would be like {{author.imdbUrl}}.There are structures called partials that can be used if we need render time inclusion of partial elements, also if needed some of the standard behavior of Mustache JS can be overridden.
You can get the example from https://github.com/mitemitreski/blog-examples/tree/master/mustache-js
Server side rendering Mustache in Spring MVC
There is an implementation of Mustache templates for Java called Mustache.java and another one called JMustache . As far as usage in web frameworks is needed there are few articles out there about using Mustache in Java web applications based on Struts for example but I went with the Spring MVC option since I found it more interesting for my use.
For the example I used the mustache-spring-view that is fairly simple to add using maven:
<dependency> <groupId>com.github.sps.mustache</groupId> <artifactId>mustache-spring-view</artifactId> <version>1.0</version> </dependency>
This will automatically retrieve jMustache :
+- com.github.sps.mustache:mustache-spring-view:jar:1.0:compile
\- com.samskivert:jmustache:jar:1.2:compile
The next part is including the view in the servlet context and adding the appropriate paths:
<beans:bean id="viewResolver" class="org.springframework.web.servlet.view.mustache.MustacheViewResolver"> <!-- FIXME reload every time--> <beans:property name="cache" value="false" /> <!-- The default view path is below --> <beans:property name="prefix" value="/WEB-INF/views/" /> <!-- The default suffix path is below --> <beans:property name="suffix" value=".mustache" /> <beans:property name="templateLoader"> <beans:bean class="org.springframework.web.servlet.view.mustache.MustacheTemplateLoader" /> </beans:property> </beans:bean>
As you can see the config is extremely simple you just need to add the path where the templates will be stored the suffix that the templates will end in, the actual template loader and if the templates should be cached. It is very good during development to set this property to true since that way you will get instant update on the changes in your templates.
The controller will be very simple one since this is just a small proof of concept:
/** * Hello Mustache. */ @Controller public class HomeController { private static final Logger logger = LoggerFactory.getLogger(HomeController.class); /** * Simple controller that * redirects to home and adds map and date objects. */ @RequestMapping(value = "/", method = GET) public String home(Locale locale, Model model) { Date date = new Date(); DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale); Properties properties = System.getProperties(); Map<String, String> map = new HashMap<String, String>((Map) properties); String formattedDate = dateFormat.format(date); model.addAttribute("serverTime", formattedDate); model.addAttribute("props", map.entrySet()); return "home"; } }
The controller just fills the serer system properties and the current time add passes the model to towards the template. Acorrding to the previous configuration the template name is home.mustache and it is located in /WEB-INF/views/.
Template is as simple as it gets, the idea here was just to illustrate how java maps can be iterated.
<!DOCTYPE HTML> <html lang="en"> <head> <meta charset=utf-8> <title>Hello Mustache</title> </head> <body> <div id="container"> <p>Current server time is {{serverTime}}</p> <p>All the current system properties</p> <ul> {{#props}} <li>{{key}} = {{value}} </li> {{/props}} </ul> </div> </body> </html>
So how does it work? Well if we take serverTime it can be java property, key or a method which makes it very simple and readable. The full example can be retrieved from my github page.
It's just the regular maven clean package and run, it's tested on tomcat
6 with Java 1.6 but it simple enough to work anywhere. While I can't
yet say that I have used the servers side rendering in a production
environment they most definitely look promising. There are plugins for vim, emacs and textmate
but there is no plugin for eclipse. On eclipse you can do a workaround
Eclipse->Preferences->General->Content_Types add the *.mustache
to be recognized as html, at least you will get the html syntax
highlighting.
The cool thing with Mustache is that you can very easily switch whether you gonna use server side rendering on client side additionally it makes it very hard to add unnecessary logic in the templates that makes development simpler.
Don't forget your app is only hot if it has awesome mustaches.
Other links
- https://github.com/janl/mustache.js/
- http://mustache.github.com/
- https://github.com/mustache/spec
- http://www.javarants.com/2010/05/03/the-ideal-web-application-templating-system/
- https://github.com/samskivert/jmustache
- http://java.dzone.com/articles/using-mustachejava-templates
- https://github.com/sps/mustache-spring-view/
- http://stackoverflow.com/questions/4410544/is-there-a-mustache-template-syntax-highlighter-or-plugin-for-eclipse
- https://groups.google.com/forum/?fromgroups#!forum/mustachejava
Published at DZone with permission of Mite Mitreski, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments