SlideShare a Scribd company logo
1 of 32
Download to read offline
Lessons Learned from Upgrading
Thymeleaf
By Jay Aisenbrey
@broadleaf
1
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Broadleaf Commerce
• Open source, Spring-based eCommerce framework
• Enterprise features
• Order Management System
• Content Management System
• Multi-Tenant Single Schema
• Fortune 500 and IR Top 100 clients
• The Container Store
• The Buckle
• O'Reilly Auto Parts
• Customizable, flexible, and scalable
2
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Thymeleaf
• Open source server-side Java template engine
• Write pure HTML, CSS, and JS that can be displayed without processing
• Built-in Spring integrations
• Uses SpEL and OGNL
• Therefore you can use static class and object functions
• Full internationalization support
• Highly customizable
• Configurable parsed template cache
• Cache where the template is and, possibly, what it evaluates to
3
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Thymeleaf 3 Features - Fragments
The old fragment expressions but expanded on
• Not only limited to use inside th:insert/th:replace/th:include
• <div th:include="home :: home_fragment"></div>
• <div th:include="~{home :: home_fragment}"></div>
• Same syntax as before i.e. ~{home :: home_fragment}
• Now available for use everywhere ${...}, *{...}, etc. can be used
• Use with th:with to use templates as variables or in an conditional
• Using fragments as parameters in other fragments
4
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Fragments - Examples
~{commons::main}
<div th:insert="~{commons :: main}">...</div>
<div th:insert="${user.admin}? ~{adm :: admintools} :
~{common :: basictools}">...</div>
<div th:with="frag=~{footer :: #main/text()}">
<p th:insert="${frag}">
</div>
5
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Fragments - Examples (base.html)
<head th:fragment="common_header(title,links)">
<title th:replace="${title}">The awesome application</title>
<!-- Common styles and scripts -->
<link rel="stylesheet" type="text/css" media="all"
th:href="@{/css/awesomeapp.css}">
<link rel="shortcut icon" th:href="@{/images/favicon.ico}">
<script type="text/javascript" th:src="@{/sh/scripts/codebase.js}"/>
<!--/* Per-page placeholder for additional links */-->
<th:block th:replace="${links}" />
</head>
6
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Fragments - Examples (main.html)
...
<head
th:replace="base :: common_header(~{::title},~{::link})">
<title>Awesome - Main</title>
<link rel="stylesheet"
th:href="@{/css/bootstrap.min.css}">
<link rel="stylesheet"
th:href="@{/themes/smoothness/jquery-ui.css}">
</head>
...
7
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Fragments - Examples (resulting main.html)
...
<head>
<title>Awesome - Main</title>
<!-- Common styles and scripts -->
<link rel="stylesheet" type="text/css" media="all"
th:href="@{/css/awesomeapp.css}">
<link rel="shortcut icon" th:href="@{/images/favicon.ico}">
<script type="text/javascript" th:src="@{/sh/scripts/codebase.js}"/>
<!--/* Per-page placeholder for additional links */-->
<link rel="stylesheet" th:href="@{/css/bootstrap.min.css}">
<link rel="stylesheet" th:href="@{/themes/smoothness/jquery-ui.css}">
</head>
...
8
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Thymeleaf 3 Features - Decoupled Templating
...
<table id="usersTable">
<tr th:each="user : ${users}">
<td class="username" th:text="${user.name}">
Jeremy Grapefruit
</td>
<td class="usertype"
th:text="#{|user.type.${user.type}|}">
Normal User
</td>
</tr>
</table>
...
9
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Thymeleaf 3 Features - Decoupled Templating
<!DOCTYPE html>
<html>
<body>
<table id="usersTable">
<tr>
<td class="username">Jeremy Grapefruit</td>
<td class="usertype">Normal User</td>
</tr>
<tr>
<td class="username">Alice Watermelon</td>
<td class="usertype">Administrator</td>
</tr>
</table>
</body>
</html>
10
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Thymeleaf 3 Features - Decoupled Templating
<?xml version="1.0"?>
<thlogic>
<attr sel="#usersTable" th:remove="all-but-first">
<attr sel="/tr[0]" th:each="user : ${users}">
<attr sel="td.username" th:text="${user.name}" />
<attr sel="td.usertype"
th:text="#{|user.type.${user.type}|}" />
</attr>
</attr>
</thlogic>
11
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Thymeleaf 3 Features
• Inline Expression
• <div th:inline="text">[[${user.name}]]</div> --> <div>[[${user.name}]]</div>
• Textual Template Mode - Ability to write Thymeleaf syntax without tags
[# th:each="item : ${items}"]
- [# th:utext="${item}" /]
[/]
• No longer dependent on Servlet API
• Enables Thymeleaf to run outside of a web container (i.e. email templating)
• Improves integration possibilities with reactive frameworks
• Supports engine throttling so that the Thymeleaf engine can execute partially and
on-demand to answer back-pressure requests
12
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Thymeleaf 3 Features
• Parser change
• Originally used an XML parser, now uses an event-driven parser
• New parser called Attoparser 2.0 (written by the same guy behind Thymeleaf)
• Performance increase
• No longer requires HTML to be valid XML (Full HTML5 support)
• Small templating caveat
• <div th:text="${text}"/> --> if text is empty this results to <div/>
• The browser attempts to find a place for the closing div and it's always wrong
• In Thymeleaf 2 this would return <div></div>
• Simply change to <div th:text="${text}></div>
13
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Variable Expressions - Thymeleaf 2
public class BroadleafVariableExpressionEval extends
SpelVariableExpressionEvaluator {
@Override
protected Map<String,Object> computeAdditionalExpressionObjects(
final IProcessingContext processingContext) {
// Map expression objects to a string
}
}
14
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Variable Expressions - Thymeleaf 3
public class BroadleafVariableExpressionObjectFactory implements
IExpressionObjectFactory{
@Override
public Set<String> getAllExpressionObjectNames() {
// Return string names to be used to use variable expressions
}
@Override
public Object buildObject(IExpressionContext context,
String expressionObjectName) {
// Based on string given return object is relates to
}
}
15
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Variable Expressions - Difference
• Slightly different API but effectively setup the same way
• HTML usage remains identical
Thymeleaf 2 - https://git.io/vbTIr
Thymeleaf 3 - https://git.io/vbTIo
Both are capital "i"s following the "T"
16
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Dialects - Thymeleaf 2
public interface IDialect {
public String getPrefix();
public Set<IProcessor> getProcessors();
public Map<String,Object> getExecutionAttributes();
public Set<IDocTypeTranslation> getDocTypeTranslations();
public Set<IDocTypeResolutionEntry> getDocTypeResolutionEntries();
}
17
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Dialects - Thymeleaf 3
public abstract class TL3EquivalentDialect
extends AbstractProcessorDialect
implements IExpressionObjectDialect {
public String getName();
public String getPrefix();
public int getDialectProcessorPrecedence();
public Set<IProcessor> getProcessors(final String dialectPrefix);
public IExpressionObjectFactory getExpressionObjectFactory();
}
18
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Dialects - Difference
• Thymeleaf 3 refactored the API into a more modular way
• i.e. IProcessorDialect, IPreProcessorDialect, IPostProcessorDialect,
IExpressionObjectDialect, IExecutionAttributeDialect
• Replaced getExecutionAttributes with getExpressionObjectFactory
• This makes more sense since you're no longer mapping a magic string to an
object
• Hooking up the dialect to the engine is exactly the same
• Again a lot of similarities
• Thymeleaf 2 - https://git.io/vbTtM
• Thymeleaf 3 - https://git.io/vbTtD
19
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Processors - Thymeleaf 2
public interface IProcessor extends Comparable<IProcessor> {
public IProcessorMatcher<? extends Node> getMatcher();
public ProcessorResult process(
final Arguments arguments,
final ProcessorMatchingContext processMatchContext,
final Node node);
}
• getMatcher - What type of HTML should this be ran on
• process - What are we doing on this HTML that matches
20
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Processors - Thymeleaf 2
• AbstractProcessor implements IProcessor
• Provides methods to resolve internationalized messages and compareTo
• AbstractAttrProcessor extends AbstractProcessor
• Implements getMatcher to say this runs on tags with certain attribute name
• AbstractElementProcessor
• Implements getMatcher to say this runs on tags with certain tag name
21
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Processors - Thymeleaf 3
public interface IProcessor {
public TemplateMode getTemplateMode(); // HTML, XML, etc.
public int getPrecedence();
}
public interface IElementProcessor extends IProcessor {
public MatchingElementName getMatchingElementName();
public MatchingAttributeName getMatchingAttributeName();
}
22
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Processors - Thymeleaf 3
public interface IElementTagProcessor extends IElementProcessor {
public void process(
final ITemplateContext context,
final IProcessableElementTag tag,
final IElementTagStructureHandler structureHandler);
}
public interface IElementModelProcessor extends IElementProcessor {
public void process(
final ITemplateContext context,
final IModel model,
final IElementModelStructureHandler structureHandler);
}
23
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Processors - Thymeleaf 3
Other interfaces (all extend IProcessor)
• ITemplateBoundariesProcessor
• ITextProcessor
• ICommentProcessor
• ICDATASectionProcessor
• IDocTypeProcessor
• IXMLDeclarationProcessor
All have their own StructureHandlers
24
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Processors - Differences
Thymeleaf 2
• getMatcher
• Method argument Arguments
• Not very defined. Hard to use
• Wild west on what you can do
inside a processor
25
Thymeleaf 3
• More granular APIs
• Method argument StructureHandler
• Very detailed API. Easy to use
• More structured on what you can do
inside a processor based on type
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Configuration - Maven POM
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring4</artifactId>
<version>3.0.9.RELEASE</version>
</dependency>
26
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Configuration - Spring Java Config
@Configuration
@EnableWebMvc
public class ThymeleafConfig extends WebMvcConfigurerAdapter implements
ApplicationContextAware {
private ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Bean
public ViewResolver viewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
resolver.setCharacterEncoding("UTF-8");
return resolver;
}
...
27
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Configuration - Spring Java Config
...
@Bean
public TemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setEnableSpringELCompiler(true);
engine.setTemplateResolver(templateResolver());
return engine;
}
private ITemplateResolver templateResolver() {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setApplicationContext(applicationContext);
resolver.setPrefix("/WEB-INF/templates/");
resolver.setTemplateMode(TemplateMode.HTML);
return resolver;
}
}
28
Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Summary
• Not a lot to upgrading unless you have lots of processors
• Even then the new API is much simpler
• New features
• Better fragment expressions
• Decoupled templating
• Increased performance
• No more XML parser
• New sleeker APIs for Variable Expressions, Dialects, Processors
• Addition of pre/post processors
29
Resources
• Migration Guide
• http://www.thymeleaf.org/doc/articles/thymeleaf3migration.html
• Extension Guide
• http://www.thymeleaf.org/doc/tutorials/3.0/extendingthymeleaf.html
• My Blog
• http://www.broadleafcommerce.com/blog/broadleaf-commerce-upgrade-to-
thymeleaf-3
• Introduction to Thymeleaf Presentation
• http://www.nimret.org/seajug/past/2016/oct/slides.pdf
Q&A
Learn More. Stay Connected.
jaisenbrey@broadleafcommerce.com
Github: cja769
Twitter: @broadleaf
32
#springone@s1p

