A keretrendszer
A JSF (Java Server Faces) technológia az egyik leginkább elterjedt webes keretrendszer, annak köszönhetően, hogy épít a JSP (Java Server Pages) technológiára és az MVC (model – view – controller) tervezési mintára.
MVC | Model - view - Controller minta
Egy Java Server Faces alkalmazás, mint általában minden Java alapú webalkalmazás egy servlet konténerben fut, és a következőket tartalmazza:
- alkalmazás specifikus adatok
- event listeners (eseményfigyelők)
- weboldalak
- szerver oldali osztályok (pl.: adatbázis elérést segítő osztályok)
ezeken kívül még
- JSP tag library a UI komponensekmegjelenítéséhez
- JSP tag library az események kezeléséhez, validálásához
- Backing beanek, melyek a UI komponensek attribútumait és funkcióit definiálják
- Validátorok, konverterek, eseményfigyelők, eseménykezelők
- egy konfigurációs fájl, mely az alkalmazással kapcsolatos beállításokat tartalmazza (ez általában a faces-config.xml)
A keretrendszer HTML és annál magasabb szintű komponenseket tartalmaz, mint pl.: validátorok, konverterek, amelyek a megjelenítendő adatokat képesek kezelni. A komponensek tartalmazhatnak attribútumokat és akár egymásba ágyazhatóak. A keretrendszer alkalmazása során a programozó az oldalakat jelölő rendszer helyett objektumok segítségével hozza létre. A fejlesztő entitásokkal dolgozik, amelyek tulajdonságokkal bírnak amiket vagy az oldal definicióiban vagy a programban beállíthatók. A keretrendszer az oldalakat futásidőben transzformálja egy komponens fába, ami akár dinamikusan is módosítható komponensek hozzáadásával, eltávolításával.
JSF állapotgép
A JSF minden kérés feldolgozásra egy állapotgépet használ, amely vezérli a folyamatot. A folyamatok 6 állapot egyikébe kerülhet.
- A nézet visszaállítása (Restore Wiew - postback)
- A rendszer a kérés feldolgozása közben megvizsgálja, hogy olyan oldara tér vissza amit már előzőleg elmentett. Ha igen (postback) akkor a JSF ebben a fázisban visszaállítja az egyes komponensek állapotát. Ha nem postback akkor a keretrendszer létrehozza a komponensfa következő elemét és az állapotgép státuszát a nézet generálása állapotba kényszeríti.
- A kérés paramétereinek rögzítése (Apply Request Values)
-
Ebben a fázisban ellenőrzésre kerülnek az input komponensek, hogy van-e hozzájuk rendelve paraméter a kérésben. Ha van azt UIinput ősosztály submittedValue tagváltozójában tárolja el.
- Validációk futtatása (Process Validation)
-
A ViewRoot-tól kezdve mélységi bejárással történik a komponensek validálása a komponensfában. Ebben a fázisban azok a komponensek kerülnek validálásra amelyekre teljesülnek az alábbi feltételek:
- a felhasználó által küldött űrlapban szerepelnek
- rendered attributuma true
- immediate attributuma false
Validálási folyamat során első sorban a kapott paraméterek (ha vannak) kerülnek konvertálásra a megfelelő java típusra. A konvertálást vagy a beépített JSF konverter vagy egyedi konverter alapján történik. Ha a validáció hibára fut, akkor a JSF a komponens üzenetei között elhelyez egy üzenetet és az állapotgépet a nézet generálása állapotba. Ha a validálás sikeres, akkor a konvertált és validált értéket beírja a komponens value tagváltozójába.
- Modell aktualizálása (Update model values)
-
Ebben a fázisban a validált értékek beírásra kerülnek a modellbe.
- Alkalmazás meghívása (Invoke application)
-
Ebben a fázisban a komponenseken keresztül az események továbbításra kerülnek az összes regisztrált osztály felé.
- Nézet generálása (Render response)
-
Az aktualizált komponensfát bejárva megtörténik a szükséges kimenet generálása.
JSF állapotgép
JSF alkalmazás könyvtár struktúrája és konfigurálása
Eclipse IDE által generált könyvtár strukúra
Az ECLIPSE IDE fejlesztő környezet a fenti képen látható módon állította elő a JSF alkalmazás könyvtár szerkezetét. Ezek közül amit feltétlen ismernünk kell:
- src - java osztályok mappája
- WebContent - ebben a mappában kapnak helyet az XHTML, CSS, JS és a többi fájl amit szeretnénk elérni a weboldalon.
- WEB-INF - a JSF alkalmazásra vonatkozó konfigurációs fájlok helye. pl.: web.xml, faces-confgi.xml, weblogic.xml stb...
- Libraries - az alkalmazás által használt külső csomagok gyűjtő helye. pl.: külső .jar fájlok
- META-INF - Különböző meta adatok leírását adhatjuk meg. Pl.: adatbázis hozzáférés a persitence.xml fájl hozzáadásával.
A keretrendszert úgynevezett telepítés leíró fájlokon keretül tudjuk konfigurálni. Két fájllal szinte minden esetben találkozunk.
web.xml
A web.xml egy kapcsolatot definiál URL címek és a szervletek között, melyek a kéréseket szolgálják ki. A Webkiszolgáló arra használja ezt a konfigurációs fájlt, hogy megkeresse az adott URL-hez tartozó szervletet, és meghívja a kéréshez tartozó osztály megfelelő metódusát. (pl. a doGet () metódus a HTTP GET kéréseket).
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>JSFTest</display-name>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<context-param>
<description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
<param-value>resources.application</param-value>
</context-param>
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
</web-app>
faces-config.xml
Az alkalmazás Backing Bean-jeit és az oldalak közötti navigációs logikát egy XML konfigurációs file, a WEB-INF/faces-config.xml írja le. Ez a file további bejegyzéseket is tartalmazhat, amelyek pl. segítik a saját validátorok és konverterek v. a többnyelvű felületek kialakítását (message bundle-ek), stb. is.
<?xml version="1.0" encoding="UTF-8"?>
<faces-config
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_1.xsd"
version="2.1">
<managed-bean>
<managed-bean-name>hangman</managed-bean-name>
<managed-bean-class>jsftest.Hangman</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>cleverTableBean</managed-bean-name>
<managed-bean-class>datatable.CleverTableBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<navigation-rule>
<from-view-id>/hangman.xhtml</from-view-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/success.xhtml</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>failure</from-outcome>
<to-view-id>/failure.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/*</from-view-id>
<navigation-case>
<from-outcome>index</from-outcome>
<to-view-id>/index.xhtml</to-view-id>
<redirect/>
</navigation-case>
<navigation-case>
<from-outcome>hangman</from-outcome>
<to-view-id>/hangman.xhtml</to-view-id>
<redirect/>
</navigation-case>
<navigation-case>
<from-outcome>clevertable</from-outcome>
<to-view-id>/clevertable.xhtml</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>
<application>
<message-bundle>resources.application</message-bundle>
<locale-config>
<default-locale>en</default-locale>
</locale-config>
</application>
</faces-config>
xhtml oldalak
A megjelenítésre általában szabványos xhtm oldalakat használ a keretrendszer. Az alábbi forrása a példák között található hangman játék xhtm forráskódját láthatjuk.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Hangman Game</title>
</head>
<body style="background: url(imgs/backg.jpg); background-size:100% auto;">
<f:view>
<h:link value="index" outcome="index" style="width: 200px; height 40px; background: #FFF;" />
<br/><br/>
<h1><h:outputText value="Hangman Game 1.0" /></h1>
<table style="background: #FFF;">
<tr>
<td>
<!-- ################################################################### -->
<!-- ##### Kiírja a böngésző felületére a value attribútum értékét ##### -->
<h:outputText style="color:red" value="The word I'm thinking about is: " />
<!-- ############################################################################## -->
<!-- ### Kiírja a böngésző felületére a hangman backing bean word tulajdonságát ### -->
<h:outputText value="#{hangman.word}" /><br /><br />
<h:form>
<h:outputText value="Show a new letter:" />
<!-- ####################################################################### -->
<!-- ### Legördülő menü, kiválasztott érték hangman backing bean
### selectedChar tulajdonsága. Az elemei pedig a hangman backing bean
### availableChars lista ### -->
<h:selectOneMenu value="#{hangman.selectedChar}">
<f:selectItems value="#{hangman.availableChars}"/>
</h:selectOneMenu>
<!-- ################################################################### -->
<!-- ### Gomb a hangman backing bean showCharacter metódus hívásához -->
<h:commandButton action="#{hangman.showCharacter}" value="Show!"/><br/><br/>
<h:outputText value="Type your guess here:" />
<!-- ################################################################### -->
<!-- ### Input mező, melynek értéke hozzá van kapcsolva a hangman backing
### bean guess string típusú tulajdonságához -->
<h:inputText value="#{hangman.guess}" />
<h:commandButton action="#{hangman.tryGuess}" value="Guess!"/><br/><br/>
<br/>
<!-- ###################################################################### -->
<!-- ### Gomb a hangman backing bean newGame metódus hívásához amellyel
### új játékot kezdeményezhetünk -->
<h:commandButton action="#{hangman.newGame}" value="New Game"/><br/><br/>
</h:form>
</td>
<td style="width:30px;">
</td>
<td>
<!-- ###################################################################### -->
<!-- ### Kép megjelenítése a böngészőben. A megjelenítést szabályozva van a
### rendered attribútummal. Az egyes képek csak akkor lesznek láthatóak
### ha a képhez tartozó rendered attribútumban megadott hangman backing
### bean-beli boolean tulajdonság értéke true -->
<h:graphicImage value="imgs/hangman.jpg" rendered="#{hangman.startPos}"/>
<h:graphicImage value="imgs/hangmanHead.jpg" rendered="#{hangman.head}"/>
<h:graphicImage value="imgs/hangmanBody.jpg" rendered="#{hangman.body}"/>
<h:graphicImage value="imgs/hangmanLeftHand.jpg" rendered="#{hangman.leftHand}"/>
<h:graphicImage value="imgs/hangmanRightHand.jpg" rendered="#{hangman.rightHand}"/>
<h:graphicImage value="imgs/hangmanLeftFoot.jpg" rendered="#{hangman.leftFoot}"/>
<h:graphicImage value="imgs/hangmanEnd.jpg" rendered="#{hangman.hangmanEnd}"/>
</td>
</tr>
<tr>
<td>
<div style="background: #FFF;">
<h:outputText value="Selected characters:" />
<br/>
<ui:repeat value="#{hangman.notAvailableChars}" var="o">
#{o} <h:outputText value=" | " />
</ui:repeat>
</div>
</td>
</tr>
</table>
</f:view>
</body>
</html>
Managed bean (Request bean-ek)
A managed bean (szokás request bean-nek is nevezni) egy JAVA osztály amely a JAVA alapú webes keretrendszer MVC (Model-View-Controller) mintában a controller szerepét tölti be. A managed bean hatókörét és refrenci nevét annotációkkal vagy a faces-config.xml -ben kell definiálni.
Managed bean hatókör
Attól függően mikor kerül szemétgyüjtésre a managed bean megkülönböztetünk
- @RequestScoped - kérés feldolgozás után
- @SessionScoped - session (munkamenet) törlése után
- @ApplicationScoped - alkalmazás leállításáig
package hu.testJsf.javaee.ejb;
import javax.ejb.Stateless;
@SessionScoped // adatai elérhetőek amíg a session létezik
@Named("TestStateLessBean") // TestStateLessBean néven elérhetjük el az osztályt
// - xhtml lapról pl.: #{TestStateLessBean.str} = str értékével
public class TestStateLessBean {
private String str = "Hello World";
public TestStateLessBean() {}
public String getStr() {
return str;
}
public String setStr(String strParam) {
return this.str = strParam;
}
}