Iván Zaera Avellón

Consultor tecnológico de desarrollo de proyectos informáticos.

Ingeniero en Informática

Ver todos los tutoriales del autor

Fecha de publicación del tutorial: 2007-12-10

Tutorial visitado 29.738 veces Descargar en PDF
Integración de JSF 1.2, Facelets e ICEFaces en Tomcat 6

Integración de JSF 1.2, Facelets e ICEFaces en Tomcat 6

Introducción

En este tutorial vamos a ver como configurar lo ultimísimo en desarrollo de aplicaciones web. Primeramente vamos a ver en qué me baso para hacer esta afirmación. Posteriormente, veremos que requisitos debe cumplir un proyecto para qué funcione. Ya veremos que el buen funcionamiento depende mucho de las versiones de las librerías e incluso de algún fichero de configuración. Como herramienta de compilación propondremos Maven.

Este tutorial asume conocimientos de uso de JSF, Facelets y Maven. Si no es así, por favor, consulta los tutoriales ya existentes en AdictosAlTrabajo sobre estos temas.

Opinión sobre JSF 1.2+Facelets

Como he dicho en la introducción, considero la integración de estas tecnologías lo ultimísimo en desarrollo de aplicaciones web. ¡Ojo! he dicho "aplicaciones web", no "portales web" ni "gestores de contenido". Que es de lo último que ha salido es un hecho objetivo, pero la palabra "ultimísimo" lleva asociado un matiz como de excelencia o superioridad sobre otras tecnologías. ésto es claramente una opinión subjetiva mía que trataré de argumentar a continuación.

Todos los que llevamos unos pocos años desarrollando en Java sabemos los altibajos que ha tenido la plataforma y, muy especialmente, la crisis en la que parecíamos sumidos los últimos años. Al menos, yo empezaba a rozar la desesperación, al ver lo frustrante y poco productivo que iba siendo el desarrollo. En especial, el tema de la productividad empezaba a ser preocupante, por la gran cantidad de ficheros XML que había que configurar y lo difícil que era desplegar algo para que funcionase, o peor aun, se mantuviese funcionando. Cada vez había que dedicar más tiempo a la tecnología y menos al análisis, diseño y codificación. O sea, que trabajábamos nosotros para la tecnología, en lugar de la tecnología para nosotros. Para colmo, "aparecían" nuevas herramientas, como Ruby, o .Net, que daban la sensación de ser mucho mas sencillas y fáciles de utilizar.

Después de muchas propuestas de frameworks, librerías, tecnologías, etc., (muchas de las cuales hemos usado en Autentia; ver tutoriales en este mismo web) se empezó a ver la luz con EJB 3.0. Parecía que, por fin, se inventaba algo en Java que era más sencillo que lo anterior y que facilitaba la vida al desarrollador. y efectivamente, era así. Con Java 5 (anotaciones) y EJB 3.0 tenemos por fin una forma sencilla de programar sin necesidad de miles de ficheros XML y complicados despliegues. Basta echar un JAR en JBOSS y todo funciona perfectamente.

A continuación seguimos con JSF 1.1, utilizando la implementación de Apache (myfaces). La idea era buena, pero el funcionamiento raro y complicado. Muchas cosas parecían contraintuitivas, y la curva de aprendizaje era muy alta. Sin embargo, la idea de modelar aplicaciones web como se ha hecho toda la vida en entornos de escritorio (Windows, GTK, QT, Swing, ...) prometía. En cualquier caso, algo faltaba, los JSPs se habían quedado cortors (eran un poco engorrosos) y no encajaban bien con JSF.

Es ahora cuando, por fin, con la llegada de JSF 1.2 y Facelets, podemos desarrollar aplicaciones fácilmente, como lo hacíamos en Swing o MFCs (Windows): con un modelo de aplicación basado en componentes, donde la pantalla se ve como un árbol de controles (botones, listados, etc.) reales, y no como una pagina HTML donde embutimos cosas que al usuario le parecen controles pero que para nosotros, los desarrolladores, son parámetros de una petición HTTP y cosas que nada tienen que ver con lo que el usuario está acostumbrado a manejar.