More Related Content

What's hot

Deepak khetawat sling_models_sightly_jsp
Deepak khetawat sling_models_sightly_jspDeepak khetawat sling_models_sightly_jsp
Deepak khetawat sling_models_sightly_jspDEEPAK KHETAWAT
 
OrchardCMS module development
OrchardCMS module developmentOrchardCMS module development
OrchardCMS module developmentJay Harris
 
.NET Core, ASP.NET Core Course, Session 10
.NET Core, ASP.NET Core Course, Session 10.NET Core, ASP.NET Core Course, Session 10
.NET Core, ASP.NET Core Course, Session 10aminmesbahi
 
Boston 2011 OTN Developer Days - Java EE 6
Boston 2011 OTN Developer Days - Java EE 6Boston 2011 OTN Developer Days - Java EE 6
Boston 2011 OTN Developer Days - Java EE 6Arun Gupta
 
JAX-RS 2.0: RESTful Web Services
JAX-RS 2.0: RESTful Web ServicesJAX-RS 2.0: RESTful Web Services
JAX-RS 2.0: RESTful Web ServicesArun Gupta
 
Lab 5a) create a struts application
Lab 5a) create a struts applicationLab 5a) create a struts application
Lab 5a) create a struts applicationtechbed
 
Spring 3.x - Spring MVC - Advanced topics
Spring 3.x - Spring MVC - Advanced topicsSpring 3.x - Spring MVC - Advanced topics
Spring 3.x - Spring MVC - Advanced topicsGuy Nir
 
