While working with a Thymeleaf application, we can easily extend the functionality of its template engine using Dialects. The process is simple:
A dialect has the following three important features:
Note: These features are optional. A dialect can only specify some of them.
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:
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 modedialectPrefix, // Prefix to be applied to name for matching (morning)null, // No tag name: match any tag namefalse, // No prefix to be applied to tag nameATTR_NAME, // Name of the attribute that will be matched (sayto)true, // Apply dialect prefix to attribute namePRECEDENCE, // 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);}}
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;}}
In the end, we’ll just add the dialect to our templateEngine bean during configuration using the addDialect
method:
@Beanpublic 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.