Ejemplo Sencillo con EJB

De ChuWiki

Un ejemplo sencillo con EJB[editar]

Un EJB (Enterprise Java Bean) es un "componente de negocio", es decir, un programa java que realiza alguna gestión compleja y que aguarda a que otro programa cliente lo invoque. Para su funcionamiento, se requiere que se instale en un servidor, que es otro software encargado de controlar el acceso al EJB, la seguridad, las transacciones y otras tareas. Gracias a esta doble relación, los EJBs ofrecen un alto rendimiento y disponibilidad a las aplicaciones distribuidas (en varias capas) que pueden ser o no de tipo WEB. Como ejemplo del uso de la tecnología EJB, vamos a desarrollar la práctica mínima que detalle el modus operandi para escribir, desplegar y probar una aplicación J2EE que hace uso de un EJB.

Como se ha comentado, al utilizar EJB, se necesita un servidor de aplicaciones. Para la práctica, se utilizó como herramienta el jdk (a partir de la versión 1.4 es suficiente), en [1]; el IDE ECLIPSE 3.1, disponible en [2], (vale cualquier otro editor o entorno) y el servidor de aplicaciones JBoss 4.0.2, [3], todo legalmente descargable en internet.

Para desarrollar y ejecutar una aplicación con EJB efectuaremos los siguientes pasos:

  • Escribir el Bean
  • Escribir el descriptor de despliegue
  • Desplegar el Bean
  • Escribir la aplicación cliente que lo utilice

El ejemplo construirá la aplicación con EJB (HolaMundoEJB), consistente en un único enterprise java bean que muestre un saludo. Tras una compilación exitosa, escribiremos su descriptor de despliegue y desplegaremos el bean en el servidor. Por último crearemos otro programa cliente que llame a nuestro EJB.


Escritura del código fuente del Bean HolaMundo[editar]

Con la versión de EJB 2.0, se requieren tres programas Java, los cuales meteremos en un "paquete", como por ejemplo, com.saludo. Posteriormente deberemos crear una estructura de directorios que coincida con el nombre de ese paquete, es decir, com/saludo. Allí es donde introduciremos los tres programas. Esta tarea podemos hacerla manualmente o mejor con el IDE de Eclipse o similar, que convierte los nombres de paquetes en directorios tal como los espera encontrar el compilador java.

Una vez aclarado dónde se meterán los tres archivos que componen el ejb, echaremos un vistazo a los fuentes que vamos a introducir. Escribimos primero la "interfaz remota", archivo que contiene los "métodos de negocio", o sea, lo que haga nuestro ejb, en este caso el manido mensaje "Hola" acompañado del nombre que añadamos como parámetro.

package com.saludo;

import java.rmi.RemoteException;
import javax.ejb.EJBObject;

public interface HolaMundoRemote extends EJBObject{
	public String saludo(String nombre) throws RemoteException;
}


A continuación escribimos la "interfaz Home", que corresponde a los métodos del ciclo de vida de un bean. Nos limitamos a escribir el código ignorando posibles errores.

package com.saludo;

import java.rmi.RemoteException;

import javax.ejb.CreateException;
import javax.ejb.EJBHome;

public interface HolaMundoHome extends EJBHome{
	HolaMundoRemote create() throws RemoteException, CreateException;
}

Por último escribimos el propio bean que, por fin, es toda una clase java. En ella estará el código de los métodos antes expuestos en las interfaces previas Home y Remote. Todo este pastiche se encarga de reunirlo y organizarlo el servidor de aplicaciones del que pronto hablaremos. Si aún no se ha instalado, los fuentes previos daran errores en algunas líneas por los "import" de clases que no existen normalmente en el jdk.

package com.saludo;

import java.rmi.RemoteException;

import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;

public class HolaMundoBean implements SessionBean{
	private static final long serialVersionUID = 1L;// Quita warning de serialización del objeto

	// Nuestro método "de negocio"
	public String saludo(String nombre){
		System.out.println("Un cliente me ha invocado");
		return "Hola, " + nombre;
	}
	// Métodos del ciclo de vida del Bean (obligatorios)
	public void ejbCreate(){}
	public void ejbActivate() throws EJBException, RemoteException {}
	public void ejbPassivate() throws EJBException, RemoteException {}
	public void ejbRemove() throws EJBException, RemoteException {}
	public void setSessionContext(SessionContext arg0) throws EJBException, RemoteException {}
}

