Java Server Faces O Reilly Cap 6

CAP 6

6.1 The Basics

6.1.1 Using JSF Components in a JSP Page

- La pagina jsp comincia con due direttive tag lib
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
che dichiarano le librerie tag usate nella pagina. Ogni direttiva taglib contiene due attributi l'uri specifica l'id univoco della libreria e il prefisso definisce il prefisso di namespace usato nella pagina. La uri non vuol dire che sia accessibile tramite web ma è solo un modo per scegliere un identificativo univoco.
- gli elementi con prefisso f sono quelli core indipendenti dal linguaggio di markup della pagina come i convertirori e validatori. La f sta per Faces. I prefissi possono variare l'importante e che siano unici nella pagina.
- h sta per html e sono componenti che devono essere renderizzati come html

- <f:view> contiene un istanza di javax.faces.component.UIViewRoot questo è un componente che agisce come contenitore per tutti gli altri. UIViewRoot sarà il padre e tutti i componenti all'interno saranno suoi figli.
- tutti gli elementi di questo tipo <f: sono detti anche custom tag

… il resto dei componenti <f: li ho saltati per ora

6.1.2 Creating JSF Components

- quando un container jsp processa una pagine manda tutti i template testuali al browser ma quando incontra una elemento di tipo custom action invoca il corrispondente tag handler. Tutti i JSF tag handlers usano le api jsf per creare componenti e associare loro con i renders la prima volta che l'utente richiede la pagina. Nel capitolo c'è un esempio di come il tag <h:inputText> viene tradotto in codice java
- Quando incontra un custom tag per prima cosa prende un riferimento all'istanza corrente della classe javax.faces.context.FacesContext. Un istanza di questa classe è associata con ogni ric"hiesta e contiene informazione sui parametri richiesti, header session data e altro.
- javax.faces.webapp.UIComponentTag è la classe che tutti i tag handlers JSF devono estendere implementando il getFacesContext() , così questo metedo è disponibile per tutti gli handlers. In altri tipi di classi si può usare il metodo statico FacesContext getCurrentInstance() per ottenere l'istanza FacesContext quando non è disponibile in altro modo, "as long as the code that calls it runs in the context of a JSF request."
- La classe FacesContext fornisce un metodo accessorio per l'istanza della javax.faces.application.Application. Questa contiene un numero di metodi per creare istanza di classi configurabili .
- Ci sono classi per l'implementazioni di componenti di diverso tipo ma possono essere sovrascritte per ottenere maggiore personalizzazione. Il metodo createComponent() restituisce una nuova istanza di una classe registrata per il componente chiamato javax.faces.Input
- Renderer classes are also registered under symbolic renderer type names; in order to associate the component with a renderer type, the setRendererType( ) is called with the renderer type name, i.e., javax.faces.Text in this example
- Esempio di un componente sovrascritto che non analizzo nel dettaglio
-Come già detto tutti i componenti estendono la classe javax.faces.webapp.UIComponentTag, questa esegue il metodo getParentUIComponentTag( ) che localizza il tag handler per del componente padre. Al componente che il tag handler rappresenta vi si può avere accesso attraverso il metodo getComponent() , che ritorna un tipo javax.faces.component.UIComponent che è la classe astratta che tutti i componenti JSF estendono
- Per accedere ai componenti padre si usa il metodo getChildren() che restituisce una java.util.List, con questa si possono fare tutte le manipolazioni alla lista dei figli. Seguono una serie di metodi per operare sulla lista di figli.
- Quando richiedi una pagina JSP come nell'esempio 6.1 tutti i JSF di tutti i tag handlers vengono creati i rispettivi componenti con le loro istanze di classi e viene settato il grado di parentela che si vede nella figura

6.3

6.1.3 Rendering the View

-altre considerazioni sui tag e il loro funzionamento saltate e vediamo il primo esempio.
- analizziamo il codice del primo esempio 6.1
- Il risultato del processo della pagina JSP contenente i componenti action è quello visualizzato sotto
- <form method="post" action="/jsfbook/expense/stage1/filterArea.faces">
il primo punto d'interesse è l'attributo action dell'elemento form. Il form render genera una url che verrà mandata in post.
- annidata nell'elemento <form> ci sono gli elementi <input> pe ogni componente JSF annidato.
From: <h:inputText id="from" size="8" /> From: <input type="text" name="_id0:_id1">
L'attributo id deve essere univoco se non viene specificato JSF lo genera automaticamente. Conviene specificare id espliciti se si deve accedere al form con altri linguaggi cliet side, altrimenti conviene lasciare fare a lui.
- oltre ai campi <input> normali c'è anche un campo hidden <input type="hidden" name="_id0"> che rappresenta il componente form . Quando la form viene spedita viene usato questo campo per identificare la form stessa utile in caso di più form nella stessa vista.

