Templatovací jazyky v Javě mají poměrně dlouhou minulost. První a zřejmě nejznámnější jsou JSP, které jsou součástí javy. Jsou nejstarší z rodiny templatovacích jazyků a přestože jsou masivně používány dodnes, mnoho lidí k nim má své výhrady:
- psaní JSP je obtížné pro ne-java programátory – přestože původní myšlenkou bylo, aby JSP psali odborníci na web (tedy „webdevelopeři“) tato myšlenka zcela jistě minula realitu; praxe je taková, že JSP píší z různých důvodu opět Java developři, jejichž je jednak nedostatek a jednak jejich zaměření je spíš na aplikační kód než na validitu a použitelnost HTML výstupu
- JSP stránky nejsou použitelné, díky životnímu cyklu JSP (JSP -> .java -> .class), mimo servletový kontejner – to znamená, že teprve servletový kontejner po nadeployování web aplikce JSP převede na implementace Servletů a přeloží je do binární podoby. Dopady tohoto mechanismu jsou poměrně jasné
- JSP stránky mají své pevné umístění – hledají se vždy na filesystemu v adresáři web aplikace; nelze je umístit na classpath (a učinit je tak součástí přenositelných knihoven), nelze je načítat z jiného zdroje – např. databáze (a umožnit tak vznik nových stránek za běhu na systémech, kde nemáme přístup na filesystém), nelze definovat jakoukoliv složitější logiku načítání stránek krom dodání Erorr 404 stránky (např. custom logika ve smyslu neexistuje-li primární šablona, použij záložní, neexistuje-li ani ta, zobraz chybu)
- JSP stránky není možné jednoduše testovat – jejich výstup získáme teprve až dotazem na servletový kontejner
- JSP nelze použít pro skládání jiného výstupu než do web browseru – např. pro skládání těl emailů musíme volit jiný templatovací engine
- debugování JSP nebylo poměrně dlouho možné a ani dnes to není zcela samozřejmá a jednoduchá věc (co se setupu týče)
- chybové hlášky JSP stránek jsou při určitém (často standardním) nastavení kontejnerů nečitelné (vztahují se k vygenerovaným servletům a nikoliv k původní template) – změna tohoto nastavení typicky vyžaduje stop/start kontejneru
- JSP stránky díky možnosti psaní scriptletů vybízejí k míchání aplikační logiky do prezentační vrstvy – s tím se myslím setkal každý z nás a leckdo se k tomu někdy i uchýlil
- v případech některých kontejnerů je při změně JSP a požadavku na její opětovné vyrenderování znatelná časová prodleva – kompilace JSP vyžaduje nějaký čas (možná se jedná jen o zlomky vteřiny, maximálně vteřiny, ale při ladění nějakých drobnostní na stránce se jakákoliv prodleva počítá)
Reakcí na zmíněné nevýhody byl vznik interpretovaných templatovacích jazyků. V tomto příspěvku bych se chtěl podívat na zoubek dvěma nejznámnějším – Apache Velocity a FreeMarkeru.
Apache Velocity
Jako první si vezmu na paškál Velocity. Nevím, zda je to pouze moje zkušenost, ale zdá se mi, že Apache Velocity je hned po JSP nejpoužívanějším templatovacím jazykem v Javě. Možná je to dáno tím, že je vývojově starší a také proto, že je vždy propagováno jako velmi jednoduché k osvojení.
Skutečně Velocity je velmi jednoduché a dokážete jej nasadit a používat týž den, kdy s tímto jazykem začnete. Velocity interpretuje rovnou originální šablonu (respektive si z šablony vytváří vlastní AST) – bez mezikroku kompilace do Java kódu, což urychluje první zobrazení po změně.
Pro vývojáře je podstatné, že umožňuje dodat vlastní implementaci ResourceLoaderu – respektive vybrat si nejvíce vyhovující z již existujících implementací (ClasspathResourceLoader, DataSourceResourceLoader, FileResourceLoader, JarResourceLoader, StringResourceLoader, URLResourceLoader).
Templatovací jazyk je velmi jednoduchý a asi není jej třeba nějak do detailu rozebírat. Jednoduchá šablona ve Velocity může vypadat třeba takto:
We’ve reached $downloadCount of Firefox 3!
We are proud to announce that we’ve achieved new Guiness record.
Top countries in download were:
| $velocityCount. | $country |
Stay loyal!
Vygenerování výsledného výstupu z Javy může vypadat například takhle:
/* first, get and initialize an engine */
VelocityEngine ve = new VelocityEngine();
ve.init();
/* next, get the Template */
Template t = ve.getTemplate( "helloworld.vm" );
/* create a context and add data */
VelocityContext context = new VelocityContext();
context.put("downloadCount", new Integer(10000000));
List topCountries = new ArrayList();
topCountries.add("United States of America");
topCountries.add("Germany");
topCountries.add("Spain");
context.put("countryList", topCountries);
/* now render the template into a StringWriter */
StringWriter writer = new StringWriter();
t.merge( context, writer );
/* show the World */
System.out.println( writer.toString() );
Velocity vám poskytne základní věci, které byste od šablonovacího enginu čekali: include (parse) direktivy pro skládání šablon, makra, jednoduchou práci s objekty, se kterými pracujete v Java – tzn. JavaBeanami apod. Pro přenášení dat do a z šablon slouží kontext, což je takový kbelík na data, se kterými se v šabloně pracuje – příjemné je, že i z šablony mohou vzejít nějaká data, o která byste mohli mít zájem v javovském kódu (a ty právě najdete ve zmíněném kontextu).
Knihovna má také již připravený vlastní servlet, který vyrenderuje výstup šablony přímo do HttpResponse.
Podívejme se však o vývojový stupeň dál.
Freemarker
Už předchozí věta je trochu hozením rukavice. Po zkušenosti s oběma knihovnami však musím konstatovat, že FreeMarker je skutečně o vývojovou etapu dál. Můžete od něj očekávat to samé co od velocity, ale řeší také plno nedostatků výše zmíněné knihovny. Na tyto nedostatky bych se chtěl podívat na následujících řádcích:
Detalní chybové hlášení
Jedním z palčivých problémů Velocity jsou chybová hlášení. Ještě nedávno byly ve Velocity problémem chybová hlášení – ani u základních chyb nebylo lehce rozeznatelné v jaké šabloně se jaká chyba vyskytuje. V tomto ohledu již Velocity udělalo pokrok, nicméně výstup FreeMarkerových chyb se mi zdá pro webdevelopry daleko srozumitelnější. Výhoda také je, že FreeMarker vypíše i stack volání jednotlivých template, takže se dá velmi jednoduše orientovat i v chybách uvnitř maker, nebo nestovaných šablon.
Užívání namespace pro linkované knihovny maker nebo JSP tagů
Ve velocity jsou všechna makra házena do na jednu kupu. Pokud byste se tedy vášnivě pustili do výraznějšího vývoje ve Velocity, za chvíli byste začali narážet na konflikty jmen. FreeMarker zavádí pro makra a proměnné namespace, přes které se na ně dá odkázat. To výrazně zpřehledňuje strukturu šablon.
Podpora JSP tagů
Jedna ze zásadních věcí ve FreeMarkeru je možnost používat JSP tagy. Pokud tedy přecházíte z JSP (jako jsme přešli my), jistě uvítáte možnost zachovat beze změny všechen kód v připravených JSP tazích. FreeMarker zvládne najít všechny tagy v odkazovaných TLD z web.xml a také dokonce všechny tagy v TLD souborech v META-INF na classpath. Jediné co FreeMarker neinterpretuje jsou JSP EL funkce definované v TLD. Tato funkcionalita nám ušetřila mraky času.
Direktivy pro práci s whitespace
Ve Velocity je velkým problémem dodržet vzhed výsledného textu ve smyslu odřádkování a odsazení. Velocity neumožňuje nijak odstraňovat nepotřebný whitespace, který ve výsledném textu nepůsobí dobře, ale ve v šabloně je kvůli přehlednosti naopak potřeba (v souvislosti se strukturou řídících direktiv apod.). FreeMarker tyto direktivy nabízí.
Metaprogramování
Ve FreeMarkeru můžete přiřadit kód šablony do proměnné, kterou pak dále používat. Interpretace obsahu proběhne pouze jednou a v dalších „použitích“ se jen vypíše již interpretovaný obsah proměnné.
Jednoduše lze také interpretovat kód v libovolné proměnné – např. mějme třídu:
public class Test {
public String getFreemarkerSnippet() {
return "${x}";
}
}
A potom freemarker šablonu (viz. dokumentace):
<#assign x = "something">
Test: ${test.freemarkerSnippet?interpret}
Výsledkem bude potom tento výstup:
Test: something
Výkon
FreeMarker je podle některých statistik rychlejší jak Velocity. Každopádně jak píší v dokumentaci k FreeMarkeru – FreeMarker pravděpodobně nikdy nebude úzkým hrdlem vaší aplikace. Nejnáročnější operací je parsování do AST, které je pak už ale cachované, takže se provádí už jen processing šablony a ten by se v rychlosti dal jistě s JSP srovnat. Pokud tedy narazíte na výkonnostní problémy – buď máte vypnutou cache, nebo bude váš problém ležet ve vrstvách níže.
Závěrem
Pokud jste nikdy nevyzkoušeli žádný z templatovacích enginů, doporučuji některý z nich určitě vyzkoušet. Pokud používáte Apache Velocity – což je pravděpodobnější případ – doporučuji rozhodně kouknout na FreeMarker, protože vás bude čekat příjemné překvapení. FreeMarker zvládnete nasadit za den, stejně jako Velocity, ale odmění se vám daleko širšími možnostmi použití a hlavně se vám s ním bude lépe pracovat.
Zajímavé jsou zkušenosti ostatních vývojářů, které lze na webu najít (pár jich uvádím v užitečných odkazech na konci článku). Poměrně zajímavé je konstatování, že valná většina lidí, která přešla od Velocity k FreeMarkeru už u FreeMarkeru zůstala. Ti kteří šli opačnou cestou od FreeMarkeru k Velocity se zase hodně rychle vrátili. Už jen to o něčem svědčí.
Zajímavé závěry lze také udělat z roadmapy k Velocity v. 2 – jistě si všimnete, že v plánovaných vylepšeních jsou věci, které ve FreeMarkeru už nějaký ten pátek máme.
Pro FreeMarker dostante podporu ve většině IDE. Do nejlepšího z nich
se podpora teprve chystá (měla by být do konce roku 2008). Velocity nemá takové zastoupení v Java editorech, nicméně je daleko větší podpora v jednodušších editorech (které jsou naopak více používány mezi webaři). V tomto ohledu má tedy FreeMarker ještě co dohánět.
Užitečné odkazy
- Krátký úvod do Apache Velocity v češtině
- Krátký úvod do FreeMarkeru v češtině
- Srovnání FreeMarker a Velocity na InRelationTo Blogu jedním z Hibernate týmu
- Pohled na 5 let historie FreeMarkeru – ohlédnutí směrem k Velocity
- Porovnání s Velocity na FreeMarker website
- Osobní zkušenosti s FreeMarkerem vůči použití JSP
- RoadMap Velocity – zajímavé jsou fíčury ve verzi 2.0 – kdo vidí FreeMarker jako já?