Bueno, pues esto es el código fuente de un ejb mínimo. Se trata ahora, de corregir todos los posibles errores y, el problema a arreglar con más urgencia es añadir la librería de los ejb que habréis podido observar en los import. En el caso de usar Eclipse y una vez instalado el servidor JBoss, es más sencillo ya que basta con indicar a la aplicación que añada el fichero jar correspondiente a los ejb. El jar que tendréis que añadir es el "jboss-j2ee.jar" y se encuentra en la carpeta "server\default\lib" de JBoss. Por supuesto que hay otras formas de resolver esto, como establecer la variable CLASSPATH para que apunte allí o trasladar esa librería a nuestro directorio, etc.


Escribiendo el descriptor de despliegue[editar]

Una aplicación EJB requiere un descriptor de despliegue que describe cada bean de esa aplicación. Este fichero descriptor tiene por nombre ejb-jar.xml y debe situarse en un directorio llamado META-INF (exactamente) y que estará a la misma altura que la carpeta com (paquete) que habíamos creado desde eclipse. El aspecto de los directorios y su contenido debe quedar así:


El contenido del descriptor es el siguiente:

<?xml version="1.0"?>
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD 
Enterprise JavaBeans 2.0//EN" "http://java.sun.com/j2ee/dtd/ejb-jar_2_0.dtd">

<ejb-jar>
  <description>Ejemplo de EJB Simple</description>
  <enterprise-beans>
    <session>
      <display-name>Bean HolaMundo</display-name>
      <ejb-name>HolaMundo</ejb-name>
      <home>com.saludo.HolaMundoHome</home>
      <remote>com.saludo.HolaMundoRemote</remote>
      <ejb-class>com.saludo.HolaMundoBean</ejb-class>
      <session-type>Stateless</session-type>
      <transaction-type>Bean</transaction-type>
    </session>
  </enterprise-beans>
</ejb-jar>

Desplegando el Bean ejemplo[editar]

Lo que se llama desplegar, es instalar la aplicación y ello conlleva generar un fichero java comprimido (.jar) que colocaremos en otro directorio concreto del servidor de aplicaciones. En dicho fichero pondremos las clases (no son necesarias las fuentes que yo si voy a añadir) e interfaces y el directorio META-INF con el ejb-jar.xml.

Para crear el jar, abrimos una consola de comandos, nos situamos en la carpeta del proyecto, justo por encima de com y META-INF y allí escribimos:

