Thymeleaf

Introduction

We now have finally come to the view part of MVC, we have looked at Repositories, Services and Controllers, before I start there is nothing stopping you creating a pure API application and then using something like React or Angular to provide the view, customers may want to retrieve data only and have no use for a Browser based GUI, especially in a very automated world of today.

Like in my other Spring Boot sections I will cover a numbers of topics to get you started and will leave you to the Thymeleaf website for the full documentation, this won't be a full step by step tutorial on Thymeleaf but more of a cheatsheet.

Thymeleaf is a JSP replacement of the old world, it is a modern server-side Java template engine for both web and standalone environments, it uses templates to create HTML web pages, objects can be passed to and incorporated into the template and then transformed into a HTML document and sent to the clients browser. Thymeleaf uses a natural HTML template as can be seen below, also thymeleaf has additional features like layouts, security, etc.


Setup and Controllers

Thymeleaf templates are stored in the resources -> templates folder, you can also create a directory inside this folder to organize the templates. Also if you notice there is a i18n folder for internationalization support which I will cover later, the static folder I cover next. You can also create other folders for images, fonts, etc.


The static folder contains static content, like CSS, Javascript, etc, this is more of Spring Boot directory layout than Thymeleaf but keeps everything organized.


Next lets take a look at how the controller uses a template before we actually look at one, generally the last statement in the controller is to create the view, we do this simply returning a view template name relative to the template directory structure, so looking at the index method (left-hand screenshot) we see that we are returning index which is the index template (right-hand screenshot), spring will process the thymeleaf template and send back to the clients browser. In the second method called registration we use a Model object that we pass to the thymeleaf template, you can add attributes to the Model object which can then be used inside the template, for example it might be a list of users that you want to create a HTML table, etc, in the registration example I am creating a userRegisterDTO attribute name and attaching a userRegisterDTO object to be used by the thymeleaf template.

Lastly regarding controllers, I wanted to show you a template that has a more relative path (left-hand screenshot), you can see that I am using the template /user/userProfile relative from the templates folder. There are times when you don't want to return to the clients browser right away but instead redirect to another controller method, you can do this using the redirect option and specifying the URL, Spring will automatically go to the routing method based on the URL instead of going back to the clients browser and redirecting (saves a network trip), an example of this can be seen in the right-hand screenshot.

Thats about it for thymeleaf and controllers its a pretty simple setup to be honest.

Decorators and Fragments

I am going to jump straight in a bit of an advanced topic because its good to have an outstand of decorators (layouts) and fragments before you start creating the templates as it make life a bit easier. In web pages you have common elements like headers, footers, Javascript tags, header tags, etc. Instead of hard coding each of these into each thymeleaf template we can create decorators and fragments that can be used by all thymeleaf templates which means a single change will then be reflected in all web pages, its basically using a hierarchical approach.

Below is going to be used as a decorator, as it contains HTML elements that will be used by many of the templates (web pages), the first thing to notice is the incorporate the thymeleaf XML namespace, this allows the template to use thymeleaf's tags, there are different thymeleaf namespaces for basic thymeleaft tags, layout thymeleaf tags and thymeleaf security tags, etc. The first th tag (thymeleaf) is in the link element, when processing the thymeleaf template, the thymeleaf resolver will pickup on these tags and process them based on its action for that tag, so th:href will write a standard HTML link tag. Remember all that thymeleaf is going to do is create a HTML web page. The th:block tag simply gets a fragment and places here in the web page, the first part of the th:replace tag is the file location of the fragment, the second part is the fragment name. The last th:block is a place hold for content to be inserted , so for an example the index template would be wrapped with this template as we will see later.


Fragments are simple blocks of HTML code, for example a nav bar, footer, copyright, etc. In the below example there are two fragments navbar and footer that can be used in any template. The th:fragment tag simply gives a name to the fragment, in the first example navbar, in the second fragment its called footer.


So what we have is a template that uses fragments that will be used as a decorator, in the index template you can see that we want to decorate this template with another template (the decorator), notice that the layout:fragment is named as content and thus the decorator content block will be replaced with this fragment. So one web page is created with a number of templates (includes decorators) and fragments, the more decorator templates and fragments you create the more reusable code that you can use, plus this means only one place to change the code which then would be reflected across all web pages.


Here is an other example of a template that can used to decorate other templates, this one is specifically used for data tables, you can build many layers on top of each other add elements that will only be used for specific web pages.


Model Data

I mentioned in the controller section above that we use the Model object to pass data to a thymeleaf template, so how do we access that data, firstly to allow the IDE to understand the type of object that we might be passing we use the @thymesVar tag in a comment, this allows the IDE to automatically show the fields/methods of an object when typing as seen in Intellij below


In the controller we use the Model object and create a films attribute that points to a List of films, the thymeleaf template uses the atribute name films to access the List of films, the @thymeVar matches the film object in the data-th-each thymeleaf loop. The film object has the same fields/methods as the film object does and thus you can use them inside the template.

If you notice I created some href links in the above template using the @{} thymeleaf, this is a thymeleaf Link URL expression which when resolved will be converted into a string, there are a number of other thymeleaf expressions as seen below



Conditional, Text, Forms, etc

Thymeleaf also offers conditional statements


Thymeleaf also allows you to write text and img tags, again remember that this code will be converted into HTML tags (span text, img tag, etc)


You can post forms, notice the href link that specifies an action and passes data back to the controller, you will also notice that security can be used using thmyeleaf security namespace, I will cover more of this in my spring security section.


Another example of a complex form with error handling, the th:object allows you to just use the fields inside the form code


Internationalization (i18n)

Lastly I want to cover internationalization (i18n), i18n is i + 18 characters in 'internationalization' + n, basically it covers languages and currencies, the language is driven by the accept-language request header (see below screenshot) in the broswer but can also use cookies or even a profiles/custom parameter, etc. Resource bundles (aka message.properties) are used to supply the language text for the application, so if the language is en-GB (see below screenshot) this would match messages_en_GB.properties file and if there is no match it would then default to the messages.properties file (default language).


First I add a property to instruct Spring where to find the messages and validation message files as I want to create my own directory structure, then I create the directory structure (right-hand screenshot) and add the message files.

You can add additional resource bundles files using Intellij by right-clicking on the Resource Bundle 'message' folder and selecting add property files to Resource Bundle, then selecting Add All and entering the bundle name, for example en_GB, en_US, etc.

The message files themselves are simple key/value pairs, the value will reflect the specific language text that you require.


So how do you use them in thymeleaf, you use the #{} message expression selector, you can see that I use the registration.title and registeration.heading in the thymeleaf template below, depending on the language of choice the specific message file will be used, be it English, German, French, etc.