Menú Curso Java EJB's : Session EJB's (Stateful y Stateless)

Espacio (Anterior) EJB's Espacio Entity EJB's (Siguiente) Espacio

Ciclo de Ejecución.

El entender el ciclo de ejecución de un EJB es clave para comprender sus diversos componentes, a continuación se describe este ciclo para un "Session Bean" :

Ciclo de Session EJB
  1. El cliente ya sea un "Servlet/JSP/Applet" o un simple programa Java de terminal, debe encontrar una referencia del EJB que desea llamar, esto se realiza a través de un directorio de nombres (JNDI/LDAP) el cual proporciona una referencia del EJB. Por lo general todo Application Server contiene este tipo de servicio el cual es activado al arranque del mismo, sin embargo, es posible que este servicio de localización sea ofrecido por un producto no incluido con el Application Server.

  2. Se envía el resultado hacia el Cliente indicando la ubicación del denominado EJB, una vez obtenida esta ubicación es posible generar el EJB.

  3. El Cliente invoca el método create del Home Interface del EJB.

  4. Posteriormente el "EJB Container" genera una instancia del EJB que fue llamado por el cliente.

  5. Es necesario asociar la instancia generada con el Remote Interface del EJB , esto permite invocar "métodos/lógica de ejecución" sobre el EJB.

  6. Se retornan los resultados de creación del EJB al Cliente.

  7. Una vez confirmado que la instancia del EJB fue generada, el cliente puede invocar los respectivos métodos sobre el EJB.

  8. A través del Remote Interface del EJB se invocan los respectivos métodos sobre la instancia del EJB.

  9. Ejecutados los métodos sobre la instancia del EJB en cuestión, se retornan los resultados al cliente.

Estructura y Componentes Adicionales.

La estructura básica de EJB's es solo una parte necesaria para la ejecución exitosa de un EJB, a continuación se mencionan otros componentes necesarios para su ejecución.

Stubs y Skeletons

La comunicación ilustrada entre el cliente y el "EJB Container" en la gráfica anterior es llevada acabo mediante procedimientos remotos (via RMI/IIOP), esto implica que el cliente y el "EJB Container" pueden residir en distintos "Hosts" (Computadoras Físicas), y de aquí surge una pregunta clásica de ambientes distribuidos : Como sabe el cliente la definición del EJB ?, Como sabe que métodos llamar ? , la manera en que el cliente se entera de esto es a través de un Stub.

Un Stub proporciona una estructura al cliente que describe los elementos definidos en Servidor, en este caso el EJB. Este Stub es generado por una herramienta proporcionada por el Application Server el cual debe estar accesible al Cliente que intenta comunicarse con el "EJB"/Application Server.El Skeleton es la contra parte del Stub que reside en Servidor, para efectos de EJB's este componente es llevado acabo a través del "Home Interface" y "Remote Interface".

Aunque es importante conocer el uso de Stubs y Skeletons en EJB's, generalmente la comunicación entre el Cliente y EJB es llevada automáticamente y sin mayor preocupación debido a que tanto el "EJB Container" y "Servlet Container" se encuentran en la misma estructura del Application Server y por ende en el mismo ("Host") (Computadora Física). Uno de los casos donde resulta crítico tomar en consideración el uso de Stubs y Skeletons es cuando se posee un ambiente de Cluster, lo cual implica que existe comunicación entre diversos Application Servers en diversos "Hosts" (Computadoras Físicas).

