${ message : g r e e t i n g }
8
J u s t t o prove t h i s i s l i v e :
The c u r r e n t time i s : ${ currentTime } .
[
Contact e m a i l : $ { c o n t a c t . e m a i l }
3Submit your message :
4Contact c z . v s e . x z i l t 0 2 . t a p e s t r y on ${ e m a i l }
Your message i s $ { message}
B a s i c Page Content
5
This i s t h e s i d e b a r c o n t e n t
6
o r g . h s q l d b . j d b c D r i v e r p r o p e r t y>
7
j d b c : h s q l d b : . / t a r g e t / work / t a p e s t r y 5 t h e s i s ; shutdown=t r u e p r o p e r t y>
8
o r g . h i b e r n a t e . d i a l e c t . HSQLDialect p r o p e r t y>
9
update p r o p e r t y> s e s s i o n −f a c t o r y>
10
11 h i b e r n a t e −c o n f i g u r a t i o n> 44
V z´ avislosti na prostˇred´ı je pak nutn´e obnovit konfiguraci projektu, napˇr. v Eclipse je v kontextov´em menu
projektu volba Maven → Update Project Configuration.
48
Po spr´avn´em nakonfigurov´ an´ı pak Tapestry 5 um´ı zajistit:
• Konfigurace entit: Bˇeˇznˇe se vˇsechny entity mus´ı uv´est uˇz v konfiguraˇcn´ım souboru hibernate.cfg.xml. Tapestry 5 je vˇsak um´ı naˇc´ıst automaticky v pˇr´ıpadˇe, ˇze jsou v pˇr´ısluˇsn´em bal´ıku entities, pˇr´ıpadnˇe dalˇs´ıch bal´ıc´ıch, kter´e specifikujeme v konfiguraci IoC kontejneru [13]. • Injekce Hibernate session: Pro pouˇzit´ı nen´ı nutn´e ruˇcnˇe vytv´aˇret Hibernate session, staˇc´ı ji do tˇr´ıdy ˇci komponenty injektovat. Tapestry uˇz se postar´a o to, ˇze je inicializov´ ana s ohledem na v´ıcevl´ aknov´ y pˇr´ıstup, tj. pro kaˇzd´ y request oddˇelenˇe [14]. • Koerce entit: Pˇri pouˇzit´ı Hibernate entity v aktivaˇcn´ım kontextu (viz 4.7.5) se pouˇzije vestavˇen´ a koerce na prim´ arn´ı kl´ıˇc a zpˇet. V podstatˇe to pak znamen´a, ˇze pˇri pasivaci se entita pˇrevede na sv˚ uj prim´ arn´ı kl´ıˇc, kter´ y se pak stane souˇc´ast´ı adresy, a pˇri aktivaci se pˇr´ısluˇsn´ a entita automaticky z datab´aze naˇcte. Konkr´etn´ı pˇr´ıklad viz napˇr´ıklad [14].
Celkovˇe se vˇsak dle m´eho n´ azoru jedn´a o drobnosti a tak jako tak se v´ yvoj´aˇr mus´ı nauˇcit mimo Tapestry 5 jeˇstˇe ORM framework, aby byl schopen entity spr´avnˇe anotovat a pracovat s datab´azovou vrstvou. Samozˇrejmˇe mu nic nebr´an´ı pouˇz´ıt i jak´ ykoli zp˚ usob standardn´ı interakce s datab´az´ı, kter´ y Java podporuje, pˇr´ıpadnˇe nˇejak´ y vlastn´ı ˇsit´ y na m´ıru konkr´etn´ım potˇreb´ am. Tapestry sice nic nepˇredepisuje a neurˇcuje, ale tak´e nepˇrin´aˇs´ı ˇz´adn´e z´asadn´ı zjednoduˇsen´ı.
5
Grails
Druh´ ym z framework˚ u, kter´ ym se budu v r´amci pr´ace zab´ yvat, je Grails. Grails je pomˇernˇe nov´ y framework pro rychl´ y v´ yvoj webov´ ych aplikac´ı na platformˇe Java, jeho prvn´ı verze vyˇsla v roce 2006[19] pod n´ azvem Groovy on Rails, kter´ y byl ovˇsem kr´atce po vyd´an´ı zmˇenˇen na ˇz´adost Davida Heinemeiera Hanssona, autora jin´eho popul´arn´ıho frameworku Ruby on Rails. Nov´ y n´azev znˇel uˇz Grails a pod n´ım vych´az´ı framework od verze 0.3 aˇz dosud[18]. Za projektem od poˇc´ atku st´ ala spoleˇcnost G2One, kterou v roce 2008 koupil SpringSource[20], jenˇz byl pomˇernˇe z´ ahy v roce 2009 pohlcen spoleˇcnost´ı VMware[21], pod jehoˇz kˇr´ıdly se rozv´ıj´ı d´ale. Jak uˇz p˚ uvodn´ı n´ azev napov´ıd´ a, je inspirovan´ y pr´avˇe Ruby on Rails (viz napˇr. [10]). Podobn´ y je 49
mu zejm´ena architekturou MVC (Model-View-Controller), podobnou organizac´ı adres´aˇr˚ u projektu, zp˚ usobem pouˇzit´ı pˇres pˇr´ıkazov´ y ˇr´adek nebo scaffoldingem. Za povˇsimnut´ı ovˇsem stoj´ı hlavnˇe d´ıky jin´ ym vlastnostem:
• Jazyk Groovy: Grails nepouˇz´ıv´a ˇcistou Javu, ale dynamicky typovan´ y jazyk Groovy. Ten se vyznaˇcuje podobnou syntax´ı jako Java45 , ovˇsem umoˇzn ˇuje vyuˇz´ıt nˇekter´e konstrukty dynamick´ ych jazyk˚ u, kter´e v Javˇe chyb´ı. V´ ysledkem kompilace Groovy k´odu je pak standardn´ı javovsk´ y JAR (Java Archive), kter´ y bˇeˇz´ı v JVM. V Groovy k´odu lze pouˇz´ıvat jak´ekoli javovsk´e tˇr´ıdy, takˇze v´ yvoj´aˇr nen´ı ochuzen o velkou s´ılu platformy Java ani o vlastn´ı dosavadn´ı pr´ aci. Je dokonce na nˇem, zda bude programovat typovˇe nebo netypovˇe, pˇr´ıpadnˇe pˇr´ıstupy kombinovat podle potˇreby46 . • Spring: Na pozad´ı je Grails postaven na rozˇs´ıˇren´em Spring frameworku. To mu poskytuje solidn´ı z´ aklady, pˇrirozenou integraci s existuj´ıc´ımi Spring projekty a moˇznosti konfigurace, od kter´e vˇsak druhou stranu pˇri dodrˇzen´ı konvenc´ı odstiˇ nuje do t´e m´ıry, ˇze pro pr´ aci s Grails nen´ı nutn´e Spring zn´ at. • Hibernate: Pro abstrakci pr´ ace s datab´az´ı a objektovˇe-relaˇcn´ı mapov´an´ı slouˇz´ı v Grails vrstva GORM (Grails Object-Relational Mapping), kter´a na pozad´ı pouˇz´ıv´a zn´am´ y ORM framework Hibernate. To mimo pˇredv´ıdateln´eho chov´an´ı a moˇznosti ps´at datab´ azov´e dotazy v HQL (Hibernate Query Language) znamen´a, ˇze lze do Grails projektu importovat existuj´ıc´ı Hibernate konfiguraci a entity, kter´e pak Grails dynamicky obohat´ı o nov´e metody a vlastnosti bˇeˇzn´ ych GORM entit, takˇze je lze pouˇz´ıvat naprosto stejn´ ym zp˚ usobem. • SiteMesh: Framework pro tvorbu a integraci r˚ uzn´ ych v´ ystup˚ u do jednotn´eho uˇzivatelsk´eho rozhran´ı m´ a v Grails na starosti zobrazovac´ı logiku a tvorbu rozvrˇzen´ı str´anky.
Seˇcteno a podtrˇzeno, pouˇzit´ı Grails neznamen´a ani zmaˇren´ı veˇsker´e dosavadn´ı pr´ace, znalost´ı a zkuˇsenost´ı, ani krok do naprost´eho nezn´ama kv˚ uli pouˇzit´ı jin´eho programovac´ıho jazyka, frameworku IoC kontejneru nebo datab´ azov´e vrstvy. Sp´ıˇse se d´a hovoˇrit o tom, ˇze se jedn´a o zn´ am´e technologie obalen´e flexibilnˇejˇs´ım dynamick´ ym programovac´ım jazykem a sv´azan´e konvencemi, kter´e nahrazuj´ı nutnost sloˇzit´e konfigurace pomoc´ı XML ˇci anotac´ı. Vˇsechny tyto vlastnosti dle m´eho n´azoru dˇelaj´ı z Grails framework, kter´ y stoj´ı za pozornost. 45 46
Publikace [8] uv´ ad´ı, ˇze validn´ı Java k´ od je t´emˇeˇr stoprocentnˇe validn´ı Groovy k´ od. V´ıce se typ˚ um vˇenuje kapitola 5.2.2
50
5.1
Instalace
Instalace je moˇzn´ a nˇekolika zp˚ usoby. Prvn´ı dva - pˇr´ım´e staˇzen´ı a checkout z Git repozit´ aˇre - popisuje instalaˇcn´ı pr˚ uvodce na str´ank´ach projektu [22]. Protoˇze k rychl´emu a efektivn´ımu v´ yvoji patˇr´ı i kvalitn´ı v´ yvojov´e n´ astroje, povaˇzuji za jednoduˇsˇs´ı a zaj´ımavˇejˇs´ı tˇret´ı moˇznost, kterou je instalace pˇr´ımo z IDE STS (SpringSource Tool Suite). STS je n´astroj postaven´ y na Eclipse, kter´ y spoleˇcnost SpringSource nab´ız´ı zdarma ke staˇzen´ı pro pouˇzit´ı se sv´ ymi produkty, a obsahuje mimo jin´e i podporu Groovy a Grails.
5.1.1
Instalace pˇ res IDE SpringSource Tool Suite
Instalace STS je moˇzn´ a bud’ do ˇcist´e Eclipse jako plugin z download site, nebo rozbalen´ım kompletn´ıho bal´ıku. Abych se vyhnul probl´em˚ um se z´avislostmi na r˚ uzn´ ych verz´ıch ostatn´ıch plugin˚ u, zvolil jsem druhou moˇznost. Po spuˇstˇen´ı n´astroje se pod volbou Install Extensions skr´ yv´a seznam instalovateln´ ych rozˇs´ıˇren´ı. Pro pr´aci s Grails slouˇz´ı volby Language and Framework Tooling → Grails Support, podporu Groovy dod´a Language and Framework Tooling → Groovy Eclipse a samotn´ y framework, pokud nen´ı nainstalovan´ y jednou z pˇredchoz´ıch moˇznost´ı, je moˇzn´e st´ ahnout zaˇskrtnut´ım Languages and Frameworks → Grails. Prvn´ı dva pluginy pˇridaj´ı do Eclipse nov´e perspektivy, podporu pro nov´e projekty a nˇekter´e kontextov´e nab´ıdky, posledn´ı pak st´ ahne aktu´ aln´ı verzi Grails frameworku do adres´aˇre, kam jsme pˇredt´ım rozbalili STS. Pro zachov´ an´ı moˇznosti pracovat s Grails pomoc´ı pˇr´ıkazov´e ˇr´adky je jeˇstˇe nutn´e pˇridat do promˇenn´e prostˇred´ı $PATH spustiteln´ y soubor $GRAILS HOME/bin/grails.
5.2
Groovy
Jeˇstˇe neˇz se pust´ıme do samotn´eho frameworku Grails, zastavme se kr´atce u jazyku Groovy, kter´ y pouˇz´ıv´ a. Groovy je dynamicky typovan´ y skriptovac´ı jazyk pro platformu Java. V k´ odu lze vyuˇz´ıvat jak´ekoli javovsk´e knihovny. V´ ysledkem jeho kompilace je standardn´ı JAR soubor, kter´ y tud´ıˇz lze spustit nad JVM, aniˇz by k tomu byl potˇreba dalˇs´ı interpret. Jeho syntaxe je aˇz na nˇekolik m´ alo v´ yjimek velmi podobn´a Javˇe a v neposledn´ı ˇradˇe tak´e umoˇzn ˇuje kombinovat typov´ y z´apis ve stylu Javy s Groovy netypov´ ym. V podstatˇe je pouze na program´atorovi, kter´ yz nich pouˇzije. Optim´ aln´ı je samozˇrejmˇe kompromis, nˇekdy je typov´a kontrola vhodn´a, jindy pˇr´ıliˇs svazuj´ıc´ı, a ani jeden z extr´em˚ u nelze doporuˇcit. Pokud zvol´ıme striktnˇe typov´ y, je k´od t´emˇeˇr totoˇzn´ y s Javou a pˇrich´ az´ıme t´ım o v´ yhody netypov´eho pˇr´ıstupu, naopak striktnˇe netypov´ y
51
pˇr´ıstup m˚ uˇze v´est k v´ıce chyb´ am nebo pˇri nedostateˇcn´e dokumentaci k obt´ıˇzn´e u ´drˇzbˇe k´odu. Pˇres veˇskerou podobnost s Javou je nutn´e zd˚ uraznit nˇekolik odliˇsnost´ı, kter´e mohou vyˇzadovat urˇcit´ y zvyk. Odliˇsnostem se vˇenuje ˇc´ast dokumentace [24], zde uvedeme nˇekolik vybran´ ych aspekt˚ u podle [8].
Skriptovac´ı jazyk:
Pro pˇr´ım´e spuˇstˇen´ı Javovsk´eho k´odu mus´ı existovat tˇr´ıda s metodou main.
Groovy toto nevyˇzaduje a podporuje m´ısto toho skripty - posloupnosti pˇr´ıkaz˚ u prov´adˇen´e v poˇrad´ı tak, jak jdou za sebou. Vyzkouˇset si to lze v jednoduch´e Swingov´e aplikaci GroovyConsole, kter´a je souˇc´ ast´ı Grails a je n´ astrojem ke spouˇstˇen´ı skript˚ u v kontextu aplikace, takˇze lze pouˇz´ıvat i tˇr´ıdy aplikace. Spouˇst´ı se pˇr´ıkazem grails console. Rozhran´ı se skl´ad´a ze dvou ˇc´ast´ı, editoru Groovy k´ odu, a konzole, kam se vypisuje v´ ystup spouˇstˇen´ ych pˇr´ıkaz˚ u.
Stˇ redn´ıky:
Groovy na rozd´ıl od Javy nevyˇzaduje ukonˇcovat pˇr´ıkazy stˇredn´ıkem. Cenou za
toto zjednoduˇsen´ı z´ apisu je pak nutnost vˇenovat zv´ yˇsenou pozornost v´ıceˇr´adkov´ ym v´ yraz˚ um, protoˇze nˇekter´e zp˚ usoby z´ apisu platn´e v Javˇe vy´ ust´ı v Groovy v chybu kompilace.
Z´ avorky:
Ve vˇetˇsinˇe pˇr´ıpad˚ u se nevyˇzaduje pˇri vol´an´ı metody ps´at z´avorky. Existuj´ı vˇsak
pˇr´ıpady, kdy to naopak nutn´e je, napˇr´ıklad pˇri vol´an´ı metody bez argument˚ u nebo pokud prvn´ım parametrem je seznam. Opˇet z´ aleˇz´ı na preferenc´ıch, publikace [8] doporuˇcuje je pouˇz´ıvat co moˇzn´a nejˇcastˇej´ı a vynech´ avat je pouze v jasn´ ych pˇr´ıpadech jako napˇr´ıklad println.
Implicitn´ı return: Pouˇz´ıv´ an´ı kl´ıˇcov´eho slova return je voliteln´e. Pokud se neuvede, n´avratovou hodnotu funkce nebo uz´ avˇeru tvoˇr´ı hodnota posledn´ıho uveden´eho v´ yrazu.
Groovy truth neboli Groovy pravda oznaˇcuje zp˚ usob vyhodnocov´an´ı v´ yraz˚ u v podm´ınk´ ach, to jest za jak´ ych podm´ınek se v´ yraz vyhodnot´ı jako true nebo false. Zat´ımco v Javˇe je nutn´e podm´ınky testovat explicitnˇe, Groovy pouˇz´ıv´a urˇcit´a pravidla pˇrevodu v´ yrazu na booleovskou hodnotu, kter´ a zjednoduˇsuj´ı z´ apis: Zdrojov´ y k´od 36: Groovy: Groovy pravda 1 // J a v o v s k y z a p i s 2
i f ( r e s u l t == null | | r e s u l t . isEmpty ( ) ) { . . . }
3
52
4 // Groovy pravda 5
if (! result ) { . . . }
Podm´ınky, za kter´ ych se v´ yraz vyhodnot´ı jako nepravda, shrnuje Tabulka 1 (podle [25] a [8]): Tabulka 1: Groovy pravda Typ
Kdy je false
Boolean
false
Reference na objekt
null
Number
0
String, GString47 , CharSequence
pr´azdn´ y ˇretˇezec
Collection, Map
pr´azdn´a kolekce / mapa
Iterator
hasNext() vrac´ı false
Enumeration
hasMoreElements() vrac´ı false
java.util.regex.Matcher
find() vrac´ı false
Pˇri vyuˇzit´ı zkr´ acen´eho z´ apisu je nutn´e m´ıt tento rozd´ıl na pamˇeti a pˇredem si rozmyslet, zda podm´ınka testuje opravdu to, co jsme zam´ yˇsleli. Nˇekdy m˚ uˇze b´ yt ˇz´adouc´ı oˇsetˇrit r˚ uzn´e hodnoty jinak (napˇr. null a pr´ azdn´ y seznam) a pouˇz´ıt nezkr´acen´ y z´apis, pˇrestoˇze podle Groovy pravdy by se obˇe vyhodnotily jako false.
Property:
Groovy zjednoduˇsuje pouˇz´ıv´an´ı bean properties uˇz na u ´rovni jazyka. Pokud deklaru-
jeme promˇennou tˇr´ıdy bez uveden´ı, zda je public, private nebo protected, Groovy ji automaticky oznaˇc´ı jako private a dopln´ı pˇr´ısluˇsn´e gettery a settery48 , pokud je tˇr´ıda nedefinuje explicitnˇe. Pˇri pˇr´ıstupu k promˇenn´ ym tˇr´ıdy se pak automaticky pouˇz´ıvaj´ı gettery a settery, nen´ı tedy nutn´e pouˇz´ıvat n´ azev metody, staˇc´ı pˇr´ıstupovat k poli jako by bylo public. To plat´ı nejen pro tˇr´ıdy napsan´e v Groovy, ale i pro veˇsker´e javovsk´e tˇr´ıdy. Kaˇzd´a JavaBean mus´ı m´ıt vˇzdy bezparametrick´ y konstruktor, ˇcehoˇz Groovy vyuˇz´ıv´a ke zjednoduˇsen´emu vytv´aˇren´ı instanc´ı. Pokud uvedeme jako parametr konstruktoru mapu49 jej´ıch properties s hodnotami, Groovy na pozad´ı po vytvoˇren´ı instance zavol´a pˇr´ısluˇsn´e settery. 48
Ve tvaru getPropertyName, respektive setPropertyName. Pro promˇenn´e typu boolean je getter ve tvaru
isPropertyName. 49 V Groovy se zapisuje jako seznam dvojic ve tvaru kl´ ıˇ c: hodnota, viz 5.2.2.
53
Zdrojov´ y k´ od 37: Groovy: JavaBeans a properties 1
c l a s s MyBean {
2
// j s o u p r o p e r t i e s
3
static String classVar
4
final String constant = ” constant ”
5
S t r i n g name
6
S t r i n g surname
7 8
// n e j s o u p r o p e r t y
9
public S t r i n g p u b l i c F i e l d
10
private S t r i n g p r i v a t e F i e l d
11 } 12 13 // v y t v o r e n i i n s t a n c e 14 MyBean b = new MyBean( name : ” H e l l o ” , surname : ”World” ) 15
a s s e r t b . getName ( ) == ” H e l l o ”
16
a s s e r t b . getSurname ( ) == ”World”
17 18 // n e z k r a c e n y z a p i s 19 MyBean . s e t C l a s s V a r ( ”x” ) 20 b . setName ( ” Hi ” ) 21
a s s e r t MyBean . g e t C l a s s V a r ( ) == ”x”
22
a s s e r t b . getName ( ) == ” Hi ”
23
a s s e r t b . g e t C o n s t a n t ( ) == ” c o n s t a n t ”
24 25 // z k r a c e n y z a p i s 26 MyBean . c l a s s V a r = ” f o o ” // p o u z i j e s e s e t t e r 27 b . name = ” bar ” 28
a s s e r t MyBean . c l a s s V a r == ” f o o ” // g e t t e r
29
a s s e r t b . name == ” bar ”
V principu se jedn´ a o podobn´ y pˇr´ıstup, jako v pˇr´ıpadˇe Tapestry 5 v kapitole 4.8.1, avˇsak uˇz na u ´rovni jazyka, takˇze lze tento zkr´ acen´ y z´apis pouˇz´ıvat jak v ˇsablon´ach, tak v k´odu tˇr´ıd.
54
5.2.1
Nov´ e oper´ atory
Zkr´acen´ı z´ apisu maj´ı za c´ıl i nˇekter´e nov´e oper´atory.
== (porovn´ av´ an´ı pomoc´ı equals()): V Groovy je oproti Javˇe pozmˇenˇeno chov´an´ı oper´ atoru pro porovn´ av´ an´ı. Ten se chov´ a jako metoda equals(), pˇr´ıpadˇe compareTo(), pokud tˇr´ıda implementuje rozhran´ı Comparable. D˚ uvodem t´eto zmˇeny je pˇredv´ıdatelnˇejˇs´ı chov´an´ı, nicm´enˇe pˇrehled oper´ ator˚ u v dokumentaci [26] u oper´atoru == uv´ad´ı, ˇze se ,,ne vˇzdy chov´ a jako equals()“ a m˚ uˇzeme ,,ˇcasem oˇcek´ avat zmˇeny, aby chov´ an´ı oper´ atoru bylo jasnˇejˇs´ı a konzistentnˇejˇs´ı”. Osobnˇe jsem nenarazil na ˇz´ adn´e nepˇredv´ıdateln´e chov´an´ı a z´apis mi subjektivnˇe pˇrijde ˇcitelnˇejˇs´ı, neˇz javovsk´e equals. Pokud je nˇekdy potˇreba v k´odu pouˇz´ıt p˚ uvodn´ı v´ yznam oper´atoru z Javy a zjistit, zda promˇenn´e a a b odkazuj´ı na stejn´e instance, pouˇz´ıv´a se v Groovy metoda a.is(b).
?. (null-safe referencov´ an´ı objekt˚ u)
odstraˇ nuje nutnost kontrolovat, zda reference na ob-
jekt je nepr´ azdn´ a50 . Tento oper´ ator ji pˇri kaˇzd´e referenci provede automaticky a pokud selˇze, vyhodnot´ı se cel´ y v´ yraz jako null, v opaˇcn´em pˇr´ıpadˇe se pokraˇcuje. Zdrojov´ y k´ od 38: Groovy: null-safe referencov´an´ı objekt˚ u 1 // n e z k r a c e n y z a p i s 2
i f ( o b j != null && o b j . p r o p e r t y != null ) { . . . }
3 // z k r a c e n y z a p i s 4
i f ( o b j ? . p r o p e r t y != null ) { . . . }
5 // r e t e z e n i o p e r a t o r u 6
p r i n t l n obj ? . property ? . address ? . c i t y ? . zip
?: (tern´ arn´ı oper´ ator)
zkracuje z´apis bloku if ... then ... else. Levou stranu tvoˇr´ı
podm´ınka, za otazn´ıkem pak n´ asleduje dvojteˇckou oddˇelen´ y k´od pro pˇr´ıpady splnˇen´ı a nesplnˇen´ı podm´ınky. Protoˇze ˇcast´ ym pouˇzit´ım je poskytnut´ı defaultn´ıch hodnot, podporuje i z´ apis s vynech´an´ım moˇznosti pro pravdiv´e vyhodnocen´ı podm´ınky, kter´e v takov´em pˇr´ıpadˇe pouˇzije hodnotu testovan´eho v´ yrazu. Zdrojov´ y k´od 39: Groovy: tern´arn´ı oper´ator 1
p r i n t l n customer . name ? customer . name : ”Unknown customer ” 50
Absence kontroly pak ˇcasto u ´st´ı v NullPointerException.
55
2
p r i n t l n customer . name ? : ”Unknown customer ”
*. (spread-dot oper´ ator) umoˇzn ˇuje zavolat metodu na kaˇzd´em prvku z nˇejak´e kolekce a vr´atit seznam v´ ysledk˚ u tˇechto vol´ an´ı. V´ ysledn´ y seznam je ve stejn´em poˇrad´ı jako p˚ uvodn´ı kolekce. Zdrojov´ y k´ od 40: Groovy: spread-dot oper´ator 1
L i s t peopleNames = p e o p l e ∗ . getName ( )
Zmˇen v oblasti oper´ ator˚ u je v´ıce, vˇsechny jsou napˇr´ıklad null-safe, takˇze funguj´ı i v pˇr´ıpadˇe, ˇze oba operandy jsou null. Tak´e nevyˇzaduj´ı, aby oba operandy byly stejn´eho typu, m´ısto toho pouˇz´ıvaj´ı pˇred samotn´ ym porovn´ an´ım koerce. Pro kompletn´ı pˇrehled oper´ator˚ u viz dokumentace v [26].
5.2.2
Typy
Z velk´e ˇc´ asti je typov´ y syst´em Groovy stejn´ y jako v Javˇe, pouˇz´ıvat lze vˇsechny primitivn´ı i objektov´e typy. Existuje vˇsak nˇekolik odliˇsnost´ı, kter´e je tˇreba m´ıt na pamˇeti, m´am ale za to, ˇze sp´ıˇse neˇz o nauˇcen´ı nov´ ych pouˇcek se jedn´a o zapomenut´ı tˇech n´avyk˚ u z Javy, na kter´e jsme si museli pracnˇe zvykat, protoˇze nebyly u ´plnˇe intuitivn´ı.
Netypov´ y z´ apis:
Kdekoli, kde n´ am nez´aleˇz´ı na typu, at’ uˇz u promˇenn´e nebo n´avratov´eho
typu funkce, se pro deklaraci pouˇz´ıv´a kl´ıˇcov´e slovo def. Do takto deklarovan´e promˇenn´e pak m˚ uˇzeme ukl´ adat cokoli a Groovy na pozad´ı mˇen´ı jej´ı typ tak, jak je tˇreba. [27]. Zdrojov´ y k´od 41: Groovy: netypov´ y z´apis 1
c l a s s Untyped {
2
def value
3
def arbitrary ( Class c ) {
4
i f ( c == S t r i n g ) { v a l u e = ” H e l l o ” }
5
e l s e i f ( c == I n t e g e r ) { v a l u e = 1 }
6
e l s e { v a l u e = null }
7 8
return v a l u e 56
}
9 10 } 11 12
d e f untyped = new Untyped ( )
13 14
p r i n t l n untyped . a r b i t r a r y ( S t r i n g )
15
a s s e r t untyped . v a l u e == ” H e l l o ”
16
p r i n t l n untyped . a r b i t r a r y ( I n t e g e r )
17
a s s e r t untyped . v a l u e == 1
ˇ ısla: C´
ˇ ısla lze st´ C´ ale deklarovat bud’ jako primitivn´ı typy, nebo objekty. I v pˇr´ıpadˇe prim-
itivn´ıch typ˚ u s nimi vˇsak m˚ uˇzeme pracovat jako s objekty a volat na nich metody, to sam´e dokonce plat´ı i o ˇc´ıseln´ ych liter´ alech. Zdrojov´ y k´od 42: Groovy: ˇc´ıseln´e typy 1
int count = 3
2
float average = 3.0
3
a s s e r t count == a v e r a g e
4
a s s e r t count + a v e r a g e == 6
5
a s s e r t count . abs ( ) == 3
6
a s s e r t ( −3) . abs ( ) == 3
7
a s s e r t count . c l a s s == j a v a . l a n g . I n t e g e r
8
a s s e r t a v e r a g e . c l a s s == j a v a . l a n g . F l o a t
9
a s s e r t 3 . c l a s s == j a v a . l a n g . I n t e g e r
10
a s s e r t ( 3 . 0 ) . c l a s s == j a v a . math . BigDecimal
Za zm´ınku stoj´ı i poˇc´ıt´ an´ı v plovouc´ı ˇr´adov´e ˇc´arce, kter´e pouˇz´ıv´a BigDecimal nam´ısto float nebo double, pokud nejsou explicitnˇe uveden´e typy. Programov´an´ı vˇsak prob´ıh´a transparentnˇe a nen´ı tˇreba pouˇz´ıvat nijak odliˇsn´ y z´apis. Umoˇzn´ı to vyhnout se nˇekter´ ym tˇeˇzko odhaliteln´ ym chyb´am a v´ ysledky odpov´ıdaj´ı oˇcek´ av´an´ı. Zdrojov´ y k´ od 43: Groovy: operace v plovouc´ı ˇr´adov´e ˇc´arce 1 // n e p r e s n e p o c i t a n i v p r i p a d e normalnich t y p u 2 double x = 0 . 1 3
int y = 3 57
4
a s s e r t x∗y != 0 . 3
5 // p r o t o z e x ∗ y == 0.30000000000000004 6
a s s e r t ( x∗y ) instanceof Double
7 8 // Groovy p o u z i v a BigDecimal 9
def a = 0.1
10
def b = 3
11
a s s e r t a ∗b == 0 . 3
12
a s s e r t ( a∗b ) instanceof BigDecimal
D˚ uvodem uveden´eho chov´ an´ı je reprezentace desetinn´ ych ˇc´ısel z des´ıtkov´e soustavy v poˇc´ıtaˇc´ıch, kter´e operuj´ı nad bin´ arn´ı soustavou. Probl´em s poˇc´ıt´an´ım s desetinn´ ymi ˇc´ısly typu double a float v Javˇe je pomˇernˇe srozumitelnˇe pops´an napˇr´ıklad v [28], ovˇsem ani BigDecimal nen´ı bez vlastn´ıch z´ adrhel˚ u, na coˇz poukazuje napˇr´ıklad [29].
ˇ ezce v Groovy funguj´ı opˇet t´emˇeˇr stejnˇe jako v Javˇe s nˇekolika m´ Groovy ˇ retˇ ezce: Retˇ alo v´ yjimkami. Pˇrednˇe mohou b´ yt uvozeny jak uvozovkami (") tak apostrofy (’). Znaky char lze pouˇz´ıvat tak´e, avˇsak je nutn´e je bud’ pˇriˇradit jednoznakov´ y ˇretˇezec do promˇenn´e s deklarovan´ ym typem (char ch = ’x’), nebo konvertovat s pouˇzit´ım kl´ıˇcov´eho slova as. Rozd´ıl mezi z´apisem s apostrofy a uvozovkami je ten, ˇze v druh´em jmenovan´em pˇr´ıpadˇe lze v r´amci ˇretˇezce pouˇz´ıvat Groovy v´ yrazy ohraniˇcen´e ${ a }. Vˇse uvnitˇr takov´eho v´ yrazu bude vyhodnoceno jako bˇeˇzn´ y Groovy k´ od, pˇrevedeno na ˇretˇezec pomoc´ı toString() a vloˇzeno na pˇr´ısluˇsn´e m´ısto v ˇretˇezci. Pokud chceme pouˇz´ıt pˇr´ımo znak $, mus´ıme ho escapovat zpˇetn´ ym lom´ıtkem. Pro oba z´ apisy tak´e existuj´ı v´ıceˇr´ adkov´e varianty, kter´e jsou uvozen´e ztrojenou uvozovkou, resp. apostrofem. Zdrojov´ y k´od 44: Groovy: ˇretˇezce 1 // char : p r i r a z e n i r e t e z c e do charu a p o u z i t i b e z d e k l a r a c e 2 char ch = ’ x ’ 3
S t r i n g r e p l a c e d = ” Hi Tom” . r e p l a c e ( ’ ’ a s char , ’ ’ a s char )
4
a s s e r t r e p l a c e d == ’ Hi Tom ’
5 6 // s t r i n g 7
S t r i n g name = ’Tom ’
8
S t r i n g e v a l u a t e d = ” Hi ${name} ”
9
S t r i n g e s c a p e d = ” Hi \$ {name} ” 58
Tabulka 2: Podporovan´e pˇrevody typ˚ u v Groovy Typ
C´ılov´ y typ
Popis
String
ˇc´ıslo
Parsuje ˇretˇezec jako ˇc´ıslo.
List
pole
Pˇrevede List na pole pˇr´ısluˇsn´ ych typ˚ u, napˇr´ıklad myList as String[]
(Groovy
nepodporuje
javovsk´a pole) List nebo pole
Set
Pˇrevede seznam nebo pole na mnoˇzinu Set
cokoli
Boolean
Pomoc´ı Groovy pravdy (viz Tabulka 1) vyhodnot´ı hodnotu jako true nebo false
Collection
List
Vytvoˇr´ı seznam, kter´ y je kopi´ı p˚ uvodn´ı kolekce; poloˇzky v seznamu jsou ve stejn´em poˇrad´ı, jako byly v p˚ uvodn´ı kolekci
String
List
Povaˇzuje ˇretˇezec za sekvenci znak˚ u, kter´e vr´at´ı v seznamu
10
S t r i n g s t a t i c S t r = ’ Hi ${name} ’ // n a h r a z e n i s e n e p r o v e d e
11
S t r i n g m u l t i l i n e = ” ” ” Hi $ {name } ,
12 thank you f o r t r y i n g t h i s out . 13 ””” 14
a s s e r t e v a l u a t e d == ’ Hi Tom ’
15
a s s e r t e s c a p e d == ’ Hi ${name} ’
Konverze
V Javˇe lze objekt pˇretypovat na urˇcit´ y typ pouze tehdy, kdyˇz je opravdu instanc´ı
dan´e tˇr´ıdy nebo jej´ıch pˇredk˚ u, pˇr´ıpadnˇe rozhran´ı. Groovy tento konstrukt podporuje tak´e, ale d´ıky jeho dynamick´emu typov´ an´ı je nadbyteˇcn´ y. Co naopak vyuˇz´ıv´a, je moˇznost pˇrev´ adˇet r˚ uzn´e typy libovolnˇe mezi sebou, k ˇcemuˇz slouˇz´ı oper´ator as. Kromˇe konverz´ı podporovan´ ych Groovy (nˇekter´e viz Tabulka 2 pˇrevzat´a z [8]) lze implementovat konverzi pro vlastn´ı objekty prostˇrednictv´ım metody asType(Class).
59
Seznamy, mapy, intervaly
Oproti jazyk˚ um, kter´e maj´ı pr´aci se seznamy a mapami zabu-
dovanou pˇr´ımo ve sv´ ych konstruktech, je pr´ace v Javˇe m´enˇe pohodln´a, protoˇze vyuˇz´ıv´a v´ yhradnˇe objekt˚ u a jejich metod. Groovy se snaˇz´ı tuto tˇeˇzkop´adnost odstranit kompaktnˇejˇs´ı syntax´ı jak pˇri vytv´aˇren´ı, tak pˇri pouˇz´ıv´ an´ı seznam˚ u a map. K tomu pˇrid´av´a jeˇstˇe nov´ y vlastn´ı datov´ y typ Range pro reprezentaci interval˚ u, kter´e se daj´ı pouˇz´ıt pro iteraci nebo pr´aci se seznamy51 . Seznamy i mapy se zapisuj´ı do hranat´ ych z´avorek [ ], mezi nimiˇz jsou hodnoty oddˇelen´e ˇc´arkou v pˇr´ıpadˇe seznamu, a dvojice kl´ ıˇ c: hodnota v pˇr´ıpadˇe mapy. Pro ˇcten´ı i z´apis se pouˇz´ıv´ a opˇet oper´ ator hranat´ ych z´ avorek, prvky jsou ˇc´ıslovan´e od nuly a pomoc´ı z´aporn´ ych ˇc´ısel se lze odkazovat na prvky od konce seznamu. Pro pˇrid´av´an´ı nov´ ych prvk˚ u na konec seznamu slouˇz´ı oper´ator lev´eho bitov´eho posunu <<. Pˇritom se jedn´a o List, resp. Map, takˇze vytvoˇren´e instance maj´ı i vˇsechny metody, na kter´e jsmˇe z Javy zvykl´ı. Zdrojov´ y k´ od 45: Groovy: seznamy, mapy, intervaly 1 // seznamy 2
L i s t myList = [ ” one ” , 2 , 3 . 5 ]
3 myList [ 1 ] = 10 4 myList << ” f o u r ” 5
a s s e r t myList . s i z e ( ) == 4
6
a s s e r t myList [ 0 ] == ” one ”
7
a s s e r t myList [ 1 ] == 10
8
a s s e r t myList [ −2] == 3 . 5
9 10 //mapy 11 Map myMap = [ ” one ” : ” f o o ” , ”two” : ” bar ” , ” t h r e e ” : 3 . 0 ] 12 myMap [ ” f o u r ” ] = 4 13 myMap [ ” t h r e e ” ] = ” baz ” 14
a s s e r t myMap [ ” one ” ] == ” f o o ”
15
a s s e r t myMap [ ” t h r e e ” ] == ” baz ”
16 17 // i n t e r v a l y 18 Range r a n g e = 0 . . 1 0 // 0 az 10 19 Range e x c l u s i v e = 0.. <10 // 0 az 9 20
L i s t s u b L i s t = myList [ 1 . . 2 ]
21 51
O kolekc´ıch v Groovy v´ıce viz [30].
60
22
for ( int i i n 0.. < s u b L i s t . s i z e ( ) ) { p r i n t l n ” Item $ i i s ${ s u b L i s t [ i ] } ”
23 24 }
Groovy nav´ıc umoˇzn ˇuje vyuˇz´ıt oper´ atory i pro vlastn´ı typy, staˇc´ı implementovat metody, na kter´e se mapuj´ı pˇr´ısluˇsn´e oper´ atory (viz [26]), a m˚ uˇzeme s vlastn´ımi typy pracovat jako se seznamy nebo prov´ adˇet na nich aritmetick´e operace. V nˇekter´ ych pˇr´ıpadech to m˚ uˇze b´ yt elegantn´ı a efektivn´ı, nicm´enˇe jako kaˇzd´ y mocn´ y n´astroj je tˇreba pouˇz´ıvat je obezˇretnˇe s rozmyslem, protoˇze v nˇekter´ ych pˇr´ıpadech m˚ uˇze v´est k neˇcitelnosti k´odu a tˇeˇzko odhaliteln´ ym chyb´am. Pro z´akladn´ı pˇrehled a porozumˇen´ı pˇr´ıklad˚ um uveden´ ym v t´eto pr´aci uveden´ y v´ yklad postaˇc´ı, pro hlubˇs´ı porozumˇen´ı doporuˇcuji prostudovat dokumentaci na domovsk´ ych str´ank´ach projektu http://groovy.codehaus.org, knihu Groovy in Action (viz [32]) nebo seri´al Practically Groovy na port´ alu IBM developerWorks (viz [33]). Zvl´aˇstn´ı pozornost si zaslouˇz´ı zejm´ena problematika uz´ avˇer˚ u (closures, viz [31]), jej´ı hlubˇs´ı vysvˇetlen´ı vˇsak pˇresahuje r´amec t´eto pr´ace a v n´asleduj´ıc´ıch pˇr´ıkladech je budeme pouˇz´ıvat sp´ıˇse intuitivnˇe.
5.3
Principy
Po exkurzi do z´ aklad˚ u Groovy pˇristupme k samotn´emu popisu pouˇz´ıv´an´ı frameworku Grails. Po jeho staˇzen´ı a pˇr´ıpadn´em nainstalov´an´ı v´ yvojov´ ych n´astroj˚ u v kapitole 5.1 je na ˇcase vytvoˇrit projekt a zaˇc´ıt vytv´ aˇret samotnou aplikaci.
5.3.1
Pˇ rikazy
Z´akladn´ı zp˚ usob pr´ ace s Grails je podobnˇe jako v pˇr´ıpadˇe Ruby on Rails pomoc´ı pˇr´ıkaz˚ u z pˇr´ıkazov´e ˇr´ adky. K vytvoˇren´ı pr´ azdn´e kostry projektu jm´enem Thesis v aktu´aln´ım adres´ aˇri napˇr´ıklad slouˇz´ı n´ asleduj´ıc´ı pˇr´ıkaz: Zdrojov´ y k´ od 46: Grails: vytvoˇren´ı nov´eho projektu 1 ˜$ g r a i l s c r e a t e −app T h e s i s
Kompletn´ı v´ ypis pˇr´ıkaz˚ u a n´ apovˇedu k nim lze z´ıskat pomoc´ı Zdrojov´ y k´od 47: Grails: n´apovˇeda
61
1 ˜$ g r a i l s h e l p
Pˇr´ıkazy Grails se vyplat´ı zn´ at, napˇr´ıklad proto, ˇze t´emˇeˇr vˇsechny tutorialy a publikace je pouˇz´ıvaj´ı, aby byl v´ yklad nez´ avisl´ y na v´ yvojov´em prostˇred´ı. STS pro usnadnˇen´ı pr´ace s pˇr´ıkazy nab´ız´ı jednak konzoli, kde je lze spouˇstˇet v kontextu aktu´alnˇe aktivn´ıho projektu, tak wizard pro vˇsechny z´ akladn´ı pˇr´ıkazy, ale v aktu´aln´ı verzi52 tak´e plnohodnotn´e kontextov´e nab´ıdky a dialogy, kter´e umoˇzn ˇuj´ı s Grails projektem pracovat podobnˇe jako s bˇeˇzn´ ymi Java/JavaEE projekty. Nov´ y projekt lze tak kromˇe pˇr´ıkladu 46 vytvoˇrit i pˇr´ımo v STS volbou File → New → Grails Project, vytv´ aˇret jednotliv´e souˇc´asti aplikace pˇres kontextov´e menu projektu a spouˇstˇet ho pˇres Run As → Grails Command (run-app). K dispozici jsou i kl´avesov´e zkratky, kter´e jeˇstˇe v´ıce urychl´ı pr´ aci bez nutnosti opouˇstˇet prostˇred´ı STS.
5.3.2
Struktura projektu
Pod´ıvejme se nyn´ı na novˇe vytvoˇren´ y projekt Thesis. Struktura projektu je dan´a konvencemi Grails, prostˇred´ı STS ji prezentuje pomoc´ı dle m´eho n´azoru lehce chaotick´eho, ale pˇresto praktick´eho logick´eho zobrazen´ı (viz obr´ azek 3). D˚ uleˇzit´e jsou zejm´ena:
• web-app: koˇrenov´ y adres´ aˇr webov´e aplikace, jak s podadres´aˇri pro styly, obr´azky, skripty a jin´e statick´e zdroje, tak standardn´ı WEB-INF s konfiguraˇcn´ımi soubory Spring aplikaˇcn´ıho kontextu applicationContext.xml a zobrazovac´ı vrstvy SiteMesh sitemesh.xml. • grails-app: adres´ aˇr s tˇr´ıdami a konfiguraˇcn´ımi soubory Grails. – conf: konfiguraˇcn´ı soubory pro Grails aplikaci. Umoˇzn ˇuj´ı ovlivnit kompilaci a start aplikace, nastavit parametry aplikace i vrstev pod n´ı (Spring, SiteMesh, Hibernate, Log4J), nebo nakonfigurovat pˇripojen´ı k datab´azi. – controllers: controllery, kter´e obsahuj´ı business logiku aplikace v podobˇe jedn´e ˇci v´ıce akc´ı, na kter´e se pak mapuj´ı URL (Uniform Resource Locator). – domain: dom´enov´e objekty tvoˇr´ıc´ı datovou vrstvu aplikace. O nich pojedn´av´a kapitola 5.6. – i18n: internacionalizaˇcn´ı soubory properties pro pˇreklad aplikace do r˚ uzn´ ych jazyk˚ u. 52
V dobˇe psan´ı pr´ ace se jedn´ a o verzi 2.5.1. Na zaˇca ´tku psan´ı pr´ ace byla aktu´ aln´ı verze 2.3.2, kter´ a vˇsak
obsahovala pouze konzoli pro spouˇstˇen´ı pˇr´ıkaz˚ u.
62
– services: sluˇzby jsou objekty obaluj´ıc´ı znovupouˇzitelnou logiku. V aplikaci se injektuj´ı do controller˚ u, kter´e je pak mohou pouˇz´ıvat. – taglib: tˇr´ıdy s vlastn´ımi GSP (Groovy Server Pages) tagy. V´ıce viz 5.5.2. – utils: adres´ aˇr, kter´ y podle odpovˇedi jednoho z autor˚ u frameworku v diskusi v [23] slouˇz´ı ,,k vloˇzen´ı tak nˇejak ˇcehokoli (...), co je specifick´e pro Grails”. – view: zobrazovac´ı logika aplikace (viz 5.5) - tzv. pohledy (views), GSP ˇsablony pro jednotliv´e akce controller˚ u, templaty pro opakuj´ıc´ı se k´od.
N´ahled projektu v STS pak tuto strukturu zobrazuje s t´ım, ˇze d˚ uleˇzit´e a ˇcasto pouˇz´ıvan´e adres´aˇre, kter´e jsou schovan´e hloubˇeji ve struktuˇre, zobraz´ı v nejvyˇsˇs´ı u ´rovni jako logick´e adres´ aˇre, takˇze jsou st´ ale na oˇc´ıch a k dispozici pro rychlejˇs´ı pr´aci (srovnejte fyzick´e a logick´e zobrazen´ı na Obr´azku 3). Kontextov´ a nab´ıdka pro jednotliv´e logick´e adres´aˇre by vˇsak dle m´eho n´ azoru mohla b´ yt l´epe pˇrizp˚ usobena jejich v´ yznamu a l´epe nav´adˇet k pˇr´ısluˇsn´ ym akc´ım (pro logick´ y adres´aˇr views nab´ızet akci k vytvoˇren´ı pohledu, pro controllers vytvoˇren´ı controlleru apod.).
5.3.3
MVC
Jak uˇz bylo ˇreˇceno v u ´vodu, je Grails typick´ ym pˇredstavitelem rodiny MVC framework˚ u. Na rozd´ıl od Tapestry 5, ve kter´e se vˇse toˇc´ı okolo str´anek, tvoˇr´ı z´akladn´ı stavebn´ı k´amen Grails aplikace controllery a jejich akce. Kaˇzd´a URL adresa je pak namapov´ana na pr´avˇe jednu akci jednoho z controller˚ u, kter´ a provede samotnou logiku (napˇr´ıklad naˇcten´ı a zpracov´an´ı dat z datab´aze pomoc´ı dom´enov´ ych tˇr´ıd modelu) a bud’ pˇresmˇeruje na jinou akci, nebo pˇred´a potˇrebn´e promˇenn´e zobrazovac´ı vrstvˇe (ˇsablon´am GSP, kter´e tvoˇr´ı vrstvu view ) a vyrenderuje v´ yslednou odpovˇed’. Adresy jsou defaultnˇe ve tvaru /controllerName/actionName/id53 , takov´ato adresa pak znamen´a zavol´ an´ı akce actionName controlleru, kter´ y je instanc´ı tˇr´ıdy ControllerNameController. Toto sch´ema je pˇrednastaven´e pˇri vytvoˇren´ı nov´eho Grails projektu, adresy vˇsak jdou namapovat libovolnˇe pomoc´ı konfigurace, ˇcemuˇz se vˇenuje kapitola 5.7. O vytv´aˇren´ı instanc´ı controller˚ u a injekci pouˇz´ıvan´ ych sluˇzeb se na pozad´ı star´a Spring IoC kontejner, v´ yvoj´ aˇr tedy implementuje pouze logiku prov´adˇenou v r´amci akce, pˇr´ıpadnˇe zobrazen´ı dat v ˇsablonˇe. Pod´ıvejme se tedy detailnˇeji na samotn´e controllery. 53
Adresy budeme uv´ adˇet relativnˇe ke kontextu projektu, cel´ a adresa tedy v tomto pˇr´ıpadˇe zn´ı http://server:
port/Thesis/controllerName/actionName/id.
63
Obr´ azek 3: Grails: Struktura projektu - fyzick´a a logick´a
5.4
Controller
Controllery jsou jednoduch´e Groovy tˇr´ıdy s akcemi v podobˇe Groovy uz´avˇer˚ u. Jdou napsat manu´alnˇe, ovˇsem Grails nab´ız´ı pˇr´ıkaz, kter´ y jejich vytv´aˇren´ı automatizuje a nav´ıc k nov´emu controlleru vytvoˇr´ı i kostru test˚ u a adres´aˇr pro GSP ˇsablony. Jedin´ ym parametrem pˇr´ıkazu je n´azev controlleru, podle konvenc´ı bez pˇr´ıpony Controller. Zdrojov´ y k´ od 48: Grails: vytvoˇren´ı controlleru 1 ˜$ g r a i l s c r e a t e −c o n t r o l l e r H e l l o
64
V prostˇred´ı STS slouˇz´ı pro vytvoˇren´ı controlleru volba Grails Tools → Create Controller... v kontextov´em menu projektu. Vytvoˇren´ y controller je hol´a tˇr´ıda HelloController s jedinou akc´ı index, kter´ a je implicitn´ı akc´ı, pokud adresa neurˇcuje jinou, tj. je pouze ve tvaru /controller. Implicitn´ı akci lze d´ ale urˇcit promˇennou controlleru defaultAction. Zdrojov´ y k´od 49: Grails: controller 1 package t h e s i s 2
class HelloController {
3
// pokud by b y l o t r e b a d e f i n o v a t j i n o u i m p l i c i t n i a k c i :
4
// d e f d e f a u l t A c t i o n = ’ myAction ’
5
def index = {
6 }
7 8 }
Akce prozat´ım neobsahuje ˇz´ adnou logiku, pˇresto nelze ˇr´ıci, ˇze by nic nedˇelala. Implicitn´ı akc´ı, pokud nen´ı ˇreˇceno jinak54 , je renderov´an´ı odpovˇedi z GSP ˇsablony, kterou je dle konvenc´ı views/controllerName/actionName.gsp. Staˇc´ı tedy tento soubor vytvoˇrit
55
a jeho obsah se
pak zobraz´ı prohl´ıˇzeˇci jako v´ ysledn´ a str´anka. Podobnˇe jako v Tapestry 5 je spojena str´anka se svou TML ˇsablonou, je v Grails spojena akce controlleru a GSP ˇsablona.
5.4.1
Pˇ red´ av´ an´ı hodnot ˇ sablonˇ e
Jedn´ım ze z´ akladn´ıch u ´kol˚ u akc´ı controlleru je pˇred´avat data do pohledu, aby je tento mohl zobrazit. V Grails se tak m˚ uˇze d´ıt nˇekolika zp˚ usoby. Nejˇcastˇeji pouˇz´ıvan´ ym je vr´acen´ı mapy promˇenn´ ych z akce controlleru. Promˇenn´e pak jsou v pohledu pojmenov´any podle kl´ıˇce. Pokud akce mapu nevrac´ı, pˇredaj´ı se do pohledu promˇenn´e controlleru. Moˇzn´e je i pˇred´an´ı mapy funkci render(): Zdrojov´ y k´ od 50: Grails: pˇred´av´an´ı dat do pohledu 1 package t h e s i s 2
class HelloController {
3
List users 54
Napˇr´ıklad pˇresmˇerov´ an´ım pomoc´ı funkce redirect nebo renderov´ an´ım jin´e ˇsablony funkc´ı render(view:
"viewName"). 55 Napˇr. v STS pˇres volbu New → Other... → Groovy → Groovy Server Page (GSP).
65
def l i s t = {
4 5
// pokud n e n i v r a c e n a zadna mapa
6
u s e r s = User . g e t L i s t ( ) }
7 8
def display = {
9 10
// v r a c e n i mapy − l z e v y n e c h a t k l i c o v e s l o v o r e t u r n
11
[ u s e r s : User . g e t L i s t ( ) , s e l e c t e d U s e r : User . g e t ( params . i d ) ] }
12 13
d e f view = {
14 15
// p r e d a n i modelu f u n k c i r e n d e r
16
r e n d e r ( view : ’ d i s p l a y ’ , model : [ u s e r s : User . g e t L i s t ( ) ] ) }
17 18 }
Tento zp˚ usob je odliˇsn´ y od Tapestry 5, kter´e na jednu stranu nutilo definovat kaˇzdou promˇennou jako property str´ anky, na druhou stranu za to nab´ızelo automatick´ y binding hodnot napˇr´ıklad pˇri odesl´an´ı formul´ aˇre. V Grails jsou obˇe ˇcinnosti oddˇelen´e, do pohledu lze pˇredat libovoln´e hodnoty a data odeslan´ a z formul´ aˇre jsou dostupn´a v objektu params (viz 5.4.2), ze kter´eho se mus´ı zpracovat ruˇcnˇe.
5.4.2
Scope
V controllerech lze pracovat s nˇekolika objekty, kter´e jsou automaticky k dispozici od Spring IoC kontejneru a liˇs´ı se svou ˇzivotnost´ı mezi r˚ uzn´ ymi HTTP (Hypertext Transfer Protocol) requesty:
• servletContext - Neboli tak´e aplikaˇcn´ı scope, umoˇzn ˇuje sd´ılet stav napˇr´ıˇc celou webovou aplikac´ı. Je instanc´ı javax.servlet.ServletContext. • session - Session udrˇzuje stav komunikace s dan´ ym klientem, typicky na z´akladˇe cookies. Objekt session je instanc´ı HttpSession. • request - Objekt slouˇz´ıc´ı k uloˇzen´ı informac´ı pouze v r´amci jednoho requestu. Tento objekt je instance HttpServletRequest.
66
• params - Mapa parametr˚ u z HTTP requestu. Zde jsou uloˇzeny hodnoty z formul´aˇr˚ u nebo parametry namapovan´e z adresy. • flash - Objekt s ˇzivotnost´ı do pˇr´ıˇst´ıho requestu od stejn´eho klienta. Typicky slouˇz´ı k uloˇzen´ı chybov´ ych hl´ aˇsek a jejich zobrazen´ı po pˇresmˇerov´an´ı.
5.4.3
Interceptory
Grails definuje dva takzvan´e interceptory, beforeInterceptor a afterInterceptor, kter´e maj´ı za u ´kol prov´est nˇejakou ˇcinnost pˇred, resp. po proveden´ı kter´ekoli akce controlleru. Maj´ı k dispozici vˇsechno, co bˇeˇzn´e akce, druh´ y z nich nav´ıc i n´avratovou hodnotu proveden´e akce. Zdrojov´ y k´od 51: Grails: interceptory 1 package t h e s i s 2
class HelloController { def beforeInterceptor = {
3
p r i n t l n ” P r e p a r i n g t o e x e c u t e a c t i o n ${ a c t i o n U r i } ”
4 }
5 6
d e f a f t e r I n t e r c e p t o r = { model −>
7
p r i n t l n ” Tracing a c t i o n ${ a c t i o n U r i }”
8 }
9 10 }
Oba interceptory podporuj´ı i druh´ y zp˚ usob syntaxe, kter´ y se odkazuje na nˇekterou z akc´ı controlleru a umoˇzn ˇuj´ı jednoduˇse urˇcit, pro kter´e konkr´etn´ı akce je zavolat (seznam only) ˇci nezavolat (seznam except). Zdrojov´ y k´ od 52: Grails: interceptory jako odkaz na metodu 1 package t h e s i s 2
class HelloController {
3
d e f b e f o r e I n t e r c e p t o r = [ a c t i o n : t h i s .& auth , e x c e p t : ’ l o g i n ’ ]
4
d e f a f t e r I n t e r c e p t o r = [ a c t i o n : t h i s .& auth , o n l y : ’ s e c u r e ’ ]
5 6
// metoda − n e n i akce , t j . n e l z e na n i namapovat a d r e s u
7
d e f auth ( ) { . . . } 67
8 // u z a v e r y − j s o u a k c e
9 10
def login = { . . . }
11
def secure = { . . . }
12 }
5.4.4
Pˇ resmˇ erov´ an´ı
V´ ysledkem akce m˚ uˇze b´ yt tak´e pˇresmˇerov´an´ı, at’ uˇz na jinou akci, nebo libovolnou URL. K pˇresmˇerov´ an´ı slouˇz´ı funkce redirect, kter´a m´a nˇekolik zp˚ usob˚ u pouˇzit´ı v z´avislosti na tom, kam se m´ a pˇresmˇerovat. Zdrojov´ y k´od 53: Grails: pˇresmˇerov´an´ı 1
r e d i r e c t ( a c t i o n : ’ myAction ’ ) // j i n o u a k c i s t e j n e h o c o n t r o l l e r u
2
r e d i r e c t ( c o n t r o l l e r : ’ o t h e r ’ , a c t i o n : ’ a c t i o n ’ ) // . . . j i n e h o
3
r e d i r e c t ( u r i : ’ / page . html ’ ) // a d r e s a r e l a t i v n e k p r o j e k t u
4
r e d i r e c t ( u r l : ’ h t t p : / /www. g r a i l s . o r g ’ ) // a b s o l u t n i a d r e s a
5 // p r e d a n i parametru 6
r e d i r e c t ( a c t i o n : ’ myAction ’ , params : [ f o o : ’ bar ’ ] )
7 //#S e c t i o n 1 na k o n c i a d r e s y 8
r e d i r e c t ( a c t i o n : ’ myAction ’ , fragment : ’ S e c t i o n 1 ’ )
5.4.5
Sluˇ zby
Pro zapouzdˇren´ı opakuj´ıc´ı se logiky podle DRY (Don’t Repeat Yourself) principu slouˇz´ı sluˇzby a jejich injekce na m´ısta, kde se pouˇz´ıvaj´ı56 . Sluˇzby pak IoC kontejner do controller˚ u ˇci jin´ ych sluˇzeb injektuje na z´ akladˇe jmenn´e konvence. Sluˇzba je opˇet hol´ a tˇr´ıda, kterou lze vytvoˇrit ruˇcnˇe, pˇr´ıpadnˇe automatizovanˇe vˇcetnˇe test˚ u v prostˇred´ı STS volbou Grails Tools → Create Service..., kter´a na pozad´ı spouˇst´ı pˇr´ıkaz se zadan´ ym n´ azvem sluˇzby: Zdrojov´ y k´od 54: Grails: vytvoˇren´ı sluˇzby 56
Podobnˇe jako v Tapestry 5, srovnejte s kapitolou 4.10.
68
1 ˜$ g r a i l s c r e a t e −s e r v i c e h e l l o
Pˇr´ıkaz vytvoˇr´ı pr´ azdnou sluˇzbu, ve kter´e potom m˚ uˇzeme implementovat poˇzadovan´e metody: Zdrojov´ y k´od 55: Grails: sluˇzba 1 package t h e s i s 2 3
class HelloService { S t r i n g s a y H e l l o ( ) { ” H e l l o World” }
4 5 }
Injekce prob´ıh´ a na z´ akladˇe n´ azvu promˇenn´e, staˇc´ı definovat promˇennou controlleru, kter´ a se jmenuje stejnˇe jako sluˇzba, pouze s mal´ ym p´ısmenem na zaˇc´atku. Pokud jsou prvn´ı dvˇe p´ısmena n´azvu promˇenn´e velk´ a, hled´ a se pro injekci sluˇzba odpov´ıdaj´ıc´ı pˇresnˇe jej´ımu n´azvu, coˇz u ´st´ı v ˇcitelnˇejˇs´ı z´ apis v pˇr´ıpadˇe, ˇze n´ azev sluˇzby zaˇc´ın´a zkratkou. Zdrojov´ y k´ od 56: Grails: injekce sluˇzby do controlleru 1 package t h e s i s 2
class HelloController {
3
d e f h e l l o S e r v i c e // s l u z b a H e l l o S e r v i c e
4
d e f JMSService // s l u z b a JMSService
5
def index = {
6
[ greeting : helloService . sayHello () ] }
7 8 }
Podle dokumentace je moˇzn´e i injektovat m´ısto implementace sluˇzby jej´ı interface, k tomu je vˇsak nutn´e ponoˇrit se hloubˇeji a zas´ ahnout do konfiguraˇcn´ıho souboru Spring frameworku a sv´ azat interface s jeho implementac´ı prostˇrednictv´ım definice Spring beany. Postup je tak podobn´ y Tapestry 5 v kapitole 4.7.3.
5.5
Pohled (View) - GSP
Technologie pouˇzit´ a pro zobrazovac´ı logiku se jmenuje GSP. V mnoh´em pˇripom´ın´a JSP, velmi podobn´a je i TML v Tapestry 5 z kapitoly 4.8, protoˇze se opˇet jedn´a o smˇes HTML tag˚ u, 69
speci´aln´ıch XML tag˚ u a v´ yraz˚ u ohraniˇcen´ ych ${ a }. V´ yhodou Grails v´ yraz˚ u oproti Tapestry5 je to, ˇze nam´ısto speci´ aln´ı expanze jsou v´ yrazy zapisov´any pˇr´ımo v Groovy, nˇekter´a usnadnˇen´ı a datov´e typy jsou zabudov´ ana pˇr´ımo do jazyka (viz Kapitola 5.2), takˇze poskytuj´ı mnohem vˇetˇs´ı volnost z´apisu. Pohled m˚ uˇze pracovat s promˇenn´ ymi, kter´e mu pˇred´a controller. Pohled pro akci z pˇr´ıkladu 56 by tak mˇel pˇr´ıstup k promˇenn´e ${greeting}: Zdrojov´ y k´od 57: Grails: pohled 1 2
${ g r e e t i n g }
${ g r e e t i n g }