Web Application Engineering

Java Server Faces

Cristian Lucchesi

Istituto di Informatica e Telematica - CNR

Web application: evoluzione

evoluzione delle applicazioni web

Java Server Faces (JSF)

JSF: tecnologie pre-esistenti

Servlet
sono il fondamento delle web application nell'architettura J2EE.
l'approccio a basso livello per la produzione del markup (lo sviluppo di una pagina web richiede, sostanzialmente, allo sviluppatore di codificare un programma che produca come output i tag della pagina html
Le servlet API forniscono un insieme di funzionalità di base (session tracking, security, logging, filtering, lifecycle events, ecc) di cui si giova il framework JSF
JSP
rappresentano il meccanismo di template standard definito nell'architettura J2EE.
le pagine JSP sono orientate ai tag: utilizzano, cioè, oltre ai consueti marcatori HTML i cosiddetti custom tag per introdurre comportamento dinamico nella pagina. Di più, consentono di inserire nella pagina codice Java embedded alternato ai tag descritti.

JSF Overview

JSF Overview

Esempio con JSF

Pagina inputname.jsp con la richiesta del nome utente inputname.jsp
Pagina greeting.jsp con il saluto all'utente greeting.jsp

Struttura tipica di un progetto JSF

rootFolder
  /ant
    build.xml          -> ant build script

  /src                 -> contiene le classi Java ed i file properties

  /WebContent
    /WEB-INF
      /classes         -> ospiterà classi Java compilate e file properties
        /lib
          jsf-impl.jar   
          jsf-api.jar    
      faces-config.xml -> lista dei bean gestiti e regole di navigazione
      web.xml  ->      -> descrittore servlet e di altri componenti
    /pages             -> folder che ospiterà le pagine jsf

Navigation

Navigation rules
<navigation-rule>
  <from-view-id>/pages/inputname.jsp</from-view-id>
  <navigation-case>
    <from-outcome>greeting</from-outcome>
    <to-view-id>/pages/greeting.jsp</to-view-id>
  </navigation-case>
</navigation-rule>
    

Creare i Managed Bean

package examples.jsf;

public class PersonBean {

   String personName;
	
   public String getPersonName() {
      return personName;
   }

   public void setPersonName(String name) {
      personName = name;
   }

Dichiarare i bean in faces-config.xml

<managed-bean>
  <managed-bean-name>personBean</managed-bean-name>
  <managed-bean-class>examples.jsf.PersonBean</managed-bean-class>
  <managed-bean-scope>request</managed-bean-scope>
</managed-bean>
  

faces-config.xml

<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC
  "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"
  "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">

<faces-config>
  <navigation-rule>
   <from-view-id>/pages/inputname.jsp</from-view-id>
    <navigation-case>
     <from-outcome>greeting</from-outcome>
     <to-view-id>/pages/greeting.jsp</to-view-id>
   </navigation-case>
  </navigation-rule>

  <managed-bean>
    <managed-bean-name>personBean</managed-bean-name>
    <managed-bean-class>jsfks.PersonBean</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
  </managed-bean>
</faces-config>  
  

file properties

messages.properties
inputname_header=JSF KickStart
prompt=Tell us your name:
greeting_text=Welcome to JSF
button_text=Say Hello
sign=!
    

inputname.jsp

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:loadBundle basename="examples.jsf.messages" var="msg"/>

<html>
 <head>
  <title>enter your name page</title>
 </head>
 <body>
   <f:view>
     <h1>
      <h:outputText value="#{msg.inputname_header}"/>
     </h1>
     <h:form id="helloForm">
      <h:outputText value="#{msg.prompt}"/>
      <h:inputText value="#{personBean.personName}" />
      <h:commandButton action="greeting" value="#{msg.button_text}" />
     </h:form>
   </f:view>
 </body>
</html>
  

inputname.jsp: spiegazioni

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>            
<f:loadBundle basename="jsfks.bundle.messages" var="msg"/>
  
<h:outputText value="#{msg.inputname_header}"/>
  

inputname.jsp: spiegazioni (cont)

1 <h:form id="helloForm">
2   <h:outputText value="#{msg.prompt}"/>
3   <h:inputText id="name" value="#{personBean.personName}" />
4   <h:commandButton action="greeting" value="#{msg.button_text}" />
5 </h:form>
  

greeting.jsp

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:loadBundle basename="jsfks.bundle.messages" var="msg"/>

<html>
  <head>
   <title>greeting page</title>
  </head>    
  <body>
     <f:view>
     	<h3>
 	 <h:outputText value="#{msg.greeting_text}" />,
 	 <h:outputText value="#{personBean.personName}" />
         <h:outputText value="#{msg.sign}" />
    	</h3>
     </f:view>
 </body>	
</html>
  

web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.5"
  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-app_2_5.xsd">

    <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>*.jsp</url-pattern>
    </servlet-mapping>
</web-app>
  

Utilizzare i validatori standard

...
<f:view>
  <h1>
    <h:outputText value="#{msg.inputname_header}"/>
  </h1>
  <h:form id="helloForm">
    <h:outputText value="#{msg.prompt}"/>
    <h:inputText value="#{personBean.personName}" required="true" />
    <h:commandButton action="greeting" value="#{msg.button_text}" />
  </h:form>
</f:view>
...
  

Verificare la lunghezza di un campo

...
  <h:form id="helloForm">
    <h:outputText value="#{msg.prompt}"/>
    <h:inputText value="#{personBean.personName}" required="true">
      <f:validateLength minimum="2" maximum="10"/>
    </h:inputText>
    <h:commandButton action="greeting" value="#{msg.button_text}" />
  </h:form>
...
  
Validatori standard

Custom validator

è possibile definire propri validatori:
  • implementando l'interfaccia javax.faces.validator.Validator, in particolare
    public void validate(FacesContext cxt, UIComponent comp, Object value);
  • definendo il validatore in faces-config.xml
    <validator>
      <validator-id>MyValidator<validator-id>	
      <validator-class>validator.MyValidator<validator-class>
    <validator>
  • utilizzando nella jsf l'elemento
    <f:validate validatorId="myValidator" />

JSF: component tree

JSF ComponentTree

JSF: rendering

JSF life-cycle

JSF life-cycle

JSF life-cycle: le fasi iniziali

fase di Restore View
viene ricercato il component tree della pagina richiesta, se si tratta della prima richiesta (initial request) il component tree viene creato.
se la request non presenta dati in POST, l'implementazione JSF porta alla fase Render Response (accade per esempio quando la pagina viene richiesta la prima volta)
fase di Apply Request Values
JSF itera sui componenti affinché ciascuno di essi memorizzi i dati di pertinenza (submitted values).

JSF life-cycle: Process Validation

fase di Process Validation
se sono definiti validatori su uno o più componenti viene attivato il processo di validazione
se ci sono errori di conversione o validazione, viene invocata direttamente la fase Render Response che porta al ri-display della pagina per garantire all'utente di correggere i dati
se non ci sono errori si aggiorna il modello dei dati. Durante la fase Update Model i "local values" sono utilizzati per aggiornare le proprietà dei bean associati ai componenti

JSF life-cycle: fasi finali

fase di Invoke Application
il metodo indicato nell'attributo action viene eseguito
questo metodo tipicamente implementa la logica di business associata all'azione dell'utente
il metodo ritorna un outcome string che viene passata al navigation handler il quale provvede al look up della pagina successiva
fase di Render Response
effettua l'encoding della risposta e la spedisce al browser
quando l'utente genera una nuova richiesta il ciclo ricomincia

Riferimenti