Apache MyFaces: un’implementazione Open Source delle specifiche JSF

In questo articolo analizzeremo il progetto Apache MyFaces che ha come scopo di creare e manutenere una implementazione Open Source (secondo la licenza Apache versione 2) delle specifiche JavaServer Faces, inoltre include una serie di sotto progetti che forniscono componenti aggiuntivi, servizi di integrazione per altre tecnologie (ad esempio Portali), etc… .

La lista completa dei sotto progetti include:

  • Core: un’implementazione delle specifiche e dei componenti JSF 1.1, JSF 1.2, JSF 2.0 e JSF 2.1 come specificato dalle JSR 127JSR 252 and JSR 314 rispettivamente;
  • Portlet Bridge: un’implementazione delle specifiche JSF Portlet Bridge come specificato dalla JSR 301;
  • Tomahawk: un set di componenti JSF components creati dal team di sviluppo MyFaces prima che passasse sotto l’egida Apache;
  • Trinidad: un set di componenti JSF donati a MyFaces da Oracle, prima conosciuti come ADF Faces;
  • Tobago: un set di componenti JSF sviluppati per MyFaces da Atanion GmbH;
  • Orchestra: un framework utilizzato per gestire la persistenza delle sessioni attraverso scope diversi;
  • Extensions Validator: un framework per la validazione JSF centrica, basato sulle annotazioni;
  • Others: sotto progetti più piccoli quali ad esempio MyFaces CommonsMyFaces Shared.

Come si può notare esiste un componente Core per ogni specifica versione di JSF, dalla 1.1 alla 2.1 che è la versione più recente disponibile e che andremo ad usare nei nostri esempi. La versione JSF 2.1 richiede come requisito la JVM 1.5 o successiva, e le implementazioni JSP 2.1, JSTL 1.2 e Java Servlet 2.5.

Il componente Core si divide poi in due sottomoduli:

  • MyFaces API: implementa tutte le classi che sono definite nella spefica JSF;
  • MyFaces Impl: fornisce classi di supporto (invisibili) che il codice di uno sviluppatore non invoca direttamente, ma che sono necessarie per il funzionamento del framework. Ad esempio le classi di rendering per i componenti JSF.

Iniziamo andando a  scaricare le librerie Core, che troviamo a questo indirizzo:

http://myfaces.apache.org/download.html

la versione più recente al momento in cui scriviamo è la 2.1.1.