Ya veréis, ya. Echarle un vistazo, probad un poquito, y no querréis volver a oír hablar de JSPs, Struts, GWT, o demás frameworks. Y si no es así, siempre podéis dejarme un comentario en este tutorial (en esta página, abajo del todo) poniéndome a caldo. Yo, desde luego, pienso recomendar a todo el que me pregunte que use estas tecnologías si no quiere tener que migrar sus aplicaciones dentro de una año o dos.

Es estándar y es el futuro. No cabe duda.

Opinión sobre ICEFaces

Separo ICEFaces de JSF 1.2+Facelets porque los dos últimos son estándar, mientras que ICEFaces no. ¿Por qué ICEFaces? Desde que se empezó a hablar de AJAX, han surgido multitud de frameworks (Prototype, DWR, GWT, ...) que, si bien aportaban facilidad de uso, no acababan de convencer. Algunos porque sólo eran Javascript cliente, otros porque, si bien integraban la parte de servidor con la de cliente, no eran realmente frameworks, sino meras librerías de comunicación. Además, no estaba claro como juntarlos con la arquitectura JEE.

Con la llegada de JSF, se empezaron a vislumbrar posibilidades de integración. Si JSF permitía al desarrollador aislarse de la arquitectura web y ver sus aplicaciones como algo parecido a una aplicación de escritorio, debería entonces ser sencillo utilizar AJAX para hacer estos controles más funcionales. Y así fue, empezaron a aparecer AJAX4JSF, ICEFaces, Tobago, ...

Sin embargo, de estas propuestas, ICEFaces es la que más me gusta, porque aisla completamente al desarrollador de AJAX. No hacen falta etiquetas especiales: se ponen los controles en la pantalla e ICEFaces se encarga de enviar entre cliente y servidor sólo la información necesaria. Es decir, ya no se envían los formularios a la antigua usanza, en un POST de HTTP, sino que solo se envían los cambios que ha hecho el usuario del cliente al servidor, y los cambios en la pantalla del servidor al cliente. No mas parpadeos entre pantalla y pantalla, no mas sobrecarga de red, no más aplicaciones pesadas. Además, con la inclusión de la librería Scriptaculous en ICEFaces, se dispone de arrastrar+soltar y de efectos (fundidos, parpadeos, apariciones, ...) para los controles.

Una maravilla.

Configurar el proyecto

