1. Introduction
Thymeleaf is a Java template engine for processing and creating HTML, XML, JavaScript, CSS and plain text. For an intro to Thymeleaf and Spring, have a look at this write-up.
Besides these basic functions, Thymeleaf offers us a set of utility objects that will help us perform common tasks in our application.
In this article, we’ll discuss a core feature in Thymeleaf 3.0 – Expression Utility Objects in Spring MVC applications. More specifically, we’ll cover the topic of processing dates, calendars, strings, objects and much more.
2. Maven Dependencies
First, let us see the required configuration needed to integrate Thymeleaf with Spring. The thymeleaf-spring library is required in our dependencies:
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring4</artifactId>
<version>3.0.1.RELEASE</version>
</dependency>
Note that, for a Spring 3 project, the thymeleaf-spring3 library must be used instead of thymeleaf-spring4. The latest version of the dependencies can be found here.
3. Expression Utility Objects
Before looking at the core focus of this writeup, if you want to take a step back and see how to configure Thymeleaf 3.0 in your web app project, have a look at this tutorial.
For the purpose of the current article, we created a Spring controller and HTML file – to test out all the features we’re going to be discussing. Below is the complete list of available helper objects and their functions:
- #dates: utility methods for java.util.Date objects
- #calendars: similar to #dates, used for java.util.Calendar objects
- #numbers: utility methods for formatting numeric objects
- #strings: utility methods for String objects
- #objects: utility methods for Java Object class in general
- #bools: utility methods for boolean evaluation
- #arrays: utility methods for arrays
- #lists: utility methods for lists
- #sets: utility methods for sets
- #maps: utility methods for maps
- #aggregates: utility methods for creating aggregates on arrays or collections
- #messages: utility methods for obtaining externalized messages inside variables expressions
3.1. Dates Objects
The first function that we want to discuss is processing of the java.util.Date objects. The expression utility objects responsible for date processing start with #dates.functionName(). The first function that we want to cover is formatting of a Date object (which is added to the Spring model parameters).
Let’s say we want to use ISO8601 format:
<p th:text="${#dates.formatISO(date)}"></p>
No matter how our date was set on the back-end side, it needs to be displayed accordingly to this standard. What’s more, if we want to be specific with the format, we can specify it manually:
<p th:text="${#dates.format(date, 'dd-MM-yyyy HH:mm')}"></p>
The function takes two variables as parameters: Date and its format.
Finally, here are a few similarly useful functions we can use:
<p th:text="${#dates.dayOfWeekName(date)}"></p> <p th:text="${#dates.createNow()}"></p> <p th:text="${#dates.createToday()}"></p>
In the first, we will receive the name of the day of the week, in the second we will create a new Date object, and finally we will create a new Date with time set to 00:00.
3.2. Calendar Objects
Calendar utilities are very similar to dates processing, except that we are using an instance of the java.util.Calendar object:
<p th:text="${#calendars.formatISO(calendar)}"></p> <p th:text="${#calendars.format(calendar, 'dd-MM-yyyy HH:mm')}"></p> <p th:text="${#calendars.dayOfWeekName(calendar)}"></p>
The only difference is when we want to create new Calendar instance:
<p th:text="${#calendars.createNow().getTime()}"></p> <p th:text="${#calendars.createToday().getFirstDayOfWeek()}"></p>
Please note, that we may use any Calendar class method in order to get requested data.
3.3. Numbers Processing
Another very handful feature is numbers-processing. Let’s focus on a num variable, randomly created with a double type:
<p th:text="${#numbers.formatDecimal(num,2,3)}"></p> <p th:text="${#numbers.formatDecimal(num,2,3,'COMMA')}"></p>
In the first line, we format decimal number by setting minimum integer digits and exact decimal digits. In the second one, in addition to integer and decimal digits, we specified the decimal separator. The options are POINT, COMMA, WHITESPACE, NONE or DEFAULT (by locale).
There is one more function that we want to present in this paragraph. It is creation of a sequence of integer numbers:
<p th:each="number: ${#numbers.sequence(0,2)}"> <span th:text="${number}"></span> </p> <p th:each="number: ${#numbers.sequence(0,4,2)}"> <span th:text="${number}"></span> </p>
In the first example, we had Thymeleaf generate a sequence from 0-2, whereas in the second in addition to minimum and maximum value, we provided a definition of step (in this example the values will change by two).
Please note, that the interval is closed on both sides.
3.4. Strings Operations
It is the most comprehensive feature of expression utility objects.
We can start the description with the utility of checking empty or null String objects. Quite often, developers would use Java methods inside Thymeleaf tags to do that, which might be not safe for null objects.
Instead, we can do this:
<p th:text="${#strings.isEmpty(string)}"></p> <p th:text="${#strings.isEmpty(nullString)}"></p> <p th:text="${#strings.defaultString(emptyString,'Empty String')}"></p>
The first String is not empty, so the method will return false. The second String is null, so we will get true. Finally, we may use #strings.defaultString(…) method to specify a default value, if String will be empty.
There are many more methods. All of them works not only with strings but also with Java.Collections. For example to use substring-related operations:
<p th:text="${#strings.indexOf(name,frag)}"></p> <p th:text="${#strings.substring(name,3,5)}"></p> <p th:text="${#strings.substringAfter(name,prefix)}"></p> <p th:text="${#strings.substringBefore(name,suffix)}"></p> <p th:text="${#strings.replace(name,'las','ler')}"></p>
or to use null-safe comparison and concatenation:
<p th:text="${#strings.equals(first, second)}"></p> <p th:text="${#strings.equalsIgnoreCase(first, second)}"></p> <p th:text="${#strings.concat(values...)}"></p> <p th:text="${#strings.concatReplaceNulls(nullValue, values...)}"></p>
Finally, there are text-style related features, that will preserve the syntax to be always the same:
<p th:text="${#strings.abbreviate(string,5)} "></p> <p th:text="${#strings.capitalizeWords(string)}"></p>
In the first method, abbreviated text will make it have a maximum size of n. If a text is bigger, it will be clipped and finished with “…”.
In the second method, we will capitalize words.
3.5. Aggregates
The last but not the least function that we want to discuss here is aggregates. They are null safe, and provide utilities to calculate average or sum from array or any other collection:
<p th:text="${#aggregates.sum(array)}"></p> <p th:text="${#aggregates.avg(array)}"></p> <p th:text="${#aggregates.sum(set)}"></p> <p th:text="${#aggregates.avg(set)}"></p>
4. Conclusion
In this article, we discussed Expression Utility Objects features implemented in the Thymeleaf framework, version 3.0.
The full implementation of this tutorial can be found in the GitHub project.
How to test? Our suggestion is to play with a browser first, then check the existing JUnit tests as well.
Please take a note, that examples do not cover all available utility expressions. If you want to learn about all types of utilities have a look here.