6.1.4 Saving the View State

- Ci sono due modi per mantenere lo stato nelle applicazioni web, salvare lo stato sul server o mandare sempre lo stato nella richiesta.
- JSP usa il primo approccio tramite id univoci, sessioni e scope.
- Salvando lo stato sul server si possono avere problemi di scalabilità, alto consumo di risorse ecc, mandandolo avanti e indietro si hanno problemi di banda soprattutto su connessioni lente. JSF permette di scegliere l'approccio preferito specificando un parametro nel file WEB-INF/web.xml
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
- I valori d'inizializzazione del parametro javax.faces.STATE_SAVING_METHOD possono essere server o client. Quando viene salvato lo stato nel client, JSF colleziona lo stato che deve essere salvato tramite il metodo saveState() (sono presenti altri dettagli di come viene eseguito il metodo)

6.1.5 Installing and Configuring a JSF Web Application

- Vediamo la struttura del primo esempido:
dentro jsfbook/expense/stage1 ci sono le pagine jsp, con i tag JSF
in /WEB-INF/ c'è il file web.xml e il faces-config.xml
in /WEB-INF/lib le librerie jsf che servono
- Nel file web.xml sono presenti queste dichiarazioni
<servlet>
<servlet-name>FacesServlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FacesServlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
- <servlet-name> dichiara un nome per le servlet che tutti i processi di tutte le richieste JSF
- <servlet-mapping> mappa le richieste con un percorso che finisce con un .faces , questa è l'estensione raccomandata. Per ogni richiesta FacesServlet rimpiazza l'estensione .faces con una .jsp e usa il path modificato per trovare la pagina definita per la vista corrispondente. Se .faces è già utilizzato se ne può usare un altra e si può mettere anche un prefisso come /faces/*
- se hai uno strumento di sviluppo JSF e si sta usando un container JSP 2.0, si potrebbe usare una estensione .jsf per le pagine jsp .

6.1.6 Running a JSP Page Containing JSF Components

- come si vede chiaramente nella figura 6.4 il codice statico della pagina viene riportato così com'è mentre quello taggato jsf viene prima tradotto in un albero JSF (quindi vengono preparate tutte le classi) e poi viene generato l'html rispettivo

6.2 Binding Components to Model Properties

- l'esempio 6.1 riproduce gli stessi valori nella pagina risultante.
- usiamo i bean per separare la logica dall'interfaccia, analizziamo ReportHandler.java
- I valori del bean alla creazione dello stesso sono di default poi vengono scritti quando l'utente manda qualcosa.
- di solito è presente anche un handler per i dati del bean

6.2.1 Using JSF EL Expressions

- Le espressioni JSP EL vengono valutate quando la pagina viene processata, cioè quando viene mandata la risposta.
- Anche JSF supporta un EL. Sintatticamente l'EL di JSP e quello di JSF sono identici. La differenza principale sta che JSF può valutare la l'espressione EL sia quando processa l'input che l'utente ha mandato sia quando renderizza la risposta. Per distingure tra le due espressioni si usano differenti delimitatori in JSP si usa ${expression}, mentre in JSF si usa #{expression}.
- Interessante tradurla in futuro: To bind a component's main value to a property of a bean or an element of another data structure, JSF uses a value binding expression. A value binding expression is the part of a JSF EL expression that evaluates to a bean property, a java.util.List or array element, or a java.util.Map entry. The entity a value binding points to can be both read and written. In programming lingo, this amounts to what's often called an rvalue (the right-hand side of an assignment expression) for read access and an lvalue (the left-hand side of an assignment expression) for write access
- Alcuni componenti come un componente di output rappresentano un valore di read-only. Non ci sono modi tramite i quali un utente può cambiarne il valore. Tutti i componenti hanno un numero di proprietà oltre al loro valore principale. Si possono usare espressioni di binding per settare un valore in output ma anche espressioni in JSF EL come per esempio
<h:outputText value="#{report.startDate} to #{report.endDate}" />
- Così come JSP EL anche JSF EL ha accesso alle variabili dell'oggetto. Al contrario dell'EL di JSP in quello di JSF non ci sono le variabili pageScope and pageContext ma ne sono introdotte altre due view and facesContext. Nella tabella 6.2 vi sono le variabili disponibili e la loro descrizione.
- La ragione per cui pageScope and pageContext sono escluse e data dal fatto che esistono durante il processo di una pagina JSP ma in JSF si possono valutare espressioni EL prima che la pagina JSP sia processata. Un'altra ragione di questa esclusione sta nel fatto che JSF può essere usata con altre teconologie oltre a JSP. La variabile facesContext rimpiazza pageContext fornendo le stesse informazioni e altre in più. Con la variabile view si può accedere ad informazioni del UIViewRoot per esempio usando una notazione come questa
#{view.children[0].children[0].valid}
- il primo figlio della view con indice 0 è la componente form e il primo figlio della form è il componente di input che ha una componente chiamata valid

6.2.2 Using Value Binding Expressions

- nell'esempio 6.2 si vede come far caricare i valori del bean al caricamento della pagina in tutti i campi di input si mette l'espressione EL che legge il valore <h:inputText size="8" value="#{reportHandler.to}" />
- <h:inputText size="8" value="#{reportHandler.to}">
<f:convertDateTime dateStyle="short" />
</h:inputText>
questo tag permette la conversione tra il tipo di dato String and java.util.Date
- le conversioni possono essere configurate in modi diversi usando attributi opzionali. Qui è stato usato l'attributo dateStyle per i dettagli vedere la pagina del libro.

6.2.4 Creating Objects Automatically as They Are Needed

- Usando l'esempio visto prima ci si chiede come vengono presi i valori. Vengono fatti automaticamente da jsf al momento, creando e configurando istanze della classe definita in faces-config.xml
- Ecco il codice xml usato per associare la pagina al bean
<managed-bean>
<managed-bean-name>reportHandler</managed-bean-name>
<managed-bean-class>
com.mycompany.expense.ReportHandler
</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
- i tre elementi visti sopra sono obbligatori, lo scope può essere di 4 tipi request, session, application, and the special value none
- quando JSF valuta un'espressione e incontra una variabile che non esiste in nessuna di questi scopes, consulta il file di configurazione e crea un'istanza del bean che matcha con il nome. Se lo scope è diverso da none JSF salva l'istanza nello scope specifico. Lo scope none può essere utile per applicazioni come l'ora corrente che deve ogni volta essere calcolata.

6.3 Conditionally Render Components

- per effetuare l'abilitazione o meno dei componenti si usano i tag combinati con le proprietà del bean
- l'esempio suggerisce che il bean ReportHandler includa al suo interno una classe Rules che definisca le regole, una classe Report che combinata con la Rules fornisce l'informazione da visualizzare o meno.

- Il metodo isManager ha bisogno di alcune spiegazioni. Come visto la sicurezza in ambiente container si basa su ruoli assegnati a utenti quando la web application viene deployata. Per verificare se un determinato utente fa parte di un determinaro ruolo la servlet HttpServletRequest chiama isUserInRole( ). Che è il metodo usato da isManager().
- Il metodo isManager() prende un riferimento all'istanza di FacesContext attraverso il metodo statico getCurrentInstance(). Metodi che non sono direttamente collegato con JSF sono delegati alla classe ExternalContext ottenibile attraverso getExternalContext(). isUserInRole() è uno di quei metodi e il metodo isManager() chiama lui con nome del ruolo manager e restituisce il risultato.
- Il metodo getCurrentUser() usa la stesso tecnica per ottenere un riferimento a ExternalContext e usa il metodo getRemoteUser() per ottenere l'username per autenticare l'utente facendo la richiesta.

6.3.2 Conditionally Include Components Using Bean Properties

- Tutti gli elementi di JSF hanno una proprietà di render. Se la si setta a false il componente e i suoi figli rimangono nella view ma non viene mai chiesto di renderizarsi.
il metodo per visualizzare i tasti chiamato è isManager() che
public boolean isManager() {
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext ec = context.getExternalContext();
return ec.isUserInRole("manager");
}

Salvo diversa indicazione, il contenuto di questa pagina è sotto licenza Creative Commons Attribution-ShareAlike 3.0 License