Templating engine

Strajk edited this page Jun 4, 2012 · 1 revision

Templating Engine

separation between view logic and rendered view
merge data (dynamic) into template (static), to create final document
dynamic data are usually pased via model in Collection
iterations, conditions, macros, includes, locale

Considered options

Apache Velocity http://velocity.apache.org/

+ general purpose, industry standard, powerful, support in IDEs
+ support from Spring
- ugly syntax, too complex

FreeMarker http://www.freemarker.org/index.html

+ general purpose, support in IDEs, easy to use
+ support from Spring

StringTemplate http://www.stringtemplate.org/

+ general purpose, lightweight, fast, easy to use
- single-person project, no support in IDEs

Other

MVEL2, Thymeleaf, SiteMesh, TeaServlet, Jamon, WebMacro

Freemarker

Replaces JSP in MVC, even more separate view.
Support for JSP taglibs, support for namespaces.
Predefined and user macros, with params support.
Internationalization. (Disable by?c)
Expresssions with strings, arithmetic, boolean arithmetic, arrays, user defined.
Output transformation (eg. escaping HTML)

Variables
${user}
${user!"Anonymous"} - default value
${cargo.weight!(item.weight * itemCount + 10)}
<#if user??> ${user} is defined </#if>
${user.weight / 2 + 100}
Include
<#include "/layout//footer.ftl">
// search for footer_en_US.ftl, footer_en.ftl, footer.ftl
If
<#if someBoolean>It was right</#if>
<#if user == "Strajk">Welcome back, admin!</#if>
<#if offer.icecream.price == 0>Free ice-cream!</#if>
List
<#list animals as being>${being.name} ${being.type}</#list>
Macros
<#macro greet person="Anonymous" where>
  <h1>Hello ${person}, welcome to ${where}!</h1>
</#macro>
<@greet person="Fred"/>

<#macro wrapper>
  <div class="wrapper">
    <#nested>
  </div>
</#macro>  
<@border>Gift to be wrapped</@border> 

Implementation

Libraries
freemarker-2.3.19.jar
org.springframework.web.servlet.view.freemarker
Settings in SpringAppEngine-servlet.xml
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
	<property name="templateLoaderPath" value="/WEB-INF/views/"/>
</bean>
<bean id="freeMarkerViewResolver"
	  class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
	<property name="cache" value="true"/>
	<property name="prefix" value=""/> <!-- Set in freemarkerConfig -->
	<property name="suffix" value=".ftl"/>
	<property name="exposeSpringMacroHelpers" value="true"/>
</bean>
Template structure
<#include "/layout/head.ftl">
<#include "/layout/navigation.ftl">
… content ...
<#include "/layout/debug.ftl">
<#include "/layout/footer.ftl">
<#include "/layout/foot.ftl">
File structure
/views/account
/views/account/_side.ftl
/views/account/card.ftl
/views/account/cards.ftl
/views/account/default.ftl
/views/account/forbidden.ftl
/views/account/groups.ftl
/views/account/upload.ftl
/views/browse
/views/browse/card.ftl
/views/browse/default.ftl
/views/browse/manage.ftl
/views/homepage
/views/homepage/default.ftl
/views/homepage/misplaced.ftl
/views/layout
/views/layout/debug.ftl
/views/layout/foot.ftl
/views/layout/footer.ftl
/views/layout/head.ftl
/views/layout/navigation.ftl