Community contributed extensions

Thymeleaf module

This is a Play framework module to use Thymeleaf 2.0 as a template engine.

Thymeleaf mainly uses the xml attributes, keeping the XML/XHTML/HTML5 templates well-formed. As the official site says, those can be correctly displayed by browsers and therefore work also as static prototypes.

This is NOT a whole replacement of the groovy template. It is rather an add-on, rendering thymeleaf template only if the alternative template exists.

Sample application

Check out the “Yet Another Blog Engine” in the samples-and-tests directory. It is copied from the framework original sample app, except groovy template files in “app/views/Application” are all replaced by the thymeleaf template files in “app/thviews”, but you can get the same output.
Be sure to do “play deps” before you run the app.

Getting started

Add the following line to your dependencies.yml:


require:
- play
- play -> thymeleaf 0.0.1

and call “play deps”. Remove 404.html and 500.html in “app/views”. (the html errors are routed to thymeleaf template)

Configuration

These are the options with default values.

thymeleaf.prefix=${application.path}/app/thviews

The place where you put thymeleaf template files

thymeleaf.suffix=

thymeleaf.templatemode=XHTML

template mode of the engine

thymeleaf.cache.ttl=

template chache ttl in milliseconds for production mode. They are not cached in DEV mode.

thymeleaf.enhancer.enabled=true

whether to enhance the application classes in order to remove “synthetic” flags for OGNL

Usage

Put thymeleaf well-formed template files like below in “app/thviews” (by default).


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" xmlns:th="http://www.thymeleaf.org">
<body>
<span th:text="${someObj.name}">The name comes here.</span>
</body>
</html>

Please refer to the official documentation for the attribute and expressions usage.

Play specific processors

Action Processor

There are some custom processors included in the module for action string conversion.
The value of the attribute names below can be parsed as an action string.

For example, define pl namespace and put some action string similar to groovy one, except for “${}”.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:pl="http://www.playframework.org" >
<body>
<a href="anotherPage.html" pl:href="Application.anotherAction(someObj.id)">Link</a>
</body>
</html>

You can get the parsed link as expected since the string inside () is parsed as an OGNL expression within the same context of the page.

Form Processor

It acts like Fasttag #{form /}. Authentication token hidden element will be inserted if the method is post.
The default method of the form is ‘GET’ contrary to Groovy template. You can override it with a normal html attribute like below:


<form pl:form="Put.yourAction()" method="post" >
...
</form>

Error Processor

“error” Attribute Processor acts like #{error /} tag in Groovy template. In the sample code below, the span tag appears only if there is an error.


<input type="text" name="user.name" th:value="${user?user.name:null}" /><span class="error" pl:error="user.name">validation error comes here.</span>

Extra implicit objects

Message Resolution

By default, thymeleaf’s StandardMessageReolver is used. Add PlayMessageResolver to TemplateEngine so that the messages are resolved by play.i18n.Messages.


Play.plugin(ThymeleafPlugin.class)
.getTemplateEngine()
.addMessageResolver(new PlayMessageResolver());

Notice

OGNL and class enhancement

Thymeleaf makes use of OGNL as a standard template expression language, and it does not handle any method that has ‘synthetic’ flag, while Play! PropertiesEnhancer marks the generated implicit getter/setter methods ‘synthetic’ for a class that has public properties. Suppose you have model classes User and Address:


public class User {
public Address address;
}

public class Address {
public String street;
}

The Play enhancer generates method User#getAddress() and Address#getStreet(), then a call from OGNL like:


<span th:text="${user.address.street}"></span>

would result in NPE because it cannot invoke the method. So the module re-enhances application classes and removes synthetic flags in order to treat the enhanced objects like normal Java beans. You can turn this off by a configuration parameter in case other precedent modules use the flags. “${addr=user.address, addr.street}” can produce the same result.