How to Extend Thymeleaf with dialects

While working with a Thymeleaf application, we can easily extend the functionality of its template engine using Dialects. The process is simple:

  • create a dialect
  • add it to the template engine
  • we’ll be able to make use of it.

Features of a dialect

A dialect has the following three important features:

  1. Processing logic: This logic is specified via processors that apply to either tags or their attributes.
  2. Preprocessing and Postprocessing logic: This kind of logic is specified via pre-processors or post-processors that are applied before or after the actually processing takes place, respectively.
  3. Expression objects: This logic is required in Thymeleaf Standard Expressions and applied to perform specialized operations.

Note: These features are optional. A dialect can only specify some of them.

Creating a dialect

For this example, let’s suppose we are working on a Spring MVC and Thymeleaf application. In this case, we would need to create a dialect that gives the following output:

Good Morning, John!

Where “John” is the logged-in username.

We can say good morning to whoever we want like this:

<p morning:sayto="${username}"> Morning! </p>

Let’s understand what each term means here:

Creating the processor

Let’s create an attribute processor, that will be triggered by a specific attribute in such open tag morning:sayto. We will extend a useful abstract class, AbstractAttributeTagProcessor, that will give us most of the class infrastructure we need:

public class SayToAttributeTagProcessor extends AbstractAttributeTagProcessor {
private static final String ATTR_NAME = "sayto";
private static final int PRECEDENCE = 10000;
public SayToAttributeTagProcessor(final String dialectPrefix) {
super(
TemplateMode.HTML, // This processor will apply only to HTML mode
dialectPrefix, // Prefix to be applied to name for matching (morning)
null, // No tag name: match any tag name
false, // No prefix to be applied to tag name
ATTR_NAME, // Name of the attribute that will be matched (sayto)
true, // Apply dialect prefix to attribute name
PRECEDENCE, // Precedence (inside dialect's precedence)
true); // Remove the matched attribute afterwards
}
protected void doProcess(
final ITemplateContext context, final IProcessableElementTag tag,
final AttributeName attributeName, final String attributeValue,
final IElementTagStructureHandler structureHandler) {
structureHandler.setBody(
"Good Morning, " + HtmlEscape.escapeHtml5(attributeValue) + "!", false);
}
}

Creating the dialect class

Next, we’ll create a dialect class, which will tell the Thymeleaf engine that our attribute processor is available to be used. We will then extend the abstract class AbstractProcessorDialect:

public class MorningDialect extends AbstractProcessorDialect {
public MorningDialect() {
super(
"Morning Dialect", // Dialect name
"morning", // Dialect prefix (morning:*)
1000); // Dialect precedence
}
/*
* Initialize the dialect's processors.
*
* It's important to pass the dialect prefix here too
*/
public Set<IProcessor> getProcessors(final String dialectPrefix) {
final Set<IProcessor> processors = new HashSet<IProcessor>();
processors.add(new SayToAttributeTagProcessor(dialectPrefix));
return processors;
}
}

Using the dialect

In the end, we’ll just add the dialect to our templateEngine bean during configuration using the addDialect method:

@Bean
public SpringTemplateEngine templateEngine(){
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setEnableSpringELCompiler(true);
templateEngine.setTemplateResolver(templateResolver());
templateEngine.addDialect(new MorningDialect());
return templateEngine;
}

And now our new attribute will work fine and give us the desired results.

Copyright ©2024 Educative, Inc. All rights reserved