Internetové technologie na platformě JAVA. Miroslav Hrúz



Podobné dokumenty
Spring framework 2.0. Roman Pichlík CZJUG

Enterprise Java (BI-EJA) Technologie programování v jazyku Java (X36TJV)

KIV/PIA 2013 Jan Tichava

Nástroje a frameworky pro automatizovaný vývoj. Jaroslav Žáček jaroslav.zacek@osu.cz

Servlety a JSP. Petr Adámek, petr.adamek@ibacz.eu

PA165: Úvod do Java EE. Petr Adámek

Technology Entry form Entry up-to-date? Internal links Faulty internal Possible internal links

Tvorba informačních systémů

Semináˇr Java X J2EE Semináˇr Java X p.1/23

(Enterprise) JavaBeans. Lekce 7

1. Distribuce Javy. 2. Vlastnosti J2EE aplikace. 3. Fyzická architektura J2EE aplikace. Distribuce Javy se liší podle jejího zamýšleného použití:

Další vlastnosti Springu Moduly Springu. Spring Framework. Pavel Mička. Pavel Mička Spring Framework 1/18

Web Services na SOAP

Tvorba informačních systémů

Tvorba podnikových aplikací v jazyce JAVA. Josef Pavlíček KII PEF CZU

UJO Framework. revoluční architektura beans. verze

Architektury informačních systémů

Vybrané partie z jazyka Java Spring a Enterprise JavaBeans (EJB)

NOVINKY V JEE EJB 3.1. Zdeněk Troníček Fakulta informačních technologií ČVUT v Praze

Architektury informačních systémů

Úvod. Petr Aubrecht (CA) Martin Ptáček (Wincor Nixdorf) Je 10 typů lidí: ti, kteří znají binární kód, a ti, kteří ne.

Obsah přednášky. Představení webu ASP.NET frameworky Relační databáze Objektově-relační mapování Entity framework

PHP framework Nette. Kapitola Úvod. 1.2 Architektura Nette

Tvorba informačních systémů

Platformy / technologie. Jaroslav Žáček

Platformy / technologie. Jaroslav Žáček jaroslav.zacek@osu.cz

PLATFORMY / TECHNOLOGIE JAROSLAV ŽÁČEK

X33EJA Enterprise Java

NetBeans platforma. Evropský sociální fond Praha & EU: Investujeme do vaší budoucnosti

Enterprise Java Beans 3.0

Technologie Java Enterprise Edition. Přemek Brada, KIV ZČU

<Insert Picture Here> Vývoj portálových řešení v Javě