Librerías (JAR's) Propietarias

Además de estos Stubs y Skeletons también existen diversas librerías que son proporcionadas en los diversos Application Servers, estas librerías (Archivos JAR) deben estar accesibles al Cliente o Servidor según lo requiera el Application Server.

Codificación de un Session (Stateless) EJB.

El siguiente EJB es utilizado para obtener el cálculo de Interés sobre cierto monto enviado por un cliente (JSP/Servlet/Applet). Al diseñar un EJB primeramente se diseñan las interfases de éste, a continuación se describen ambas:

Para compilar las Clases de un EJB es necesario tener acceso a la implementación J2EE de las respectivas Clases, en este caso, JBoss proporciona esta libreria en la siguiente ubicación :

$JBOSS_HOME/server/default/lib/jboss-j2ee.jar ; donde $JBOSS_HOME es el directorio raíz de instalación de JBoss.

Por lo tanto antes de intentar compilar estas Clases, dicha libreria debe ser agregada all CLASSPATH del ambiente Java.

"Remote Interface" Intereses.java
package com.osmosislatina.ejb.intereses;

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

public interface Intereses extends EJBObject { 

   public double calcularInteres(double capital, double tasa, double plazo)
       throws RemoteException;

}

Como toda otra interfase en Java, nótese que solo se describen los métodos que serán empleados por el EJB, el único método definido para este EJB es denominado calcularInteres el cual toma 3 parámetros de ejecución; otros detalles notorios de este "Remote Interface" y cualquier otro son:

  • Siempre se hereda ("inherit") la implementación de EJBObject.

  • Todos los métodos definidos deben declarar la posibilidad de generar el error ("exception") RemoteException la cual puede ser invocada al ocurrir un error al nivel de Red.

"Home Interface" InteresesHome.java

El "Home Interface" de un "EJB" define los métodos utilizados para la creación/destrucción del mismo, por lo que pudiera ser considerada una interfase administrativa para el EJB.

package com.osmosislatina.ejb.intereses;

import javax.ejb.EJBHome;
import javax.ejb.CreateException;
import java.rmi.RemoteException;

public interface InteresesHome extends EJBHome { 

   Intereses create() throws RemoteException, CreateException; 

}

Los detalles notorios de este "Home Interface" y cualquier otro son:

  • Siempre se hereda ("inherit") la implementación de EJBHome.

  • Todos los métodos definidos deben declarar la posibilidad de generar el error ("exception") RemoteException la cual puede ser invocada al ocurrir un error al nivel de Red.

  • El método create el cual genera la instancia del EJB debe declarar la posibilidad de la excepción CreateException la cual le indicariá al cliente la inhabilidad de crear el EJB.

"Enterprise Bean Class" InteresesBean.java

Una vez definidas las interfases del EJB es posible implementar el EJB en sí.

package com.osmosislatina.ejb.intereses;

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

public class InteresesBean implements SessionBean { 
      
   public double calcularInteres(double capital, double tasa, double plazo) { 
   
   System.out.println("Un Cliente llamo la función para calculo de Interés");
   return capital * Math.pow(1+tasa, plazo) - capital;
   }

   public InteresesBean() {}
   public void ejbCreate() {}
   public void ejbRemove() {}
   public void ejbPassivate() {}
   public void ejbActivate() {}
   public void setSessionContext(SessionContext sc) {}
}

Aquí se puede notar que la implementación del EJB utiliza la clase SessionBean, debido a esto es necesario implementar todos aquellos métodos definidos en SessionBean que incluyen:

  • ejbCreate: Invocado al crearse una instancia del EJB.

  • ejbRemove: Llamado para eliminar una instancia del EJB.

  • ejbPassivate: Este método es utilizado para guardar "x" instancia de un EJB a memoria secundaria ("Disco Duro/Swap"), esto puede ocurrir cuando los recursos del Application Server/"EJB Container" sean excedidos y sea necesario reubicar (pasivar) ciertos elementos fuera de éste.

  • ejbActivate: Este método es invocado cuando se desea recuperar la instancia de un EJB de memoria secundaria.

  • setSessionContext: Método utilizado para mantener cierta información de sesión respecto al EJB.

En este EJB no se define ningún tipo de lógica para estos métodos, sin embargo, en ocasiones se define cierta lógica que debe ser ejecutada al crear,destruir,activar y/o pasivar cualquier EJB, esto será explorado en otra sección de este curso.

Además de estos métodos, deben implementarse todos aquellos definidos en el "Remote Interface" del EJB, en este caso solo existe calcularInteres donde se define la lógica de negocios a realizarse.

"Deployment Descriptor" ejb-jar.xml

El "Deployment Descriptor" es la última parte a definir en la generación de un EJB.

<?xml version="1.0" encoding="UTF-8"?>

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

 <ejb-jar>
      <description>Calculo de Intereses</description>
      <display-name>Calculo</display-name>
      <enterprise-beans>
        <session>
          <ejb-name>Calculo</ejb-name>
          <home>com.osmosislatina.ejb.intereses.InteresesHome</home>
          <remote>com.osmosislatina.ejb.intereses.Intereses</remote>
          <ejb-class>com.osmosislatina.ejb.intereses.InteresesBean</ejb-class>
          <session-type>Stateless</session-type>
          <transaction-type>Bean</transaction-type>
        </session>
      </enterprise-beans>
 </ejb-jar>

Se puede notar que son definidos los nombres de cada parte del EJB en conjunción con otros parámetros, de especial importancia es el parámetro ejb-name el cual indicará el nombre asociado con este EJB y que eventualmente será publicado por el "Servidor de Nombres" JNDI/LDAP.

La generación del "Deployment Descriptor" generalmente se lleva acabo a través de alguna herramienta proporcionada con el Application Server, aunque es posible definirlo manualmente, observará que diversos parámetros son un tanto crípticos y por ende se opta por automatizar su creación a través de las herramientas proporcionadas con el Application Server que este utilizando.

Creación del EJB (Archivo JAR) y Ejecución ("Deployment")

Finalmente es necesario agrupar todos los componentes del EJB en un archivo JAR, al igual que el "Deployment Descriptor", la creación de este archivo EJB-JAR generalmente se lleva acabo a través de herramientas proporcionadas con el Application Server y varía según este.

A continuación se describe la creación de éste archivo EJB-JAR mediante el comando jar proporcionado con el JDK, dada la siguiente estructura de directorios/archivos, ejecute el comando jar cvf Intereses.jar * estando en el directorio raíz :

 
  +-com-+
  |     |
  |     +-osmosislatina-+
  |                     | 
  |                     +-ejb-+
  +-META-INF-+                |
             |                +-intereses-+
             |                            | 
             +-ejb-jar.xml                +-Intereses.class
                                          | 
                                          +-InteresesHome.class
                                          |
                                          +-InteresesBean.class

El proceso anterior genera el archivo Intereses.jar, el cual contiene un EJB en estado para ser ejecutado en el "EJB Container".

La ejecución ("Deployment") de un EJB en un Application Server/"EJB Container" varía substancialmente de vendedor a vendedor, en el caso de JBoss solo es necesario colocar el archivo JAR (EJB-JAR) generado anteriormente, bajo el directorio $JBOSS_HOME/server/default/deploy y esto inicializa el EJB, donde $JBOSS_HOME es el directorio raíz de JBoss; sin embargo, vale mencionar que en otros Application Servers como WebLogic o WebSphere pueden utilizarse herramientas especiales para realizar esta tarea de ejecución ("Deployment").

Codificación del Cliente para un Session(Stateless) EJB.

Para interactuar con el Session Bean es necesario crear un cliente, a continuación se diseña un cliente que opera como un programa Java de terminal, este cliente también pudo ser diseñado como un JSP/Servlet o Applet, sin embargo, para otorgar mayor sencillez a su creación se opto por este tipo de cliente.

"Cliente del EJB" ClienteIntereses.java

package com.osmosislatina.ejb.intereses;

import java.util.Properties;
import javax.rmi.PortableRemoteObject; 
import javax.naming.*;

class ClienteIntereses
 {
    public static void main(String[] args)
    {
       Properties env = new Properties();
       
       // Definir las propiedades y ubicación de búsqueda de Nombres JNDI.
       env.setProperty("java.naming.factory.initial",  
                       "org.jnp.interfaces.NamingContextFactory");
       env.setProperty("java.naming.provider.url",  "localhost:1099");
       env.setProperty("java.naming.factory.url.pkgs",  "org.jboss.naming");

       try
       {
          // Traer el Contexto de Nombre 
          InitialContext jndiContext = new InitialContext(env);
          System.out.println("Contexto Disponible");
          
          // Traer la Referencia del EJB
          Object ref  = jndiContext.lookup("Calculo");
          System.out.println("Se encontró Referencia del EJB!");
          
          // Traer la referencia del "Home Interface "
          InteresesHome home = (InteresesHome) 
          PortableRemoteObject.narrow (ref, InteresesHome.class);

          // Crear un Objeto  a partir del "Home Interface"
          Intereses interes = home.create();

          // Llamar la función 
          System.out.println("Interés de 10,000 Capital, a tasa 10%, 
                              bajo 2 plazos anuales:");
          System.out.println(interes.calcularInteres(10000, 0.10, 2));
       }
       catch(Exception e)
       {
          System.out.println(e.toString());
       }
    }
 }

  1. La primer sección de este programa define las propiedades del directorio para nombramientos JNDI, en este caso se indica el Directorio de nombres que reside en la maquina local (localhost) utilizando el puerto TCP 1099, este directorio JNDI es ejecutado automáticamente al iniciar JBoss y es el que otorga servicios de nombramiento a los EJB's.

  2. La segunda sección (donde inicia el Bloque try) inicializa el Contexto JNDI con los parámetros definidos anteriormente (env).

  3. Una vez inicializado el Contexto JNDI se realiza una búsqueda para el componente llamado Calculo, este nombre es precisamente aquel designado en el "Deployment Descriptor" del EJB, en otras palabras, se esta realizando una búsqueda por el EJB; si es exitosa la búsqueda se imprime un mensaje.

  4. Posteriormente se trae una referencia del "Home Interface", seguido de la generación del Objeto a través de la función create.

  5. Finalmente se llama la función calcularInteres del Objeto.

Antes de intentar compilar este programa llamado ClienteIntereses.java recuerde que debido al uso de Procedimientos Remotos(RMI/IIOP), se requieren los Stubs correspondientes; en este caso los Stubs corresponden a las interfases InteresesHome.class e Intereses.class, ambas fueron compiladas para el EJB. Esta inclusión anterior significa que deben estar disponibles en el CLASSPATH de Java al compilarse el cliente.

Además de estas Clases, debido a que el "EJB Container" en cuestión es JBoss, se deberán incluir los archivos JAR que son requeridos por Clientes que intentan accesar JBoss, esto es, también deben ser agregados al CLASSPATH de Java, el siguiente comando lo demuestra:

[root@servidor1 jboss]# java -classpath "$CLASSPATH:/usr/local/jboss/
client/jbossall-client.jar com.osmosislatina.ejb.intereses.ClienteIntereses

Session (Stateful) EJB.

A diferencia del Session EJB descrito anteriormente, existe otro tipo de Session EJB sub-clasificado Stateful , como su nombre lo indica, este tipo de EJB mantiene un estado ("state") para el cliente (JSP/Servlet); al utilizar el Stateless EJB diseñado anteriormente el Cliente lo invoca una sola vez y posteriormente no mantiene ningún tipo de estado conversacional entre éste, esto implica que el EJB no mantiene registro alguno del Cliente, tal como el caso anterior donde el cliente realiza un Calculo de Intereses y posteriormente se da por terminada la operación entre el EJB y cliente.

En un Stateful EJB, el EJB como tal mantiene información acerca del Cliente (JSP/Servlet) que lo ha llamado; aunque este tipo de EJB resulta útil para cierto tipo de diseños, en tiempos recientes su uso ha sido criticado por la simple razón que también es posible mantener este mismo estado ("state") dentro de un JSP o Servlet. Una de las razones por las que se opta por mantener estado ("state") dentro de un JSP/Servlet a diferencia de un EJB es debido al nivel de complejidad que conlleva diseñar éste último.

Aunque es recomendable evitar el uso Session Stateful EJB's, existen casos en los que es ideal mantener estado ("state") del cliente dentro del EJB, este caso resulta cuando el EJB interactúa con sistemas de información como Bases de Datos o ERP's, este mecanismo forma el principio de Entity EJB's los cuales serán descritos en la siguiente sección.

Terminos Legales de Contenido ©2000-2011 Osmosis Latina

Diseñado bajo estándares : XHTML   CSS  

webmaster@osmosislatina.com