Martin has posted 7 posts at DZone. You can read more from them at their website. View Full User Profile

Trimou Templates Introduction

09.07.2013
| 3682 views |
  • submit to reddit

Trimou is a simple to use and easy to extend templating engine for any Java SE or Java EE application. It is a Mustache template implementation available under the Apache License 2.0. This article is just a brief summary, highlighting some of the most useful features of Trimou. You can read the documentation and study the example code to know more.

The basic set of features of every Mustache implementation are defined in the Mustache specification. Trimou passes all the spec tests (version 1.1.2), except "Section - Alternate Delimiters" from lambdas optional module. But it's not just a Mustache implementation...

Where is the template?

This is a task for a special component called template locator which is able to automatically locate the template contents for the given template identifier. Actually you can have more than one template locator - those with higher priority are called first.

Trimou provides some built-in implementations (classpath, filesystem) which work well in Java SE. ServletContextTemplateLocator (a part of the servlet extension) on the other hand is designed for servlet containers and is able to locate the template anywhere in the web app.
 
MustacheEngine engine = MustacheEngineBuilder
  .newBuilder()
  .addTemplateLocator(new ServletContextTemplateLocator(10, "/WEB-INF/templates"))
  .build();
// Pass the template contents as a String
Mustache m1 = engine.compileMustache("my-foo-template", "{{foo}}");
// And now use the locator
Mustache m2 = engine.getMustache("my-template.html");

i18n support

Trimou has a very basic i18n support. It provides three optional resolvers (NumberFormatResolver, DateTimeFormatResolver, ResourceBundleResolver) and one optional lambda (ResourceBundleLambda).

// DateTimeFormatResolver example
MustacheEngine engine = MustacheEngineBuilder
                           .newBuilder()
                           .setProperty(DateTimeFormatResolver.CUSTOM_PATTERN_KEY, "DD-MM-YYYY HH:mm")
                           .addResolver(new DateTimeFormatResolver())
                           .build();
Mustache mustache = engine.compileMustache("{{now.formatCustom}}");
Assert.assertEquals("Now: 03-05-2013 22:05", mustache.render(ImmutableMap.<String, Object> of("now", new Date())));

Template inheritance

This feature is not supported in the spec. However it's very important from the maintainability point of view. Trimou basically follows the way mustache.java implements template inheritance. In the extended template, the sections to extend are defined - use $ to identify such sections. In extending templates, the extending sections are defined - again, use $ to identify such sections. Sections to extend may define the default content.

This a template to extend:

{{$header}}
  The default header
{{/header}}
In between...
{{$content}}
  The default content
{{/content}}
© 2013

Can be extended in this way:

Hello world!
{{<super}}
  {{$header}}
    My own header
  {{/header}}
{{/super}}
Lalala...

And the result is:

Hello world!
This a template to extend
  My own header
In between...
  The default content
© 2013
Lalala...

CDI support

Contexts and Dependency Injection for the Java EE platform is a great programming model. Named CDI beans are automatically accessible via Unified EL and thus available on JSP/JSF pages. Trimou built-in CDI extension allows you to do the same. It automatically registers a special resolver which is able to lookup a named bean.

Suppose we have the following bean:

@Named("provider")
@RequestScoped
public class DataProvider {
    public String[] getData() {
        return new String[] {"foo","bar"};
    }
}

We can automatically use it in our template:

<ul>
{{#provider.data}}
    <li>{{this}}</li>
{{/provider.data}}
</ul>

to render something like:

<ul>
    <li>foo</li>
    <li>bar</li>
</ul>

CDI extension also implements a custom scope which is active during each rendering of a template (there is exactly one bean instance per template rendering). This could be useful in Java SE where usually only @ApplicationScoped and @Dependent built-in scopes are available. You can annotate your bean with org.trimou.cdi.context.RenderingScoped to declare the rendering scope.

PrettyTime - a nice way of displaying date and time

Most applications do have to display the date and time correctly. There's a lot of stuff in Java to handle dates properly. But sometimes it's useful to render nice relative timestamps like "right now" and "10 minutes from now". This is why Trimou integrates PrettyTime.

MustacheEngine engine = MustacheEngineBuilder.newBuilder().build();
// The PrettyTimeResolver is automatically loaded if you place the extension jar on the classpath
Mustache mustache = engine.compileMustache("prettyTime","{{now.prettyTime}}");
String output = mustache.render(ImmutableMap.<String, Object> of("now", new Date()));
// Renders something similar:
// moments from now

Minify your templates

It's very common to minify JavaScript/CSS files so why not the template itself? You can save some bandwidth and also increase the performance of the rendering a little bit. Trimou integrates small and efficient HtmlCompressor library. There are two ways to minify the templates.

It’s possible to register a special listener to minify templates before parsing/compilation:

MustacheEngine engine = MustacheEngineBuilder.newBuilder().addMustacheListener(Minify.htmlListener()).build();
Mustache mustache = engine.compileMustache("minify_html","<html><body>     <!-- My comment -->{{foo}}  </body></html>");
String output = mustache.render(ImmutableMap.<String, Object> of("foo", "FOO"));
// Renders:
// <html><body> FOO </body></html>

Or use a special lambda to minify some parts of the template contents:

MustacheEngine engine = MustacheEngineBuilder.newBuilder().build();
Mustache mustache = engine.compileMustache("minify_html_lambda","<html><body><!-- Remains -->{{#mini}}<!-- Will be removed -->   FOO {{/mini}}</body></html>");
String output = mustache.render(ImmutableMap.<String, Object> of("mini", Minify.htmlLambda()));
// Renders:
// <html><body><!-- Remains --> FOO </body></html>

Eventually you can also implement your own minifier and leverage the existing infrastructure.

Published at DZone with permission of its author, Martin Kouba.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Adrian Mitev replied on Mon, 2013/09/09 - 2:48pm

 How is it in comparison with Freemarker? Is mustache.java a good competitor to java EL expressions?

Martin Kouba replied on Wed, 2013/09/11 - 3:55am in response to: Adrian Mitev

Freemarker is evidently proven and feature-rich. One thing I was missing was template inheritance to manage layouts, but I know this can be achieved by the means of macros and directives. I'm not sure about performance.

It's difficult to say whether Trimou (mustache.java is actually a different Mustache implementation) is a good competitor for EL because it does not cover the same use case. EL is a standardized expression language - defines the way to access application data, whereas Trimou is a complete templating engine. Anyway EL provides a lot of view logic constructs (especially EL 3.0). Trimou (and Mustache in general) on the other hand promotes templates with minimal logic.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.