public static void main(string[] args) { System.out.println(new Main().getClass().getAnnotation(Greet.class).text());

2012 ET NETERA a.s. Wicket přehled technologie Martin Strejc

Softwarové komponenty a Internet

Základy Guice Vazby Scopes. Google Guice. základní seznámení s frameworkem Google Guice

Tvorba informačních systémů

Elektronická podpora výuky předmětu Komprese dat

Spring Framework Handout

Návrhové vzory Tvorba objektů

Databázové a informační systémy

X36WWW. Technologie aplikačních serverů. Miroslav Bureš,, Martin Klíma. X36WWW: 12. přednáška 1

Tvorba informačních systémů

Úvod do problematiky vývoje Vývoj informačních systémů

Tvorba informačních systémů

E LEARNINGOVÁ WEBOVÁ APLIKACE PRO VÝUKU BIOMEDICÍNSKÉHO INŽENÝRSTVÍ Petr Huňka

Michal Krátký, Miroslav Beneš

Ing. Přemysl Brada, MSc., Ph.D. Ing. Martin Dostal. Katedra informatiky a výpočetní techniky, FAV, ZČU v Plzni

Systémová administrace portálu Liferay

Podpora aplikační logiky v J2EE aplikačních rámcích

KAPITOLA 3. Architektura aplikací na frameworku Rails. V této kapitole: modely, pohledy, řadiče.

Vývoj informačních systémů. Architektura, návrh Vzory: Doménová logika

Zabezpečení webové vrstvy a EJB projektu Část nastavení specifická pro Glassfish, část dána Java EE

Google Web Toolkit. Martin Šurkovský, SUR března Katedra informatiky

X33EJA Web Services. Martin Ptáček, KOMIX s.r.o.

Stručný úvod pro programátory. Michal Kuchta

Multiplatformní osobní organizér v jazyce Java

Java Server-side. Štěpán Kuchař. VŠB-TUO FEI Katedra informatiky

MATURITNÍ OTÁZKY ELEKTROTECHNIKA - POČÍTAČOVÉ SYSTÉMY 2003/2004 PROGRAMOVÉ VYBAVENÍ POČÍTAČŮ

Platforma J2EE. Lukáš Zapletal liberix.cz. Platforma Java 2 Enterprise Edition vývoj webových aplikací

Bridge. Známý jako. Účel. Použitelnost. Handle/Body

Technologie Java. Jaroslav Žáček

3. Je defenzivní programování technikou skrývání implementace? Vyberte jednu z nabízených možností: Pravda Nepravda

Komponentově orientované webové frameworky. Jiří Stránský twitter.com/jistr

Enterprise Java (BI-EJA) Technologie programování v jazyku Java (X36TJV)

Snadný vývoj webových aplikací s Nette. Lukáš Jelínek

TÉMATICKÝ OKRUH Softwarové inženýrství

Architektura softwarových systémů

Platforma J2EE. Lukáš Zapletal liberix.cz. Platforma Java 2 Enterprise Edition

Obsah přednášky. Technologie. Enterprise Java Beans. Enterprise Java Beans. EJB kontejner. Enterprise Java Beans (EJB)

KIV/PIA Semestrální práce

Webové služby a XML. Obsah přednášky. Co jsou to webové služby. Co jsou to webové služby. Webové služby a XML

Statické proměnné a metody. Tomáš Pitner, upravil Marek Šabo

Ruby on Rails. Bc. Tomáš Juřík Bc. Bára Huňková

1 Webový server, instalace PHP a MySQL 13

Vývoj informačních systémů. Architektura, návrh Vzory: Doménová logika

Komponentní technologie

Jalapeño: pekelně ostrá Java persistence v Caché. Daniel Kutáč Senior Sales Engineer

Návrhové vzory. Jakub Klemsa, Jan Legerský. 30. října Objektově orientované programování.

OMO. 4 - Creational design patterns A. Singleton Simple Factory Factory Method Abstract Factory Prototype Builder IoC

Spring portfolio. Tomáš Krátký

Tvorba informačních systémů

Architektura aplikace

Třídy a objekty. Třídy a objekty. Vytvoření instance třídy. Přístup k atributům a metodám objektu. $z = new Zlomek(3, 5);

Anotace a Hibernate. Aleš Nosek Ondřej Vadinský Daniel Krátký

Obsah přednášky 7. Základy programování (IZAPR) Přednáška 7. Parametry metod. Parametry, argumenty. Parametry metod.

Databáze EMS podacích lístků

GTL GENERATOR NÁSTROJ PRO GENEROVÁNÍ OBJEKTŮ OBJEKTY PRO INFORMATICA POWERCENTER. váš partner na cestě od dat k informacím

Session Beans. Petr Aubrecht CA. Vtipy budou tentokrát o krizi:

Základy objektové orientace I. Únor 2010

Využití OOP v praxi -- Knihovna PHP -- Interval.cz

Databázové aplikace pro internetové prostředí PHP úvod, základní princip, vkládání skriptu, komentáře, výpis na obrazovku

Použití databází na Webu

Úvod do Web Services

Úvod do Groovy pro Java experty

1. Webový server, instalace PHP a MySQL 13

Analýza a Návrh. Analýza

Vývoj informačních systémů. Přehled témat a úkolů

Java a Caché IV: Manipulace s objekty

Technologie JavaBeans

Transkript:

České vysoké učení technické v Praze Fakulta elektrotechnická ČVUT FEL katedra počítačů Bakalářská práce Internetové technologie na platformě JAVA Miroslav Hrúz Vedoucí práce: Ing. Andrej Zachar Studijní program: Elektrotechnika a informatika strukturované bakalářské Obor: Informatika a výpočetní technika srpen 2007

ii

Poděkování Chtěl bych poděkovat firmě SimpleWay s.r.o., kde jsem měl tu možnost seznámit se s technologiemi, které popisuji ve svojí bakalářské práci. iii

iv

Prohlášení Prohlašuji, že jsem svou bakalářskou práci vypracoval samostatně a použil jsem pouze podklady uvedené v přiloženém seznamu. Nemám závažný důvod proti užití tohoto školního díla ve smyslu 60 Zákona č. 121/2000 Sb., o právu autorském, o právech souvisejících s právem autorským a o změně některých zákonů (autorský zákon). V Praze dne 21.8. 2007............................................................. v

vi

Abstract The goal of this bachalor thesis is to show possibilities of the Java platform for building web applications. Content of this paper is from on piece a recherche and from other piece an implementation. In the beginning I make the reader acquainted with technologies like Java EE, Spring framework and Hibernate ORM. In the next section I show the principles of Extreme programming and Test-Driven development. In the last section I apply knowledges of foregoing parts to the practical project, to the portal for seeking roommates. I show illuminating apply of Extreme programming in the real life. Abstrakt Cílem této bakalářské práce je ukázat možnosti JAVA platformy pro tvorbu webových aplikací. Obsah díla je z části rešeršní, z části implementační. V úvodu seznamuji čtenáře s technologiemi jako Java EE, Spring framework a Hibernate ORM. V další části ukazuji principy Extrémního programování a Testem řízeného vývoje. V poslední části aplikuji teoretické znalosti z předchozího textu na praktickém projektu, portálu pro hledání spolubydlících. Ukazuji názornou aplikaci Extrémního programování v každodenním životě. vii

viii

Obsah Seznam obrázků xiii 1 Úvod 1 1.1 Nároky a technická obtížnost textu......................... 1 1.2 Typografická úprava a členění textu........................ 1 2 Rešerše 3 2.1 Java EE........................................ 3 2.1.1 Vícevrstvá architektura (N-tier architecture)............... 3 2.1.2 Koncept kontejneru............................. 3 2.1.3 Aplikační servery............................... 3 2.1.3.1 Servletové kontejnery....................... 4 2.1.3.2 Java EE aplikační servery..................... 4 2.1.4 Výběr technologií............................... 4 2.2 Spring framework................................... 4 2.2.1 Aplikační framework............................. 4 2.2.2 Historie.................................... 4 2.2.3 Hlavní přednosti............................... 5 2.2.4 Moduly.................................... 5 2.2.5 Inversion of Control............................. 6 2.2.5.1 Dependecy lookup......................... 7 2.2.5.2 Dependecy injection........................ 7 2.2.6 Rozhraní BeanFactory a ApplicationContext............... 8 2.2.6.1 BeanFactory............................ 8 2.2.6.2 Životnost beany.......................... 9 2.2.6.3 Typové konverze.......................... 11 2.2.6.4 Autowiring............................. 11 2.2.6.5 ApplicationContext........................ 12 2.2.7 Spring Web MVC.............................. 12 2.2.7.1 Návrhový vzor MVC....................... 12 2.2.7.2 Rozdělení webových frameworků................. 14 2.2.7.3 Architektura............................ 14 2.2.7.4 Dispacher servlet.......................... 16 2.2.7.5 Webové scopy........................... 17 2.2.8 Spring Web Flow............................... 18 2.2.8.1 Struktura.............................. 18 2.2.8.2 Stavy................................ 18 2.2.8.3 Výhody............................... 19 2.2.8.4 Nevýhody.............................. 19 2.2.8.5 Scope................................ 19 2.2.8.6 Syntax............................... 20 2.2.8.7 Konfigurace............................. 22 2.3 Hibernate....................................... 22 2.3.1 ORM framework............................... 22 2.3.2 JPA...................................... 23 2.3.3 Mapování................................... 23 2.3.4 Anotace.................................... 24 2.3.5 Práce s objekty................................ 24 ix

2.3.6 Dotazy.................................... 25 2.3.6.1 HQL API.............................. 25 2.3.6.2 Criteria API............................ 25 2.3.7 Lazy, Eager loading............................. 26 2.3.8 Integrace se Springem............................ 26 2.3.8.1 Deklarativní transakce....................... 26 2.4 Extrémní programování............................... 27 2.4.1 Historie.................................... 27 2.4.2 Role...................................... 27 2.4.3 Základní postupy............................... 28 2.4.3.1 Plánovací hra............................ 28 2.4.3.2 Malé iterace............................ 28 2.4.3.3 Metafora.............................. 28 2.4.3.4 Testování.............................. 29 2.4.3.5 Jednoduchý návrh......................... 29 2.4.3.6 Refaktorování........................... 29 2.4.3.7 Párové programování....................... 29 2.4.3.8 Kolektivní vlastnictví kódu.................... 29 2.4.3.9 40-ti hodinový pracovní týden.................. 29 2.4.3.10 Zákazník na správném místě (On-site customer)........ 30 2.4.3.11 Standardní podoba kódu..................... 30 2.4.3.12 Sjednocené pracovní prostředí.................. 30 2.5 Testovací framework JUnit............................. 30 2.5.1 JUnit 3.x................................... 30 2.5.1.1 Architektura............................ 30 2.5.1.2 Assert................................ 30 2.5.1.3 Integrace s IDE.......................... 31 2.5.2 JUnit 4.x................................... 31 2.5.2.1 Hlavní změny oproti 3.x...................... 31 2.5.2.2 assertthat............................. 31 2.5.2.3 Předpoklady a teorie....................... 32 2.6 Testovací framework JMock............................. 32 2.6.1 Mockování, Mock objekty.......................... 32 2.6.2 Architektura................................. 33 2.6.3 Příklad.................................... 33 3 Implementace 35 3.1 Zadání......................................... 35 3.2 Analýza........................................ 35 3.2.1 Co už je naimplementováno?........................ 35 3.2.2 Průzkum trhu................................. 35 3.2.3 Prototypy................................... 36 3.3 Implementace..................................... 36 3.3.1 Iterace 1.................................... 36 3.3.2 Iterace 2.................................... 44 3.3.3 Iterace 3.................................... 44 3.3.4 Iterace 4.................................... 53 4 Zhodnocení 59 4.1 Shrnutí........................................ 59 4.2 Možnosti rozšíření.................................. 59 x

4.3 Osobní zkušenosti.................................. 59 5 Obsah přiloženého CD 61 6 Literatura 63 7 Seznam použitých zkratek 65 xi

xii

Seznam obrázků 2.1 Kontext Java EE technologií, zdroj: [6]....................... 3 2.2 Spring framework, zdroj: [13]............................ 5 2.3 Princip IoC, zdroj: [13]................................ 6 2.4 Návrhový vzor MVC, zdroj: [15].......................... 13 2.5 MVC implementace JSP Model 2, zdroj: [1].................... 13 2.6 Architektura aplikace ve Spring MVC, zdroj: [20]................. 14 2.7 Stavy objektu a přechody pomocí metod persistent manageru, zdroj: [17]... 25 2.8 Průběh vývoje v XP................................. 28 3.1 Základní UI prototyp................................. 36 3.2 Vkládání nového inzerátu.............................. 37 3.3 Validace položky................................... 43 3.4 Nový inzerát více lokalit............................... 45 3.5 Hledání v poptávkách................................ 48 xiii

xiv

KAPITOLA 1. ÚVOD 1 1 Úvod Internet se v dnešní době stal nepostradatelnou záležitostí, můžeme ho využívat různými způsoby a vydolovaných informací je více než dost. Je to v dnešní době, stále, nejperspektivnější reklamní médium na světě. Zákazníků, přejících si mít na internetu svoji prezentaci stále přibývá. Není proto od věci se seznámit s technologiemi použitými pro vývoj internetových aplikací. Tato práce pojednává o tvorbě rozsáhlejších aplikací na platformě JAVA. JAVA spolu s technologiemi.net a Ruby on rails vede žebříčky statistik použitých platforem [12] a pokud si zvolíme vhodnou metodiku vývoje, aplikace nám roste pod rukama velice rychle. 1.1 Nároky a technická obtížnost textu Práce by měla sloužit jako studijní materiál všem, kteří mají zájem vyvíjet internetové aplikace na platformě Java. Předpokládám proto patřičnou znalost tohoto jazyka. Je dobře, pokud má čtenář znalost vývoje webových aplikací na jiné platformě (například s PHP). Na škodu nejsou zkušenosti s vývojem pro Java EE, znalost tvorby JSP stránek nebo JPA, plně postačuje absolvování předmětu X36TJV - Technologie programování v jazyku Java, vyučovaného u nás na fakultě. 1.2 Typografická úprava a členění textu Veškerý text je psán pomocí nástroje L A TEX, s použitím připravené šablony, kterou poskytuje katedra. Text je členěn hierarchicky do kapitol, sekcí a podsekcí. Pro lepší čitelnost a orientaci v textu budu veškerý kód psát takto, pokud budu v textu hovořit o rozhraních, zapisuji je takto. Třídy a metody zapisuji takto. Práce je psána v češtině, ačkoliv je IT odvětví charakteristické všemožnými anglickými termíny, tam, kde to lze, jsem použil jejich český ekvivalent s originálním zněním v závorkách.

2 KAPITOLA 1. ÚVOD

KAPITOLA 2. REŠERŠE 3 2 Rešerše 2.1 Java EE Java Enterprice Edition je platforma určená pro vývoj byznys aplikací. Stávající specifikace Java EE 5 definuje řadu technologií a API potřebných pro vývoj rozsáhlých systémů. Dříve se platforma označovala zkratkou J2EE, z marketingových důvodů, stejně jako JRE 1.5 se označuje Java 5, se přejmenovala na Java EE. Aktuálně je celé JVM opensourceováno a Javě nic nestojí v cestě stát se nejpoužívanější platformou od mobilních telefonů po velké byznys aplikace. Kromě standardních API jsou k dispozici stovky opensourceových knihoven, frameworků a projektů. Nejdříve se seznámíme se základy. Obrázek 2.1: Kontext Java EE technologií, zdroj: [6] 2.1.1 Vícevrstvá architektura (N-tier architecture) Architektura byznys aplikace v Java EE se typicky skládá z částí, jež ukazuje obrázek 2.1. Vždy se jedná o model klient/server [2], resp. request/response, serverová část se skládá z webového kontejneru, doplněného v případě použití specifikace EJB o EJB kontejner, dále jakéhokoliv perzistentního datového úložiště (představme si například klasickou relační databázi) a nějakého klienta, v našem případě webového prohlížeče. 2.1.2 Koncept kontejneru Kontejner je takový softwarový objekt, který je alokován uvnitř daného aplikačního serveru nebo aplikačního frameworku. Zodpovídá za přidělování zdrojů daným komponentám. Řídí životní cyklus objektů. Někdy se pojmy jako framework a kontejner záměrně zaměňují, např. EJB a EJB kontejner, Spring a Spring kontejner. 2.1.3 Aplikační servery Aplikační server je jádrem Java EE technologie. Podle počtu implementovaných specifikací je můžeme rozdělit do dvou skupin

4 KAPITOLA 2. REŠERŠE 2.1.3.1 Servletové kontejnery Implementují pouze webový kontejner a technologie v něm dostupné, viz 2.1. Jeho nasazení je vhodné obecně pro menší a střední aplikace. Cílem mojí práce je ukázat, že i bez těžkotonážního kanónu jménem EJB jsme schopni vytvořit robustní aplikaci přesně podle našich představ. Mezi zástupce této kategorie patří Apache Tomcat - opensource projekt vydaný pod Apache licencí, nejběžnější a nejdostupnější vůbec. Jetty - opensource, webový server pro statický a dynamický obsah, optimalizace pro výkon. 2.1.3.2 Java EE aplikační servery stacku. Narozdíl od předchozí kategorie, Java EE AS implementují plnou specifikaci z Java EE GlassFish (Sun Java AS) - opensource řešení od Sun Microsystems, referenční implementace JBoss AS - opensource IBM Websphere AS - komerční, vlastní implementace JVM BEA WebLogic AS - komerční 2.1.4 Výběr technologií Při výběru aplikačního serveru musíme zvážit, co daný projekt opravdu potřebuje, jaký používáme aplikační framework, jaký ORM nástroj nebo jaké další API jsou nezbytné, popřípadě jaké používáme IDE. V zásadě bychom měli zvolit jednoho dodavatele řešení a nekombinovat dodavatele JVM, AS, frameworku a dalších API a knihoven nebo zvolit takovou kombinaci, která je odzkoušená a bezproblémová; například Sun JVM, Glassfish AS, JSF, EJB, Toplink Essentials a NetBeans IDE, vše pěkně standardní nebo v našem případě Sun JVM, Apache Tomcat, Spring framework, Spring Web MVC a WebFlow, Hibernate a Eclipse IDE. 2.2 Spring framework 2.2.1 Aplikační framework Aplikace se dnes netvoří celé od základů, spíše se podobají stavebnicím. Proč bychom měli znovu objevovat kolo, když už ho někdo před námi vymyslel a funguje dobře. Framework je softwarový systém, který nám pomáhá řešit nejčastější problémy při implementaci, měl by zrychlovat a usnadňovat vlastní vývoj, řídit životní cyklus aplikace a pomáhat oddělit nízkoúrovňový kód od vlastní aplikační logiky daného zadání. 2.2.2 Historie Odlehčený J2EE framework Spring vznikl původně jako demo aplikace knihy Roda Johnsonna: Expert One-to-One: J2EE design and development z roku 2002, která ukázala v době EJB 2.0, že lze v J2EE programovat také jednoduše. Později, roku 2003 byl založen opensource projekt na portálu sourceforge.net, který vycházel z původního kódu a postupně se stal mezi vývojáři velmi populární. Dnes je Spring ve stabilní verzi 2.0, čas ukázal, že koncept,

KAPITOLA 2. REŠERŠE 5 který Rod Johnsonn navrhl je správný. Stávající Java EE 5 se velmi Springem inspirovala a budoucí specifikace Java EE 6 se plánuje Springu přiblížit ještě více. 2.2.3 Hlavní přednosti Snazší a příjemnější práce s J2EE, neinvazivnost, nenutí používat nic, co právě nepotřebujeme, objektově orientovaný návrh je důležitější než jakákoliv implementační technologie, JavaBeans jako silný konfigurační nástroj, testování je zásadní, Spring dělá kód snadněji testovatelný, modularita, umožňuje zvolit jen ty komponenty, které potřebujeme, usnadňuje práci s dalšími frameworky, použití jako sjednocující přístup rozličných technologií a implementací, usnadňuje práci s vyjímkami, kdy je zaobaluje do lépe čitelných. Obrázek 2.2: Spring framework, zdroj: [13] 2.2.4 Moduly Důležitým aspektem je, že Spring lze použít i na servletovém kontejneru, dokonce i čistě s Java SE. Modulárnost je také docílena tím, že se skládá z více.jar archivů, základních i volitelných, přičemž si vybereme, co z něj chceme použít. Spring Core - hlavní jádro frameworku, jediný povinný modul, metodika Inversion of Control, rozhraní BeanFactory Spring DAO - abstrakce a zjednodušení práce s JDBC

6 KAPITOLA 2. REŠERŠE Spring ORM - integrace s ORM frameworky, vlastní implementace perzistentního API i na JRE 1.4 bez JPA Spring Web - integrace s webovými frameworky jako JSF, Struts2, Velocity, vlastní implementace webového frameworku Spring Web MVC Spring AOP - podpora aspektově orientovaného programování Spring J2EE - podpora pro EJB, JMX, JMS, web service 2.2.5 Inversion of Control Návrhový vzor IoC je založen na tzv. Hollywoodském principu: Nevolejte mi, já zavolám vám. [5]. Aplikace se vzdává odpovědnosti za vytváření a nastavení instancí ve prospěch frameworku, resp. jeho IoC kontejneru. Jedná se o stěžejní vlastnost, proto ji ukážu na příkladu. Obrázek 2.3: Princip IoC, zdroj: [13] Zapíšeme třídu SampleContoller dvěma způsoby, jednak klasicky a jednak s využitím techniky IoC. SampleContollerWithoutIoC.java public class SampleContollerWithoutIoC implements org.springframework.web.servlet.mvc.controller { public ModelAndView handlerequest(httpservletrequest request, HttpServletResponse response) throws Exception { Connection connection = DatabaseUtils.getConnection(); UserDAO dao = DAOFactory.createUserDAO("hibernate", connection); List users = dao.getusers(); DatabaseUtils.closeConnection(conn); return new ModelAndView("userList", "users", users); SampleContollerWithIoC.java public class SampleContollerWithIoC implements org.springframework.web.servlet.mvc.controller { private UserDAO dao = null; public void setuserdao(userdao userdao) { this.dao = userdao; public ModelAndView handlerequest(httpservletrequest request, HttpServletResponse response) throws Exception { List users = dao.getusers();

KAPITOLA 2. REŠERŠE 7 return new ModelAndView("userList", "users", users); action-servlet.xml <?xml version="1.0" encoding="utf-8"?> <beans> <bean id="samplecontroller" class="samplecontollerwithioc"> <property name="userdao" ref="userdao"/> </bean> </beans> Ve třídě SampleContollerWithoutIoC jsme ručně nastavovali komponentu dao. Ve třídě SampleContollerWithIoC jsme ji dostali již nakonfigurovanou. Představme si příklad v kontextu reálného života, komponentu dao využívají desítky tříd. Co by se stalo, kdybychom byli nuceni změnit rozhraní tovární metody createuserdao? Museli bychom změnit i implementaci v desítkách tříd, které dao používají, což odporuje první zásadě OOP: Přidávej vlastnost jen na jednom místě!. 1 Účel souboru action-servlet.xml a vlastní konfigurace bean, jak vidíme v příkladu, řeším v kapitole 2.2.6. 2.2.5.1 Dependecy lookup Návrhový vzor IoC můžeme rozdělit do dvou technik, první z nich je dependecy lookup. Je to návrhový vzor, pomocí něhož objekt žádá kontejner o beanu. Toto řešení bylo použito v EJB 2.X v technologii JNDI, kdy požadovaná beana musela implementovat API specifické pro daný kontejner. Evoluce ukázala, že toto není nejvhodnější řešení. Spring jej používá pro získání beany z ruky. XmlBeanFactory beanfactory = new XmlBeanFactory("action-servlet.xml"); DemandService demandservice = (DemandService) beanfactory.getbean("demandservice"); 2.2.5.2 Dependecy injection Druhou technikou IoC je návrhový vzor dependecy injection, který řeší samotné nastavení a nainjektování potřebných objektů a jejich závislostí. Vlastní vložení závislostí může probíhat pomocí Setter injection - Nainjektování závislostí pomocí JavaBeans setterů. Příklad je uveden v kapitole 2.2.5. Constructor injection - Nainjektování závislostí pomocí konstruktoru. public class SampleContollerWithIoC implements Controller { private UserDAO dao = null; public SampleContollerWithIoC(UserDAO userdao) { this.dao = userdao; public ModelAndView handlerequest(httpservletrequest request, HttpServletResponse response) throws Exception { 1 V takto jednoduchém příkladu to samozřejmě lze obejít, vývojář komponenty dao by byl nucen provést změnu s ohledem na kompatibilitu, každopádně je to problém, do kterého se nemusíme dostat.

8 KAPITOLA 2. REŠERŠE List users = dao.getusers(); return new ModelAndView("userList", "users", users); action-servlet.xml <bean id="samplecontroller" class="samplecontollerwithioc"> <constructor-arg ref="userdao"/> </bean> Method injection - Použití pro speciální případy, pro netriviálnost zde neuvedu příklad. 2 Mezi další typ dependecy injection, který Spring avšak nepodporuje, patří Interface injection, na kterém je založen kontejner frameworku Avalon. Nejpoužívanější je metoda Setter injection, nejčastěji z těchto důvodů: je jednodušší pracovat s defaultními hodnotami properties daného objektu, pomocí getteru získáme okamžitě hodnotu dané property, settery mohou být v případě potřeby volány vícekrát, což konstruktor být nemůže, gettery/settery jsou zděděny na rozdíl od konstruktorů jako klasické metody. 2.2.6 Rozhraní BeanFactory a ApplicationContext 2.2.6.1 BeanFactory BeanFactory je ústřední částí celého frameworku, řídí životní cyklus, konfiguraci a vlastní injektaci všech bean. Kontejner startuje podle nasazení aplikace, např. na aplikačním serveru pomocí definice v deployment deskriptoru web.xml nebo v JUnit testovací sadě pomocí připravených startovacích API, můžeme ho také samozřejmě nainicializovat ručně, jak jsme viděli v kapitole 2.2.5.1. Manageovaný objekt může být jakýkoliv, v této souvislosti se mluví o tzv. POJO, což v překladu znamená starý dobrý java objekt. Je to jakýkoliv objekt, který není nucen dodržovat implementační omezení dané platformy. Vlastní konfigurace vzájemných vztahů bean můžeme definovat pomocí: XML - nejčastější a nejpřehlednější zápis, odděluje konfiguraci od vlastního použití, anotací - podobně jako EJB, je konfigurace zapsána v POJO, JavaBean properties, Jakarta Commons atributes. Pokud využíváme XML konfigurace, máme minimálně jeden kořenový konfigurační soubor, nazveme jej např. applicationcontext.xml, na který ve webovém nasazení ukazuje depoloyment descriptor. web.xml 2 Pokud chceme nainjektovat beany s různými scopy (viz. 2.2.6.2), nevystačíme si s setter injection, čtenáře odkazuji na referenční dokumentaci Springu [13].

KAPITOLA 2. REŠERŠE 9 <?xml version="1.0" encoding="utf-8"?> <web-app> <!-- Context Configuration locations for Spring XML files --> <context-param> <param-name>contextconfiglocation</param-name> <param-value>/web-inf/applicationcontext.xml</param-value> </context-param> <!-- Base dispacher s servlet mapping --> <servlet> <servlet-name>action</servlet-name> <servlet-class>org.springframework.web.servlet.dispatcherservlet</servlet-class> <init-param> <param-name>contextconfiglocation</param-name> <param-value>/web-inf/action-servlet*.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.html</url-pattern> </servlet-mapping> </web-app> Kromě kořenového aplikačního kontextu 3 nadefinujeme servlet, který se vždy stará o jeden typ požadavků (v našem případě o vše s příponou.html), které zpracovává DispacherServlet. Podrobněji je tomu věnována kapitola 2.2.7.4. Jelikož budu mluvit o jedné jediné konfiguraci, budu ApplicationContext.xml a action-servlet.xml vědomě zaměňovat. Víme, kam zapsat XML konfigurace, aby se automaticky načetly, podíváme se ted na základní syntaxi. Hodnotu do property dané beany můžeme zapsat bud to rovnou, <?xml version="1.0" encoding="utf-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> <bean id="bean" class="samplebean"> <property name="property" value="value"/> </bean> </beans> nebo odkazem na jinou beanu. <bean id="bean" class="samplebean"> <property name="property" ref="bean2"/> </bean> <bean id="bean2" class="samplebean2" /> 2.2.6.2 Životnost beany výraz. 3 Nic nám nebrání mít kořenových konfiguračních souborů více, v tagu <param-value/> může být regulární

10 KAPITOLA 2. REŠERŠE Každá beana má z hlediska konverze IoC kontejneru s klientem svoji životnost (obor viditelnosti), které říkáme scope. Kromě definice závislostí beany, Spring jednoduše dovoluje si zvolit i její scope. Od verze 2.0 můžeme vytvářet beany 5ti (resp. 6ti) scopů. sigleton - existuje jen jedna instance, která se vytvoří při první injekci, u dalších se injektuje tato, prototype - pro každou injektaci se vytvoří nová instance, request - beana platí po dobu HTTP requestu, 4 session - beana platí po dobu HTTP session, global session - beana platí po dobu HTTP global session, custom - pokud potřebujeme nestandardní řešení, Spring dovoluje definovat vlastní. prototype Defaultně se vždy použije singleton. Je to logické, ve většině případů nás stav beany nezajímá a plně si s tím vystačíme, pokud ale potřebujeme vytvářet pokaždé nové instance, tj. chceme zohledňovat stav beany, musíme uvést explicitně parametr scope. <bean id="bean3" class="samplebean3" scope="prototype" /> web scopes Jako příklad uvedu následující beany: <bean id="loginaction" class="loginaction" scope="request"/> <bean id="userpreferences" class="userpreferences" scope="session"/> <bean id="userpreferences" class="userpreferences" scope="globalsession"/> Po každém HTTP requestu se vytvoří nová instance beany loginaction, zatímco intuitivně beana userpreferences má mít platnost po celou dobu relace. Ve většíně případů ve webové aplikaci si při definici bean vystačíme pouze s prvními dvěma standardními scopy. Pokud potřebujeme nainjektovat beanu s webovým (nebo custom) scopem do beany se standardním scopem, musíme k tomu požít chytrého objektu - proxy, který nainjektovanou beanu zastupuje. Při volání metody beany proxy získá objekt ze scopu a deleguje její volání. <bean id="userpreferences" class="com.foo.userpreferences" scope="session"> <aop:scoped-proxy/> </bean> <bean id="userservice" class="com.foo.simpleuserservice"> <property name="userpreferences" ref="userpreferences"/> </bean> K webovým scopům však nejčastěji přistupujeme jako ke kontejnerům, do kterých ukládáme objekty (a z nich vybíráme) programově. Tuto praktiku ukazuji spolu s SWF scopy v kapitolách 2.2.7.5, 2.2.8.5. 4 Tyto 3 tzv. webové scopy mají smysl pouze ve webové aplikaci s použitím webové implementace ApplicationContextu - s XmlWebApplicationContext.

KAPITOLA 2. REŠERŠE 11 2.2.6.3 Typové konverze Typová konverze je způsob převodu hodnot zapsaných v XML deskriptoru na reálné objekty. Chtěli bychom například zapsat něco jako <bean id="bean" class="samplebean"> <property name="measure" value="90/60/90"/> </bean> public Class SampleBean { private Measure measure; public Measure getmeasure() { return measure; public void setmeasure(measure measure) {this.measure=measure; Spring nám nabízí možnost implementace Property editoru, na který se kontejner obrátí v případě, že v setteru narazí na daný typ, který neumí automaticky dosadit. public class MeasurePropertyEditor extends java.beans.propertyeditorsupport { @Override public void setastext(string measure) throws IllegalArgumentException { try { //set data from String to value setvalue(value); catch (NumberFormatException e) { throw new IllegalArgumentException(); Implementaci metody setastext nechávám na čtenáři. Kromě ní existuje inverzní metoda getastext(). Property editor zaregistrujeme například do beany customeditorconfigurer, kterou umístíme na viditelné místo z ApplicationContextu. <bean id="customeditorconfigurer" class="org.springframework.beans.factory.config.customeditorconfigurer"> <property name="customeditors"> <map> <entry key="measure"> <bean class="measurepropertyeditor" /> </entry> </map> </property> </bean> 2.2.6.4 Autowiring Ohledně Spring IoC kontejneru stojí za to zmínit ještě jednu zajímavou vlastnost - autowiring. <bean id="bean" class="samplebean" autowire="byname" /> Tím řekneme Sprigu, aby se pokusil automaticky vyřešit závislosti injektovaných bean sám, bez nutnosti je explicitně uvádět. Hodnota v parametru autowire může nabývat nejčastěji následujících hodnot: no - žádný autowiring,

12 KAPITOLA 2. REŠERŠE byname - Spring hledá ve svém ApplicationContextu beanu, podle jména JavaBean property, bytype - Spring hledá beanu podle typu JavaBean property, funguje pouze pokud se v beaně nevyskytuje více properties stejného druhu. 2.2.6.5 ApplicationContext Rozhraní ApplicationContext obaluje BeanFactory a rozšiřuje její funkcionalitu o internacionalizaci, publikování událostí nebo nahrávání zdrojů. Ukáži na příkladu internacionalizaci, resp. použití souboru.properties, kde uvádíme k danému klíči jeho hodnotu. Sample.properties bean.value = someothervalue Kdekoliv v naší XML konfiguraci tyto proměnné můžeme pomocí Expression Language 5 použít, například takto. <bean id="bean" class="samplebean"> <property name="property" value="${bean.value"/> </bean> Vše bude fungovat, pokud doplníme ApplicationContext o beanu <bean id="propertyconfigurer" class="org.springframework.beans.factory.config. PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:sample.properties</value> </list> </property> </bean> 2.2.7 Spring Web MVC V této kapitole představím webové frameworky, vysvětlím cestu, jak jsme se k nim dostali a ukážu Springovskou implementaci webového frameworku Spring Web MVC. Jako všechny moderní webové frameworky je Spring MVC, jak už jeho název napovídá, založen na návrhovém vzoru Model View Controller. 2.2.7.1 Návrhový vzor MVC Z historického pohledu se před nástupem JSP používaly pouze servlety, s nimiž se výsledný HTML výstup generoval obtížně. Z dnešního pohledu je tento způsob vhodný jen pro nejjednodušší případy. Při příchodu specifikace JSP 1.0 byla zvolena architektura tzv. Model 1, kdy je HTTP požadavek delegován přímo na příslušnou JSP stránku, v níž je umístěn veškerý kód pomocí skriptletů. 6 Tento přístup se dnes označuje termínem špagetový kód, postrádáme tu jakékoliv 5 EL se primárně používá pro vyhodnocování výrazů na JSP stránkách, pro přístup k hodnotám z Command Objektů a podobně. 6 Skriptlet je speciální tag, v němž je umístěn přímo Java kód <% /*java code here*/ %>.

KAPITOLA 2. REŠERŠE 13 Obrázek 2.4: Návrhový vzor MVC, zdroj: [15] rozdělení do vrstev, centralizovaný přístup HTTP požadavků a potenciální možnost rozšíření aplikace. Specifikace JSP 1.1, kromě přístupu psaní logiky aplikace pomocí tagů, přinesla implementaci návrhového vzoru MVC (obrázek 2.4), kterou označujeme jako Model 2. Obrázek 2.5: MVC implementace JSP Model 2, zdroj: [1] MVC slouží k oddělení aplikační, prezentační logiky a datového modelu. Není použit jen ve webových frameworcích, ale například v desktopových aplikacích u knihoven Swing a SWT. Jeho kořeny můžeme najít ve Smalltalku, kdy byl původně použit pro zakomponování klasického postupu vstup-zpracování-výstup do GUI programů. Controller - prostředník mezi vrstvami Model a View Model - představuje vlastní data zobrazovaná ve View View - transformuje Model do prezentační podoby Jelikož HTTP protokol je typu request/response, tedy bezestavový, nemůžeme zde aplikovat typický MVC pattern. Model 2 je upravené MVC schéma, kdy jediný rozdíl spočívá v tom, že View nemůže volat Controller. Vzájemnou interakci si můžeme představit tak, že klient pošle požadavek na webový server, ten je vzápětí delegován na servlet, který představuje controller, servlet zavolá aplikační

14 KAPITOLA 2. REŠERŠE logiku, ze které získá model, ten zaregistruje do scopu viditelného z JSP, které představuje view. Následně provede přesměrování na View a posléze na JSP, které si vyzvedne data ze scopu a ten výsledek zobrazí.[15] V prostředí webu existuje několik implementací, které odpovídají návrhovým vzorům: Front Controller (Service to worker) - frameworky Struts, Spring Web MVC, WebWork, Ruby on Rails Dispacher view (View helper) - frameworky JSF-based (JSF, Seam, Shale), Tapestry, Wicket, Echo2 Rozdíl mezi přístupy je v okamžiku volání aplikační logiky. V případě Front Controller u se aplikační logika volá před předáním zpracování do View, zatímco u Dispacher View se volá aplikační logika uvnitř View pomocí View Helper u[3]. 2.2.7.2 Rozdělení webových frameworků Nejdůležitější roli hraje úroveň abstrakce nad protokolem HTTP. Čím větší je úroveň abstrakce, tím méně se musí jednotlivé vrstvy starat o samotný protokol. Takto dělíme webové frameworky do dvou skupin Požadavkově orientované (Request based) - založené na Front Controlleru, Komponentově orientované (UI component based, event-based) - založené na View Helperu. Budoucnost patří komponentově orientovaným webovým frameworkům. Ty umožňují vývojáři pracovat na úrovni UI komponent a událostí, tedy stejně jednoduše jako s dalšími např. s desktopovými frameworky (Swing, SWT). Snadno například vytvoříme RAD nástroj pro WYSIWYG editaci webové aplikace. 2.2.7.3 Architektura Obrázek 2.6: Architektura aplikace ve Spring MVC, zdroj: [20] Architektura aplikace ve Spring Web MVC je rozdělena do navzájem nezávislých vrstev, jak vidíme na obrázku 2.6. User Interface - prezentační vrstva, stará se o generování výstupu k uživateli (nejčastěji XHTML), většinou použito JSP, ke kterému existují implementace rozhraní View

KAPITOLA 2. REŠERŠE 15 org.springframework.web.servlet.view.jstlview. Jako příklad si uvedeme jednoduchou JSP stránku. 7 SampleJSP.jsp <?xml version="1.0" encoding="utf-8"?> <html><body> <c:choose> <c:when test="${1 + 1 == 10"> we count in binary base </c:when> <c:otherwise> we don t count in binary base </c:otherwise> <c:choose> </body></html> Web - webová vrstva řeší přechody mezi stránkami a odstiňuje servisní vrstvu od vlastní implementace. Hlavní rozhraní v této vrstvě je Controller. AbstractController - základní abstraktní kontrolér BaseCommandController,AbstractCommandController - pracuje s Command Objectem, tj. objekt, do kterého namapujeme vstupní hodnoty z hodnot získaných HTTP requestu, ten pak používáme ve View vrstvě SimpleFormController,AbstractSearchController - umožňuje například přechody mezi jednotlivými obrazovkami pomocí reakce na výsledek metody MultiActionController - umožňuje reagovat na více typů HTTP requestů, defaultně se metoda obsluhující danou namapovanou stránku jmenuje stejně jak tato stránka UrlFilenameViewController - pomocí namapované stránky zobrazí JSP se stejným jménem Příklad na takový jednoduchý kontrolér je uveden hned v kapitole 2.2.5. Service - V této vrstvě se nachází implementace daných byznys requirementů, jako jediná má přístup k perzistentní vrstvě. Jelikož je tato vrstva obvykle v každé aplikaci jiná, Spring k ní nenabízí žádné rozhraní. Jako příklad ukážu rozhraní IUserService public interface IUserService { public boolean isloginfree(string login); public AbstractUser getuser(string login); public boolean saveuser(abstractuser user); Persistence - Perzistentní vrstva implementuje ukládání,nahrávání a práci s objekty datového modelu z databáze. Nejčastěji implementuje metody CRUD (create,retrieve,update,delete). Spring ve svém ORM modulu dovoluje použít deklarativní transakce imlementované pomocí AOP nebo zaobaluje méně čitelné vyjímky do čitelnějších. Spolupráce s Hibernate frameworkem je hlavně docílena pomocí tříd HibernateTemplate 7 Uvedené tagy začínající XML namespacem c nebo ftm jsou součástí knihovny JSTL, kde jsou definovány základní tagy pro větvení kódu, zobrazování, iterace, definování a používání proměnných nebo pro formátování textu.

16 KAPITOLA 2. REŠERŠE HibernateDaoSupport Jako příklad zde uvedu rozhraní IOfferDao. Ukázku deklarativních transakcí spolu s implementaci rozhraní IOfferDao si ukážeme v kapitole 2.3.8.1. public interface IOfferDao { void saveorupdate(offer offer); Offer getofferbyid(long id); Offer getofferby(inzerent inzerent); void delete(offer offer); List<Offer> gettopitems(int maxresult); Domain model - datový model, soubor tzv. Bussiness Objectů, které abstrahují entity z doménového modelu do programu, který s nimi pracuje, nakonfigurovaných pro O/R mapování daným perzistentním nástrojem. Ukážeme si jednoduchý příklad se zápisem pomocí JPA anotací. Inzerent.java @Entity public class Inzerent extends AbstractUser { private String firstname = ""; private String lastname = ""; private String telephone = ""; //appropriate getters and setters Podrobněji se této problematice věnuji v kapitole 2.3. 2.2.7.4 Dispacher servlet DispacherServlet je Front Controller, jak jsem ukázal v kapitole 2.2.7.1. Nyní si ukážeme jednoduchý příklad, kde dáme vše probrané v této kapitole do kontextu. V deployment deskriptoru jsme nadefinovali pro všechny přístupy na *.html obsluhu servletu action, jemuž odpovídá konfigurace action-servlet.xml 8, jak je uvedeno v kapitole 2.2.6. V action-servlet.xml nadefinujeme: <bean id="urlmapping" class="org.springframework.web.servlet.handler.simpleurlhandlermapping"> <property name="alwaysusefullpath" value="true" /> <property name="mappings"> <props> <prop key="/sample-web-page.html">samplecontroller2</prop> </props> </property> </bean> <bean id="samplecontroller2" class="samplecontroller2"> <property name="view" value="samplejsp" /> </bean> 8 Podle jména servletu action se přidá automaticky -servlet.

KAPITOLA 2. REŠERŠE 17 Tedy každý požadavek o sample-web-page.html bude zpracovávat beana samplecontroller2, ta má nasetovánu JSP stránku 9, která se ve výsledku zobrazí. Implementace třídy SampleController2 bude velmi podobná příkladu SampleContollerWithIoC u kapitoly 2.2.5. public class SampleContoller2 implements org.springframework.web.servlet.mvc.controller { private String view; public void setview(string view) { this.view = view; public ModelAndView handlerequest(httpservletrequest request, HttpServletResponse response) throws Exception { return new ModelAndView(view); Pokud potřebujeme jen jednoduše podle požadavku na sample-web-page.html zobrazit jen JSP stránku a nic jiného, tak k tomu použijeme kontrolér UrlFilenameViewController, který hledá View a posléze JSP se stejným jménem jako je html požadavek. V příkladu by stačilo změnit odpovídající kontrolér. <bean id="urlfilenameviewcontroller" class="org.springframework.web.servlet.mvc.urlfilenameviewcontroller" /> 2.2.7.5 Webové scopy Jak jsem zmínil v kapitole 2.2.6.2, častěji k webovým scopům přistupujeme jako ke kontejnerům pro data, jež mají být viditelná v rámci námi definovaného scopu. Request - platnost jen v průběhu jednoho HTTP požadavku, v requestu přichází parametry z HTTP GETu, Session - platnost v průběhu HTTP session, Global session - platnost v průběhu HTTP global session, Základní možnosti práce uvádím v následujícím příkladu, například s pomocí třídy org.springframework.web.context.request.dispatcherservletwebrequest. HttpServletRequest request; //gets as method parameter HttpSession session = request.getsession(); DispatcherServletWebRequest webrequest = new DispatcherServletWebRequest(request); Integer id = (Integer) request.getparameter("id"); id = (Integer) webrequest.getattribute("id", RequestAttributes.SCOPE_REQUEST); session.setattribute("string", id.tostring()); webrequest.setattribute("string", id.tostring(), RequestAttributes.SCOPE_SESSION); webrequest.setattribute("string", id.tostring(), RequestAttributes.SCOPE_GLOBAL_SESSION); 9 V tomto jednoduchém kontextu si můžeme představit například tu, jež jsem ukázal v kapitole 2.2.7.3.

18 KAPITOLA 2. REŠERŠE 2.2.8 Spring Web Flow Spring Web Flow je mocný nástroj pro definici toku obrazovek ve webové aplikaci. Snadno řeší problémy, které konvenční přístup řeší velmi neefektivně. Hlavní idea spočívá v klíčové abstrakci konverzace mezi uživatelem a serverem - ve flow. Flow je něco více než jednotlivý požadavek, něco méně než celá session. Jediné flow řídí celou konverzaci, když se od uživatele očekává nějaký vstup, flow je pozastaveno a čeká na uživatelův vstup. Klient ovládá konverzaci pomocí událostí, podle kterých se flow rozhoduje, co udělat dál. 2.2.8.1 Struktura Definice flow není nic jiného než konečný automat s počátečním stavem, množinou stavů, ve kterých se může nacházet, množinou konečných stavů a vlastními přechody do dalších stavů. Takovýto zápis provádíme bud to do XML souboru nebo do java kódu (použití při speciálních případech a napojeních na další systémy). Pro začátek zde uvedu úvodní zápis, ve kterém flow konfigurujeme. sample-flow.xml <?xml version="1.0" encoding="utf-8"?> <flow xmlns="http://www.springframework.org/schema/webflow" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-1.0.xsd"> </flow> 2.2.8.2 Stavy Start State - Počáteční stav, jako u každého automatu je právě jeden. Parametr idref odkazuje na jiný stav. <start-state idref="actionstate" /> End State - Koncový stav, pokud je ve flow na nejvyšší úrovni, ukončí se jeho provádění, zresetují se všechny proměnné. <end-state id="endstate" /> View State - Stav, ve kterém dochází k vykreslení zadaného obsahu. <view-state id="viewstate"> <transition to="actionstate" /> </view-state> Action State - Stav, ve kterém dochází k nějaké akci, tj. zavolání metody dané beany a obvykle podle návratu následuje přechod do jiného stavu. <action-state id="actionstate" > <action bean="actionbean" method="sampleaction" /> <transition to="decisionstate" /> </action-state> Decision State - Stav, určený k větvení logiky, testuje podmínku, podle které přejde do dalšího stavu.

KAPITOLA 2. REŠERŠE 19 <decision-state id="decisionstate" > <if test="requestparameters.id gt 0" then="viewstate" else="subflowstate"/> </decision-state> SubFlow State - Do flow můžeme vnořit jiné flow jako subflow a pomocí koncového stavu daného subflow reagovat a přejít dle logiky aplikace. Vhodné pokud se určité sekvence stavů a přechodů opakují ve více flow. <subflow-state id="subflowstate" flow="inner-flow"> <transition on="ok" to="viewstate" /> <transition on="cancel" to="endstate"/> </subflow-state> 2.2.8.3 Výhody Za hlavní výhody SWF můžeme bezpochyby označit: oddělení navigace od vlastního kódu, automatické řízení stavu aplikace, vyšší úroveň abstrakce, dovoluje volat metody střední vrstvy bez nutnosti použití kontroléru. 2.2.8.4 Nevýhody Spring Web Flow nemůžeme použít tam, kde kvůli velké práci, než se zprovozní jen jedna jediná obrazovka, se nám jej nevyplatí nasadit. Avšak po určité velikosti a složitosti přechodů mezi stránkami v aplikaci tato nevýhoda padá. 2.2.8.5 Scope Stejně jako webové scopy ve Spring Web MVC, existují ve SWF podobné kontejnery pro uložení jakýchkoliv krátkodobých dat. Přistupuje se k nim přes rozhraní Map pomocí instance třídy RequestContext. SampleFormAction.java public org.springframework.webflow.event sampleaction(org.springframework.web.servlet.support. RequestContext context) { Object object = context.getxxxscope().get("key"); context.getxxxscope().put("key",object); context.getexternalcontext().getrequestmap().put("key",object); Object object = context.getexternalcontext().getsessionmap().get("key"); context.getexternalcontext().getglobalsessionmap().put("key",object); context.getexternalcontext().getapplicationmap().put("key",object); return success(); kde za XXX dosadíme jeden za 4 scopů použitelných ve SWF: request - mají platnost pouze pro daný požadavek,

20 KAPITOLA 2. REŠERŠE flash - platí dokud uživatel neopustí aktuální stav, flow - platí pro celé flow, conversation - platí po dobu životnosti mateřského flow. Na příkladu vidíme, že pomocí třídy RequestContext máme přístup i ke klasickým webovým scopům představeným v kapitole 2.2.7.5, s tím rozdílem, že k nim přistupujeme jako k mapě. Poslední dosud nepředstavený je application scope, který platí v průběhu chodu celé aplikace. Nutno poznamenat, že data v jakémkoliv scopu, kromě singletonu, nejsou viditelná všemi uživateli dohromady. 2.2.8.6 Syntax <transition/> - Definujeme přechod do jiného stavu, parametry on, to, on-exception. Parametr to je povinný. Pokud provádíme ve stavu více akcí, přechod můžeme podmínit výsledkem právě jedné metody. <action-state id="actionstate" > <action bean="actionbean" method="sampleaction" /> <action bean="actionbean" method="sampleaction2" /> <transition on="sampleaction.success" to="decisionstate" /> <transition on-exception="exception" to="endstate" /> </action-state> <global-transitions/> - Vhodné použít, pokud se přechody v každém stavu z flow opakují. <global-transitions> <transition on="globalevent1" to="state1"/> <transition on="globalevent2" to="state2"/> </global-transitions> <xxx-actions/> - Pomocí tagu definujeme akce: <start-actions/> - akce se provedou po vstupu do flow, <end-actions/> - akce se provedou před koncem flow, <entry-actions/> - akce se provedou po vstupu do stavu, <exit-actions/> - akce se provedou před koncem stavu, <renderer-actions/> - akce se provedou před vlastním renderováním ve viewstate. <xxx-mapper/> - Tagem definujeme mapování do flow/z subflow: <input-mapper/> - vstupní mapování, <output-mapper/> - výstupní mapování. Pokud chceme v subflow přistoupit k datům z nadřazeného flow, máme 2 možnosti, jak toho dosáhnout. První možností je použít conversation scope, který je v subflow viditelný. Tímto ale daná data zviditelníme i pro všechny ostatní subflow. Další možností je použít mapování atributů. V hlavním flow definujeme:

KAPITOLA 2. REŠERŠE 21 <subflow-state id="samplesubflow" flow="sample-flow"> <attribute-mapper> <input-mapper> <mapping source="flowscope.number" target="number"/> </input-mapper> <output-mapper> <output-attribute name="result"/> </output-mapper> </attribute-mapper> <transition to="decisionstate"/> </subflow-state> Zápisem <mapping source="flowscope.number" target="number"/> vezmeme proměnnou number uloženou ve flow scope a předáme jí pomocí input-mapperu do subflow. Zápisem <output-attribute name="result"/> získáme proměnnou result z output-mapperu a předáme jí do flow scope tohoto flow. V subflow je ovšem musíme definovat také: <flow> <input-mapper> <input-attribute name="number"/> </input-mapper>... some logic <end-state id="finish"> <output-mapper> <output-attribute name="result"/> </output-mapper> </end-state> </flow> Zápisem <input-attribute name="number"/> získáme pomocí input-mapperu proměnnou number do flow scope, zápisem <output-attribute name="result"/> umístěným v koncovém stavu mapujeme proměnnou result z flow scope do output-mapperu. redirect - Pokud chceme násilně přesměrovat tok aplikace, převážně použijeme jeden ze dvou hlavních přístupů: flowredirect - přesměrování na jiné flow, externalredirect - přesměrování na kompletně jiný HTTP požadavek 10. <end-state id="finish" view="flowredirect:sampleflow"/> <end-state id="finish" view="externalredirect:sample-web-page.html"/> Pro kompletní přehled syntaxe a práci s SWF odkazuji čtenáře na referenční dokumentaci SWF. [14] 10 Rozdíl je samozřejmě ten, že ve druhém případě se postupuje k dispacher servletu, zatímco první případ zůstává ve flowcontrolleru.

22 KAPITOLA 2. REŠERŠE 2.2.8.7 Konfigurace SWF zapojíme do naší aplikace tím, že přidáme následující beany do XML deskriptoru Springu. action-servlet.java <?xml version="1.0" encoding="utf-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:flow="http://www.springframework.org/schema/webflow-config" xsi:schemalocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/webflow-config http://www.springframework.org/schema/webflow-config/spring-webflow-config-1.0.xsd"> <bean name="/sample-web-page.html" class="org.springframework.webflow.executor.mvc.flowcontroller"> <property name="flowexecutor" ref="flowexecutor" /> </bean> <!-- Launches new flow executions and resumes existing executions. --> <flow:executor id="flowexecutor" registry-ref="flowregistry"/> <!-- Creates the registry of flow definitions for this application --> <flow:registry id="flowregistry"> <flow:location path="/web-inf/sample-flow.xml"/> </flow:registry> <!-- All formactions in application --> <bean id="formaction" class="sampleformaction" /> </beans> Uvedená konfigurace je opravdu základní, pro větší počet stránek a flow se nehodí. Lepší konfigurace je uvedena v implementaci portálu www.chcispolubydlici.cz, jehož zdrojové kódy jsou obsaženy na přiloženém CD. 2.3 Hibernate Tato část by měla čtenáři osvětlit použití perzistentní vrstvy ve webové aplikaci. Vysvětlím cestu k ORM frameworkům, jejich dnešní standard JPA a blíže se podíváme na jednu z implementací - JBoss Hibernate framework. 2.3.1 ORM framework Z historického pohledu existuje více přístupů, jak řešit problém s napojením perzistentní vrtsvy k javovské aplikaci. Problém spočívá v tom, že zde máme dva přístupy - OOP přístup používaný v Javě a relační přístup používaný v relačních databázích. JDBC - vlastní implementace perzistentní vrstvy pomocí JDBC API, zápis SQL dotazů a metod DAO tříd, které volají příslušné procedury - příliš zdlouhavé, dnes v podstatě přežitek Serializace - ukládání/načítání serializovatelných hierarchií objektů do/z souboru nebo DB - pracuje se jen s celými hierarchiemi - nevhodné

KAPITOLA 2. REŠERŠE 23 Objektová DB - použití objektového databázového stroje, neexistuje jediné řešení, které by se prosadilo v praxi EJB 2.x Entity Beany - starší EJB 2.x specifikace, v 3.0 se přešlo k ORM-based JPA Dlouhou dobu převládal první způsob, až do doby, kdy se objevily první ORM nástroje jako Castor a Hibernate. ORM je mapovací nástroj mezi OOP světem, kde základní nosič dat je třída, vztah mezi objekty je definován kompozicí a je vždy jednosměrný, a mezi světem relační DB, kde nosičem dat je tabulka, sloupce definují atributy entity a vztah (relace) mezi tabulkami je definován pomocí cizích klíčů nebo vztahové tabulky a je vždy obousměrný. ORM mapuje třídy na tabulky, jejich instance na jednotlivé řádky tabulky. 2.3.2 JPA Java Persistence API je dnešní standard, který popisuje základní myšlenky ORM. Hibernate 3.x byl přepsán, aby odpovídal tomuto standardu. Jako referenční implementace byl zvolen framework Oracle Toplink Essentinals. Mezi další hlavní ORM řešení patří: Oracle Toplink - komerční Apache ibatis - opensource JBoss Hibernate - opensource Řešení používající JPA jej berou jako základní balík vlastností, budeme-li používat čistě samotné JPA, teoreticky bychom mohli vyměnit jeden ORM framework za jiný bez změny jediné řádky kódu. JPA bohužel neřeší všechny problémy a tak jsou frameworky nuceny používat vlastní nestandardní řešení. 2.3.3 Mapování Vlastní mapování z objektů na tabulky zapisujeme v JPA pomocí anotací. U Hibernate se také můžeme setkat se zápisem metadat pomocí XML nebo XDoclet. Zde ukážu jen první způsob, protože se jedná o standard. Anotace zapisujeme bud to před atribut třídy, kde framework používá pro přístup k položkám Java Reflection API (gettery/settery nemusí být vůbec implementovány), nebo do getteru JavaBean třídy, kdy framework pro přístup používá volání getterů/setterů[19]. JavaBeans přístup je nejčastější. @Entity public class Customer implements Serializable { private Integer id; private String name; @Id @GeneratedValue public Integer getid() {return id; public void setid(integer id) { this.id = id; public String getname() { return name; public void setname(string name) { this.name = name; @Entity public class Producer implements Serializable { private Integer id; private String name; private List<Customer> customers;