Continuamos nuestra aplicación de ejemplo después de una pequeña (por decir algo) pausa. Confiamos en tener tiempo esta semana para ir añadiendo nuevas entradas.

Estructura de la Aplicación usando un único War

Nuestra aplicación de ejemplo será una aplicación web, y utilizará la librería de ICEfaces 2.0. Para crear un proyecto de este tipo seguiremos estos pasos, desde el Netbeans:

Desde el menú de File – New Project… seleccionar la categoría: Java Web – Web Application.

Datos del proyecto:

  • Nombre del proyecto: demo-war
  • Path del proyecto: [path_de_proyectos]/
  • Dedicar carpeta /lib para guardar las libs del proyecto: no
  • Establecer como proyecto principal: si

Pulsar en Siguiente, y continuar con estos datos:

  • Server: Glassfish V3 Domain
  • Usar la carpeta lib para guardar jars del servidor: no
  • Java EE Version: Java EE 6 Web (necesario para poder usar JSF 2.0)
  • Enable Context and Dependency Injection: ok
  • Context path: /demo-war

Pulsar en Siguiente, y continuar con estos datos:

  • Frameworks: seleccionamos sólo ICEfaces, y marcamos la opción de Compatibilidad con ICEfaces 1.8 (ICEfaces 2.0 only).

El proyecto se generará de forma automática. Para probar que se ha generado correctamente, arrancamos el servidor Glassfish V3 y desplegamos la aplicación. Abrimos un navegador y accedemos a esta url:

Nos aparecerá una pantalla con título «ICEfaces 2», y contenido «Welcome to ICEfaces 2. Add ICEfaces 1.8 components «. Ya tenemos funcionando nuestra primera aplicación con JSF 2.0, y ICEfaces 2. ¿Quién dijo fácil?

Un vistazo a los ficheros generados

Vamos a echar un vistazo a los ficheros generados de forma automática. Los primeros que vamos a mirar serán los que están en «[demo-war]/Web Pages/WEB-INF/». Son ficheros de configuración de la aplicación: descriptores de despliegue.

/Web Pages/WEB-INF/beans.xml

Es un fichero de configuración utilizado para inyección de dependencias del contenedor (CDI). Lo dejaremos vacío. Podeis ver más información sobre él en esta URL:http://relation.to/Bloggers/WhyIsBeansxmlRequiredInCDI

<?xml version=»1.0″ encoding=»UTF-8″?>
<beans 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/beans_1_0.xsd»>
</beans>

/Web Pages/WEB-INF/sun-web.xml

Es el fichero descriptor de despliegue propio del Glassfish para la aplicación web. En él se configurarán parámetros propios del servidor de aplicaciones. En el fichero generado por el NetBeans, indica de forma explícita que el context-root será “/demo-war”.

También se pueden indicar otros parámetros, como el “keepgenerated” a true, para que mantenga el .java que se compila para cada jsp.

<?xml version=»1.0″ encoding=»UTF-8″?>
<!DOCTYPE sun-web-app PUBLIC «-//Sun Microsystems, Inc.//DTD Application Server 9.0 Servlet 2.5//EN» «http://www.sun.com/software/appserver/dtds/sun-web-app_2_5-0.dtd«>
<sun-web-app error-url=»»>
<context-root>/demo-war</context-root>
<class-loader delegate=»true»/>
<jsp-config>
<property name=»keepgenerated» value=»true»>
<description>Keep a copy of the generated servlet class’ java code.</description>
</property>
</jsp-config>
</sun-web-app>

/Web Pages/WEB-INF/web.xml

Es el fichero descriptor de despliegue para la aplicación web. Está definido en la especificación de JavaEE. Todas las aplicaciones web tienen que tener el suyo.

