JSF è la tecnologia che si propone di rendere più semplice e produttiva l‘attività di sviluppo dell‘interfaccia nelle applicazioni web Java EE. Vediamo un primo semplice esempio di applicazione.
Introduzione
Negli articoli precedenti abbiamo introdotto alcuni concetti teorici di base su JSF. Abbiamo parlato del modello a componenti ed eventi, e abbiamo introdotto il ciclo di vita di gestione delle richieste di JSF. Ora andremo a vedere un primo semplice esempio di applicazione, il classico login, che ci consentirà di capire come i concetti esaminati si traducano poi nella pratica.
L‘applicazione che vedremo è volutamente semplice, in quanto l‘obiettivo è puntualizzare alcuni concetti e non esaminare nel dettaglio tutte le possibilità fornite a livello di codice da JSF.
Un semplice esempio
L‘esempio che vediamo è un‘applicazione costituita da due pagine. La prima, la login.jsp, contiene il classico form di immissione delle credenziali dell‘utente, username e password. La seconda pagina, risultato.jsp, è la pagina che informa sull‘esito dell‘operazione di login. L‘esempio è disponibile come WAR nel file allegato scaricabile dal link in alto a sinistra.
Il codice della pagina JSP login.jsp è il seguente:
<%@ page contentType="text/html;charset=windows-1252"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
login
Username:
Password:
Come si vede la pagina è del tutto simile ad una classica pagina JSP alla quale siamo abituati, tag HTML insieme ad altri particolari tag. Già da una prima analisi si possono individuare alcuni elementi che contraddistinguono la presenza di JSF nel codice della pagina.
- La dichiarazione delle due taglib
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
la taglib core che definisce i tag di base di JSF indipendenti dalla tecnologia di rendering della pagina e la taglib html che fornisce componenti riusabili specifici per renderizzare in HTML i componenti server di JSF.
- I custom tag utilizzati
, e che rappresentano una text-box di input di tipo text, una di tipo password ed un command button. - La definizione del valore degli input di tipo text e password e dell‘azione associata al command button con una notazione simile a quella dell‘Expression Language.
La pagina risultato.jsp è una pagina di saluto all‘utente che ha effettuato il logon ed è la seguente:
<%@ page contentType="text/html;charset=windows-1252"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
risultato
Anche in questo caso notiamo la definizione delle taglib di JSF e la presenza del tag
Entrambe le pagine fanno riferimento, vedremo come, a un JavaBean fatto come segue:
package it.mokabyte.jsf;
public class UtenteBean {
private String username;
private String password;
public UtenteBean() {
}
public String login() {
String outcome;
//Qui va inserito il richiamo alla logica per
//l‘autenticazione dell‘utente
if ((username != null && username.trim().equals("mokabyte")) &&
(password != null && password.trim().equals("mokabyte"))) {
outcome = "success";
} else {
outcome = "failure";
}
return outcome;
}
}
public void setUsername(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
public void setPassword(String password) {
this.password = password;
}
public String getPassword() {
return password;
}
}
Non ci resta che vedere come questi elementi della nostra semplice applicazione interagiscono.
La configurazione di una applicazione JSF
Per comprendere come i vari elementi visti siano legati è necessario introdurre un elemento fondamentale di una applicazione JSF, il file faces-config.xml. Questo file definisce tutte le innumerevoli caratteristiche di una applicazione JSF. Nel contesto del nostro semplice esempio ci serve introdurre le due definizioni di base che è necessario fare per consentire all‘applicazione di funzionare: le navigation rules ed i managed beans.
Nel faces-config.xml è possibile definire, esternamente al codice, tutto il flusso dell‘applicazione web in maniera assolutamente analoga a quanto veniva fatto in Struts nello struts-config.xml.
La sezione del file che definisce le regole di navigazione per la nostra applicazione è la seguente:
/login.jsp
success
/risultato.jsp
failure
/login.jsp
Come si vede è possibile definire delle regole di navigazione tra i tag
Ora resta da comprendere come fornire al framework l‘informazione necessaria alla gestione del flusso di navigazione e come legare le informazioni che provengono dall‘interfaccia utente ad oggetti di business. Qui entrano in gioco i cosiddetti Managed Beans.
È possibile definire a livello di applicazione dei bean che il framework si prende in carico di gestire. Questi bean costituiscono il legame in una applicazione JSF tra il livello di View e il livello di Model. Sono qualcosa di analogo alle Action di Struts anche se in realtà in questi bean sono sia presenti attributi che è possibile mappare agli elementi della pagina JSP sia metodi detti action methods che vanno in esecuzione a fronte di azioni effettuate dall‘utente sull‘interfaccia. Si potrebbe dire in maniera molto semplicistica che un Managed Bean è una classe che racchiude in sà© le funzionalità che in Struts erano assolte da ActionForm e Action.
La definizione di un managed bean nel faces-config.xml è la seguente:
utente
it.mokabyte.jsf.UtenteBean
session
Viene associato in questo modo un nome logico “utente” a una istanza della classe it.mokabyte.jsf.UtenteBean vista in precedenza, e questa istanza viene memorizzata in sessione. L‘istanziamento e la gestione di questo bean è completamente a carico del framework. All‘interno delle viste dell‘applicazione è possibile quindi fare riferimento al nome logico ad esso associato per leggere e scrivere nelle proprietà del bean o per referenziare un suo metodo con la notazione vista nelle pagine JSP precedenti: value=”#{utente.username}”.
Questo è quello che abbiamo fatto nella pagina di login con le proprietà username e password e con il metodo login.
Avendo messo insieme i vari pezzi della nostra semplice applicazione dovrebbe essere più chiaro cosa avviene a run-time, tenendo sempre a mente il ciclo di vita di gestione di una richiesta JSF visto nell‘articolo precedente.
Ricevuta la richiesta per la pagina di login il framework costruisce il tree di componenti della pagina, lo memorizza e passa alla fase di Render Response per la sua renderizzazione. L‘utente inserisce username e password nei campi di input e clicca sul command button. A questo punto i valori inseriti negli input text vengono memorizzati nella fase Apply Requests nei componenti lato server che rappresentano i campi di input. Successivamente nella fase Update Model Values gli attributi validi e tipizzati vengono memorizzati negli attributi corrispondenti del managed bean. Nel nostro caso non sono state definite validazioni sui campi. A questo punto ha luogo la fase di Invoke Application nella quale l‘action method login() va in esecuzione. La logica di autenticazione viene eseguita e il framework riceve il risultato che gli consente di inoltrare il flusso alla vista corretta nella fase di Render Response.
Tutto questo avviene ovviamente alle spalle dello sviluppatore che è quindi svincolato dal dover realizzare in proprio tutta una serie di operazioni quali acquisizione dei campi di input dalla request, conversione e validazione dei campi di input, gestione del flusso di navigazione, e può invece concentrarsi sullo sviluppo della sua logica applicativa.
Inoltre con JSF lo sviluppatore è sollevato anche dallo sviluppo dei componenti di interfaccia che sono forniti in gran numero e per tutte le esigenze dal framework.
Definizione del controller JSF nel web.xml
Per far si che le richieste vengano gestite dal controller di JSF, che manco a dirlo è una servlet, è necessario effettuare le opportune definizioni nel web.xml dell‘applicazione.
Innanzitutto va definita la servlet di controllo di JSF nel modo seguente:
Faces Servlet
javax.faces.webapp.FacesServlet
1
Va poi ovviamente definito il mapping corretto per questa servlet. Un modo per effettuare il mapping è il seguente:
Faces Servlet
/faces/*
In questo modo ogni richiesta mappata su un URL del tipo /faces/nomepagina.jsp viene gestita dal controller di JSF.
Ad esempio, l‘URL di richiesta della nostra pagina di login.jsp è del tipo:
http://server_name:port/appname/faces/login.jsp
Conclusioni
In questo articolo abbiamo visto un primo semplicissimo esempio di applicazione JSF. Ovviamente lo scopo non era di presentare una applicazione spettacolare ma piuttosto di introdurre alcuni elementi di base che consentano di iniziare a comprendere, da un lato, come i concetti teorici già visti si traducono nella pratica e, dall‘altro, come è strutturata a livello di codice un‘applicazione JSF.
Ovviamente sono stati tralasciati per semplicità molti aspetti quali la validazione dei campi, la gestione dei messaggi di errore, le modalità di invocazione della business logic e molti altri che saranno presentati successivamente.
Riferimenti
[1] David Geary, Cay Horstmann, “Core Java Server Faces”, Sun Microsystems Press, 2004
[2] Bill Dudney, Jonathan Lehr, Bill Willis, LeRoy Mattingly, “Mastering Java Server Faces”, Wiley Publishing, 2004
[3] Kito D. Mann, “Java Server Faces In Action” Manning Pubblications, 2005
[4] Autori Vari, “The Java EE 5 Tutorial”, Sun Microsystems, Febbraio 2007