Nella stessa pagina in basso troviamo i link ai download per gli altri sotto progetti, in particolare se andiamo sul link di MyFaces Tomahawk (http://myfaces.apache.org/tomahawk/download.html) possiamo recuperare un file .war di esempi che ci permettono di visionare tutti i componenti a disposizione.

Vediamo ora come creare un esempio funzionante utilizzando l’IDE Eclipse.

Dalla barra dei menu di Eclipse clicchiamo su File -> New -> Project…, nel wizard per il New Project, selezioniamo Web -> Dynamic Web Project:

Creiamo un nuovo Progetto Web Dinamico

Clicchiamo su Next si aprirà questo pannello:

Inseriamo il nome del Progetto (TestMyFaces), il runtime Target (abbiamo scelto Tomcat v7.0) e per Configuration selezioniamo dalla tendina il valore JavaServer Faces v2.0.

Clicchiamo su Next finchè non arriviamo alla finestra JSF Capabilities:

Elenco delle librerie JSF presenti in Eclipse

Dobbiamo ora includere le librerie Core e Impl di MyFaces, lo facciamo cliccando su Manage Libraries:

clicchiamo su Manage libraries...

Clicchiamo poi su New… e come User Library Name inseriamo MyFaces-2.1.1:

Indichiamo il path delle nostre librerie MyFaces

Ora possiamo includere la libreria MyFaces ed infine clicchiamo su Finish:

Spuntiamo la casella di MyFaces-2.1.1

Dobbiamo ora includere le librerie prerequisito di MyFaces Core che sono:

  • commons-beanutils-1.8.3.jar;
  • commons-codec-1.3.jar;
  • commons-collections-3.2.jar;
  • commons-digester-1.8.jar;
  • commons-logging-1.1.1.jar.

queste librerie le troviamo all’interno del pacchetto zip o tar.gz che contiene le librerie Core.

Abbiamo inoltre bisogno delle librerie da cui dipende MyFaces Tomahawk, che troviamo nel pacchetto zip o tar.gz che contiene gli esempi (http://myfaces.apache.org/tomahawk/download.html)):

  • batik-awt-util-1.6-1.jar;
  • batik-ext-1.6-1.jar;
  • batik-gui-util-1.6-1.jar;
  • batik-util-1.6-1.jar;
  • commons-el-1.0.jar;
  • commons-fileupload-1.2.1.jar;
  • commons-io-1.3.2.jar;
  • commons-lang-2.4.jar;
  • commons-validator-1.3.1.jar;
  • jstl-1.2.jar;
  • oro-2.0.8.jar;
  • standard-1.1.2.jar;
  • tomahawk-1.1.10.jar;
  • xml-apis-1.0.b2.jar;
  • xmlParserAPIs-2.0.2.jar.

Tutte queste librerie le inseriamo nella cartella WEB-INF/lib come mostrato in figura:

Inseriamo le librerie nella cartella WebContent/WEB-INF/lib

inserendole in quella cartella, le librerie saranno caricate automaticamente all’interno del Build Path del progetto, sotto la voce Web App libraries:

Ritroviamo le librerie sotto la voce Web App libraries

Dobbiamo ora configurare la Web Application andando a modificare il file web.xml. Lo apriamo in Eclipse e lo rendiamo uguale al seguente:

<?xml version="1.0" encoding="ASCII"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
version="3.0">
<display-name>TestMyFaces</display-name>
<context-param>
<param-name>org.apache.myfaces.CHECK_EXTENSIONS_FILTER</param-name>
<param-value>true</param-value>
</context-param>
<filter>
<filter-name>extensionsFilter</filter-name>
<filter-class>org.apache.myfaces.webapp.filter.ExtensionsFilter
</filter-class>
<init-param>
<param-name>uploadMaxFileSize</param-name>
<param-value>100m</param-value>
</init-param>
<init-param>
<param-name>uploadThresholdSize</param-name>
<param-value>100k</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>extensionsFilter</filter-name>
<url-pattern>*.jsf</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>extensionsFilter</filter-name>
<url-pattern>/faces/*</url-pattern>
</filter-mapping>
<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>
<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
<param-value>resources.application</param-value>
</context-param>
<listener>
<listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
</listener>
</web-app>


Il parametro fondamentale da definire è il nome del Filtro extensionFilter mappato sulla classe org.apache.myfaces.webapp.filter.ExtensionsFilter è questa il cuore del framework che intercetta le chiamate durante il ciclo di vita della JSF. All’interno del web.xml  possono essere specificate dei parametri iniziali che sono definiti nella classe MyFacesConfig, tali parametri possono essere omessi e di conseguenza vengono settati al valore di default.

Creiamo ora una pagina di index della nostra applicazione che non farà altro che un redirect verso una pagina JSF (in formato xhtml):

<html>
<head> </head>
<body>
<jsp:forward page="/faces/testjsf.jsp" />
</body>
</html>

Creiamo ora una pagina JSP, facendo click col tasto destro su WebContent -> New -> Other -> Web -> JSP File, inseriamo un nome ad esempio MyFacesPage ed infine scegliamo il template come mostrato in figura:

Scegliamo dai template disponibili quello JSF con sintassi xhtml e default view setup

Inseriamo il namespace dei tag Tomahawk (xmlns:t=”http://myfaces.apache.org/tomahawk”), e proviamo alcuni tag Tomahawk come ad esempio le label (t:outputLabel), gli input (t:inputText) ed un componente avanzato quale un Captcha (t:captcha):

<?xml version="1.0" encoding="ISO-8859-1" ?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" version="2.0">
<jsp:directive.page language="java"
contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" />
<jsp:text>
<![CDATA[ <?xml version="1.0" encoding="ISO-8859-1" ?> ]]>
</jsp:text>
<jsp:text>
<![CDATA[ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> ]]>
</jsp:text>
<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:t="http://myfaces.apache.org/tomahawk">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Insert title here</title>
</head>
<body>
<f:view>
<h:form id="form">
<h:panelGrid columns="2">
<t:outputLabel  value="Inserisci il codice mostrato"/>
<t:inputText value="#{testCaptchaBean.value}"/>
<h:commandLink value="Ricarica immagine" />
<t:captcha captchaSessionKeyName="#{testCaptchaBean.sessionKeyName}" />
<h:commandButton value="Invia" action="#{testCaptchaBean.check}"/>
<t:outputLabel value="#{testCaptchaBean.status}"/>
</h:panelGrid>
</h:form>
</f:view>
</body>
</html>
</jsp:root>

Ora dobbiamo definire un Bean Java che mappi e conservi i valori degli attributi value dei componenti JSF ed implementi la action invocata dal commandButton, per fare questo basta creare una classe Java nella cartella src del nostro progetto ed inserire questo codice:

package it.appuntisoftware;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpSession;
public class TestCaptchaBean {
public final static String SESSION_KEY_NAME = "SessionKeyName";
public final static String CORRETTO = "Corretto!";
public final static String SBAGLIATO = "Sbagliato";
String status;
String value;
public String check() {
// Compara il valore del CAPTCHA con quello inserito dall'utente.
String captchaValue = (String)((HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true))
.getAttribute(SESSION_KEY_NAME);
if(captchaValue.equalsIgnoreCase(value)) {
status = CORRETTO;
} else {
status = SBAGLIATO;
}
return "";
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getSessionKeyName() {
return SESSION_KEY_NAME;
}
}

Infine bisogna inserire nel faces-config.xml il Bean che abbiamo creato in questo modo esso sarà istanziato automaticamente a runtime dal VariableResolver (ritorna un oggetto e lo crea se questo è referenziato per la prima volta), inoltre dobbiamo specificare lo scope del Bean che nel nostro caso sarà di tipo request:


<?xml version="1.0" encoding="UTF-8"?>
<faces-config
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-facesconfig_2_0.xsd"
version="2.0">
<managed-bean>
<managed-bean-name>testCaptchaBean</managed-bean-name>
<managed-bean-class>it.appuntisoftware.TestCaptchaBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
</faces-config>

A questo punto la nostra applicazione è completa, non ci resta che lanciarla sul nostro Application Server Tomcat e provarla. Se inseriamo il corretto valore del Captcha che ci viene presentato allora riceviamo come risposta il valore Corretto!, in caso contrario otteniamo il risultato Sbagliato:

La nostra applicazione di esempio

1 Stella2 Stelle3 Stelle4 Stelle5 Stelle (Nessun voto ancora)
Loading...
You can leave a response, or trackback from your own site.

Leave a Reply

*