2

i tried to find tutorials online, but i only found them in the context of web applications. in my case what i have is an html template that i want to fill "manually", meaning it should run from a static main method without spring or any other framework. just "plain thymeleaf"

i have for example a test html file containing: <p th:text="#{test.message}">This is a report</p>

how does the java code look like that simply fills this variable? i couldn't find a minimal running code example.

  • 1
    Does this help? https://stackoverflow.com/questions/73739292/how-to-generate-static-files-from-a-spring-thymeleaf-project/73749027#73749027 – Metroids Oct 06 '22 at 14:40

1 Answers1

3

The following is a standalone Thymeleaf demo (no web application needed; no Spring used):

Assumptions:

I have a messages file called test.properties containing the following:

test.message=This is a message to you.

I have a related HTML template called test.html:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
    <p th:text="#{test.message}">This is a report</p>
    <p th:text="${note}">This is a note</p>
</html>

In the above template, I added Thymeleaf variable expression (${note}), as well as the message expression - just to make the demo more complete. You may not even need that.

You need to make sure that the HTML template and the properties file are in the same location, because I am using the StandardMessageResolver - see below.


I created a standalone Thymeleaf template engine class:

import org.thymeleaf.TemplateEngine;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import org.thymeleaf.context.Context;
import org.thymeleaf.extras.java8time.dialect.Java8TimeDialect;
import org.thymeleaf.messageresolver.IMessageResolver;
import org.thymeleaf.messageresolver.StandardMessageResolver;
import java.util.Map;

public class HtmlTemplateEngine {

    private final TemplateEngine templateEngine;

    public HtmlTemplateEngine() {

        templateEngine = new org.thymeleaf.TemplateEngine();
        templateEngine.addDialect(new Java8TimeDialect()); // optional extra

        ClassLoaderTemplateResolver templateResolver
                = new ClassLoaderTemplateResolver(Thread
                        .currentThread().getContextClassLoader());
        templateResolver.setTemplateMode(TemplateMode.HTML);
        templateResolver.setPrefix("/thymeleaf/");
        templateResolver.setCacheTTLMs(3600000L); // one hour
        templateResolver.setCacheable(true);
        templateResolver.setCharacterEncoding("UTF-8");
        templateEngine.setTemplateResolver(templateResolver);
        IMessageResolver messageResolver = new StandardMessageResolver();
        templateEngine.setMessageResolver(messageResolver);
    }

    // use this if you do not want to pass a Context (see below). It basically does
    // the same as the Context-based example, by transferring Map data to a Context:
    public String getTemplate(String templateName, Map<String, Object> parameters) {
        Context ctx = new Context();
        if (parameters != null) {
            parameters.forEach((k, v) -> {
                ctx.setVariable(k, v);
            });
        }
        return this.templateEngine.process(templateName, ctx).trim();
    }

    public String getTemplate(String templateName, Context ctx) {
        return this.templateEngine.process(templateName, ctx).trim();
    }

}

Some of the entries are default values - so they could be removed without affecting anything (for example the StandardMessageResolver will be used by default if you do not provide one).

I chose to use a ClassLoaderTemplateResolver. There are other choices you can make.


I use the above artifacts as follows:

private void processSimpleReport() {
    Map<String, Object> model = new HashMap<>();
    model.put("note", "my note here");

    Context ctx = new Context();
    //ctx.setLocale(Locale.US); // optional for i18n
    ctx.setVariables(model);

    HtmlTemplateEngine engine = new HtmlTemplateEngine();

    String s = engine.getTemplate("test.html", ctx);
    System.out.println(s);
}

Your question only uses a message - the model variables are just optional extras I added for this demo.


The resulting HTML is:

<!DOCTYPE html>
<html>
    <p>This is a message to you.</p>
    <p>my note here</p>
</html>
andrewJames
  • 19,570
  • 8
  • 19
  • 51