Ja bych jeste doplnil StringTemplate http://www.stringtemplate.org
Používám StringTemplate na generování konfigurovatelných xml výstupů. Jako hlavní výhodu považuji, že umí opravdu jen to, co je potřeba k vygenerování výstupu a nic víc.
Ad Grails: podle me jsou opravdu nejsilnejsi, kdyz clovek zacina na zelene louce s databazovou aplikaci, ale i tak se mohou hodit, nebot Groovy a GSP stranky jsou docela dobry urychlovac prace s prehlednym zapisem. Do projektu, ktery uz pouziva neco jineho, bych to asi nemichal, ale je mozne, ze ve specialnich pripadech by slo rychle zmigrovat. Jinak uvnitr je opravdu Hibernate (a nad nim GORM – uzivatelsky o neco prijemnejsi), Spring (na DI a transakce), Sitemesh na reuse layoutu a GSP namisto JSP – vytvorit napr. custom tag je mnohem jednodussi. Novou aplikaci v Grails napise clovek obvykle tak, ze vytvori model entit a z nej necha Grails framework vygenerat databazi (tu obvykle neni nutne menit, max. pridat nejaky index na urychleni), view a controller – ty se nasledne upravi tak, aby aplikace delala presne to, co uzivatele potrebuji.
Ad Eclipse: ano, nastavil bych to web developerovi temer presne tak, jako by to mel na serveru, aby se o to nemusel moc starat. Eclipse nikomu nebrani editovat stranky jakymkoli jinym editorem. Taky by, pravda, slo nahrat mu na lokalni stanici jen Tomcat se SVN klientem (rucni kopirovani dekuji nechci
a Eclipse uplne vynechat.
Ad Jakub) Vím o tom zatím houbeles, ale myslel jsem, že Grails přinášejí kompletní řešení pro web – tzn. od datové vrstvy po prezentační (vím, že Grailsy jsou založené na Hibernate a Springu). Pokud tomu tak je, tak je to obtížně použitelné v případě, že už máte existující řešení založené na nějakém CMS. Zatím to navíc vypadá, že Eclipse s Tomcatem by byla pro řadu webařů obtížně zkousnutelná – ideální stav je, když mohou mít aplikaci rozběhanou rovnou někde na serveru, editovat soubory přes Sambu a rovnou vidět jak se jejich změny projevují – bez jakékoliv starosti o setup projektu v Apache nebo Tomcat. My je navíc chceme co nejméně zatěžovat s něčím, co není jejich primární starost (a to je HTML výstup), takže v těchto ohledech postupujeme velmi opatrně.
Ad Tomáš) SiteMesh i Tiles pokud vím jsou layoutovací frameworky, které se starají o poskládání výsledné stránky z jednotlivých součástí. Daly by se přirovnat k SSI include nebo k prostému includu v JSP – samozřejmě jsou v tomto ohledu daleko mocnější, jinak by neměly vůbec šanci vzniknout. Jsou docela šikovné pro rozsáhlejší weby, pro jednodušší si člověk krásně vystačí s JSP tagy (které se navíc od v. 2.0 mohou psát také jako JSPčka – takže to bylo z mého pohledu vždy jednodušší, než integrace dalšího frameworku). Velocity nebo Freemarker oproti tomu jsou knihovny pro kompletní tvorbu textového výstupu – tzn. obsahují základní cykly, podmínky, práce s proměnnými a jejich výpisem do výstupu, makry apod. SiteMesh a Tiles se navíc myslím integrují jako filry web aplikace, takže jsou nepoužitelné, pokud výstupem má být soubor na disku nebo email apod. (za předpokladu, že si to neohnete).
Dobrý den
Jaký je vztah Freemarket versus SiteMesh? Vím, že někdy se tyto šablonovací frameworky používají i dohromady. Dal by se jednoduše nahradit freemarket za SiteMesh, nebo oba dělají trochu něco jiného? A co Tiles2? Také je to šablonovací systém a viděl jsem ho dohromady s Freemarketem. Koukal jsem do dokumentace, takže vím jak je používat, ale pořád si je nějak vzájemně nedokážu zařadit.
2 Novoj & Václav: ano, třeba už „jen“ Grails
. K tématu – osobně bych šel cestou nastavit web developerovi projekt s Tomcatem v Eclipse, používat se to za chvilku naučí, změny hned uvidí přímo v reálné aplikaci a může to rovnou commitovat do SVN. Klíčové je, používat takový framework a styl kódu v HTML templates, aby mu to nebránilo v rychlém čtení template a plynulé práci. Podle mě když bude Java programátor dobře spolupracovat, jdou takhle krásně použít i JSP např. se Stripes frameworkem a tags, ale možná že Velocity či Freemarker by pomohly ještě víc. JSP stránky s tunou scriptletů bych tvůrci webu samozřejmě nedával – zabil by mě nebo dal výpověď, případně obojí.
To mě moc těší.
Groovy má pro nás přichystáno spoustu příjemných překvapení.
Václave, máš dar přesvědčovat lidi
Posouvám Groovy v seznamu TODO na vyšší příčku (a to už je hodně vysoko po tvojí prezentaci na CZJUGu).
To rozdělení do kategorií code in template a template in code je docela výstižné.
Pro kategorii code in template může Groovy také nabídnout několik zajímavých možností (čerpám z http://groovy.codehaus.org/Groovy+Templates):
* SimpleTemplateEngine – for basic templates
* GStringTemplateEngine – stores the template as writable closures (useful for streaming scenarios)
* XmlTemplateEngine – works well when the template and output are valid XML
Zatím s tím nemám hlubší zkušenosti, ale podle dokumentace by to mělo být velmi blízko Velocity či FreeMarkeru. Otázka zní, proč rovnou nepoužít Velocity či FreeMarker, když už je člověk zná, že?
Tady narážíme na dvě pojetí:
1) code in template
2) template in code
JSP, Velocity, Freemarker jdou tou první cestou – ta je z mého pohledu pro lidi zvyklé dělat web přirozenější (i když u JSP už je to na hraně).
Groovy jak jsem koukl na odkazovaný example jde tou druhou cestou. Možná do této kategorie patří i Ruby ale to bych jen hádal z kontextu. Možná mě Jindra doplní.
Ačkoliv mě Groovy hodně oslovilo a už pracujeme na jeho integraci, pro webový výstup zatím pro nás není favoritem.
Ad Daniel) Díky za doplnění.
V společnosti Velocity a FreeMarkeru bych pro doplnění a vybalancování zmínky o Ruby rád uvedl parametrizované stringy v Groovy (GStrings), jako další možnost pro ty, co mohou míchat Javu a Groovy, a jako perličku také na nich postavené groovlety (http://groovy.codehaus.org/Groovlets).
Ups… striplo mi to ten tag
Je to „metal:block“
Ad Novoj) Jak se delaji primo v Zope, to nevim. Pouzivam TAL jen v ramci PHP, kdyz v nem delam, v Zope to bude asi stejne. Pouziva se napr. misto ruznych XHTML tagu tag , ktery pak nese dale akcni atributy (tal:repeat, tal:condition etc), ale do vystupu nejde. Tzn. vase sablona je stale 100% XML, ale vystup muze byt plaintext.
Priznavam, ze v takovem pripade je to trosku „ukecane“ reseni. Nicmene u me je takovych pripadu minimum a ostatni schopnosti TALu (makra, sloty, kombinace s XInclude) to bohate vyvazuji.
Ad Jindra) Ruby flame se vám dostane všude
, ale teď vážně – s Ruby nemám hlubší zkušenost, ale obávám se, že je to tak trochu všechno nebo nic (i když JRuby už by snad mělo být s Javou asi rozumně použitelné).
Navíc u nás máme vývoj striktně oddělený a web vrstvu dělají striktně webdevelopeři, kteří jsou odborníci na web, ale nejsou to programátoři. Pro ně je IMHO daleko zkousnutelnější jednoduchý template engine jako FreeMarker než komplexní řešení jakým je Ruby.
Ad Daniel) všechny termíny slyším prvně, takže těžko budu reagovat – letmo jsem kouknul na Zope a docela pěkně je tam řešené to prolnutí HTML šablony a kódu, jak se ale dělají plain text šablony?!
Je skoda, ze obe dve javovske implementace TALu z pythonskeho Zope ( http://christophermrossi.com/jpt/ , http://javazpt.sourceforge.net/) vypadaji, ze jsou u ledu.
(Treba PHP ma implementaci na velice dobre urovni a za zadny Smarty a podobny bych to nevymenil, pro samotny Python taky zadna standalone implementace neni zrovna dvakrat aktivne vyvijena (AFAIK) – ale tam to jisti Genshi.)
Takze pro me jsou JSP pres vsechny svoje negativa zatim suverenem.
zkusil jsem vsechny – jsp, velocity i freemakrer. Freemarker ma tu uzasnou vlastnost ze jeho direktivy jsou XML-like, t.j. oproti velocity zvladal freemarker sablonu i obyc. html editor.
U velocity mi vyhovovalo ze jedna chyba (napr. neplatny nazev promenne) vypsal jen vyjimku do sablony, kdezto freemearker (ve std. nastaveni) zastavi vykonavani cele sablony.
Nejvic mi ale vyhovoval templatovaci engine v RoR – zadne vymysleni vlastnich direktiv – proste co je v a v (jsp like) je kod v Ruby se vsi svoji eleganci (kam se na to hrabe EL)…. doporucuju vyzkouset a poznate co v javovejch templatovacich frameworcich chybi a kam by mel smerovat vyvoj:-)