Gli
elementi di interfaccia utente lato client
Ogni 'modello di interazione' lato server, per poter
venire effettivamente utilizzato, deve venire associato
ad uno o più elementi di interfaccia utente,
selezionati in base alle caratteristiche della piattaforma
client e compatibili con lo schema di comportamento
desiderato.
Tali gruppi di elementi GUI lato client vengono in gergo
JSF denominati RenderKit e costituiscono, in ottica
Model-View-Controller, i componenti view di JSF.
L'implementazione Early Access Release 2 di JSF - sulla
quale sono basati i contenuti di questa serie articoli
- fornisce un RenderKit in HTML standard, ed è
ragionevole presumere che nuovi RenderKit verso ulteriori
linguaggi di markup (XML, DHTML, light-HTML o WAP per
dispositivi wireless) verranno realizzati da produttori
indipendenti successivamente al rilascio definitivo
di Java Server Faces.
Si
noti che per ogni modello di interazione lato server
possono esistere una o più rappresentazioni a
livello di interfaccia utente, denominate Renderer.
In ogni tag JSF vengono quindi specificati sia il modello
di interazione lato server richiesto sia il Renderer
desiderato. Questa separazione di ruoli permette di
adattare facilmente la presentazione della Web UI alle
caratteristiche della piattaforma client di fruizione
e di mantenere effettivamente separati i compiti degli
autori di componenti da quelli dei grafici Web e degli
sviluppatori di applicazioni.
Il
suddetto HTML RenderKit fornisce un numero estremamente
ampio di componenti, in grado di realizzare tutti i
modelli di interazione lato server precedentemente esaminati.
Analizziamo i principali:
Si
noti come il nome di ogni componente lato client identifichi
in maniera univoca il modello di interazione lato server
cui esso è associato.
La lista appena fornita, che rappresenta comunque un
sottoinsieme dei componenti disponibili, è destinata
ad espandersi in maniera significativa già a
partire dall'imminente Early Access Release 3 di Java
Server Faces, per la quale è previsto un congruo
incremento dei componenti lato server (e, conseguentemente,
di quelli lato client) con l'implementazione di funzionalità
più generiche di input e di output, di rappresentazione
di immagini e di selezioni multiple da un ventaglio
di possibilità.
Una delle caratteristiche di maggiore interesse del
framework Java Server Faces è inoltre dato dalla
sua estensibilità: a partire dalla suddetta EA
3 verranno infatti documentate le API che permettono
agli sviluppatori di estendere le funzionalità
di JSF attraverso la modellazione di nuovi schemi di
interazione lato server e la codifica dei corrispondenti
componenti lato client.
I
model object
Un elemento fondamentale dell'architettura Java Server
Faces è dato da quegli oggetti cui spetta la
responsabilità di modellare e gestire le informazioni
di stato associate agli elementi di interfaccia. Tali
oggetti, denominati model object in gergo JSF, vengono
implementati come oggetti JavaBean.
Nell'attuale versione EA Release 2 di Java Server Faces
la loro implementazione, peraltro tipicamente elementare
e basata sui classici accessori getXXX() e setXXX(),
è di responsabilità dello sviluppatore.
Tale situazione è comunque destinata a mutare
nei successivi rilasci di JSF, che saranno dotati di
meccanismi evoluti di gestione e conversione dello stato
associato ai componenti, ed in cui la codifica diretta
di model object rappresenterà l'eccezione anziché
la regola.
L'accoppiamento tra model object realizzati dallo sviluppatore
e componenti di interfaccia è possibile nel rispetto
dei relativi vincoli di type compatibility, riepilogati
nella seguente tabella:
Rivestono
poi un ruolo importante nel contesto dei model object
e del loro dialogo con i diversi componenti di un'applicazione
i meccanismi di validazione e di data conversion forniti
da Java Server Faces.
Tale framework dispone infatti di strutture automatizzate
rivolte alla validazione dello stato dei componenti
prima ancora che esso venga notificato ai model object
e basate su di un insieme standard di tag ed attributi,
tramite i quali risulta possibile imporre vincoli precisi
ai valori di input.
Le
funzionalità predefinite di validazione sono
rappresentate dai seguenti tag:
Il
criterio di estensibilità che domina le specifiche
di JSF si applica anche ai componenti di validazione
e permette agli sviluppatori di definire nuovi criteri
di verifica e controllo preventivo dei dati tramite
l'implementazione di classi e tag appositi.
Discorso
analogo vale per le funzionalità di conversione,
intese come quei meccanismi che regolano il flusso dei
dati tra model object e componenti di presentazione.
Tipicamente i primi manterranno le informazioni di stato
in oggetti semanticamente affini ai dati da modellare,
mentre i secondi avranno l'esigenza di convertire -
tanto in lettura quanto in scrittura - tali informazioni
in formati di presentazione facilmente comprensibili
e gestibili dall'utente.
Java Server Faces fornisce agli sviluppatori numerosi
meccanismi automatici di conversione, tramite i quali
risulta possibile delegare il processo di conversione
tra view e model layer direttamente a JSF. In particolare
sono supportate in maniera nativa le conversioni da
e verso tipi numerici, java.util.Date, java.util.Time
e java.util.DateTime a partire da stringhe formattate
in logica java.text.DateFormat, java.text.TimeFormat
e java.text.NumberFormat.
Per far fronte a necessità particolari JSF supporta
infine la definizione ed implementazione di meccanismi
di conversione ad hoc attraverso la codifica di appositi
oggetti Converter.
L'oggetto
ApplicationHandler e la gestione degli eventi
Nell'ottica del rispetto degli standard esistenti e
della minimizzazione dei tempi di apprendimento, la
gestione degli eventi in contesto JSF segue schemi già
collaudati e familiari agli sviluppatori Java ed è
basata sull'usuale combinazione di classi Listener ed
Event.
In risposta alle azioni dell'utente i componenti generano
degli eventi, dei quali un'applicazione Java Server
Faces può venire notificata tramite la registrazione
di adeguati oggetti Listener.
Il
framework Java Server Faces conosce tre classi di eventi:
eventi di tipo value-changed: vengono generati
all'atto della modifica dello stato di un componente
di tipo UITextEntry, UISelectOne o UISelectBoolean e
gestiti da oggetti di classe ValueChangedListener; un
classico esempio è dato dalla selezione di una
checkbox da parte di un utente;
eventi di tipo action: i componenti UICommand
generano un evento di questa classe in seguito alla
loro attivazione da parte dell'utente, tipicamente tramite
un click su di un bottone o di un hyperlink; gli eventi
di questa classe vengono gestiti da oggetti ActionListener;
eventi a livello di applicazione: sostanzialmente
analoghi agli action event, vengono generati in seguito
ad un'azione i cui effetti si applicano ad un intero
albero di componenti. Un tipico esempio è dato
dal click sul bottone submit di un form, che provoca
l'aggiornamento dello stato di tutti i componenti innestati.
Particolarmente
importanti sono gli eventi dell'ultimo tipo, i cui effetti
si ripercuotono sull'intero stato dell'applicazione.
Essendo per loro stessa natura 'globali', la gestione
di tali eventi è delegata ad un'apposita classe
singleton che implementa l'interfaccia javax.faces.lifecycle.ApplicationHandler.
Tale
classe, componente necessario di ogni sistema software
basato su Java Server Faces, ha il ruolo di recepire
gli application event, di coordinarne l'impatto a livello
globale - sincronizzandoli se necessario con lo stato
dei componenti - e di gestire la navigazione dell'utente
all'interno dell'applicazione.
Si
noti che nel presente articolo, così come nell'applicazione
d'esempio allegata, lo spazio riservato ai meccanismi
di gestione degli eventi è volutamente limitato.
Ciò è dovuto al fatto che, per quanto
già decisa nelle sue generali linee semantiche,
la relativa logica di gestione è ancora soggetta
ad evoluzioni a livello sintattico.
Java
Server Faces e NetView
Esaminati i componenti fondamentali e l'architettura
generale di JSF siamo in grado di applicare le nostre
nuove conoscenze ad un esempio pratico.
Supporremo infatti che il committente di NetView - la
sempre più fantomatica multinazionale ACME -
ci abbia richiesto di dotare la nostra Web Application
di funzionalità di configurazione relative alla
specifica di alcuni parametri globali che influenzano
il comportamento dell'applicazione.
Il nostro cliente non manca di informarci del fatto
che la quantità e complessità dei dati
di configurazione è destinata ad evolversi fortemente
nel tempo, così come lo spettro dei dispositivi
client cui tali funzionalità dovranno risultare
accessibili.
Alla luce di queste esigenze la scelta di Java Server
Faces appare ben fondata: la sua completa estensibilità,
il supporto per Renderer diversi e la futura integrazione
con sistemi RAD di design e sviluppo di interfacce utente
Web coprono in maniera soddisfacente tutte le aree funzionali
che costituiscono dei fattori discriminanti per il nostro
committente.
Implementeremo quindi il nostro form di configurazione
tramite la Early Access Release 2 di Java Server Faces,
il rilascio più aggiornato disponibile al momento
della realizzazione del presente articolo. L'implementazione
delle funzionalità richieste si articolerà
su quattro punti principali:
-
l'integrazione delle funzionalità di configurazione
all'interno di NetView;
- la
realizzazione dello strato view - ossia la Web UI
- relativo al form di configurazione;
l'implementazione dei model object delegati a rappresentare
e modellare le informazioni di configurazione;
- la
codifica dell'oggetto ApplicationHandler - responsabile
del trattamento degli eventi a livello di applicazione
e della user navigation - e la gestione del suo ciclo
di vita.
L'analisi
del problema
Le attività di analisi legate alla richiesta
del committente sono, in questo caso, piuttosto elementari
e si limitano all'identificazione dei parametri di configurazione
desiderati e dei rispettivi vincoli sintattici e semantici.
In seguito alle usuali sessioni di analisi operate congiuntamente
con il cliente emerge il bisogno di gestire le seguenti
informazioni:
-
due descrizioni del sistema software NetView - la
prima estremamente concisa, la seconda più
dettagliata - adatte ad identificare l'applicazione
in caso di gestione remota o di dialogo con servizi
terzi; tali descrizioni sono semplicemente composte
di caratteri alfanumerici;
- una
master password SNMP, utilizzata per la comunicazione
con router e dispositivi di rete remoti; tale password
non deve, ovviamente, risultare visibile agli utenti;
- l'impostazione
della modalità di log desiderata, che può
essere delegata ad un demone esterno in protocollo
syslog o venire eseguita direttamente da NetView su
file XML ovvero database relazionali in formato SQL;
- l'imposizione
di un limite giornaliero di traffico, al superamento
del quale si rende necessario contattare un amministratore
di sistema; tale soglia non può comunque essere
inferiore ai 100 MB giornalieri;
- la
selezione della modalità di notifica all'amministratore
di una condizione di traffico eccessivo; le possibilità
da supportare sono via E-mail, ICQ o SMS.
Tali
informazioni verranno coagulate in una pagina JSF composta
da un form, ad ogni elemento del quale corrisponderanno
un parametro di configurazione ed una property del model
object models.ConfigurationBean, in base alla seguente
logica:
-
per le due descrizioni di NetView utilizzeremo rispettivamente
i componenti textentry_input e textentry_textarea,
vale a dire un campo di input single-line ed un'area
di input multilinea;
- rappresenteremo
la password SNMP in un componente textentry_secret,
che implementa in maniera nativa la semantica richiesta
(campo di input single-line e no-echo);
- modelleremo
la modalità di log attraverso il componente
selectone_radiogroup, il quale implementa la semantica
della mutua esclusione dei valori possibili tramite
un gruppo di bottoni radio;
- l'input
del limite giornaliero di traffico verrà gestito
tramite un normale campo di input textentry_input;
in questo caso sfrutteremo le funzionalità
di validazione di Java Server Faces per impedire all'utente
di proporre soglie di traffico inferiori al limite
dei 100 MB giornalieri;
- la
selezione della notifica all'amministratore di sistema
avverrà tramite il componente selectone_optionlist,
tradotto dal Renderer in una drop-down listbox;
- infine
le informazioni testuali da fornire all'utente all'interno
della pagina JSF verranno rappresentate da componenti
output_text.
In
un contesto reale alla gestione del form di configurazione
si accompagnerebbe la codifica dei relativi comportamenti
all'interno di NetView; nel nostro esempio, focalizzato
unicamente sullo strato di interfaccia utente, tralasceremo
tali attività implementative. Parimenti non ci
porremo il problema della persistenza delle informazioni
di configurazione, che verranno semplicemente mantenute
nel model object deputato, andando perdute allo shutdown
dell'applicazione.
Integrazione
in NetView
Le scelte architetturali che caratterizzano la nostra
applicazione si rivelano valide, e rendono triviale
il problema dell'integrazione delle nuove funzionalità,
la cui soluzione consiste nella definizione di una nuova
azione "config" a livello di FrontControllerServlet
e nella definizione di un dispatcher, ConfigDispatcher,
la cui unica attività consiste nell'invocare
la view "config.jsp" contenente la definizione
della Web UI del form di configurazione in formato JSF.
Il secondo ed ultimo passo dell'integrazione in NetView
delle nuove funzionalità consiste nella modifica
del deployment descriptor secondo quanto richiesto dalle
attuali specifiche Java Server Faces:
Definizione della classe listener NetViewServletContextListener,
la cui funzione - come vedremo - consiste nel gestire
il ciclo di vita dell'oggetto ApplicationHandler attraverso
i seguenti tag:
<listener>
<listener-class>
NetViewServletContextListener
</listener-class>
</listener>
L'attivazione delle funzionalità Java Server
Faces attraverso la dichiarazione del Faces Servlet
e la sua assegnazione alle URL /faces/*:
<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>
La
Web UI
L'interfaccia utente che implementa le funzionalità
di configurazione richieste dal cliente è contenuta
nella view "config.jsp", che passiamo ora
ad analizzare in dettaglio.
Le
pagine che utilizzano i componenti JSF dichiarano la
rispettiva tag library con la seguente sintassi:
<%@
taglib prefix="faces"
uri="http://java.sun.com/j2ee/html_basic/"
%>
Il
model object models.ConfigurationBean associato ai componenti
UI Java Server Faces utilizzati da NetView viene istanziato
come un normale JavaBean tramite una direttiva useBean:
<jsp:useBean
id="configurationBean"
class="models.ConfigurationBean" scope="session"
/>
Segue
quindi l'apertura del tag <faces:usefaces>, chiuso
al termine della view appena prima dell'inclusione di
"bottombar.jsp"; all'interno di tale tag è
possibile utilizzare liberamente i componenti JSF.
I
nostri elementi di interfaccia JSF vengono raggruppati
in un unico form, denominato "configForm"
e dichiarato con la seguente sintassi:
<faces:form
id="configForm" formName="configForm">
All'interno
del form provvediamo ad emettere le necessarie informazioni
testuali destinate all'utente con dei tag del tipo:
<faces:output_text
id="titleMsg" text="Descrizione breve:"
key="titleMsg" />
Tali
informazioni si sarebbero ovviamente potute presentare
a video in maniera più diretta; tuttavia, codificando
ogni messaggio in un apposito tag faces eseguiamo quell'attività
di formalizzazione dell'output che ci permetterà
in futuro di implementare con facilità sofisticate
funzionalità di internazionalizzazione e localizzazione.
Passiamo
quindi alla rappresentazione dei parametri di configurazione,
che viene effettuata con la massima semplicità
attraverso gli elementi di interfaccia utente selezionati
in fase di analisi.
Le
descrizioni di NetView vengono modellate come campi
di input textentry_input e textentry_textarea. Si noti
che, grazie all'esplicita associazione con le relative
property dei model object, lo sviluppatore è
completamente sgravato dal compito di gestire lo stato
dell'applicazione Web. JSF sincronizzerà automaticamente
componenti view e model object in risposta alle azioni
dell'utente.
<faces:textentry_input
id="appTitle" modelReference="${configurationBean.appTitle}"
/>
<faces:textentry_textarea
id="appDesc" modelReference="${configurationBean.appDesc}"
/>
Va
rilevato come la dichiarazione dell'attributo modelReference
avvenga in sintassi JSTL: in effetti, qualora ce ne
fossimo dimenticati, la Custom Tag Library Java Server
Faces è completamente integrata con JSP e JSTL,
e dal suo interno è possibile utilizzare tutta
la potenza e flessibilità di questi due framework.
Per
la password SNMP utilizziamo invece un campo di input
textentry_secret:
<faces:textentry_secret
id="snmpPassword"
modelReference="${configurationBean.snmpPassword}"
/>
La
modalità di log viene presentata all'utente come
un gruppo di bottoni radio:
<faces:selectone_radiogroup
id="logMode"
modelReference="${configurationBean.logMode}">
<faces:selectitems id="logModesList"
modelReference="${configurationBean.logModesList}"/>
</faces:selectone_radiogroup>
Si
noti che in questo caso, a titolo di esempio, abbiamo
scelto di non specificare i possibili valori della property
logMode all'interno della pagina JSP, ma di renderli
parte del model object models.configurationBean. Essi
risultano quindi completamente indipendenti dallo strato
di interfaccia utente.
Il
traffico massimo giornaliero viene impostato dall'utente
attraverso un campo textentry_input cui è associato
un LongRangeValidator che controlla l'ammissibilità
del valore inserito:
<faces:textentry_input
id="maxDailyTraffic"
modelReference="${configurationBean.maxDailyTraffic}"
size="10" >
<faces:validator
className=
"javax.faces.validator.LongRangeValidator"
/>
<faces:attribute
name=
"javax.faces.validator.LongRangeValidator.MINIMUM"
value="100" />
</faces:textentry_input>
Per
l'impostazione della notifica all'amministratore di
sistema operiamo una scelta opposta rispetto alla modalità
dei log. In questo caso i possibili valori di input
non fanno parte del model object, ma vengono specificati
a livello di interfaccia utente come sottotag <faces:selectitem>
del tag <faces:selectone_optionlist>, il quale
permette all'utente di operare la sua scelta da una
drop-down listbox.
<faces:selectone_optionlist
id="alarmMode"
modelReference="${configurationBean.alarmMode}">
<faces:selectitem value="email"
label="Notifica via E-mail" />
<faces:selectitem value="icq" label="Notifica
via ICQ" />
<faces:selectitem value="sms" label="Notifica
via SMS" />
</faces:selectone_optionlist>
Segue
quindi il tag <faces:command_button>, grazie al
quale l'utente ha la possibilità di confermare
le nuove impostazioni inviando il form al server; tale
tag verrà rappresentato dal Renderer sotto forma
di bottone:
<faces:command_button
id="ok" label="Ok" key="okButton"
commandName="configOk" />
La
sezione Java Server Faces della nostra view JSP termina
quindi con la chiusura del form e del container tag
JSF:
</faces:form>
</faces:usefaces>
L'implementazione
dei model object
I model object rappresentano lo stato dell'applicazione
Web ed hanno il compito di fornire servizi di persistenza
ai componenti di Web UI JSF. Nel nostro caso sarà
sufficiente codificare un unico model object, models.ConfigurationBean,
delegato a rappresentare i parametri di configurazione
impostati dall'utente attraverso la view "config.jsp";
come è lecito attendersi, si tratterà
di un JavaBean le cui proprietà corrisponderanno
perfettamente agli elementi di interfaccia utente analizzati
nel paragrafo precedente.
L'implementazione
delle descrizioni di NetView, della password SNMP e
della soglia di traffico è elementare e consta
semplicemente di quattro membri privati supportati dai
rispettivi accessori:
private
String appTitle="NetView versione 1.2";
private String appDesc="Web application di esempio
"+
"per MokaByte. "+
"Campo di test per JSP, JSTL e JSF";
private String snmpPassword="qwerty";
private int maxDailyTraffic=500;
public String getAppTitle() { return appTitle; }
public void setAppTitle(String appTitle) {
this.appTitle=appTitle;
}
public String getAppDesc() { return appDesc; }
public void setAppDesc(String appDesc) {
this.appDesc=appDesc;
}
public String getSnmpPassword() { return snmpPassword;
}
public void setSnmpPassword(String snmpPassword) {
this.snmpPassword=snmpPassword;
}
public int getMaxDailyTraffic() { return maxDailyTraffic;
}
public void setMaxDailyTraffic(int maxDailyTraffic)
{
this.maxDailyTraffic=maxDailyTraffic;
}
È
da rilevare come nessuna operazione esplicita ci venga
richiesta per la gestione del tipo della property maxDailyTraffic:
JSF si prende automaticamente cura della conversione
in intero di quanto inserito dall'utente nel form di
input.
Incredibilmente
semplice è la gestione della property alarmMode,
in cui verrà memorizzata la modalità di
notifica all'amministratore; essa viene infatti codificata
come una semplice String property - in maniera assolutamente
identica ad appTitle, appDesc e snmpPassword. Il nostro
model object è infatti completamente ignaro dell'esistenza
di una lista di valori ammissibili per questa proprietà,
funzionalità che viene integralmente gestita
da Java Server Faces dietro le quinte:
private
String alarmMode="email";
public String getAlarmMode() { return alarmMode; }
public void setAlarmMode(String alarmMode) {
this.alarmMode=alarmMode;
}
Appena
più complicata è l'implementazione della
property associata alla modalità dei log. In
questo caso, infatti, abbiamo scelto di rendere le possibili
impostazioni di questa proprietà parte integrante
del model object.
Provvediamo quindi a modellare tramite un'elementare
non-mutable data class la nozione di 'modalità
di log' come insieme di due valori stringa, pari rispettivamente
al codice della classe di log ed alla sua rappresentazione
visuale (descrizione):
public
class LogMode {
private String value;
private String label;
public LogMode(String value,String label) {
this.value=value;
this.label=label;
}
public String getValue() { return value; }
public String getLabel() { return label; }
}
Dotiamo
quindi il nostro model object della conoscenza di tutte
le modalità di log supportate; in considerazione
del carattere esemplificativo della nostra applicazione
decidiamo di innestare nel codice i dati corrispondenti:
private
LogMode logModes[]=new LogMode[] {
new LogMode("syslogd","Esterna syslogd")
,
new LogMode("xml","Interna XML")
,
new LogMode("sql","Interna SQL")
};
Nel
costruttore del model object provvediamo alla conversione
del vettore di oggetti LogMode nel formato gestito da
Java Server Faces, vale a dire una lista di oggetti
javax.faces.component.SelectItem:
private
ArrayList logModesList; // lista di oggetti
// SelectItem
public ConfigurationBean() {
// Popoliamo il vettore delle modalita' di log,
// creando un oggetto SelectItem per ogni LogMode
LogMode lm;
logModesList=new ArrayList(logModes.length);
for (int i=0;i<logModes.length;++i) {
lm=logModes[i];
logModesList.add(
new SelectItem(lm.getValue(),lm.getLabel(),
lm.getLabel())
);
}
.
.
.
}
Implementiamo
quindi la property logMode come semplice String property;
Java Server Faces - sulla scorta degli oggetti SelectItem
da noi specificati - provvederà in maniera autonoma
a gestire l'interazione con l'utente fornendo direttamente
al model object models.ConfigurationBean il codice della
modalità di log impostata via Web UI:
//
Modalita' di log corrente in formato JSF
// (value del LogMode corrispondente)
private String logMode;
public String getLogMode() { return logMode; }
public void setLogMode(String logMode) {
this.logMode=logMode;
}
Infine
ci assicuriamo di fornire un default valido per la modalità
di log, specificando un opportuno valore all'atto della
creazione del model object:
public
ConfigurationBean() {
.
.
.
// Impostiamo la modalita' di log corrente a syslogd,
// memorizzando in logMode (proprieta' JSF) il valore
// del LogMode corrispondente
logMode=logModes[0].getValue();
}
L'oggetto
ApplicationHandler
Come già fatto notare, ogni Web Application in
ambiente Java Server Faces deve possedere una classe
singleton che implementi l'interfaccia javax.faces.lifecycle.ApplicationHandler,
la cui responsabilità consiste nel dirigere la
navigazione dell'utente all'interno dell'applicazione
in risposta agli eventi di tipo application level. Nel
nostro caso l'implementazione di tale classe sarà
particolarmente semplice, non dovendo gestire la nostra
applicazione che un unico evento globale, corrispondente
alla conferma da parte dell'utente dei dati inseriti
nel form di configurazione.
Il
fulcro di un oggetto ApplicationHandler è rappresentato
dal suo metodo processEvent() che - in logica vagamente
JDK 1.0 - viene notificato allo scattare di qualsiasi
evento. Esso provvede quindi ad identificare l'evento
ricevuto e, in base allo stato dell'applicazione, aggiorna
i componenti del sistema e guida se necessario la navigazione
dell'utente all'interno delle View JSF / JSP:
public
class NetViewApplicationHandler implements
ApplicationHandler {
// Metodo di gestione degli eventi JSF; in NetView esiste
// un unico evento, "configOk", generato alla
conferma del
// form di configurazione
public boolean processEvent(FacesContext context,
FacesEvent facesEvent) {
boolean returnValue=false;
String treeId=null;
if (facesEvent instanceof FormEvent) {
// Abbiamo a che fare con un evento generato da
// un form
FormEvent formEvent=(FormEvent)facesEvent;
if (formEvent.getCommandName().
equals("configOk")) {
// L'utente ha confermato le modifiche
// al form di configurazione; torniamo
// alla pagina principale di NetView
treeId="/main";
}
}
.
.
.
return returnValue;
}
}
È
responsabilità dello sviluppatore gestire il
ciclo di vita dell'oggetto ApplicationHandler, istanziandolo
alla creazione del ServletContext dell'applicazione
e rilasciandolo alla sua distruzione.
Questo ruolo viene svolto in NetView dalla classe NetViewServletContextListener,
che abbiamo visto venire dichiarata come listener a
livello di deployment descriptor:
public
class NetViewServletContextListener
implements ServletContextListener {
public NetViewServletContextListener() {
}
public void contextInitialized(ServletContextEvent e)
{
// Costruiamo ed attiviamo l'ApplicationHandler
// di NetView
ApplicationHandler handler=
new NetViewApplicationHandler();
.
.
.
lifecycle.setApplicationHandler(handler);
}
public void contextDestroyed(ServletContextEvent e)
{
}
}
Conclusione
Con il presente articolo si conclude la trattazione
di Java Server Faces, il framework Java per la realizzazione
di interfacce utente ad applicazioni Web e distribuite:
insieme ne abbiamo esaminato la struttura generale ed
i componenti fondamentali, cosa che ci ha permesso di
apprezzare le virtù di loosely coupling, componentizzazione,
riusabilità ed estensibilità di questa
API.
Successivamente abbiamo applicato le conoscenze così
ottenute ad una situazione pratica che, per quanto limitata,
ha chiarito come la qualità del design di Java
Server Faces si accompagni ad una notevole semplicità
d'uso e di comprensione.
Il prossimo mese approcceremo l'ultimo degli argomenti
di questa lunga serie di articoli dedicata al tema delle
Web UI in Java. In particolare, dopo esserci sino ad
ora concentrati sullo studio delle due fondamentali
Tag Library JSTL - nelle sue sottolibrerie Core, XML,
DB e I18N - e Java Server Faces, vedremo come sia possibile
per lo sviluppatore implementare ed utilizzare nuove
Custom Tag Library, con le quali estendere le funzionalità
del framework Java Server Pages.
Bibliografia
[1] JSF - Java Server Faces: http://java.sun.com/j2ee/javaserverfaces
[2] Lavinio Cerquetti: "JSF: Java Server Faces
- I parte", Mokabyte N. 71 - Febbraio 2003
Risorse
Scarica qui il codice
presentato nell'articolo (NetView versione 1.2).
L'implementazione di esempio di NetView è stata
testata sotto JBoss 3.0.3 e Tomcat 5 (Milestone 5.0.0)
in ambiente Linux con database IBM DB2.
Lavinio
Cerquetti si occupa di design e sviluppo del software
in ambienti distribuiti ed in architetture J2EE multi-tier.
Può essere contattato all'indirizzo di e-mail
lcerquetti@mokabyte.it
|