Por lo que llevamos investigado hasta el momento en Autentia, montar un proyecto con estas tres tecnologías sobre JBoss es algo relativamente sencillo. Sin embargo, si queremos ejecutar en Tomcat 6, la cosa cambia. ésto es debido a que este despliegue es muy dependiente de las versiones de las librerías. Por ello, vamos a ver que "pom.xml" (fichero de configuración de Maven) necesitaría el proyecto para funcionar:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
        
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.autentia</groupId>
        <artifactId>tutorial</artifactId>
        <packaging>war</packaging>
        <version>1.0-SNAPSHOT</version>
        
        <dependencies>
                
                <!-- Core -->
                <dependency>
                        <groupId>junit</groupId>
                        <artifactId>junit</artifactId>
                        <version>3.8.1</version>
                        <scope>test</scope>
                </dependency>
                <dependency>
                        <groupId>log4j</groupId>
                        <artifactId>log4j</artifactId>
                        <version>1.2.14</version>
                </dependency>
                
                <!-- Core J2EE -->
                <dependency>
                        <groupId>javax.servlet</groupId>
                        <artifactId>servlet-api</artifactId>
                        <version>2.3</version>
                        <scope>provided</scope>
                </dependency>
                <dependency>
                        <groupId>javax.servlet</groupId>
                        <artifactId>jstl</artifactId>
                        <version>1.1.2</version>
                </dependency>
                <dependency>
                        <groupId>taglibs</groupId>
                        <artifactId>standard</artifactId>
                        <version>1.1.2</version>
                </dependency>
                <dependency>
                        <groupId>javax.el</groupId>
                        <artifactId>el-api</artifactId>
                        <version>1.0</version>
                        <scope>provided</scope>
                 </dependency>
                
                <!-- JSF -->
                <dependency>
                        <groupId>javax.faces</groupId>
                        <artifactId>jsf-api</artifactId>
                        <version>1.2_04-p01</version>
                </dependency>
                <dependency>
                        <groupId>javax.faces</groupId>
                        <artifactId>jsf-impl</artifactId>
                        <version>1.2_04-p01</version>
                </dependency>
                <dependency>
                        <groupId>org.icefaces</groupId>
                        <artifactId>icefaces-facelets</artifactId>
                        <version>1.6.1</version>
                </dependency>
                
                <!-- ICEFaces -->
                <dependency>
                        <groupId>org.icefaces</groupId>
                        <artifactId>icefaces</artifactId>
                        <version>1.6.1</version>
                </dependency>
                <dependency>
                        <groupId>org.icefaces</groupId>
                        <artifactId>icefaces-comps</artifactId>
                        <version>1.6.1</version>
                </dependency>
                <dependency>
                        <groupId>backport-util-concurrent</groupId>
                        <artifactId>backport-util-concurrent</artifactId>
                        <version>3.1</version>
                </dependency>
                <dependency>
                        <groupId>commons-logging</groupId>
                        <artifactId>commons-logging</artifactId>
                        <version>1.1</version>
                </dependency>
                <dependency>
                        <groupId>commons-beanutils</groupId>
                        <artifactId>commons-beanutils</artifactId>
                        <version>1.7.0</version>
                </dependency>
                <dependency>
                        <groupId>commons-collections</groupId>
                        <artifactId>commons-collections</artifactId>
                        <version>3.2</version>
                </dependency>
                <dependency>
                        <groupId>commons-digester</groupId>
                        <artifactId>commons-digester</artifactId>
                        <version>1.8</version>
                </dependency>           
                <dependency>
                        <groupId>commons-fileupload</groupId>
                        <artifactId>commons-fileupload</artifactId>
                        <version>1.2</version>
                </dependency>
                <dependency>
                        <groupId>commons-discovery</groupId>
                        <artifactId>commons-discovery</artifactId>
                        <version>0.4</version>
                </dependency>
                <dependency>
                        <groupId>commons-el</groupId>
                        <artifactId>commons-el</artifactId>
                        <version>1.0</version>
                </dependency>
                <dependency>
                        <groupId>xerces</groupId>
                        <artifactId>xercesImpl</artifactId>
                        <version>2.8.1</version>
                </dependency>
                <dependency>
                        <groupId>net.sf.jcharts</groupId>
                        <artifactId>krysalis-jCharts</artifactId>
                        <version>1.0.0-alpha-1</version>
                </dependency>
                
        </dependencies>
        
        <repositories>
                <repository>
                        <id>java.net</id>
                        <url>http://download.java.net/maven/1</url>
                        <layout>legacy</layout>
                </repository>
        </repositories>

</project>