3) web development
3) web development3) web development
3) web developmenttechbed
 
Spring MVC
Spring MVCSpring MVC
Spring MVCyuvalb
 
.NET Core, ASP.NET Core Course, Session 11
.NET Core, ASP.NET Core Course, Session 11.NET Core, ASP.NET Core Course, Session 11
.NET Core, ASP.NET Core Course, Session 11aminmesbahi
 
Annotation-Based Spring Portlet MVC
Annotation-Based Spring Portlet MVCAnnotation-Based Spring Portlet MVC
Annotation-Based Spring Portlet MVCJohn Lewis
 

What's hot (20)

Java EE 6 & Spring: A Lover's Quarrel
Java EE 6 & Spring: A Lover's QuarrelJava EE 6 & Spring: A Lover's Quarrel
Java EE 6 & Spring: A Lover's Quarrel
 
Deepak khetawat sling_models_sightly_jsp
Deepak khetawat sling_models_sightly_jspDeepak khetawat sling_models_sightly_jsp
Deepak khetawat sling_models_sightly_jsp
 
Overview of JEE Technology
Overview of JEE TechnologyOverview of JEE Technology
Overview of JEE Technology
 
OrchardCMS module development
OrchardCMS module developmentOrchardCMS module development
OrchardCMS module development
 
Spring Framework - III
Spring Framework - IIISpring Framework - III
Spring Framework - III
 
Spring Framework -I
Spring Framework -ISpring Framework -I
Spring Framework -I
 
.NET Core, ASP.NET Core Course, Session 10
.NET Core, ASP.NET Core Course, Session 10.NET Core, ASP.NET Core Course, Session 10
.NET Core, ASP.NET Core Course, Session 10
 
Boston 2011 OTN Developer Days - Java EE 6
Boston 2011 OTN Developer Days - Java EE 6Boston 2011 OTN Developer Days - Java EE 6
Boston 2011 OTN Developer Days - Java EE 6
 
jQuery plugins & JSON
jQuery plugins & JSONjQuery plugins & JSON
jQuery plugins & JSON
 
Mvc by asp.net development company in india - part 2
Mvc by asp.net development company in india  - part 2Mvc by asp.net development company in india  - part 2
Mvc by asp.net development company in india - part 2
 
JAX-RS 2.0: RESTful Web Services
JAX-RS 2.0: RESTful Web ServicesJAX-RS 2.0: RESTful Web Services
JAX-RS 2.0: RESTful Web Services
 
Lab 5a) create a struts application
Lab 5a) create a struts applicationLab 5a) create a struts application
Lab 5a) create a struts application
 
Spring 3.x - Spring MVC - Advanced topics
Spring 3.x - Spring MVC - Advanced topicsSpring 3.x - Spring MVC - Advanced topics
Spring 3.x - Spring MVC - Advanced topics
 
3) web development
3) web development3) web development
3) web development
 
Hibernate III
Hibernate IIIHibernate III
Hibernate III
 
Spring jdbc
Spring jdbcSpring jdbc
Spring jdbc
 
Spring MVC
Spring MVCSpring MVC
Spring MVC
 
.NET Core, ASP.NET Core Course, Session 11
.NET Core, ASP.NET Core Course, Session 11.NET Core, ASP.NET Core Course, Session 11
.NET Core, ASP.NET Core Course, Session 11
 
