2008-04-07

JSF 1.1 Basic

Az alap JSF tudásomat frissítettem fel mostanában kicsit. A témában korlátlan mennyiségű változatos terjedelmű és minőségű anyag lelhető fel a neten. Maga a technológia viszonylag ódivatú a többi egyre jobban vastagkliens-irányba haladó framework-höz képest. Talán azért vettem rá magamat az átnézésére, hogy megadjam neki a végtisztességet.

Egyelőre ennyi link:
GuessNumber tutorial Egynek jó példaprogram, bár kicsit régi.
www.coreservlets.com API-k, mindenféle.

JSF-ről egyébként nem post-ot, hanem könyvet kéne -kellett volna- írni (nem is tudom hogy van-e jó magyar könyv), mindenesetre az alábbiakat véstem fel magamnak ad hoc, abszolút a teljesség igénye nélkül. Update 2008.07.23: A Szoftverfejlesztés J2EE Platformon című könyvnek van egy egész használható, JSF-fel foglalkozó fejezete. Azt hiszem mostanában elég sokat fogom ajánlgatni J2EE fejlesztéshez ezt a könyvet, pedig nem fizetnek érte. Ez egy kicsit szétszórt és dinamikus post lesz, szóval ha van valami amit nagyon megjegyeznivalónak találok, akkor azt beszúrom ide valahova. Meglehet hogy némelyik témát meg sem említem, némelyikbe pedig nagyon belemegyek. Ez van. Ez nem cikk hanem jegyzet.

Webalkalmazás konfiguráció

Sima szervlet technológiára épít, tehát a web.xml-ben kell megadni a Faces servlet-et, a mappingjét és a faces config fájlokat a javax.faces.CONFIG_FILES paraméterben, vesszővel elválasztva. Legjobb megnézni egy példát. Ha van /WEB-INF/faces-config.xml, azt nem kell explicite megadni, az magától betöltődik utoljára. Elvileg ezt nem is _szabadna_ megadni, de ki kell próbálni mi történik.

A JSF paraméterek prefixe javax.faces. Meg lehet még adni a JSF fájlok kiterjesztését (DEFAULT_SUFFIX), valamit az életciklusról (LIFECYCLE_ID) és azt, hogy az állapot a szerveren vagy a kliensen legyen lementve (STATE_SAVING_METHOD). értéke 'server' vagy 'client'.

Ha a STATE_SAVING_METHOD értéke 'client', akkor Base64 enkódolással, a com.sun.faces.VIEW hidden változóban van eltárolva a view a HTML-ben. Ebben az esetben a session timeout nem probléma. Meggátolja a form repost-ot. Ha server, akkor megadható a com.sun.faces.NUMBER_OF_VIEWS_IN_SESSION. A FacesContext-ben tárolódik el a state.

Itt van még némi infó a szabványos JSF konfigurációs paraméterekről.

Alkalmazhatók még saját, nem-standard paraméterek is.

JSF életciklus

Bő lére eresztett leírás a JSF életciklusról itt.
Összefoglalva:

  • Restore view postback esetén előkeresi az elmentett view-t, init esetén felépíti a view-t és elmenti
  • Apply request values a request paramétereket beteszi a view-be ha meg van adva UI komponensben immediate, itt fog megtörténni a validálás események képződnek
  • Process validations validációk lefutnak a beírt értékekre. Ha elbukik error msg-k kirakódnak és render response hívódik.
  • Update model values A Managed Bean-ekbe itt történik meg az értékek visszaírása. Ha nem sikerül konvertálni egyből a render response fázisba megy error msg-kkel.
  • Invoke application Form submit és egyebek lekezelése.
  • Render response HTML Renderelés.

Managed Bean-ek

faces-config fájlokban kell őket összehegeszteni a JSP lapokkal. Alapvetően POJO-k, de tartalmazhatnak akció és eseménykezelő metódusokat is, tehát nem csak egy oldal állapotának hordozására, hanem az eseményeinek lekezelésére is ezek a Managed Bean-ek használhatóak. Managed Bean lehet Map vagy List leszármazott is. Publikus default konstruktor kell. Setterek csak akkor kellenek, ha a faces-configban inicializálni akarjuk.