Cosas importantes a tener en cuenta sobre este pom:

  • Debéis añadir el repositorio Maven de Sun (http://download.java.net/maven/1) para encontrar sus librerías.

  • Las dependencias de ICEFaces, deben ser descargadas manualmente de http://www.icefaces.org e instaladas en el repositorio local.

  • La dependencia "el-api" debe ser "provided". Si echáis un "el-api.jar" en el directorio "WEB-INF/lib" de vuestra aplicación, Tomcat no arrancará.

  • La dependencia "icefaces-facelets" proporciona la implementación de Facelets. Por lo tanto, no añadáis ninguna otra dependencia de ninguna implementación de facelets o tendréis conflictos entre ambas y no funcionará.

  • Las versiones del API y de la implementación de JSF deben ser las que se especifican en el "pom" (1.2_04-p01) y no otras. Con otras no funciona bien, dando una excepción "Expired View" (la vista ha expirado). Por supuesto, ésto es sólo válido para la versión 1.6.1 de ICEFaces.

Si buscáis en los foros, existe un repositorio Maven en el sitio web de JBoss con la dependencia ICEFaces configurada para evitarnos especificar las dependencias transitivas. ¡No la uséis si vais a desplegar en Tomcat porque no funciona!

Para finalizar, citaremos otros puntos a tener en cuenta para este despliegue, que van más allá del "pom". Estos atañen a los ficheros de configuración de la aplicación web:

web.xml

Hay que tener definidos los siguientes servlets:

   <servlet>
                <description>Servlet JSF estandar (para usar sin ICEFaces)</description>
                <servlet-name>Faces Servlet</servlet-name>
                <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
                <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet>
                <description>Servlet JSF de ICEFaces</description>
                <servlet-name>Persistent Faces Servlet</servlet-name>
                <servlet-class>com.icesoft.faces.webapp.xmlhttp.PersistentFacesServlet</servlet-class>
                <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet>
                <description>ICEFaces request blocking servlet</description>
                <servlet-name>Blocking Servlet</servlet-name>
                <servlet-class>com.icesoft.faces.webapp.xmlhttp.BlockingServlet</servlet-class>
                <load-on-startup>1</load-on-startup>
        </servlet>


Y los mapeos de servlets:


   <servlet-mapping>
                <servlet-name>Persistent Faces Servlet</servlet-name>
                <url-pattern>*.jsf</url-pattern>
        </servlet-mapping>
        <servlet-mapping>
                <servlet-name>Persistent Faces Servlet</servlet-name>
                <url-pattern>/xmlhttp/*</url-pattern>
        </servlet-mapping>
        <servlet-mapping>
                <servlet-name>Blocking Servlet</servlet-name>
                <url-pattern>/block/*</url-pattern>
        </servlet-mapping>


Fijaos en que la extensión .JSF la mapeamos al servlet de ICEFaces (Persistent Faces Servlet), no al de la implementación de referencia de JSF (Faces Servlet).

faces-config.xml

Lo primero de todo, es configurar el "faces-config.xml" con el esquema XML de la versión 1.1 de JSF. ésto hace que ICEFaces se ejecute en modo compatibilidad 1.1 en JSF 1.2. Si no fuera así no funcionaria, porque ICEFaces no funcionará en modo JSF 1.2 puro hasta la versión 2.0. Para ello hay que definir el siguiente DOCTYPE de XML:

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



Y añadir el namespace por defecto siguiente al elemento "faces-config":

<faces-config xmlns="http://java.sun.com/JSF/Configuration">



Desgraciadamente, al ejecutarse en modo compatibilidad con JSF 1.1, algunas de las novedades de JSF 1.2 (como por ejemplo, el no tener que usar la etiqueta "f:loadBundle" en cada página para cargar los recursos multi-idioma) no estarán disponibles. Por suerte, es algo pasajero.

A continuación debemos añadir el soporte de Facelets:

    <application>

        ...

        <view-handler>com.icesoft.faces.facelets.D2DFaceletViewHandler</view-handler>
 
        ...

    </application>



Y ya tenemos nuestro proyecto listo para funcionar en Tomcat 6.0.

Conclusiones

Como veis, no es difícil integrar todas estas tecnologías en un solo proyecto. Sin embargo, hay que ser muy cuidadoso con las versiones y la configuración de los proyectos porque puede impactar mucho en su funcionamiento.

En Autentia contamos con una amplia experiencia en desarrollo de aplicaciones, por lo que siempre recomendamos a nuestros clientes enfocarse en la resolución de la problemática del negocio y delegar las partes más complicadas de la tecnología a empresas especializadas. Ya sabéis que siempre nos tenéis disponibles para ello en http://www.autentia.com.

Disfrutad del futuro del desarrollo de aplicaciones web, que ya esta aquí.







A continuación puedes evaluarlo:

Regístrate para evaluarlo

Por favor, vota +1 o compártelo si te pareció interesante

Share |
Anímate y coméntanos lo que pienses sobre este TUTORIAL:

Fecha publicación: 2009-04-30-12:54:58

Autor:

[Jaime Carmona Loeche] Se te ve muy optimista con este nuevo Framework. A priori, parece una pasada y yo voy a darle un poco de chicha a ver qué tal rueda.... Dime, ¿conoces los puntos negativos? ¿Serías capaz de comparar las ventajas y desventajas de esta tecnología con respecto a otras? Yo, por falta de conocimiento, no me atrevo hacerlo, pero da la sensación de qué, las desventajas, no las mencionas cegado por tu optimismo. ¡Saludos y gracias por el tutorial!