Annotation-Based Spring Portlet MVC
Annotation-Based Spring Portlet MVCAnnotation-Based Spring Portlet MVC
Annotation-Based Spring Portlet MVC
 
Spring core
Spring coreSpring core
Spring core
 

Similar to Lessons learned from upgrading Thymeleaf

SpringOnePlatform2017 recap
SpringOnePlatform2017 recapSpringOnePlatform2017 recap
SpringOnePlatform2017 recapminseok kim
 
Spring 4.3-component-design
Spring 4.3-component-designSpring 4.3-component-design
Spring 4.3-component-designGrzegorz Duda
 
Running Java Applications on Cloud Foundry
Running Java Applications on Cloud FoundryRunning Java Applications on Cloud Foundry
Running Java Applications on Cloud FoundryVMware Tanzu
 
High Performance Cloud Native APIs Using Apache Geode
High Performance Cloud Native APIs Using Apache Geode High Performance Cloud Native APIs Using Apache Geode
High Performance Cloud Native APIs Using Apache Geode VMware Tanzu
 
Designing, Implementing, and Using Reactive APIs
Designing, Implementing, and Using Reactive APIsDesigning, Implementing, and Using Reactive APIs
Designing, Implementing, and Using Reactive APIsVMware Tanzu
 
Not Only Reactive - Data Access with Spring Data
Not Only Reactive - Data Access with Spring DataNot Only Reactive - Data Access with Spring Data
Not Only Reactive - Data Access with Spring DataVMware Tanzu
 
AEM Sightly Deep Dive
AEM Sightly Deep DiveAEM Sightly Deep Dive
AEM Sightly Deep DiveGabriel Walt
 
Migrating to Angular 5 for Spring Developers
Migrating to Angular 5 for Spring DevelopersMigrating to Angular 5 for Spring Developers
Migrating to Angular 5 for Spring DevelopersGunnar Hillert
 
Cloud-Native Streaming and Event-Driven Microservices
Cloud-Native Streaming and Event-Driven MicroservicesCloud-Native Streaming and Event-Driven Microservices
Cloud-Native Streaming and Event-Driven MicroservicesVMware Tanzu
 
Migrating to Angular 4 for Spring Developers
Migrating to Angular 4 for Spring Developers Migrating to Angular 4 for Spring Developers
Migrating to Angular 4 for Spring Developers VMware Tanzu
 
Enable SQL/JDBC Access to Apache Geode/GemFire Using Apache Calcite
Enable SQL/JDBC Access to Apache Geode/GemFire Using Apache CalciteEnable SQL/JDBC Access to Apache Geode/GemFire Using Apache Calcite
Enable SQL/JDBC Access to Apache Geode/GemFire Using Apache CalciteChristian Tzolov
 
Use Web Skills To Build Mobile Apps
Use Web Skills To Build Mobile AppsUse Web Skills To Build Mobile Apps
Use Web Skills To Build Mobile AppsNathan Smith
 
Django Tutorial | Django Web Development With Python | Django Training and Ce...
Django Tutorial | Django Web Development With Python | Django Training and Ce...Django Tutorial | Django Web Development With Python | Django Training and Ce...
Django Tutorial | Django Web Development With Python | Django Training and Ce...Edureka!
 
groovy transforms
groovy transformsgroovy transforms
groovy transformsPaul King
 
Enable SQL/JDBC Access to Apache Geode/GemFire Using Apache Calcite
Enable SQL/JDBC Access to Apache Geode/GemFire Using Apache CalciteEnable SQL/JDBC Access to Apache Geode/GemFire Using Apache Calcite
Enable SQL/JDBC Access to Apache Geode/GemFire Using Apache CalciteVMware Tanzu
 
State of modern web technologies: an introduction
State of modern web technologies: an introductionState of modern web technologies: an introduction
State of modern web technologies: an introductionMichael Ahearn
 
New in Spring Framework 5.0: Functional Web Framework
New in Spring Framework 5.0: Functional Web FrameworkNew in Spring Framework 5.0: Functional Web Framework
New in Spring Framework 5.0: Functional Web FrameworkVMware Tanzu
 
Iwt note(module 2)
Iwt note(module 2)Iwt note(module 2)
Iwt note(module 2)SANTOSH RATH
 
Ed presents JSF 2.2 and WebSocket to Gameduell.
Ed presents JSF 2.2 and WebSocket to Gameduell.Ed presents JSF 2.2 and WebSocket to Gameduell.
Ed presents JSF 2.2 and WebSocket to Gameduell.Edward Burns
 
Reactive Data Access with Spring Data
Reactive Data Access with Spring DataReactive Data Access with Spring Data
Reactive Data Access with Spring DataVMware Tanzu
 

Similar to Lessons learned from upgrading Thymeleaf (20)

SpringOnePlatform2017 recap
SpringOnePlatform2017 recapSpringOnePlatform2017 recap
SpringOnePlatform2017 recap
 
Spring 4.3-component-design
Spring 4.3-component-designSpring 4.3-component-design
Spring 4.3-component-design
 
Running Java Applications on Cloud Foundry
Running Java Applications on Cloud FoundryRunning Java Applications on Cloud Foundry
Running Java Applications on Cloud Foundry
 
High Performance Cloud Native APIs Using Apache Geode
High Performance Cloud Native APIs Using Apache Geode High Performance Cloud Native APIs Using Apache Geode
High Performance Cloud Native APIs Using Apache Geode
 