Navigáció

Jóanyag.

Összefoglalva: Meg lehet adni, hogy melyik oldalról milyen 'outcome' hatására melyik oldalra menjen. Az 'outcome' String típusú értéket a Managed Bean-ekben lévő action metódusok adják. Pl. ha egy save() sikerült az outcome lehet "success", ha nem akkor "failed".
  • Egy from-view -hez meg lehet adni több outcome-t és egy default-ot.
  • From-view -t meg lehet adni pattern-nel, ami azt jelenti hogy a végén lehet wildcard (*).
  • Az egész form-view lehet egy darab wildcard, sőt a form-view tag ki is hagyható, üresen viszont nem hagyható. Ilyenkor 'global outcome'-okról beszélünk.
  • Ha ütközés van mindig az utolsó szabály érvényesül.
  • #{beanName.beanActionMethod} : meg lehet adni, hogy csak
  • erre az egy action-ra érvényesüljön a navigációs szabály.
  • NavigationHandler az invokeApplication fázisban hívódik.
  • to-view -be külső url is megadható.
Akciómetódusok

(ActionListener, validator és valueChange metódusokkal nem foglalkozom most.)
Publikus, paraméter nélküli metódusok Object visszatérési értékkel.
Pl. Enum-ot is visszaadhat, amit String-gé alakítva kijön az outcome.
Ha null-t ad vissza marad az aktuális nézeten.

JBB Q#20588: megmondja hogyan lehet oldalak között információt áramoltatni.

Nem lehet paramétert átadni (legfeljebb trükkösen).
Ha van több azonos nevu metódus automatikusan kiválasztja az action metódust, aminek nincs paramétere és Object a visszatérési értéke.

Implicit objektumok
  • applicationScope : egész alkalmazásra vonatkozó
  • cookie : cookie, requestre
  • facesContext : FacesContext példány requestre
  • header, headerValues : HTTP header, request
  • initParam : az alkalmazásra vonatkozó init paraméterek
  • param, paramValues: request paraméterek
  • requestScope
  • sessionScope
  • view : gyökér UIComponent
Ha van egy images könyvtárunk a WEB-INF-en kívül, így tudunk benne hivakozni egy képre JSF-ből:
image="#{facesContext.externalContext.requestContextPath}/images/picture.gif"/>

Value Binding Syntax

#-vel kezdődik nem $-vel mint JSP-ben. Megpróbál nem elszállni NPE-vel, akkor inkább üres értéket ír ki. Input-oknál viszont simán elszáll, ha nem találja a Managed Bean-t vagy a property-t amibe be kéne írni valamit. Általában String-gé konvertálgat kiírásnál.

Egyebek

A h:form-nak van egy 'prependId' atributuma, ami alapállapotban true és ennek hatására a formban lévő input elemek id-it prefixeli a form nevével. Ezt érdemes false-ra állítani, ha a managed bean-eket post paraméterekhez akarjuk bind-olni. Viszont érdemes true-ra állítani ha több -esetleg iterációval előállított- form van az oldalon.

Lehet választani, hogy az f:loadBundle-t írjuk a jsp-be, vagy a message-bundle, resource-bundle -t a faces-config-ba. A standard validátorok üzeneteit a message-bundle alkalmazásával lehet felülírni. Pl. ilyesmi nevű MessageFormat-okat kell definiálni:

javax.faces.validator.LengthValidator.MAXIMUM

A requiredMessage-t pedig egyedileg megadhajtuk EL-lel így: #{msg.myMessage}, de valami bug miatt csak a resource-bundle alkalmazásával fog működni, f:loadBundle-lel nem.

2008-04-02

Appszerver deatmatch Part 1

