|
a risolvere tutti i problemi, ma mai nessuna di esse potra' porne uno. Einstein
|
|
| Home Page |
|
| Articoli |
|
| News |
|
| Forum |
|
| Classi |
|
|
|
|
|
Composizione di componenti JSF con Facelets
By
Fabio Staro
10 aprile 2006
Valutazione Acquisita:
20
|
 |
|
JSF, acronimo di JavaServer Faces, è un framework per applicazioni web basato su un modello a componenti, modello introdotto in un precedente articolo (cfr. [Staro]). In questo articolo descriviamo la possibilità di creare componenti JSF attraverso la composizione (composite pattern, cfr. [GoF]) di componenti già presenti. Nell’articolo diamo per acquisita una conoscenza del framework JSF e dei custom tag JSTL. La figura che segue mostra una semplice mappa di inserimento:  Analizziamo il codice della pagina JSP (di seguito ne riportiamo uno stralcio):
… <h:panelGrid columns="3"> <h:outputLabel id="label_nome" value="Nome *"/> <h:inputText id="txt_nome" required="true" value="#{persona.nome}"/> <h:message for="txt_nome"/> <h:outputLabel id="label_cognome" value="Cognome *"/> <h:inputText id="txt_cognome" required="true" value="#{persona.cognome}"/> <h:message for="txt_cognome"/> <h:outputLabel id="label_data" value="Data di Nascita"/> <h:panelGroup id="data_group"> <h:inputText id="txt_giorno" required="true" size="2" value="#{persona.giorno}" /> <h:outputText value=" / "/> <h:selectOneMenu value="#{persona.mese}"> <f:selectItem itemLabel="01" itemValue="1"/> <f:selectItem itemLabel="02" itemValue="2"/> <f:selectItem itemLabel="03" itemValue="3"/> <f:selectItem itemLabel="04" itemValue="4"/> <f:selectItem itemLabel="05" itemValue="5"/> <f:selectItem itemLabel="06" itemValue="6"/> <f:selectItem itemLabel="07" itemValue="7"/> <f:selectItem itemLabel="08" itemValue="8"/> <f:selectItem itemLabel="09" itemValue="9"/> <f:selectItem itemLabel="10" itemValue="10"/> <f:selectItem itemLabel="11" itemValue="11"/> <f:selectItem itemLabel="12" itemValue="12"/> </h:selectOneMenu> <h:outputText value=" / "/> <h:inputText id="txt_anno" required="true" size="4" value="#{persona.anno}"/> </h:panelGroup> <h:panelGroup id="msg_group"> <h:message for="txt_giorno"/> <h:message for="txt_anno"/> </h:panelGroup> <h:outputLabel id="label_telefono" value="Telefono"/> <h:inputText id="txt_telefono" required="true" value="#{persona.telefono}"> <f:validateLength minimum="6" maximum="15"/> </h:inputText> <h:message for="txt_telefono"/> </h:panelGrid> … E’ possibile notare come all’interno del tag panelGrid la struttura data dalla sequenza di tag h:outputLabel, h:inputText e h:message si ripeta per ogni campo di testo (nel codice la struttura è evidenziata in rosso). Nel caso reale di una mappa di inserimento con dieci o peggio venti campi di input il sorgente JSP diviene lungo, poco manutenibile e ripetitivo. In modo analogo la sequenza di tag, h:inputText, h:selectOneMenu, f:selectItem, h:panelGroup, etc., che costituiscono il campo “Data di Nascita” è da ripetere in modo del tutto analogo nella struttura se nella mappa di inserimento vi fossero due o più date. Di seguito mostriamo una tecnica, basata sulla tecnologia Facelets, con la quale è possibile risolvere tale “prolissità” e avere codice leggibile e facilmente manutenibile. Tuttavia prima di addentrarci è obbligatorio osservare che la tecnologia Facelets non si limita solo alla composizione di componenti JSF (aspetto analizzato in tale articolo) ma presenta molte più features tra le quali: - Templating (in modo analogo a Tiles);
- Composizione di componenti;
- Creazione di librerie di componenti;
- Supporto completo a EL, comprese le funzioni;
- Supporto ai custom tag JSTL.
Infine osserviamo che Facelets lavora sia con la specifica JSF versione 1.1 e 1.2 e sia con le implementazioni della specifica della SUN e di Apache MyFaces.
|
|
|
Il … Risultato
|
top
|
|
Per quanto detto sopra vogliamo costruire due tag (“inputText” e “inputDate”) per mezzo dei quali sia possibile ridurre il codice nella JSP, aumentarne la chiarezza e conseguentemente migliorare la manutenibilità. Inoltre i due nuovi tag saranno riutilizzabili in contesti analoghi portando ad una ottimizzazione nel riuso del codice durante il processo di sviluppo. Alla fine il sorgente che produrrà l’output mostrato in figura sarà un file XHTML compatto, chiaro e manutenibile: <!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:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:c="http://java.sun.com/jstl/core" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:jip="http://www.javaportal.it/jsf"> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"></meta> <title>Inserimento</title> </head> <body> <h1>INSERIMENTO</h1> <hr/> <h:form> <h:panelGrid columns="3"> <jip:inputText nomeCampo="nome" obbligatorio="true" label="Nome:" simboloObbligatorio="*" managedBean="#{persona}"/> <jip:inputText nomeCampo="cognome" obbligatorio="true" label="Cognome:" simboloObbligatorio="*" managedBean="#{persona}"/> <jip:inputDate nomeCampo="dataNascita" obbligatorio="true" label="Data di Nascita:" simboloObbligatorio="*" managedBean="#{persona}"/> <jip:inputText nomeCampo="telefono" obbligatorio="false" label="Telefono:" managedBean="#{persona}"> <f:validateLength minimum="6" maximum="15"/> </jip:inputText> </h:panelGrid> <br/> <h:commandButton value="Inserimento" action="ok"/> </h:form> </body> </html> Osservando il codice sopra riportato notiamo come nel tag HTML sia specificato il namespace dei nuovi tag “inputText” e “inputDate”: xmlns:jip=”http://www.javaportal.it/jsf” Questo, come vedremo tra un attimo, è specificato nella definizione del tagfile.
|
|
Composizione di componenti
|
top
|
|
I passi necessari per la realizzazione dei “composition component” con le caratteristiche sopra descritte sono: - Installare Facelets;
- Creare un file XML definizione dei composition component (“tagfile”);
- Dichiarare il “tagfile” nel file web.xml;
- Creare il sorgente XHTML con la composizione dei componenti JSF;
|
|
INSTALLARE FACELETS
|
top
|
I passi necessari per la realizzazione dei “composition component” con le caratteristiche sopra descritte sono: - Installare Facelets;
- Creare un file XML definizione dei composition component (“tagfile”);
- Dichiarare il “tagfile” nel file web.xml;
- Creare il sorgente XHTML con la composizione dei componenti JSF;
Per installare Facelets è necessario eseguire il download della distribuzione dal sito: http://facelets.dev.java.net/ Nella directory WEB-INF/lib del progetto web copiamo i file jar: - jsf-facelets.jar
- standard.jar
- el-api.jar
- el-ri.jar
Nel file web.xml è necessario aggiungere le seguenti righe di codice: <context-param> <param-name>facelets.REFRESH_PERIOD</param-name> <param-value>2</param-value> </context-param> <context-param> <param-name>facelets.DEVELOPMENT</param-name> <param-value>true</param-value> </context-param> <context-param> <param-name>javax.faces.DEFAULT_SUFFIX</param-name> <param-value>.xhtml</param-value> </context-param> La tabella che segue descrive il significato dei parametri facelets: 
Ultimo passo necessario per concludere l’installazione delle Facelets è dichiarare la nuova classe FaceletViewHandler, implementazione concreta della classe astratta ViewHandler presente nel package javax.faces.application. Questo è possibile aggiungendo nel file faces-config.xml le seguenti righe di codice: <application> <view-handler> com.sun.facelets.FaceletViewHandler </view-handler> </application> Prima di proseguire con l’esempio approfondiamo il punto appena descritto. Osserviamo che il framework JavaServer Faces presenta molti punti di estensione rappresentati da pluggable classes che all’occasione possono essere sostituite o decorate (cfr. il pattern Decorator [GoF]). Il diagramma delle classi che segue da una vista d’insieme delle pluggable classes :
Figura: le classi pluggable del framework JavaServer Faces Queste sono descritte nella tabella : 
Osserviamo che in generale non è necessario sostituire completamente l’implementazione di default di una classe pluggable con una nuova classe. Infatti il più delle volte è possibile ed anzi è preferibile aggiungere nuove funzionalità alla classe originale attraverso un processo di decorazione (decorator pattern, cfr. [GoF]). Di seguito riportiamo la firma del costruttore della classe FaceletViewHandler: public FaceletViewHandler(ViewHandler parent) { … this.parent = parent; } Possiamo osservare come al costruttore è passato il riferimento dell’implementazione originale del ViewHandler. Pertanto la classe FaceletViewHandler delega alla classe “parent”, implementazione originale del ViewHandler, la soluzione di funzionalità non alterate dalla presenza delle Facelets e gestisce direttamente le nuove funzioni di creazione, restore e display della view (cfr. [JSF]). La classe FaceletViewHandler pertanto decora l’implementazione di default del ViewHandler.
|
|
CREAZIONE DEL TAGFILE
|
top
|
Il “tagfile” è un file XML che specifica: - Il nome dei tag;
- Il nome dei file sorgente dei tag;
- Il namespace;
Di seguito riportiamo il tagfile di definizione per “inputText” e “inputDate”:
<?xml version="1.0"?> <!DOCTYPE facelet-taglib PUBLIC "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN" "http://java.sun.com/dtd/facelet-taglib_1_0.dtd"> <facelet-taglib> <namespace>http://www.javaportal.it/jsf</namespace> <tag> <tag-name>inputText</tag-name> <source>inputText.xhtml</source> </tag> <tag> <tag-name>inputDate</tag-name> <source>inputDate.xhtml</source> </tag> </facelet-taglib>
|
|
DICHIARAZIONE DEL TAGFILE NEL FILE WEB.XML
|
top
|
|
Il tagfile sopra definito deve essere dichiarato nel file web.xml. E’ sufficiente aggiungere le seguenti righe di codice (jip.taglib.xml è il nome del tagfile): <context-param> <param-name>facelets.LIBRARIES</param-name> <param-value>/WEB-INF/facelets/tags/jip.taglib.xml</param-value> </context-param>
|
|
IL FILE SORGENTE PER IL TAG
|
top
|
|
Di seguito riportiamo il sorgente, file inputText.xhtml, del tag “inputText”: <!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" xmlns:c="http://java.sun.com/jstl/core"> <!-- ATTRIBUTI DEL TAG: managedBean nomeCampo label obbligatorio --> <ui:composition> <c:if test="${empty obbligatorio}"> <c:set var="obbligatorio" value="true"/> </c:if> <c:if test="${empty label}"> <c:set var="label" value="${nomeCampo}"/> </c:if> <h:outputLabel id="label_${nomeCampo}" value="${label}${simboloObbligatorio}"/> <h:inputText id="txt_${nomeCampo}" value="${managedBean[nomeCampo]}" required="${obbligatorio}"> <ui:insert/> </h:inputText> <h:message for="txt_${nomeCampo}"/> </ui:composition> </html> Osserviamo che il sorgente sopra riportato è un file XHTML. Come prima cosa sono dichiarati i namespace dei tag utilizzati: xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h=”http://java.sun.com/jsf/html” xmlns:f="http://java.sun.com/jsf/core" xmlns:c="http://java.sun.com/jstl/core" In particolare nella definizione del tag “inputText” sono usati i tag Facelets “composition” ed “insert”. Il primo delimita la composizione dei componenti JSF, il secondo indica la possibilità facoltativa di poter passare elementi, per esempio converter e/o validator, al body del tag h:inputText. Per esempio il sorgente presentato nel paragrafo “Il…Risultato” presenta le seguenti righe di codice: <jip:inputText nomeCampo="telefono" obbligatorio="false" label="Telefono:" managedBean="#{persona}"> <f:validateLength minimum="6" maximum="15"/> </jip:inputText> con le quali il validator f:validateLength è inserito, durante il processo di composizione, al posto del tag ui:insert. Osserviamo le seguenti righe di codice del sorgente inputText.xhtml: <h:inputText id="txt_${nomeCampo}" value="${managedBean[nomeCampo]}" required="${obbligatorio} "> <ui:insert/> </h:inputText> Posssiamo notare come il valore del componente h:inputText è legato ad una proprietà di un managed bean attraverso l’espressione: ${managedBean[nomeCampo]} per esempio se il managed bean è “persona” è nomeCampo ha il valore di “telefono” la riga di sopra si risolve come #{persona.telefono}. Osserviamo che con la nuova specifica EL l’espressione ${managedBean[nomeCampo]} può essere scritta in modo del tutto equivalente usando al posto dell’operatore $ l’operatore #. L’uso alternativo di #{…} e ${…} è consentito con le Facelets e gli operatori # e $ sono del tutto interscambiabili presentanto le medesime features. Di seguito, per completezza, riportiamo il sorgente del tag “inputDate”: <!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" xmlns:c="http://java.sun.com/jstl/core"> <ui:composition> <c:if test="${empty obbligatorio}"> <c:set var="obbligatorio" value="true"/> </c:if> <c:if test="${empty label}"> <c:set var="label" value="${nomeCampo}"/> </c:if> <c:set var="giornoProperty" value="giorno_${nomeCampo}"/> <c:set var="annoProperty" value="anno_${nomeCampo}"/> <c:set var="meseProperty" value="mese_${nomeCampo}"/> <h:outputLabel id="label_${nomeCampo}" value="${label}${simboloObbligatorio}"/> <h:panelGroup id="data_group"> <h:inputText id="txt_giorno_${nomeCampo}" required="${obbligatorio}" size="4" value="#{managedBean[giornoProperty]}"/> <h:outputText value=" / "/> <h:selectOneMenu value="#{managedBean[meseProperty]}"> <f:selectItem itemLabel="01" itemValue="1"/> <f:selectItem itemLabel="02" itemValue="2"/> <f:selectItem itemLabel="03" itemValue="3"/> <f:selectItem itemLabel="04" itemValue="4"/> <f:selectItem itemLabel="05" itemValue="5"/> <f:selectItem itemLabel="06" itemValue="6"/> <f:selectItem itemLabel="07" itemValue="7"/> <f:selectItem itemLabel="08" itemValue="8"/> <f:selectItem itemLabel="09" itemValue="9"/> <f:selectItem itemLabel="10" itemValue="10"/> <f:selectItem itemLabel="11" itemValue="11"/> <f:selectItem itemLabel="12" itemValue="12"/> </h:selectOneMenu> <h:outputText value=" / "/> <h:inputText id="txt_anno_${nomeCampo}" required="${obbligatorio}" size="4" value="#{managedBean[annoProperty]}"/> </h:panelGroup> <h:panelGroup id="msg_group"> <h:message for="txt_giorno_${nomeCampo}"/> <h:message for="txt_anno_${nomeCampo}"/> </h:panelGroup> </ui:composition> </html>
|
|
Conclusioni e Biografia
|
top
|
|
In questo articolo abbiamo introdotto un aspetto della tecnologia Facelets. Questa però come osservato presenta molte altre features che semplificano il modo di costruire le view in JSF. Bibliografia: [GoF]: Gamma, Erich, Richard Helm, Ralph Johnson, and John Vlissides. 1995. Design Patterns: Elements of Reusable Object-Oriented Software. Pubblicato da Addison-Wesley. [JSF]: Kito De Mann. 2005. JavaServer Faces In Action. Pubblicato da Manning Publications Co. [Staro]:Fabio Staro. 2006. Componenti JavaServer Faces (JSF). Pubblicato da Java Italian Portal, http://www.javaportal.it/, 1 febbraio 2006. AUTORE: Fabio Staro, Architetto Software e Responsabile Tecnico presso la Direzione Ricerca ed Innovazione di Engineering Ingegneria Informatica S.p.A. Email: fabio.staro@eng.it
|
|
|

Eccetto dove diversamente specificato, i contenuti di questo sito sono rilasciati sotto licenza Creative Commons
|
|
|