Designing, Implementing, and Using Reactive APIs
Designing, Implementing, and Using Reactive APIsDesigning, Implementing, and Using Reactive APIs
Designing, Implementing, and Using Reactive APIs
 
Not Only Reactive - Data Access with Spring Data
Not Only Reactive - Data Access with Spring DataNot Only Reactive - Data Access with Spring Data
Not Only Reactive - Data Access with Spring Data
 
AEM Sightly Deep Dive
AEM Sightly Deep DiveAEM Sightly Deep Dive
AEM Sightly Deep Dive
 
Migrating to Angular 5 for Spring Developers
Migrating to Angular 5 for Spring DevelopersMigrating to Angular 5 for Spring Developers
Migrating to Angular 5 for Spring Developers
 
Cloud-Native Streaming and Event-Driven Microservices
Cloud-Native Streaming and Event-Driven MicroservicesCloud-Native Streaming and Event-Driven Microservices
Cloud-Native Streaming and Event-Driven Microservices
 
Migrating to Angular 4 for Spring Developers
Migrating to Angular 4 for Spring Developers Migrating to Angular 4 for Spring Developers
Migrating to Angular 4 for Spring Developers
 
Enable SQL/JDBC Access to Apache Geode/GemFire Using Apache Calcite
Enable SQL/JDBC Access to Apache Geode/GemFire Using Apache CalciteEnable SQL/JDBC Access to Apache Geode/GemFire Using Apache Calcite
Enable SQL/JDBC Access to Apache Geode/GemFire Using Apache Calcite
 
Use Web Skills To Build Mobile Apps
Use Web Skills To Build Mobile AppsUse Web Skills To Build Mobile Apps
Use Web Skills To Build Mobile Apps
 
Django Tutorial | Django Web Development With Python | Django Training and Ce...
Django Tutorial | Django Web Development With Python | Django Training and Ce...Django Tutorial | Django Web Development With Python | Django Training and Ce...
Django Tutorial | Django Web Development With Python | Django Training and Ce...
 
groovy transforms
groovy transformsgroovy transforms
groovy transforms
 
Enable SQL/JDBC Access to Apache Geode/GemFire Using Apache Calcite
Enable SQL/JDBC Access to Apache Geode/GemFire Using Apache CalciteEnable SQL/JDBC Access to Apache Geode/GemFire Using Apache Calcite
Enable SQL/JDBC Access to Apache Geode/GemFire Using Apache Calcite
 
State of modern web technologies: an introduction
State of modern web technologies: an introductionState of modern web technologies: an introduction
State of modern web technologies: an introduction
 
New in Spring Framework 5.0: Functional Web Framework
New in Spring Framework 5.0: Functional Web FrameworkNew in Spring Framework 5.0: Functional Web Framework
New in Spring Framework 5.0: Functional Web Framework
 
Iwt note(module 2)
Iwt note(module 2)Iwt note(module 2)
Iwt note(module 2)
 
Ed presents JSF 2.2 and WebSocket to Gameduell.
Ed presents JSF 2.2 and WebSocket to Gameduell.Ed presents JSF 2.2 and WebSocket to Gameduell.
Ed presents JSF 2.2 and WebSocket to Gameduell.
 
Reactive Data Access with Spring Data
Reactive Data Access with Spring DataReactive Data Access with Spring Data
Reactive Data Access with Spring Data
 

More from VMware Tanzu

What AI Means For Your Product Strategy And What To Do About It
What AI Means For Your Product Strategy And What To Do About ItWhat AI Means For Your Product Strategy And What To Do About It
What AI Means For Your Product Strategy And What To Do About ItVMware Tanzu
 
Make the Right Thing the Obvious Thing at Cardinal Health 2023
Make the Right Thing the Obvious Thing at Cardinal Health 2023Make the Right Thing the Obvious Thing at Cardinal Health 2023
Make the Right Thing the Obvious Thing at Cardinal Health 2023VMware Tanzu
 
Enhancing DevEx and Simplifying Operations at Scale
Enhancing DevEx and Simplifying Operations at ScaleEnhancing DevEx and Simplifying Operations at Scale
Enhancing DevEx and Simplifying Operations at ScaleVMware Tanzu
 
Spring Update | July 2023
Spring Update | July 2023Spring Update | July 2023
Spring Update | July 2023VMware Tanzu
 
Platforms, Platform Engineering, & Platform as a Product
Platforms, Platform Engineering, & Platform as a ProductPlatforms, Platform Engineering, & Platform as a Product
Platforms, Platform Engineering, & Platform as a ProductVMware Tanzu
 
Building Cloud Ready Apps
Building Cloud Ready AppsBuilding Cloud Ready Apps
Building Cloud Ready AppsVMware Tanzu
 
Spring Boot 3 And Beyond
Spring Boot 3 And BeyondSpring Boot 3 And Beyond
Spring Boot 3 And BeyondVMware Tanzu
 
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdfSpring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdfVMware Tanzu
 
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023VMware Tanzu
 
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023VMware Tanzu
 
tanzu_developer_connect.pptx
tanzu_developer_connect.pptxtanzu_developer_connect.pptx
tanzu_developer_connect.pptxVMware Tanzu
 
Tanzu Virtual Developer Connect Workshop - French
Tanzu Virtual Developer Connect Workshop - FrenchTanzu Virtual Developer Connect Workshop - French
Tanzu Virtual Developer Connect Workshop - FrenchVMware Tanzu
 