Van még egy elmaradásom. Szóval a legutóbbi Java User Meeting-en lement az Appserver deatmatch első része, azaz a Sun ingyenes Glassfish v2 szerverét nyüstöltük. Azaz nyüstölte két hozzáértő ember, egy előregyártott "vendégkönyv" ejb-webes alkalmazással, mi pedig figyeltük a kivetítőn ténykedéseiket. Nézzük a nyolc feladatot:

1. Egy EJB3 + JPA alapú egyszerű webes vendégkönyv alkalmazás beüzemelése a gépre telepített adatbázissal, bónuszként a benne lévő webszolgáltatás WSDL-ének letöltése.

Hamar ment, rögtön a második részt is kipipálva. Belenéztünk a WSDL-be (csúnya nagy XML, lényeg hogy automatikusan generálódott) és csináltunk egy teszthívást a Glassfish admin konzol segítségével. A teszthívás azt jelenti, hogy kitöltögettük a Glassfish WSDL alapján dinamikusan generált HTML formját és submitáltuk.

2. Build script-ből (távoli) deploy.

Netbeans-ből nyomták Ant-tal egy speciális Glassfish task-kal. Tehát nem sima másolási műveletről volt szó, bár úgy hallottam támogatja a hot-deploy-t is, azaz pár másodpercenként szkennel egy könyvtárat és ha talál változást benne akkor újradeployol.

3. Loggolási konfig megváltoztatása egy alkalmazás alatt futásidőben.

Ezt is az admin konzolon lehetett megcsináli és a logot is ott néztük csilivili táblázatban. Szokásosan loggerenként lehet severity level-t állítgani. A példaalkalmazás ilyen szempontból hazabeszélős volt, mert épített arra, hogy a Glassfish admin konzolja a Java Logging API-t támogatja (és csak azt). log4j konfigot gondolom a log4j.xml kézzel való szerkesztésével lehetett volna állítgatni és a csilivili html táblázatról is le kellett volna mondani, de ennek mégis jobban örültem volna.

4. A vendégkönyv távoli debug-olása.

Ez is simán ment, de a Glassfish-t újra kellett indítani a Debugolás megkezdése előtt. Úgy rémlik a JBoss-t nem szoktuk újraindítgatni, fixre be van állítva neki egy kapcsoló hogy engedélyezi a debug kliensek csatlakozását. A kapcsolót persze nem lehet menet közben váltogatni. Netbeans volt a debugoló kliens, de más is lehetett volna, mert standard debug portot használ.

5. Adatforrás megváltoztatása futásidőben.

Ez nem ment (exception), bár nem is vártuk el. Szerintem semmelyik alkalmazásszervernél nem működik. Az alkalmazás újraindításával viszont már simán ment. Ezt is az admin felületen állítgatták.

6. Appszerver leállítása majd újraindítása a deployolt alkalmazással.

Ezt észre sem vettem. Nem mértünk időt, de 10 másodperc körül lehetett sacc per kábé.

7. LDAP azononosítás (ha belefér az időbe)

Ez sikerült volna, de már kezdtünk kicsit kicsúszni az időből. Az mondták 10 perc alatt megvan általában, még 2 perc kéne (8 perc eltelt akkor).

8. Terheléses teszt (JMeter)

Terheltünk, 1700 request/sec-en ketyegett egy átlag notebook-on. Már nem emlékszem a pontos számokra, de tuningolással talán fel tudták vinni 2200-re. (JVM paraméterek.) A terhelésnél a loggolás ki volt kapcsolva és a debug mód sem működött. Ennek a pontnak akkor lett volna értelme, ha azonos hardveren van mivel összehasonlítani, így magában nem sokat mond.

Nagyon jól felkészültek voltak a srácok. Kíváncsi vagyok a többi versenyzőre 2 hónap múlva. Remélhetőleg felveszik a kesztyűt és ők is komolyan veszik a dolgot. Továbbá előtte kipróbálják azért a tesztalkalmazást, esetleg megcsinálják benne a szükséges változtatásokat, hogy fusson a saját appszerverükön is.