Icefaces, JBoss, Maven2 y
EJB3: Parte 2.
Como ya os prometí
en el anterior tutorial de esta ‘saga’, en este pretendemos
configurar la parte del módulo Web y del módulo Modelo
para empezar a trabajar.
Por lo tanto, nuestro
objetivo será configurar correctamente la aplicación
Web para que se pueda desplegar correctamente en Jboss e Icefaces y
configurar el proyecto eclipse de manera correcta al igual que el
proyecto EJB.
Suponemos que ya
tenéis instalado JBoss 4.2.2 y ‘enlazado’ con eclipse y
habéis finalizado con éxito el tutorial anterior.
-
Estructura
del proyecto WEB.Al
ser un proyecto Web dinámico, y siguiendo la estructura de
Maven2, tendremos: (si no lo tenéis así, modificadlo
para que así sea)
-
Los fuentes en la carpeta
src/main/java -
Los recursos en src/main/resources
(No olvidéis añadirla al proyecto como carpeta de
fuentes) -
Las clases compiladas en:
target/classes -
Los ficheros de la aplicación
Web: src/main/webapp
-
Creando
descriptor web.xml.
El descriptor web.xml (en
src/main/webapp/WEB-INF) tendrá la siguiente forma:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
<?xml version="1.0" encoding="UTF-8"?> <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_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>Web</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>server</param-value> </context-param> <context-param> <param-name>com.icesoft.faces.uploadDirectory</param-name> <param-value>upload</param-value> </context-param> <context-param> <param-name>com.icesoft.faces.uploadMaxFileSize</param-name> <param-value>4048576</param-value> </context-param> <servlet> <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> <servlet-name>Blocking Servlet</servlet-name> <servlet-class>com.icesoft.faces.webapp.xmlhttp.BlockingServlet</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>*.jspx</url-pattern> </servlet-mapping> <!-- Persistent Faces Servlet Mapping --> <servlet-mapping> <servlet-name>Persistent Faces Servlet</servlet-name> <url-pattern>*.iface</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> <servlet-mapping> <servlet-name>Blocking Servlet</servlet-name> <url-pattern>/block/*</url-pattern> </servlet-mapping> <servlet> <servlet-name>uploadServlet</servlet-name> <servlet-class>com.icesoft.faces.component.inputfile.FileUploadServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>uploadServlet</servlet-name> <url-pattern>/uploadHtml</url-pattern> </servlet-mapping> <listener> <listener-class>com.icesoft.faces.util.event.servlet.ContextEventRepeater</listener-class> </listener> </web-app> |
-
Fichero de
configuración de JSF: faces-config.xml
El fichero de
configuración faces-config.xml (en src/main/webapp/WEB-INF)
tendrá la siguiente forma:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?xml version="1.0" encoding="UTF-8"?> <!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> <managed-bean> <description> Test Bean </description> <managed-bean-name>testCtrl</managed-bean-name> <managed-bean-class> com.autentia.tutoriales.icefaces.beans.TestCtrl </managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean> </faces-config> |
Por ahora, sólo
hemos configurado un bean de Sesión que nos servirá de
ejemplo.
-
Fichero
index.jsp y test.jspxCrearemos dos ficheros jsp. El
primero, que será el fichero de bienvenida, que redirigirá
al fichero test.jspx. Nuestro único objetivo será
demostrar que hemos configurado todo correctamente.El
fichero index.jsp (en src/main/webapp) tendrá la siguiente
forma:
1 2 3 4 5 6 7 |
<html> <head> </head> <body> <jsp:forward page="test.iface" /> </body> </html> |
-
Vamos a
crear el Bean.Crearemos
la clase: com.autentia.tutoriales.icefaces.beans.TestCtrl:
El
fichero test.jspx (JSP y XML) (en src/main/webapp) tendrá la
siguiente forma:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<f:view xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ice="http://www.icesoft.com/icefaces/component" xmlns:jsp="http://java.sun.com/JSP/Page"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"></meta> <title>Test</title> </head> <body> <ice:outputLabel for="" value="#{testCtrl.label}"></ice:outputLabel> </body> </html> </f:view> |
1 2 3 4 5 6 7 |
package com.autentia.tutoriales.icefaces.beans; public class TestCtrl { public String getLabel() { return "Esta es una etiqueta"; } } |
-
Configuración
de las trazas.Cread
en la carpeta src/main/resources los ficheros:
-
commons-logging.properties
1org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger -
log4j.properties
123456789# Main loggerslog4j.rootLogger=INFO, stdoutlog4j.logger.org.apache=ERROR# Console appenderlog4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.Target=System.outlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1} - %m%n
-
Preparando
para desplegar el proyecto WEB
Lo
añadimos al servidor Jboss en eclipse (no lo arranquéis
aún)
Pulsamos
sobre propiedades del proyecto y en ‘J2EE Module Dependencies’
marcamos únicamente ‘Maven Dependencies’
Arrancamos
el servidor y entramos en http://localhost:8080/Web
Debemos
ver una página muy simple:
-
Estructura
del proyecto Modelo.Al
ser un proyecto EJB 3.0, y siguiendo la estructura de Maven2,
tendremos: (si no lo tenéis así, modificadlo para que
así sea)
-
Los fuentes en la carpeta
src/main/java
-
Los recursos en src/main/resources
(No olvidéis añadirla al proyecto como carpeta de
fuentes)
-
Las clases compiladas en:
target/classes
-
Configuración
de las trazas.Haced
lo mismo que hicimos para el módulo Web -
Crearemos
un EJB de sesión sin estado de prueba.Creamos
el interfaz Local:
com.autentia.tutoriales.modelo.services.TestServices
1 2 3 4 5 6 7 8 |
package com.autentia.tutoriales.modelo.services; import javax.ejb.Local; @Local public interface TestService { public String test(); } |
Y ahora el Bean:
com.autentia.tutoriales.modelo.services.TestServicesImpl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package com.autentia.tutoriales.modelo.services; import javax.ejb.Stateless; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @Stateless public class TestServiceImpl implements TestService { private static Log log = LogFactory.getLog(TestServiceImpl.class); public String test() { log.info("Me llaman"); return "Y este es el valor"; } } |
Vamos a crearnos una clase
que nos permita localizar los EJBs de manera transparente:
com.autentia.tutoriales.modelo.util.EjbLocator
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
package com.autentia.tutoriales.modelo.util; import javax.naming.InitialContext; import javax.naming.NamingException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class EjbLocator { private static Log log = LogFactory.getLog(EjbLocator.class); private static final InitialContext ctx; static { try { ctx = new InitialContext(); } catch (NamingException e) { log.fatal("It is not possible to create a new InitialContext.", e); throw new RuntimeException(e); } } /** * Constructor privado. */ private EjbLocator() { } /** * Retorna una referencia a un EJB Local */ @SuppressWarnings("unchecked") public static <T> T lookupLocalBean(Class<? extends T> beanClass) throws NamingException { final String jndiName = beanClass.getSimpleName() + "/local"; final T bean = (T)jndiLookup(jndiName); return bean; } private static Object jndiLookup(String jndiName) throws NamingException { final Object obj; try { obj = ctx.lookup(jndiName); if (log.isDebugEnabled()) log.debug("Found JNDI name: " + jndiName); } catch (NamingException e) { log.fatal("Can not found JNDI name: " + jndiName); throw e; } return obj; } } |
-
Invocamos
al Modelo desde el Web:Configuramos
el proyecto Web en eclipse añadiendo la dependencia del
proyecto Modelo:
Editamos la clase TestCtrl
dejándola así:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
package com.autentia.tutoriales.icefaces.beans; import javax.naming.NamingException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.autentia.tutoriales.modelo.services.TestService; import com.autentia.tutoriales.modelo.services.TestServiceImpl; import com.autentia.tutoriales.modelo.util.EjbLocator; public class TestCtrl { private static Log log = LogFactory.getLog(TestCtrl.class); TestService servicio; public TestCtrl() { log.debug("Constructor:TestCtrl"); try { servicio = EjbLocator.lookupLocalBean(TestServiceImpl.class); } catch (NamingException e) { log.error ("Error al iniciar el controlador: ", e); } } public String getLabel() { log.info("Me llaman"); return "Esta es una etiqueta"; } public String getValor() { return servicio.test(); } } |
Mostramos el valor en la
página test.jspx:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<f:view xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ice="http://www.icesoft.com/icefaces/component" xmlns:jsp="http://java.sun.com/JSP/Page"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"></meta> <title>Test</title> </head> <body> <ice:outputLabel for="valor" value="#{testCtrl.label}"></ice:outputLabel> <ice:outputText id="valor" value="#{testCtrl.valor}"></ice:outputText> </body> </html> </f:view> |
Invocamos a la aplicación
(no olvidéis añadir el proyecto Modelo al servidor y
arrancarlo).: http://localhost:8080/Web/
Veremos una página muy
simple:
En apariencia sólo
tenemos una página muy sencilla, pero la realidad es que ya
tenemos un arquetipo de aplicación bastante interesante
técnicamente:
-
JSF e Icefaces preparaditos para
utilizar (me encanta eso del partial submit de icefaces). -
EJB 3.0 deseando ayudarnos con su
magia. -
Las dependencias de las librerías
manejadas por Maven2 y ‘enganchadito’ todo con Eclipse gracias a
m2Eclipse. -
Desplegado y funcionando en Jboss.
Aún nos queda trabajo
por hacer… os adelanto que lo próximo será
inventarnos un modelo de datos, crearnos un esquema en MySQL que lo
represente, crear las clases de entidad (Entity) y
hacernos un DAO implementado en un EJB de sesión sin estado.