jar cfv holamundo.jar com/saludo/* META-INF/ejb-jar.xml

Esto causa la creación del fichero comprimido "holamundo.jar". Las opciones cfv sirven para crear el archivo indicando la ruta donde buscar y que muestre (verbose) todos los mensajes oportunos durante el proceso. Además, al mencionar dos rutas (la de las clases y la del ejb-jar), se añaden ambos contenidos. También se añadirá automáticamente el fichero MANIFEST. Si has llegado hasta aquí, paciencia, ya queda poco. Lo próximo es terminar el despliegue colocando el fichero "holamundo.jar" en un lugar concreto del servidor de aplicaciones. Suponiendo que tienes instalado el servidor JBoss, que dicho sea de paso, es de los contenedores para EJB más sencillos y populares, y no has cambiado la configuración, debería existir un directorio llamado \server\default\deploy que cuelga del directorio principal. Allí debes "soltar" el resultado "holamundo.jar". Estamos a punto de comprobar el despliegue...

En este punto y si no ha habido ningún error, el despliegue se ha completado. Bastará arrancar el servidor JBoss y ejecutar la utilidad run del directorio bin. Se abrirá una consola donde se mostrarán gran cantidad de mensajes informativos. Debemos estar atentos de que no salten excepciones java, que pueden ser provocadas por varias razones pero muy probablemente por algún error en el fichero jar o en las clases o en la fase de despliegue (a mí me costó tres intentos). En caso de error, hay que revisar todos los mensajes que se exhiben en la consola de JBoss, como excepciones u otros orientativos que suelen ser suficientes. Si todo marcha bien, en las últimas líneas tendrá que aparecer que se ha desplegado nuestro bean "holamundo". En concreto, las últimas líneas que muestra JBoss son algo así:

...
21:13:52,953 INFO  [EjbModule] Deploying HolaMundo
21:13:53,187 INFO  [ProxyFactory] Bound EJB Home 'HolaMundo' to jndi 'HolaMundo'

21:13:53,187 INFO  [EJBDeployer] Deployed: file:/D:/jboss-4.0.5.GA/server/defaul
t/deploy/holamundo.jar
21:13:53,593 INFO  [TomcatDeployer] deploy, ctxPath=/jmx-console, warUrl=.../dep
loy/jmx-console.war/
21:13:54,046 INFO  [Http11BaseProtocol] Starting Coyote HTTP/1.1 on http-0.0.0.0
-8080
21:13:54,203 INFO  [ChannelSocket] JK: ajp13 listening on /0.0.0.0:8009
21:13:54,250 INFO  [JkMain] Jk running ID=0 time=0/79  config=null
21:13:54,296 INFO  [Server] JBoss (MX MicroKernel) [4.0.5.GA (build: CVSTag=Bran
ch_4_0 date=200610162339)] Started in 24s:93ms

Escribiendo una aplicación cliente[editar]

Una vez desplegado nuestro Bean en el servidor, se hace necesario un programa cliente que lo invoque. Hay que aclarar que este es un ejemplo mínimo y que los EJB se utilizan para grandes aplicaciones distribuidas con mucho tráfico como el comercio electrónico, la banca y similares. En cualquier caso es un buen modo de acercarnos a esta nueva modalidad de programación y para probarla finalmente, necesitamos otro programa que requiera sus servicios y probar que todo marcha según lo previsto.

Un bean enterprise es un componente del lado del servidor que espera llamadas de clientes. Escribir un cliente EJB puede ser a veces una tarea compleja. Sin un cliente, no podremos probar dichos beans. El conocer cómo los clientes acceden y llaman a nuestros beans es una importante fase de una aplicación con EJB.

Para esta práctica creamos un nuevo programa separado del anterior donde crearemos una clase que aquí he llamado BeanCliente. Para este nuevo proyecto, es importante señalar que deberemos añadirle de nuevo las librerías necesarias para resolver todas las referencias con J2EE y la relación con el proyecto anterior. Para arreglarlo, vincularemos las librerías e incluiremos los correspondientes imports.

Para vincular las librerías al proyecto, en Eclipse haríamos: Project -> Properties (pestaña Libraries) y ahí pulsamos el botón "Add external jar" para incluir los siguientes ficheros: jboss-j2ee.jar, jboss-client.jar,jbossall-client.jar y nuestro holamundo.jar. Los tres primeros se encuentran en las carpetas de jboss (normalmente la "client"), y el último era el resultado del paso 3.

Tras estos pasos preparatorios ya podemos escribir el fuente que tiene el siguiente aspecto:

import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;

import com.saludo.HolaMundoHome;
import com.saludo.HolaMundoRemote;

public class BeanCliente {

	public static void main(String[] args) {
		// Preparación de propiedades para construir el contexto inicial de JNDI
		Properties prop = new Properties();
		prop.put(Context.INITIAL_CONTEXT_FACTORY,
				"org.jnp.interfaces.NamingContextFactory");
		prop.put(Context.PROVIDER_URL, "localhost:1099");
		
		try{
			// Intentamos obtener el contexto inicial antes preparado
			InitialContext jndiContext = new InitialContext(prop);
			System.out.println(" >> Obtenido un contexto JNDI");
			
			// Obtener una referencia al Bean
			Object ref = jndiContext.lookup("HolaMundo"); // Nombre del ejb en el ejb-jar.xml
			System.out.println(" >> Obtenida una referencia al Bean \"HolaMundo\"");
			
			// Obtener una referencia desde aquí a la interfaz Home del Bean
			HolaMundoHome home = (HolaMundoHome)
				PortableRemoteObject.narrow(ref, HolaMundoHome.class);
			
			// Creación de la interfaz remota a partir de la interfaz Home:
			HolaMundoRemote h = home.create();
			
			// Invocamos finalmente al Bean 
			System.out.println("Invocando el EJB: " + h.saludo("Pedro"));
		}catch(Exception ex){
			System.out.println(ex.toString());
		}
	}
}

Pues esta era la última pieza del ejemplo. Si no nos hemos encontrado problemas (o mejor, si ya los hemos resuelto) tenemos lista la infraestructura para poner en marcha la práctica.

Si no está ya arrancado el servidor JBoss, lo iniciamos y estamos atentos a que el Bean HolaMundo se ha desplegado satisfactoriamente. Hecho eso, sólo queda invocar el cliente, ejecutando el programa sin más, como aplicación de consola. Se puede hacer desde el propio Eclipse o desde una interfaz de comandos como prueba de funcionamiento.

 >> Obtenido un contexto JNDI
 >> Obtenida una referencia al Bean "HolaMundo"
Invocando el EJB: Hola, Pedro

A partir de aquí ya podríamos avanzar con ejemplos más complejos, como un entorno WEB con JSP, Servlets y EJB o un EJB de Entidad, que por cierto, lo tengo pendiente probar.

Pero eso lo dejamos para el próximo día, esperando que todos los pasos anteriores os hayan salido satisfactoriamente y os sirvan para empezar a comprender el complejo mundo de las aplicaciones con J2EE.

Bueno, pues hasta aquí hemos llegado por hoy.

--Pete 17:37 25 ene 2007 (EST)

Enlaces[editar]