Tanzu Developer Connect Workshop - English
Tanzu Developer Connect Workshop - EnglishTanzu Developer Connect Workshop - English
Tanzu Developer Connect Workshop - EnglishVMware Tanzu
 
Virtual Developer Connect Workshop - English
Virtual Developer Connect Workshop - EnglishVirtual Developer Connect Workshop - English
Virtual Developer Connect Workshop - EnglishVMware Tanzu
 
Tanzu Developer Connect - French
Tanzu Developer Connect - FrenchTanzu Developer Connect - French
Tanzu Developer Connect - FrenchVMware Tanzu
 
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023VMware Tanzu
 
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring BootSpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring BootVMware Tanzu
 
SpringOne Tour: The Influential Software Engineer
SpringOne Tour: The Influential Software EngineerSpringOne Tour: The Influential Software Engineer
SpringOne Tour: The Influential Software EngineerVMware Tanzu
 
SpringOne Tour: Domain-Driven Design: Theory vs Practice
SpringOne Tour: Domain-Driven Design: Theory vs PracticeSpringOne Tour: Domain-Driven Design: Theory vs Practice
SpringOne Tour: Domain-Driven Design: Theory vs PracticeVMware Tanzu
 
SpringOne Tour: Spring Recipes: A Collection of Common-Sense Solutions
SpringOne Tour: Spring Recipes: A Collection of Common-Sense SolutionsSpringOne Tour: Spring Recipes: A Collection of Common-Sense Solutions
SpringOne Tour: Spring Recipes: A Collection of Common-Sense SolutionsVMware Tanzu
 

More from VMware Tanzu (20)

What AI Means For Your Product Strategy And What To Do About It
What AI Means For Your Product Strategy And What To Do About ItWhat AI Means For Your Product Strategy And What To Do About It
What AI Means For Your Product Strategy And What To Do About It
 
Make the Right Thing the Obvious Thing at Cardinal Health 2023
Make the Right Thing the Obvious Thing at Cardinal Health 2023Make the Right Thing the Obvious Thing at Cardinal Health 2023
Make the Right Thing the Obvious Thing at Cardinal Health 2023
 
Enhancing DevEx and Simplifying Operations at Scale
Enhancing DevEx and Simplifying Operations at ScaleEnhancing DevEx and Simplifying Operations at Scale
Enhancing DevEx and Simplifying Operations at Scale
 
Spring Update | July 2023
Spring Update | July 2023Spring Update | July 2023
Spring Update | July 2023
 
Platforms, Platform Engineering, & Platform as a Product
Platforms, Platform Engineering, & Platform as a ProductPlatforms, Platform Engineering, & Platform as a Product
Platforms, Platform Engineering, & Platform as a Product
 
Building Cloud Ready Apps
Building Cloud Ready AppsBuilding Cloud Ready Apps
Building Cloud Ready Apps
 
Spring Boot 3 And Beyond
Spring Boot 3 And BeyondSpring Boot 3 And Beyond
Spring Boot 3 And Beyond
 
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdfSpring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
 
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
 
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
 
tanzu_developer_connect.pptx
tanzu_developer_connect.pptxtanzu_developer_connect.pptx
tanzu_developer_connect.pptx
 
Tanzu Virtual Developer Connect Workshop - French
Tanzu Virtual Developer Connect Workshop - FrenchTanzu Virtual Developer Connect Workshop - French
Tanzu Virtual Developer Connect Workshop - French
 
Tanzu Developer Connect Workshop - English
Tanzu Developer Connect Workshop - EnglishTanzu Developer Connect Workshop - English
Tanzu Developer Connect Workshop - English
 
Virtual Developer Connect Workshop - English
Virtual Developer Connect Workshop - EnglishVirtual Developer Connect Workshop - English
Virtual Developer Connect Workshop - English
 
Tanzu Developer Connect - French
Tanzu Developer Connect - FrenchTanzu Developer Connect - French
Tanzu Developer Connect - French
 
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
 
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring BootSpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
 
SpringOne Tour: The Influential Software Engineer
SpringOne Tour: The Influential Software EngineerSpringOne Tour: The Influential Software Engineer
SpringOne Tour: The Influential Software Engineer
 
SpringOne Tour: Domain-Driven Design: Theory vs Practice
SpringOne Tour: Domain-Driven Design: Theory vs PracticeSpringOne Tour: Domain-Driven Design: Theory vs Practice
SpringOne Tour: Domain-Driven Design: Theory vs Practice
 
SpringOne Tour: Spring Recipes: A Collection of Common-Sense Solutions
SpringOne Tour: Spring Recipes: A Collection of Common-Sense SolutionsSpringOne Tour: Spring Recipes: A Collection of Common-Sense Solutions
SpringOne Tour: Spring Recipes: A Collection of Common-Sense Solutions
 

Recently uploaded

Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 

Recently uploaded (20)

Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 

