Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to make Spring Thymeleaf process a string template?

I would like to write something like :

    @Autowired
    private SpringTemplateEngine engine;
....
  // Thymeleaf Context
  WebContext thymeleafContext = new WebContext(request, response, request.getServletContext(), locale);

    // cached html of a thymeleaf template file
    String cachedHtml=....

    // process the cached html
  String html=engine.process(cachedHtml, thymeleafContext);

By default, the [process] method can't do that. I can understand from the docs that I need a special Template Resolver :

In order to execute templates, the process(String, IContext) method will be used: final String result = templateEngine.process("mytemplate", ctx); The "mytemplate" String argument is the template name, and it will relate to the physical/logical location of the template itself in a way configured at the template resolver/s.

Does anyone know how to solve my problem ?

The goal is to cache the Thymeleaf templates (files) in strings and then process theses strings rather than the files.

like image 354
Serge Tahé Avatar asked Apr 03 '14 07:04

Serge Tahé


People also ask

Do people still use Thymeleaf?

The Thymeleaf library has been around at least for 10 years and it is still actively maintained as of today. It is designed to allow stronger collaboration between design and developer teams for some use cases, as Thymeleaf templates look like HTML and can be displayed in the browser as static prototypes.

Is Thymeleaf a template engine?

Thymeleaf is a modern server-side Java template engine for both web and standalone environments.


1 Answers

The solution we ended up using consisted of a new IResourceResolver with a custom Context rather than a custom TemplateResolver. We chose this because we still wanted to use classpath scanning in most cases, but occasionally had dynamic content.

The following shows how we did it:

public class StringAndClassLoaderResourceResolver implements IResourceResolver {


    public StringAndClassLoaderResourceResolver() {
        super();
    }


    public String getName() {
        return getClass().getName().toUpperCase();
    }


    public InputStream getResourceAsStream(final TemplateProcessingParameters params, final String resourceName) {
        Validate.notNull(resourceName, "Resource name cannot be null");
        if( StringContext.class.isAssignableFrom( params.getContext().getClass() ) ){
            String content = ((StringContext)params.getContext()).getContent();
            return IOUtils.toInputStream(content);
        }
        return ClassLoaderUtils.getClassLoader(ClassLoaderResourceResolver.class).getResourceAsStream(resourceName);
    }

    public static class StringContext extends Context{

        private final String content;

        public StringContext(String content) {
            this.content = content;
        }

        public StringContext(String content, Locale locale) {
            super(locale);
            this.content = content;
        }

        public StringContext(String content, Locale locale, Map<String, ?> variables) {
            super(locale, variables);
            this.content = content;
        }

        public String getContent() {
            return content;
        }
    }

Test Case

public class StringAndClassLoaderResourceResolverTest {

    private static SpringTemplateEngine templateEngine;

    @BeforeClass
    public static void setup(){
        TemplateResolver resolver = new TemplateResolver();
        resolver.setResourceResolver(new StringAndClassLoaderResourceResolver());
        resolver.setPrefix("mail/"); // src/test/resources/mail
        resolver.setSuffix(".html");
        resolver.setTemplateMode("LEGACYHTML5");
        resolver.setCharacterEncoding(CharEncoding.UTF_8);
        resolver.setOrder(1);

        templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(resolver);
    }

    @Test
    public void testStringResolution() {
        String expected = "<div>dave</div>";
        String input = "<div th:text=\"${userName}\">Some Username Here!</div>";
        IContext context = new StringAndClassLoaderResourceResolver.StringContext(input);
        context.getVariables().put("userName", "dave");
        String actual = templateEngine.process("redundant", context);
        assertEquals(expected, actual);
    }

    @Test
    public void testClasspathResolution(){
        IContext context = new Context();
        context.getVariables().put("message", "Hello Thymeleaf!");
        String actual = templateEngine.process("dummy", context);
        String expected = "<h1>Hello Thymeleaf!</h1>";
        assertEquals(expected, actual);
    }
}

Dummy template file at src/main/resources/mail/dummy.html

<h1 th:text="${message}">A message will go here!</h1>

Note: We used Apache CommonsIO's IOUtils for converting the String to an InputStream

like image 153
David Welch Avatar answered Oct 24 '22 20:10

David Welch