Preparing Message Payloads with Thymeleaf

By | August 8, 2017

In this article I will show how to prepare message payloads with parameters in different formats using the Thymeleaf template engine. No previous knowledge of Thymeleaf is assumed.

Thymeleaf logo copyright © The Thymeleaf Team.

Thymeleaf logo copyright © The Thymeleaf Team.

As far as I am concerned there are several use cases for this. Some examples are:

  • System integration.
    Requests can be maintained as plain files and no code has to be written to create message payloads.
    In addition I am able to create messages for legacy systems, for which there is no library that supports marshalling of messages, and insert parameters into these messages.
  • Creating test request in test client code.
  • Generating mock response messages in mock services.

Setting Up the Project

I will use Spring Boot 2.0.0.M3, which is the latest version available as of writing this article, and Thymeleaf 3.0.7.RELEASE. The Thymeleaf version is the version specified in the Spring Boot Thymeleaf starter, so any version 3 of Thymeleaf will suffice.

Use the following link to generate the skeleton for this article’s example project.
For the curious, the above link uses the Spring Initializr web page to generate a Maven project with Java and Spring Boot.
Once the archive is downloaded, unpack it to a location of your choice and open/import the Maven project into your IDE.

Adding Dependencies

The test in the example project will use REST-Assured and Hamcrest. In REST-Assured I will use only the XML and JSON path parts.
Add the following dependencies to the pom.xml file in the <dependencies> element of the example project:

Tests

Being the flawless developer that I am, I always write my tests first 🙂 (it is significantly easier being flawless writing articles about writing code that you already have written while you pretend that you write the code for the first time). With the boasting out of the way, lets look at some tests. I’ve implemented my tests in the test class that Spring Initializr generated for me, that is MessagePayloadsWithThymeleafApplicationTests. There will be some syntax errors at first, since we haven’t implemented the Thymeleaf configuration class yet, but please bear with me.

Obviously we can’t run the tests at this stage but I will examine the code close, since this is the kind of code you will write in your programs if you want to use Thymeleaf to retrieve, for instance, test messages or responses for a mock service.

  • There is an instance variable named mMessageTemplateEngine of the type SpringTemplateEngine.
    This is the object used when interacting with Thymeleaf. The astute reader notice that it is there is the word “Spring” in the name. Yes, the Spring-people have extended the Thymeleaf class TemplateEngine but the examples in this article work equally well using plain vanilla Thymeleaf – see note below.
  • The Thymeleaf class Context is used in all three tests to pass information to the template engine.
    I have used this class since retrieving message templates is not really closely tied to web applications and there is no servlet context, nor servlet request or response to set on the context, as required by, for instance, the WebContext context class in Thymeleaf.
    Of course, there is nothing stopping you from using Thymeleaf to retrieve message templates in a web application but I would use a separate template engine for message templates.
  • In all three test methods, the messages are retrieved in the same way.
    First an instance of the Thymeleaf class Context is created and then variables are set in the context. Finally the message is retrieved by invoking process on the template engine.
    The only thing that sets retrieving message templates of different formats, be it JSON, XML or plain text, apart is the template name.
  • In the xmlMessageTest method, REST-assured’s XML-path is used to retrieve the contents of the XML elements that are expected to be modified in the XML template.
  • In a similar manner in the jsonMessageTest method, REST-assureds JSON-path is used to retrieve the contents of the JSON elements expected to be modified in the JSON template.
  • In all three test methods I log the processed messages to the console.
    This is just to have some visual feedback for the sake of this example and nothing I would normally do.

A note on using the Thymeleaf TemplateEngine Type

If you want to create a Spring bean of the type TemplateEngine in your Spring Boot project, you may want to consider two things:

First, you need to add a dependency to the OGNL library. This is also true of you want to use Thymeleaf in a non-Spring project. The reason for this is that if you use the Spring classes that inherit from the Thymeleaf classes, they change the default expression language used by Thymeleaf from OGNL to Spring expression language. If you use Thymeleaf directly, then the default expression language is OGNL.

Second, the Spring Boot Thymeleaf starter will create a Spring bean named templateEngine of the type TemplateEngine, so you will need to use @Qualifier on any autowired parameters etc if you decide to create a TemplateEngine bean with another name.

Template Directories and Files

As I promised earlier, there will be three different types of templates; XML, JSON and text templates. As to prepare for projects where there are more than three templates, a separate directory will be used for each of the three formats.

  • In src/main/resources/templates create three directories named “json”, “text” and “xml”.
  • In each of the directories create a file that is named “currency_conversion_request” that has a postfix that matches the formats (“.xml”, “.json” and “.txt”).
    The result should look something like this in your IDE:

    Thymeleaf message templates directory structure.

JSON Message Template

In the “currency_conversion_request.json” file, enter the following:

