Thymeleaf Basics In Spring Boot

I recently started on the path on building content on the fly that gets sent out as soon as possible, using a template engine, but from a back-end perspective. If that makes sense? This is for an event-driven application that sits there and listens for incoming messages. A simple one. Consume the message as soon as it comes out of the queue. Inspect and analyze its contents, looking for specific keys in the payload that sets off those triggers. Compose a message and then send it about its merry way. That’s about it in a nutshell.

This differed in my previous experiences. A long time ago, I was part of a team that ported a JavaScript-powered Windows 8 application into a full Java web application. Back then we used Java Server Pages (JSP). In PHP I’ve used Smarty for CakePHP, and Blade for Laravel. But all these were for front-end views like web pages or forms, for example.

For back-end stuff in Java, not so much HTML templating going on for me. Or none at all. Until now. I mean, usually I just deal with databases, CSVs, RESTful APIs, dump files into FTP directories, or SCP stuff into a Linux box. You know, back-end stuff.

So there were 1 or 2 other template engines recommended, FreeMarker being one of those. I finally settled with Thymeleaf instead. Lots of documentation. Nice integration with Spring/Spring Boot. I’m sure the others have that too.

Anyway, posting something about the things I’ve learned in this experience without going into entire specifics of that project except for things related to Thymeleaf.

Pull in Thymeleaf’s Spring Boot packages from (in Gradle):

compile group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf'

Template Engine Configuration

First is configuring it in the application. Going with the bean annotation approach. Started by defining the template engine and a template resolver.

// Other code omitted for brevity
    @Bean
    public SpringTemplateEngine templateEngine() {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver());
        return templateEngine;
    }

    @Bean
    public ClassLoaderTemplateResolver templateResolver() {
        ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
        templateResolver.setPrefix("/custom/templates/");
        templateResolver.setSuffix(".html");
        templateResolver.setCharacterEncoding(StandardCharsets.UTF_8.name());
        templateResolver.setCacheable(false); // default is true
        templateResolver.setTemplateMode(TemplateMode.HTML); // default
        return templateResolver;
    }

Here it tells ThymeLeaf on how to resolve the templates. I’ve placed it in a custom location – /custom/templates/, and this is still relative to the resources directory. The default is just /templates/. The line with setPrefix() can be skipped if templates were placed in the latter. The setSuffix(“.html”) says to look for the template with the name that ends in .html always without having to explicitly include that when passing the template name later on.

FileTemplateResolver can also be used too. That would mean the templates can be placed somewhere else in the filesystem so that it is not tied to the application/JAR file structure. The configuration will be a bit different.

If there’s need to not create actual template files, if the intent is to skip having to to read templates from directories, then StringTemplateResolver is an option. Just assign the template to a String. That’s it. No need to set the template location. In fact there are no setPrefix() and setSuffix() methods for this resolver. The TemplateMode defaults to HTML. Actually, it’s the same for the default of other template resolvers.

Of course, Thymeleaf can also process/create XML, XHTML, and plain text documents.

The Template

Moving on, now that I have the basic template engine configuration in place I am gonna put a simple template in that folder above. I’m going to call it – my-hello-template.html – because I’m boring. 😅 (At least it’s not Hello World, right?)

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<title>Template with Thymeleaf in Spring Boot</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<body>
    <p>Hello, my name is <span th:text="${firstName + ' ' + lastName}"></span> from Philippines</p>
    <p th:text="${'I am a ' + description}"></p><br />
    <p>Visit me at my website below:
        <a th:text="${websiteName}" th:href="@{${websiteUrl}}"></a>
    </p>
</body>
</html>

I’ve placed a few variables in the template using standard expressions. An extensive documentation is provided by Thymeleaf at their site, but to get started quickly here is one: https://www.thymeleaf.org/doc/articles/standarddialect5minutes.html

Nothing much going on here. It is just HTML. The actual dynamic values will be injected later on when the application runs.

It’s All About The Context

The direct and obvious way to get the values into the template is by using the Context class and setting the properties with the values in it. This can be done like the code snippet below.

// Other code omitted for brevity
import org.thymeleaf.context.Context;

...

    public String getContent() {
        Context context = new Context();
        context.setVariable("firstName", "Jose");
        context.setVariable("lastName", "Yamut");
        context.setVariable("description", "programmer");
        context.setVariable("websiteUrl", "https://www.joseyamut.xyz");
        context.setVariable("websiteName", "joseyamut.xyz");
        return this.templateEngine.process("my-hello-template", context);
    }

Very straightforward. Key-value pairs as usual. The keys map out to the variable names I have in my template. Then I use the template engine’s process() method, passing along the name of the template and the Context object as parameters, respectively.

I can also use a Map object to define those properties. Then it will look like so,

// Other code omitted for brevity
Map<String, String> map = new HashMap<>();
map.put("firstName", "Jose");

...
...
Context context = new Context();
context.setVariables(map);

The End

The final output in String will look like the following,

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
    <title>Template with Thymeleaf in Spring Boot</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <body>
        <p>Hello, my name is 
            <span>Jose Yamut</span> from Philippines
        </p>
        <p>I am a, programmer</p>
        <br />
        <p>Visit me at my website below:        
            <a href="https://www.joseyamut.xyz">joseyamut.xyz</a>
        </p>
    </body>
</html>

Similar Posts: