#jjug_ccc #ccc_f2 @bufferings Special thanks to Daniel Fernández, who is a Founder and Lead Developer of Thymeleaf. He kindly gave me some advices for my presentation and allow me to use his session materials of Devoxx Belgium 2015 and Spring I/O 2016. Special Thanks! The Thymeleaf Artwork by The Thymeleaf Project is licensed under the Creative Commons CC BY-SA 3.0 License.
#jjug_ccc #ccc_f2 @bufferings What is Thymeleaf? • A template engine for Java • Open Source — Apache 2.0 License • First version 2011 — Currently 3.0.0 • Processes HTML, XML, JavaScript, CSS, Text • View layer in Spring MVC apps • Also MVC 1.0, vert.x, ratpack, Spring Reactive
#jjug_ccc #ccc_f2 @bufferings “the template can be a document as valid as the final result, the engine syntax doesn't break the document's structure” [Comparison of web template engines - Wikipedia, the free encyclopedia] Natural Templates What is Thymeleaf? https://en.wikipedia.org/wiki/Comparison_of_web_template_engines
#jjug_ccc #ccc_f2 @bufferings Natural Templates What is Thymeleaf? http://www.thymeleaf.org/doc/articles/petclinic.html Statically Opened WebApp Output
#jjug_ccc #ccc_f2 @bufferings Yet prototyping is very optional What is Thymeleaf? • No need for double attributes: • src + th:src, href + th:href • No need for prototyping text • Expressions can be inlined
Welcome to our e-shop, [[${session.user.name}]]. td>
#jjug_ccc #ccc_f2 @bufferings JerseyMVC? Getting Started If you are interested in using Thymeleaf with JerseyMVC, let’s join #ccc_cd4 Tada-san’s session!
#jjug_ccc #ccc_f2 @bufferings Standard Dialect Using Thymeleaf The out-of-the-box dialect in Thymeleaf • Standard Expressions • Standard Processors • etc… James Carrot
#jjug_ccc #ccc_f2 @bufferings Standard Dialect Using Thymeleaf The out-of-the-box dialect in Thymeleaf • Standard Expressions • Standard Processors • etc… James Carrot
#jjug_ccc #ccc_f2 @bufferings Standard Dialect Using Thymeleaf The out-of-the-box dialect in Thymeleaf • Standard Expressions • Standard Processors • etc… James Carrot
#jjug_ccc #ccc_f2 @bufferings 1. th:text Standard Processors • , &, " and ‘ will be escaped (in Html mode) • Unescaped processor is “th:utext” James Carrot HtmlEscape.escapeHtml4Xml(unbescape) http://goo.gl/MDQr8E Mitsuyuki Shiiba output of running webapp
#jjug_ccc #ccc_f2 @bufferings My Tips • Keep natural templating • otherwise it would be stale soon • Keep template simple • no tricky template • no logics in template • no mix of html and javascript
#jjug_ccc #ccc_f2 @bufferings What is Thymeleaf 3.0? • Dev of the 3.0 branch started July 2014 • AttoParser is started in late 2012 • Almost complete rewrite of the engine • 63K+ lines of code 85% new • 77K+ lines of test 40% new • 220 listres of coffee 100% arabica
#jjug_ccc #ccc_f2 @bufferings Full HTML5 Support • New parsing system • No longer XML-based • Created from scratch with Thymeleaf in mind Whatever valid template! http://www.attoparser.org/
#jjug_ccc #ccc_f2 @bufferings TEXT Mode Dear [(${customer.name})], This is the list of our products: [# th:each="prod : ${products}"] - [(${prod.name})]. Price: [(${prod.price})] EUR/kg [/] Thanks, The Thymeleaf Shop
#jjug_ccc #ccc_f2 @bufferings Migration Guide • Templates • almost 100% compatible • (It is recommended to delete th:inline=“text”) • Configuration • a few modifications are needed
#jjug_ccc #ccc_f2 @bufferings Migration Guide Configuration change for Spring Boot Application. I created thymeleaf3-spring-boot. You can use it until the official one is released. There are only 2 steps. 1. Modify pom.xml 2. Add an exclude paramter https://github.com/bufferings/thymeleaf3-spring-boot
#jjug_ccc #ccc_f2 @bufferings Notes for Migration Migration Guide • Please make sure you don’t have any “[[xxx]]” syntax in your html and especially in your JavaScript code. • If you use extra libraries, please check it supports Thymeleaf 3.0
#jjug_ccc #ccc_f2 @bufferings HTML Mode • From Java SAX parser(+nekoHTML) to AttoParser • AttoParser is an event-based parser with Thymeleaf in mind 1. New Template Mode http://www.attoparser.org/
#jjug_ccc #ccc_f2 @bufferings HTML Mode • No need for in or <style><br/>1. New Template Mode<br/><script><br/>/*<![CDATA[*/<br/>var user = ...<br/>if (user.signupYear < 1990) {<br/>alert('You\'ve been here for a long time!');<br/>}<br/>/*]]>*/<br/> Thymeleaf 2.1
#jjug_ccc #ccc_f2 @bufferings HTML Mode • No need for in or <style><br/>1. New Template Mode<br/><script><br/>var user = ...<br/>if (user.signupYear < 1990) {<br/>alert('You\'ve been here for a long time!');<br/>}<br/> Thymeleaf 3.0
#jjug_ccc #ccc_f2 @bufferings Improved Inlining 1. New Template Mode • Output values without a supporting tag • Already existed th:inline=“text" in Thymeleaf 2.1 • Now a 1st-class citizen, no th:inline needed • In fact, better remove them
This is called [[${product.name}]] and it's great!
#jjug_ccc #ccc_f2 @bufferings Improved Inlining For unescaped output, you can use “[(…)]” 1. New Template Mode Description: [(${description})] Description: p>
#jjug_ccc #ccc_f2 @bufferings TEXT Mode(and JAVASCRIPT, CSS) 1. New Template Mode Dear [(${customer.name})], This is the list of our products: [# th:each="prod : ${products}"] - [(${prod.name})]. Price: [(${prod.price})] EUR/kg [/] Thanks, The Thymeleaf Shop
#jjug_ccc #ccc_f2 @bufferings TEXT Mode(and JAVASCRIPT, CSS) 1. New Template Mode Dear [(${customer.name})], This is the list of our products: [#th:block th:each="prod : ${products}"] - [(${prod.name})]. Price: [(${prod.price})] EUR/kg [/th:block] Thanks, The Thymeleaf Shop
#jjug_ccc #ccc_f2 @bufferings TEXT Mode(and JAVASCRIPT, CSS) 1. New Template Mode Dear [# th:utext="${customer.name}" /], This is the list of our products: [#th:block th:each="prod : ${products}"] - [(${prod.name})]. Price: [(${prod.price})] EUR/kg [/th:block] Thanks, The Thymeleaf Shop
#jjug_ccc #ccc_f2 @bufferings TEXT Mode(and JAVASCRIPT, CSS) 1. New Template Mode Dear [#th:block th:utext="${customer.name}" /], This is the list of our products: [#th:block th:each="prod : ${products}"] - [(${prod.name})]. Price: [(${prod.price})] EUR/kg [/th:block] Thanks, The Thymeleaf Shop
#jjug_ccc #ccc_f2 @bufferings TEXT Mode(and JAVASCRIPT, CSS) 1. New Template Mode Dear [(${customer.name})], This is the list of our products: [# th:each="prod : ${products}"] - [(${prod.name})]. Price: [(${prod.price})] EUR/kg [/] Thanks, The Thymeleaf Shop
#jjug_ccc #ccc_f2 @bufferings RAW Mode 1. New Template Mode Mainly for inserting untouched resources (files, URL responses, etc.) into the templates being processed.
#jjug_ccc #ccc_f2 @bufferings 2. Fragment Expressions In Standard Dialect • Template Layout(existing in Themeleaf 2.1) • Fragment Expressions(from Thymeleaf 3.0)
#jjug_ccc #ccc_f2 @bufferings • Ability for processors to do nothing • Expression result: underscore(‘_') • Use prototyping text as default values 3. No-Operation Token no user authenticated
#jjug_ccc #ccc_f2 @bufferings Independence From Servlet API • Already in 2.1 for non-web applications • Non-ServletAPI webs had unsolved needs • Non-absolute URL handling, context integration /* Customize the way URLs are handled: context, rewriting, etc. */ tempEngine.setLinkBuilder(new ILinkBuilder() {...}); /* Customize the way context variables are maintained */ tempEngine.setEngineContextFactory(new IEngineContextFactory() {...});
#jjug_ccc #ccc_f2 @bufferings 6. Reactive Friendliness • Sorry, I will study spring reactive! • If you are interested in, please check this repo: https://github.com/thymeleaf/thymeleafsandbox- springreactive
#jjug_ccc #ccc_f2 @bufferings 7. StringTemplateResolver • If you want to check Thymeleaf Standard Dialect, you can write codes like this: @Test public void test() { TemplateEngine engine = new TemplateEngine(); Context context = new Context(); context.setVariable("name", "Mitsuyuki"); String result = engine.process( "I'm [[${name}]].", context); assertThat(result, is("I'm Mitsuyuki.")); }
#jjug_ccc #ccc_f2 @bufferings 7. StringTemplateResolver • Please note that if you use Spring, you should use SpringStandardDialect.: @Test public void test() { TemplateEngine engine = new TemplateEngine(); engine.setDialect(new SpringStandardDialect()); Context context = new Context(); context.setVariable("name", "Mitsuyuki"); String result = engine.process( "I'm [[${name}]].", context); assertThat(result, is("I'm Mitsuyuki.")); }
#jjug_ccc #ccc_f2 @bufferings 7. StringTemplateResolver • Please note that if you use Spring, you should use SpringStandardDialect.: @Test public void test() { TemplateEngine engine = new TemplateEngine(); engine.setDialect(new SpringStandardDialect()); Context context = new Context(); context.setVariable("name", "Mitsuyuki"); String result = engine.process( "I'm [[${name}]].", context); assertThat(result, is("I'm Mitsuyuki.")); }
#jjug_ccc #ccc_f2 @bufferings 7. StringTemplateResolver • StringTemplateResolver will consider the template being resolved as the template itself. • This is the default template resolver of TemplateEngine.
#jjug_ccc #ccc_f2 @bufferings Summary • You don’t need any big change for migrating from Thymeleaf 2.1 to 3.0. • On the other hand, inside was changed so much that you can get the performance improvement. • So why don’t you use Thymeleaf 3.0? Thank you!
#jjug_ccc #ccc_f2 @bufferings Reference • Thymeleaf Web Site http://www.thymeleaf.org/ • Thymeleaf by Daniel Fernández https://youtu.be/GVq0uzpHYoQ • The Thymeleaf Artwork by The Thymeleaf Project is licensed under the Creative Commons CC BY-SA 3.0 License.