En él se ha configurado nuestra aplicación para que utilice el Servlet de JSF (FacesServlet)para todas las peticiones a URLs que terminen en “.jsf” (nuestras páginas web), o para todas las que comiencen por “/icefaces/*” (que -si no me equivoco- serán peticiones internas generadas por los componentes de icefaces).

Se indica, además, el tiempo (en minutos) en el que una sesión de usuario puede estar inactiva antes de que se deseche.

Y también se indica que el welcomeFile será “index.html” o “ welcomeICEfaces.jsf”. De esta forma, cuando se accede a una URL sin indicar la página se comprobará si en el directorio existe “index.html” o “welcomeICEfaces.jsf”. Por ejemplo, al acceder a “http://localhost/demo-war/” estaremos accediendo en realidad a “http://localhost/demo-war/welcomeICEfaces.jsf” (porque no tenemos “index.html”). O también, si accediéramos a «http://localhost/demo-war/directorio_ejemplo/» el Glassfish intentará buscar un fichero index.html, o un jsf de welocomeICEfaces.jsf. Si no lo encuentra, devolverá un código de error 404. Pero primero, buscará esas páginas indicadas como welcomeFile.

Una petición a la url “http://localhost/demo-war/welcomeICEfaces.jsf” estará gestionada por elFacesServlet -por lo indicado en el «servlet-mapping» del web.xml-. Este FacesServletasociará el árbol de componentes JSF a la petición del usuario según lo indicado en el fichero“/welcomeICEfaces.xhtml”. Es decir, una petición a un XXX.jsf tendrá que tener asociado un fichero XXX.xhtml.

<?xml version=»1.0″ encoding=»UTF-8″?>
<web-app version=»3.0″ 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_3_0.xsd«>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<context-param>
<param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>
<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>*.jsf</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/icefaces/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>welcomeICEfaces.jsf</welcome-file>
</welcome-file-list>
</web-app>

Después de revisar los ficheros descriptores de despliegue, veamos el fichero a partir del cual se genera el código HTML:

/Web Pages/welcomeICEfaces.xhtml

En este fichero se define el HTML de presentación de la página, utilizando etiquetas de JSF y de ICEfaces. La mayoría de las etiquetas de componentes de icefaces requieren que estén dentro de un formulario de icefaces (<ice:form …).

<?xml version=’1.0′ encoding=’UTF-8′ ?>
<!–
Document   : welcomeICEfaces
Created on : 18-oct-2010, 16:29:20
Author     : Alejandro Arriola <alejandro.arriola@programia.es>
–>
<!DOCTYPE html PUBLIC «-//W3C//DTD XHTML 1.0 Transitional//EN» «http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd«>
<html xmlns=»http://www.w3.org/1999/xhtml«
xmlns:ui=»http://java.sun.com/jsf/facelets«
xmlns:f=»http://java.sun.com/jsf/core«
xmlns:h=»http://java.sun.com/jsf/html«
xmlns:ice=»http://www.icesoft.com/icefaces/component«>
<h:head>
        <title>ICEfaces 2</title>
<h:outputScript name=»jsf.js» library=»javax.faces»/>
    </h:head>
    <h:body>
        <div id=»header»>
<!–
<ui:include src=»/header.xhtml» >
<ui:param name=»param_name» value=»param_value» />
</ui:include>
–>
</div>
<div id=»content»>
<ice:form id=»iceForm»>
                <ice:outputText value=»Welcome to ICEfaces 2. Add ICEfaces 1.8 components»/>
             <!–
drop ICEfaces components here
–>
</ice:form>
         </div>
</h:body>
</html>

 

Enlace con los fuentes del proyecto generado: demo-war_01.rar

 

Organización de las clases de nuestro proyecto en Packages

Vamos a organizar las clases de nuestro proyecto según estos paquetes:

  • es.programia.exception: Paquete con clases de excepción para nuestro proyecto.
    • checked: Excepciones checked, que extienden de Exception.
    • uncheked: Excepciones unchecked, que extienden de RuntimeException.
  • es.programia.demo.ejb: Paquete con las clases de EJB de la aplicación.
  • es.programia.demo.entities: Paquete con las clases de entidad de JPA de la aplciación.
  • es.programia.demo.faces: Package con las clases de Managed Beans de JSF de la aplicación.
  • es.programia.demo.utils: Paquete con clases de utilidad propios de la aplicación. Por ejemplo, la clase de constantes ConstDemo.
  • es.programia.utils: Paquete con clases de utilidad generales. Por ejemplo, clase de gestión de ficheros de properties Props.

 

Otra forma de estructurar la aplicación en contenedores Java EE 5:

Hasta antes de la versión Java EE 6, para poder acceder a un EJB desde una aplicación web de forma local teníamos que tener los dos componentes -el EJB y el WAR- en una misma aplicación EAR. Y queremos utilizar un EJB para poder acceder a nuestras entidades de JPA dentro de un contexto transaccional, por lo que la estructura de nuestras aplicaciones web solía ser de esta forma:

  • Librería de clases, con las clases de entidad, los interfaces de los EJB, las clases de utilidad, etc.
  • Componente EJB, con las clases de implementación de EJBs.
  • Componente WAR, con las páginas xhtml y las clases relacionadas con la capa web.
  • Componente EAR, Enterprise Application Resource, que contiene el módulo de EJB y el módulo WAR

Para cada uno de estos cuatro componentes, tendríamos un proyecto distinto de Netbeans:

  • Proyecto de librería de clases, que generaría un «demo-classes.jar».
  • Proyecto de EJB, que generaría un «demo-ejb.jar», con dependencia al «demo-classes.jar».
  • Proyecto de Web Application, que generaría un «demo-war.war», con dependencia al «demo-classes.jar».
  • Proyecto de EAR, que generaría un «demo-ear.ear», que contiene los módulos EJB y WAR, que sería el componente desplegado en el servidor de aplicaciones.

 

En la siguiente parte prepararemos nuestras clases de entidad, y accederemos a ellas desde un EJB.