Trimou Templates Introduction
Join the DZone community and get the full member experience.
Join For FreeTrimou 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.
Opinions expressed by DZone contributors are their own.
Trending
-
Decoding eBPF Observability: How eBPF Transforms Observability as We Know It
-
Azure Virtual Machines
-
Top 10 Pillars of Zero Trust Networks
-
Java Concurrency: Condition
Comments