Note that:

  • In the value of the from_currency key, there is some kind of placeholder.
    This is a Thymeleaf placeholder used in JSON, and as we will see below, text message templates. Thymeleaf will replace this placeholder with the value of the variable from_currency found in the Thymeleaf context.
  • The placeholders include the characters [(${ and })].
    These characters will also be replaced/removed when a placeholder is replaced by a value.
  • In the value of the to_currency key there is also a placeholder similar to the one we just saw.
  • Apart from the two placeholders, there is nothing special about the JSON message.

Text Message Template

In the “currency_conversion_request.txt” file, enter the following:

Note that:

  • As with the JSON message above, there is a placeholder for the from_currency.
  • Again there is a placeholder for the to_currency key.
  • The placeholders include the characters [(${ and })].
    These characters will also be replaced/removed when a placeholder is replaced by a value.
  • Apart from the two placeholders, there is nothing special about the text message.

XML Message Template

In the “currency_conversion_request.xml” file, enter the following:

Note that:

  • There is a namespace declaration for the Thymeleaf namespace looking like this:
    xmlns:th=”http://www.thymeleaf.org”
    This is required in XML templates used with a Thymeleaf template resolver that operates in XML mode. This namespace declaration will not, as we will see later when we run our tests, show up in the messages generated from this template.
  • There is an attribute th:text=”${from_currency}” in the <FromCurrency> element.
    We see that the namespace of this attribute is the Thymeleaf namespace, as declared earlier. As with the namespace declaration, this attribute declaration will not appear in the messages generated from this template. It will, however, tell Thymeleaf to insert the value of the from_currency variable into the <FromCurrency> element.
  • The contents of the <FromCurrency> element is empty.
    As before, Thymeleaf will insert the name of the currency to exchange from in this element.
  • The <ToCurrency> element will be handled in a similar manner by Thymeleaf.

Thymeleaf Configuration

The only thing that now remains before we will be able to run the tests in the example is the Thymeleaf configuration. Being a small example program, I created it in the same package as the main class.

Note that:

  • There are three Spring beans of the type SpringResourceTemplateResolver.
    The different template resolvers handle the three different formats; XML, JSON and text templates. The reason for having different template resolvers is that the resolvers operate in different modes and that the templates for the different formats reside in their own directories, as we saw when creating the template files earlier.
    If I were to use pure Thymeleaf without Spring, then I would use ClassLoaderTemplateResolver template resolvers in this example and I would also have to modify the configuration of the template resolvers slightly.
  • Each of the template resolvers have the same prefix.
    The prefix sets the root of the location where the templates can be found. In this case it is in the templates directory on the classpath.
  • Each of the template resolvers have different resolvable patterns configured.
    The resolvable patterns is used by the resolver to determine whether a requested template should be resolved by the resolver or passed on to the next resolver. Note that the template suffix, such as .xml and .json, is not included in the resolvable patterns.
  • Each of the template resolvers have different suffix set on them.
    Since this example uses different suffixes for the different template types, .xml, .json and .txt, the template resolver needs for a type need to be configured with the appropriate suffix.
    Thus when resolving a template, a template resolver will use the prefix + template name + suffix to find the location and name of the template which to look for. The template name is, as we saw when implementing the tests, supplied when processing a template.
  • Each of the template resolvers have a different template mode configured.
    The reason for this is using templates in different format. We could have used text template mode for all templates but I felt that using a template mode that matched the type of template file is more appropriate.
  • All template resolvers are configured not to cache templates.
    Thymeleaf allows for caching of templates and setting a cache eviction policy etc. Not caching templates allow modifications of the templates while the application is running and the modifications being picked up the next time a template is resolved. If you want to be able to modify templates while running your application then having the templates located on the classpath may not be the best option.
  • Each of the template resolvers have a different order configured.
    Template resolvers are kept in a chain ordered by the order attribute. When resolving a template, the first template resolver in the chain first gets a chance to resolver the template. If it cannot resolver the template, then the next resolver will be tried etc.
    Template resolvers that does not have an order will be executed last in the chain.<
  • There is a Spring bean named messageTemplateEngine.
    This is the template engine used by in the tests in this example to resolver message templates.
  • The messageTemplateEngine Spring bean definition takes a parameter of the type Collection<SpringResourceTemplateResolver>.
    This tells Spring to inject all the Spring beans of the type SpringResourceTemplateResolver into this bean at creation time. If there are Spring beans of this type defined elsewhere in the application, they will also be included in this collection.

Running the Tests

If we now run the tests implemented earlier, they should all pass and, among a lot of other output to the console, we should be able to see messages of the three different formats.

The JSON message should look like this:

The XML message should look like this:

Finally, the text message should look like this:

This concludes the example using Thymeleaf to prepare message payloads.
The example project can be found on GitHub.

Happy coding!

Leave a Reply

Your email address will not be published. Required fields are marked *