Lessons learned from upgrading Thymeleaf

  • 1. Lessons Learned from Upgrading Thymeleaf By Jay Aisenbrey @broadleaf 1
  • 2. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Broadleaf Commerce • Open source, Spring-based eCommerce framework • Enterprise features • Order Management System • Content Management System • Multi-Tenant Single Schema • Fortune 500 and IR Top 100 clients • The Container Store • The Buckle • O'Reilly Auto Parts • Customizable, flexible, and scalable 2
  • 3. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Thymeleaf • Open source server-side Java template engine • Write pure HTML, CSS, and JS that can be displayed without processing • Built-in Spring integrations • Uses SpEL and OGNL • Therefore you can use static class and object functions • Full internationalization support • Highly customizable • Configurable parsed template cache • Cache where the template is and, possibly, what it evaluates to 3
  • 4. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Thymeleaf 3 Features - Fragments The old fragment expressions but expanded on • Not only limited to use inside th:insert/th:replace/th:include • <div th:include="home :: home_fragment"></div> • <div th:include="~{home :: home_fragment}"></div> • Same syntax as before i.e. ~{home :: home_fragment} • Now available for use everywhere ${...}, *{...}, etc. can be used • Use with th:with to use templates as variables or in an conditional • Using fragments as parameters in other fragments 4
  • 5. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Fragments - Examples ~{commons::main} <div th:insert="~{commons :: main}">...</div> <div th:insert="${user.admin}? ~{adm :: admintools} : ~{common :: basictools}">...</div> <div th:with="frag=~{footer :: #main/text()}"> <p th:insert="${frag}"> </div> 5
  • 6. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Fragments - Examples (base.html) <head th:fragment="common_header(title,links)"> <title th:replace="${title}">The awesome application</title> <!-- Common styles and scripts --> <link rel="stylesheet" type="text/css" media="all" th:href="@{/css/awesomeapp.css}"> <link rel="shortcut icon" th:href="@{/images/favicon.ico}"> <script type="text/javascript" th:src="@{/sh/scripts/codebase.js}"/> <!--/* Per-page placeholder for additional links */--> <th:block th:replace="${links}" /> </head> 6
  • 7. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Fragments - Examples (main.html) ... <head th:replace="base :: common_header(~{::title},~{::link})"> <title>Awesome - Main</title> <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"> <link rel="stylesheet" th:href="@{/themes/smoothness/jquery-ui.css}"> </head> ... 7
  • 8. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Fragments - Examples (resulting main.html) ... <head> <title>Awesome - Main</title> <!-- Common styles and scripts --> <link rel="stylesheet" type="text/css" media="all" th:href="@{/css/awesomeapp.css}"> <link rel="shortcut icon" th:href="@{/images/favicon.ico}"> <script type="text/javascript" th:src="@{/sh/scripts/codebase.js}"/> <!--/* Per-page placeholder for additional links */--> <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"> <link rel="stylesheet" th:href="@{/themes/smoothness/jquery-ui.css}"> </head> ... 8
  • 9. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Thymeleaf 3 Features - Decoupled Templating ... <table id="usersTable"> <tr th:each="user : ${users}"> <td class="username" th:text="${user.name}"> Jeremy Grapefruit </td> <td class="usertype" th:text="#{|user.type.${user.type}|}"> Normal User </td> </tr> </table> ... 9
  • 10. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Thymeleaf 3 Features - Decoupled Templating <!DOCTYPE html> <html> <body> <table id="usersTable"> <tr> <td class="username">Jeremy Grapefruit</td> <td class="usertype">Normal User</td> </tr> <tr> <td class="username">Alice Watermelon</td> <td class="usertype">Administrator</td> </tr> </table> </body> </html> 10
  • 11. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Thymeleaf 3 Features - Decoupled Templating <?xml version="1.0"?> <thlogic> <attr sel="#usersTable" th:remove="all-but-first"> <attr sel="/tr[0]" th:each="user : ${users}"> <attr sel="td.username" th:text="${user.name}" /> <attr sel="td.usertype" th:text="#{|user.type.${user.type}|}" /> </attr> </attr> </thlogic> 11
  • 12. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Thymeleaf 3 Features • Inline Expression • <div th:inline="text">[[${user.name}]]</div> --> <div>[[${user.name}]]</div> • Textual Template Mode - Ability to write Thymeleaf syntax without tags [# th:each="item : ${items}"] - [# th:utext="${item}" /] [/] • No longer dependent on Servlet API • Enables Thymeleaf to run outside of a web container (i.e. email templating) • Improves integration possibilities with reactive frameworks • Supports engine throttling so that the Thymeleaf engine can execute partially and on-demand to answer back-pressure requests 12
  • 13. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Thymeleaf 3 Features • Parser change • Originally used an XML parser, now uses an event-driven parser • New parser called Attoparser 2.0 (written by the same guy behind Thymeleaf) • Performance increase • No longer requires HTML to be valid XML (Full HTML5 support) • Small templating caveat • <div th:text="${text}"/> --> if text is empty this results to <div/> • The browser attempts to find a place for the closing div and it's always wrong • In Thymeleaf 2 this would return <div></div> • Simply change to <div th:text="${text}></div> 13
  • 14. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Variable Expressions - Thymeleaf 2 public class BroadleafVariableExpressionEval extends SpelVariableExpressionEvaluator { @Override protected Map<String,Object> computeAdditionalExpressionObjects( final IProcessingContext processingContext) { // Map expression objects to a string } } 14
  • 15. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Variable Expressions - Thymeleaf 3 public class BroadleafVariableExpressionObjectFactory implements IExpressionObjectFactory{ @Override public Set<String> getAllExpressionObjectNames() { // Return string names to be used to use variable expressions } @Override public Object buildObject(IExpressionContext context, String expressionObjectName) { // Based on string given return object is relates to } } 15
  • 16. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Variable Expressions - Difference • Slightly different API but effectively setup the same way • HTML usage remains identical Thymeleaf 2 - https://git.io/vbTIr Thymeleaf 3 - https://git.io/vbTIo Both are capital "i"s following the "T" 16
  • 17. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Dialects - Thymeleaf 2 public interface IDialect { public String getPrefix(); public Set<IProcessor> getProcessors(); public Map<String,Object> getExecutionAttributes(); public Set<IDocTypeTranslation> getDocTypeTranslations(); public Set<IDocTypeResolutionEntry> getDocTypeResolutionEntries(); } 17
  • 18. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Dialects - Thymeleaf 3 public abstract class TL3EquivalentDialect extends AbstractProcessorDialect implements IExpressionObjectDialect { public String getName(); public String getPrefix(); public int getDialectProcessorPrecedence(); public Set<IProcessor> getProcessors(final String dialectPrefix); public IExpressionObjectFactory getExpressionObjectFactory(); } 18
  • 19. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Dialects - Difference • Thymeleaf 3 refactored the API into a more modular way • i.e. IProcessorDialect, IPreProcessorDialect, IPostProcessorDialect, IExpressionObjectDialect, IExecutionAttributeDialect • Replaced getExecutionAttributes with getExpressionObjectFactory • This makes more sense since you're no longer mapping a magic string to an object • Hooking up the dialect to the engine is exactly the same • Again a lot of similarities • Thymeleaf 2 - https://git.io/vbTtM • Thymeleaf 3 - https://git.io/vbTtD 19
  • 20. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Processors - Thymeleaf 2 public interface IProcessor extends Comparable<IProcessor> { public IProcessorMatcher<? extends Node> getMatcher(); public ProcessorResult process( final Arguments arguments, final ProcessorMatchingContext processMatchContext, final Node node); } • getMatcher - What type of HTML should this be ran on • process - What are we doing on this HTML that matches 20
  • 21. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Processors - Thymeleaf 2 • AbstractProcessor implements IProcessor • Provides methods to resolve internationalized messages and compareTo • AbstractAttrProcessor extends AbstractProcessor • Implements getMatcher to say this runs on tags with certain attribute name • AbstractElementProcessor • Implements getMatcher to say this runs on tags with certain tag name 21
  • 22. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Processors - Thymeleaf 3 public interface IProcessor { public TemplateMode getTemplateMode(); // HTML, XML, etc. public int getPrecedence(); } public interface IElementProcessor extends IProcessor { public MatchingElementName getMatchingElementName(); public MatchingAttributeName getMatchingAttributeName(); } 22
  • 23. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Processors - Thymeleaf 3 public interface IElementTagProcessor extends IElementProcessor { public void process( final ITemplateContext context, final IProcessableElementTag tag, final IElementTagStructureHandler structureHandler); } public interface IElementModelProcessor extends IElementProcessor { public void process( final ITemplateContext context, final IModel model, final IElementModelStructureHandler structureHandler); } 23
  • 24. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Processors - Thymeleaf 3 Other interfaces (all extend IProcessor) • ITemplateBoundariesProcessor • ITextProcessor • ICommentProcessor • ICDATASectionProcessor • IDocTypeProcessor • IXMLDeclarationProcessor All have their own StructureHandlers 24
  • 25. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Processors - Differences Thymeleaf 2 • getMatcher • Method argument Arguments • Not very defined. Hard to use • Wild west on what you can do inside a processor 25 Thymeleaf 3 • More granular APIs • Method argument StructureHandler • Very detailed API. Easy to use • More structured on what you can do inside a processor based on type
  • 26. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Configuration - Maven POM <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf</artifactId> <version>3.0.9.RELEASE</version> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring4</artifactId> <version>3.0.9.RELEASE</version> </dependency> 26
  • 27. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Configuration - Spring Java Config @Configuration @EnableWebMvc public class ThymeleafConfig extends WebMvcConfigurerAdapter implements ApplicationContextAware { private ApplicationContext applicationContext; public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } @Bean public ViewResolver viewResolver() { ThymeleafViewResolver resolver = new ThymeleafViewResolver(); resolver.setTemplateEngine(templateEngine()); resolver.setCharacterEncoding("UTF-8"); return resolver; } ... 27
  • 28. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Configuration - Spring Java Config ... @Bean public TemplateEngine templateEngine() { SpringTemplateEngine engine = new SpringTemplateEngine(); engine.setEnableSpringELCompiler(true); engine.setTemplateResolver(templateResolver()); return engine; } private ITemplateResolver templateResolver() { SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver(); resolver.setApplicationContext(applicationContext); resolver.setPrefix("/WEB-INF/templates/"); resolver.setTemplateMode(TemplateMode.HTML); return resolver; } } 28
  • 29. Unless otherwise indicated, these slides are © 2013-2016 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Summary • Not a lot to upgrading unless you have lots of processors • Even then the new API is much simpler • New features • Better fragment expressions • Decoupled templating • Increased performance • No more XML parser • New sleeker APIs for Variable Expressions, Dialects, Processors • Addition of pre/post processors 29
  • 30. Resources • Migration Guide • http://www.thymeleaf.org/doc/articles/thymeleaf3migration.html • Extension Guide • http://www.thymeleaf.org/doc/tutorials/3.0/extendingthymeleaf.html • My Blog • http://www.broadleafcommerce.com/blog/broadleaf-commerce-upgrade-to- thymeleaf-3 • Introduction to Thymeleaf Presentation • http://www.nimret.org/seajug/past/2016/oct/slides.pdf
  • 31. Q&A
  • 32. Learn More. Stay Connected. jaisenbrey@broadleafcommerce.com Github: cja769 Twitter: @broadleaf 32 #springone@s1p