Consultor tecnológico de desarrollo de proyectos informáticos.
Ingeniero Técnico en Telecomunicaciones
Puedes encontrarme en Autentia: Ofrecemos servicios de soporte a desarrollo, factoría y formación
Somos expertos en Java/J2EE
Fecha de publicación del tutorial: 2008-01-17
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:
-
<?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:
-
<?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.jspx
Crearemos 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:
-
<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:
|
<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> |
-
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
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger
log4j.properties
# Main loggers
log4j.rootLogger=INFO, stdout
log4j.logger.org.apache=ERROR
# Console appender
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.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
-
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
-
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
-
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í:
-
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:
-
<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.
A continuación puedes evaluarlo:
Fecha publicación: 2009-05-23-01:15:17
Autor:











