Tema 2. Introducción a los Enteprise Beans

Un enterprise bean es un componente (objeto) distribuido gestionado por un servidor, escrito en el lenguaje Java y que implementa la lógica de negocio de una aplicación. Por ejemplo, en una aplicación de control de inventario, un enterprise bean podría implementar la lógica de negocio mediante métodos llamados checkInventoryLevel y orderProduct. Mediante la invocación de estos productos, los clientes remotos podrían acceder a los servicios de inventario proporcionados por la aplicación.

Los enterprise beans simplifican el desarrollo de aplicaciones distribuidas de gran tamaño por varias razones:

Es recomendable usar enterprise beans cuando la aplicación que deseamos desarrollar cumple alguno de los siguientes requisitos:

Existen tres tipos de enterprise beans:

2.1 Tipos de enterprise beans

2.1.1 Beans de sesión

Los beans de sesión representan sesiones interactivas con uno o más clientes. Los bean de sesión pueden mantener un estado, pero sólo durante el tiempo que el cliente interactua con el bean. Esto significa que los beans de sesión no almacenan sus datos en una base de datos después de que el cliente termine el proceso. Por ello se suele decir que los beans de sesión no son persistentes.

A diferencia de los bean de entidad, los beans de sesión no se comparten entre más de un cliente, sino que existe una correspondencia uno-uno entre beans de sesión y clientes. Por esto, el contenedor EJB no necesita implementar mecanismos de manejo de concurrencia en el acceso a estos beans.

Existen dos tipos de beans de sesión: con estado y sin él.

Beans de sesión sin estado

Los beans de sesión sin estado no se modifican con las llamadas de los clientes. Los métodos que ponen a disposición de las aplicaciones clientes son llamadas procedurales que reciben datos y devuelven resultados, pero que no modifican internamente el estado del bean. Esta propiedad permite que el contenedor EJB pueda crear un almacén (pool) de instancias, todas ellas del mismo bean de sesión sin estado y asignar cualquier instancia a cualquier cliente. Incluso un único bean puede estar asignado a múltiples clientes, ya que la asignación sólo dura el tiempo de invocación del método solicitado por el cliente.

Cuando un cliente invoca un método de un bean de sesión sin estado, el contenedor EJB obtiene una instancia del almacén. Cualquier instancia servirá, ya que el bean no puede guardar ninguna información referida al cliente. Tan pronto como el método termina su ejecución, la instancia del bean está disponible para otros clientes. Esta propiedad hace que los beans de sesión sin estado sean muy escalables para un gran número de clientes. El contenedor EJB no tiene que mover sesiones de la memoria a un almacenamiento secundario para liberar recursos, simplemente puede obtener recursos y memoria destruyendo las instancias.

Es apropiado usar beans de sesión sin estado cuando una tarea no está ligada a un cliente específico:

Algunos ejemplos de bean de sesión sin estado podrían ser:

Beans de sesión con estado

En un bean de sesión con estado, las variables de instancia del bean almacenan datos específicos obtenidos durante la conexión con el cliente. Cada bean de sesión con estado, por tanto, almacena el estado conversacional de un cliente que interactua con el bean. Este estado conversacional se modifica conforme el cliente va realizando llamadas a los métodos de negocio del bean. El estado conversacional no se guarda cuando el cliente termina la sesión.

Algunos ejemplos de beans de sesión con estado podrían ser:

Debido a que el bean guarda el estado conversacional con un cliente determinado, no le es posible al contenedor crear un almacen de instancias y compartirlo entre muchos clientes. Por ello, el manejo de beans de sesión con estado es más pesado que el de beans de sesión sin estado.

Uso de beans de sesión

En general, se debería usar un bean de sesión con estado si se cumplen las siguientes circunstancias:

Para mejorar la eficiencia de la aplicación, se debería usar beans de sesión sin estado si se cumple alguna de las siguientes condiciones:

2.1.2 Beans de entidad

Los beans de entidad modelan conceptos de negocio que puede expresarse como nombres. Esto es una regla sencilla más que un requisito formal, pero ayuda a determinar cuándo un concepto de negocio puede ser implementado como un bean de entidad. Los beans de entidad representan “cosas”: objetos del mundo real como hoteles, habitaciones, expedientes, estudiantes, y demás. Un bean de entidad puede representar incluso cosas abstractas como una reserva. Los beans de entidad describen tanto el estado como la conducta de objetos del mundo real y permiten a los desarrolladores encapsular las reglas de datos y de negocio asociadas con un concepto específico. Por ejemplo un EJB Estudiante encapsula los datos y reglas de negocio asociadas a un estudiante. Esto hace posible manejar de forma consistente y segura los datos asociados a un concepto.

Los beans de entidad se corresponden con datos en un almacenamiento persistente (base de datos, sistema de ficheros, etc.). Las variables de instancia del bean representan los datos en las columnas de la base de datos. El contenedor debe sincronizar las variables de instancia del bean con la base de datos. Los beans de entidad se diferencian de los beans de sesión en que las variables de instancia se almacenan de forma persistente.

Son muchas las ventajas de usar beans de entidad en lugar de acceder a la base de datos directamente. El uso de beans de entidad para transformar en objetos los datos proporciona a los programadores un mecanismo más simple para acceder y modificar los datos. Es mucho más fácil, por ejemplo, cambiar el nombre de un estudiante llamando a student.setName() que ejecutando un comando SQL contra la base de datos. Además, el uso de objetos favorece la reutilización del software. Una vez que un bean de entidad se ha definido, su definición puede usares a lo largo de todo el sistema de forma consistente. Un EJB Estudiante proporciona un forma completa de acceder a la información del estudiante y eso asegura que el acceso a la información es consistente y simple.

La representación de los datos como beans de entidad puede hacer que el desarrollo sea más sencillo y menos costoso.

Diferencias con los beans de sesión

Los beans de entidad se diferencian de los beans de sesión, principalmente, en que son persistentes, permiten el acceso compartido, tienen clave primaria y pueden participar en relaciones con otros beans de entidad:


Persistencia

Debido a que un bean de entidad se guarda en un mecanismo de almacenamiento se dice que es persistente. Persistente significa que el estado del bean de entidad existe más tiempo que la duración de la aplicación o del proceso del servidor J2EE. Un ejemplo de datos persistentes son los datos que se almacenan en una base de datos.

Los beans de entidad tienen dos tipos de persistencia: Persistencia Gestionada por el Bean (BMP, Bean-Managed Persistence) y Persistencia Gestionada por el Contenedor (CMP, Container-Managed Persistence). En el primer caso (BMP) el bean de entidad contiene el código que accede a la base de datos. En el segundo caso (CMP) la relación entre las columnas de la base de datos y el bean se describe en el fichero de propiedades del bean, y el contenedor EJB se ocupa de la implementación.

Acceso compartido

Los clientes pueden compartir beans de entidad, con lo que el contenedor EJB debe gestionar el acceso concurrente a los mismos y por ello debe usar transacciones. La forma de hacerlo dependerá de la política que se especifique en los descriptores del bean.

Clave primaria

Cada bean de entidad tiene un identificador único. Un bean de entidadad alumno, por ejemplo, puede identificarse por su número de expediente. Este identificador único, o clave primaria, permite al cliente localizar a un bean de entidad particular.

Relaciones

De la misma forma que una tabla en una base de datos relacional, un bean de entidad puede estar relacionado con otros EJB. Por ejemplo, en una aplicación de gestión administrativa de una universidad, el bean alumnoEJB y el bean actaEBJ estarían relacionados porque un alumno aparece en un acta con una calificación determinada.

Las relaciones se implementan de forma distinta según se esté usando la persistencia manejada por el bean o por el contenedor. En el primer caso, al igual que la persistencia, el desarrollador debe programar y gestionar las relaciones. En el segundo caso es el contenedor el que se hace cargo de la gestión de las relaciones. Por ello, estas últimas se denominan a veces relaciones gestionadas por el contenedor.

Persistencia manejada por el contenedor

El término persistencia manejadad por el contenedor significa que el contenedor EJB maneja todos los accesos a bases de datos requeridos por el bean. El código del bean no contiene ninguna llamada SQL. Como resultado, el código del bean no está atado a un tipo específico de almacenamiento persistente. A causa de esta flexibilidad, incluso si se vuelve a desplegar el bean en un servidor distinto de J2EE que use una base de datos distinta, no hará falta recompilar el código del bean. En breve, los beans son más portables.

Para poder generar las llamadas de acceso a los datos, el contenedor necesita información que se proporciona en el esquema abstracto del bean de entidad

Esquema abstracto

El esquema abstracto es una parte del descriptor de despliegue de un bean de entidad. El término abstracto distingue este esquema del esquema físico del sistema de almacenamiento de datos subyacente. En una base de datos relacional, por ejemplo, el esquema físico está formado por estructuras como tablas y columnas.

En el esquema abstracto se define un nombre del enterprise bean. Este nombre puede ser usado luego como referencia en preguntas escritas en el lenguaje EJB QL (Enterprise JavaBeans Query Language). Es necesario definir una consulta EJB QL para cada método de búsqueda del bean (excepto findByPrimaryKey). Esta consulta EJB QL es ejecutada por el contenedor EJB cada vez que se invoca el método de búsqueda.

La siguiente figura muestra un esquema abstracto sencillo que describe las relaciones entre cuatro beans de entidad.

Campos persistentes

Los campos persistentes de un bean de entidad se almacenan en el almacén de datos subyacente. El conjunto de campos persistentes representa el estado del bean. En tiempo de ejecución, el contenedor EJB sincroniza automáticamente este estado con la base de datos. Durante el despliegue, el contenedor suele hacer corresponder el bean de entidad con una tabla de la base de datos y hacer corresponder los campos persistentes con las columnas de la tabla.

Por ejemplo, el bean ClienteEJB podría tener campos persistentes como nombre, apellidos, direcciónCorreo y telefono. En persistencia gestionada por el contenedor estos campos son virtuales. Se declaran en el esquema abstracto, pero no se codifican como variables de instancia en el bean. En su lugar, los campos persistentes se identifican en el código con métodos de acceso (de tipo get y set).

Campos de relación

Un campo de relación es como una clave externa en una base de datos: identifica a un bean relacionado. Al igual que un campo persistente, un campo de relación es virtual y se define en el enterprise bean con un método de acceso. Pero a diferencia de los campos persistentes, un campo de relación no representa el estado del bean.

2.1.3 Beans dirigidos por mensajes

Son el tercer tipo de beans propuestos por la última especificación de EJB. Estos beans permiten que las aplicaciones J2EE reciban mensajes JMS de forma asíncrona. Así, el hilo de ejecución de un cliente no se bloquea cuando está esperando que se complete algún método de negocio de otro enterprise bean. Los mensajes pueden enviarse desde cualquier componente J2EE (una aplicación cliente, otro enterprise bean, o un componente Web) o por una aplicación o sistema JMS que no use la tecnología J2EE.

Diferencias con los beans de sesión y de entidad

La diferencia más visible es que los clientes no acceden a los beans dirigidos por mensajes mediante interfaces (explicaremos esto con más detalle más adelante), sino que un bean dirigido por mensajes sólo tienen una clase bean.

En muchos aspectos, un bean dirigido por mensajes es parecido a un bean de sesión sin estado.

Las variables de instancia de estos beans pueden contener algún estado referido al manejo de los mensajes de los clientes. Por ejemplo, pueden contener una conexión JMS, una conexión de base de datos o una referencia a un objeto enterprise bean.

Cuando llega un mensaje, el contenedor llama al método onMessage del bean. El método onMessage suele realizar un casting del mensaje a uno de los cinco tipos de mensajes de JMS y manejarlo de forma acorde con la lógica de negocio de la aplicación. El método onMessage puede llamar a métodos auxiliares, o puede invocar a un bean de sesión o de entidad para procesar la información del mensaje o para almacenarlo en una base de datos.

Un mensaje puede enviarse a un bean dirigido por mensajes dentro de un contexto de transacción, por lo que todas las operaciones dentro del método onMessage son parten de un única transacción.

2.2 Implementación de un enterprise bean

Para implementar un enterprise bean, el desarrollador debe proporcionar cuatro elementos: una interfaz remota del bean, una interfaz home, una clase enterprise bean y un fichero de descripción del despliegue. La interfaz home declara métodos de fábricación (factory methods) que usan los clientes Java para crear nuevos enterprise beans, localizar enterprise beans existentes y destruir los beans. La interfaz remota declara los métodos de negocio del enterprise bean, que usan los clientes Java en tiempo de ejecución. La clase enterprise bean encapsula la lógica del bean e implementa los métodos de negocio definidios en la interfaz remota. El descriptor de despliegue es un fichero de configuración XML que describe al servidor EJB el enterprise bean y sus atributos de tiempo de ejecución. Es responsabilidad del desarrollador del bean crear estos cuatro elementos y empaquetarlos en un fichero JAR listo para el despliegue.

Cuando se despliega un enterprise bean, el desplegador usa las herramientas proporcionadas por el servidor EJB para abrir el fichero JAR y leer el ficher XML descriptor del despliegue. La información de este fichero se usa para configurar la conducta en tiempo de ejecución del enterprise bean y distintos elementos relacionados con el servidor. El enterprise bean se despliega en un contenedor, que es el nombre que recibe la parte del servidor de aplicaciones que almacena instancias de enterprise beans. El contenedor se responsabiliza de gestionar las transacciones, seguridad, concurrencia, persistencia y recursos que usa el enterprise bean en tiempo de ejecución. Además, el contenedor genera los proxies EJBHome y EJBObject que implementan las interfaces home y remota del bean (los stub, usando la terminología de RMI). Estos proxies proporcionan a los clientes Java distribuidos que se encuentran en la capa de presentación un acceso a los enterprise beans de la capa intermedia.

Los clientes Java usan JNDI para obtener una referencia remota al EJBHome de un enterprise bean. Después usa el EJBHome para crear o encontrar enterprise beans específicos en el contenedor EJB. Cuando lo consigue, recibe una referencia remota a un EJBObject. El EJBObject implementa la interfaz remota del enterprise bean.

Los clientes Java acceden al enterprise bean a través de sus proxies remotos EJBHome y EJBObject, en lugar de directamente. El contenedor EJB intercepta las invocaciones de los métodos realizadas sobre los proxies remotos, de forma que pueda manejar el entorno de ejecución del bean asociado con la invocación. Las invocaciones de métodos sobre el EJBHome hacen que el contenedor localice o cree una instancia del bean y proporcione una referencia remota EJBObject del mismo al cliente. Las invocaciones de métodos sobre el EJBObject se delegan a una instancia del enterprise bean, que contiene la lógica de negocio necesaria para dar servicio a la petición. El contenedor EJB puede usar muchas instancias de la clase enterprise bean para dar soporte a los clientes, lo cual permite que sobrellevar incrementos puntuales de carga de clientes aumentando el número de instancias gestionandas e incluso construyendo clusters de contenedores y distribuyendo las instancias.

A continuación explicamos un poco más cada uno de los componentes del bean, dando también indicaciones de nomenclatura de los nombres de ficheros. Usaremos como ejemplo el bean HelloWorldEJB.

Interfaz remota o local

La interfaz remota (HelloWorld.java) o local (HelloWorldLocal.java) del bean son las interfaces que definen los métodos de acceso que un enterprise bean ofrece a sus clientes. Estas interfaces pueden definir un acceso remoto al bean, usando la interfaz Remote de RMI, o pueden definir un acceso local al bean para aquellos casos en que el bean va a ser usado por clientes en la misma máquina virtual Java. Esta interfaz será implementada por los métodos de negocio que se definen en el fichero de definición de la clase del bean y por el contenedor EJB, que añade los aspectos del nivel de sistema.

HelloWorld.java

  package HelloWorldSLBean;

  import java.rmi.*;
  import javax.ejb.*;

  public interface HelloWorld extends EJBObject {
     public String sayHello() throws RemoteException;
}

 HelloWorldLocal.java

   package HelloWorldSLBean;

   import java.rmi.*;
   import javax.ejb.*;

   public interface HelloWorldLocal extends EJBLocalObject {
      public String hi() throws EJBException;
}

Interfaz Home

La interfaz home (HelloWorldHome.java) o la interfaz home local (HelloWorldHomeLocal.java) son las interfaces que definen los métodos de gestión del ciclo de vida de las instancias del bean. Si recordamos el módulo de RMI, esta interfaz es lo que en RMI se denomina una clase factoría. Algunos ejemplos de métodos de esta interfaz son los métodos create, remove o findByPrimaryKey que crean, eliminan o buscan una instancia de bean. Esta interfaz es implementada por el contenedor EJB. La interfaz home también puede ser remota o local, dependiendo si el acceso al bean va a ser desde otra máquina virtual Java o desde la misma.

HelloWorldHome.java

  package HelloWorldSLBean;

  import java.rmi.*;
  import javax.ejb.*;
 
  public interface HelloWorldHome extends EJBHome {
     public HelloWorldRemote create() throws RemoteException, CreateException;
  }

HelloWorldHomeLocal.java

  package HelloWorldSLBean;

  import java.rmi.*;
  import javax.ejb.*;

  public interface HelloWorldHomeLocal extends EJBLocalHome {
    public HelloWorld create() throws CreateException, EJBException;
  }

Clase enterprise bean

La clase enterprise bean (HelloWorld.java) implementa los métodos de negocio del bean. El fichero es el mismo, independientemente de que la implementación del bean sea local o remota.

HelloWorldBean.java

  package HelloWorldSLBean;

  import javax.ejb.*;
 
  public class HelloWorldBean implements SessionBean {
     public String sayHello() {
        String ret = new String("Hola; soy Domingo");
        return ret;
     }
   
     public void ejbCreate(){}
     public void ejbActivate(){}
     public void ejbPassivate(){}
     public void ejbRemove(){}
     public void setSessionContext(SessionContext cntx) {}
  }

Fichero XML descriptor del despliegue

El fichero de descripción del despliegue (ejb-jar.xml) es el fichero XML que especifica información declarativa sobre el enterprise bean que será usada por el contenedor EJB para manejar los aspectos de nivel de sistema (seguridad, transacciones, persistencia, etc.).

ejb-jar.xml

  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE ejb-jar PUBLIC
  '-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN'
  'http://java.sun.com/j2ee/dtds/ejb-jar_1_1.dtd'>
 
  <ejb-jar>
  <display-name>Hello World</display-name>
  <enterprise-beans>
  <session>
  <description>Hello World EJB</description>
  <display-name>HelloWorld</display-name>
  <ejb-name>HelloWorldEJB</ejb-name>
  <home>HelloWorldSLBean.HelloWorldHome</home>
  <remote>HelloWorldSLBean.HelloWorld</remote>
  <ejb-class>HelloWorldSLBean.HelloWorldBean</ejb-class>
  <session-type>Stateless</session-type>
  <transaction-type>Container</transaction-type>
  </session>
  </enterprise-beans>
  </ejb-jar>

Fichero EJB JAR que empaqueta el bean

Como hemos visto en el tema anterior, todos los ficheros que constituyen el bean se empaquetan en un único fichero con la utilidad JAR. La estructura del fichero JAR es:

/META-INF/ejb-jar.xml
/META-INF/weblogic-ejb-jar.xml
/HelloWorldSLBean/HelloWorld.class
/HelloWorldSLBean/HelloWorldHome.class
/HelloWorldSLBean/HelloWorldBean.class

En el directorio META-INF se incluyen los ficheros de descripción del despliegue: el fichero estándar (ejb-jar.xml) y el personalizado para el servidor de aplicaciones (weblogic-ejb-jar.xml). La mayoría de servidores EJB proporcionan herramientas gráficas que crean el fichero de descripción y empaquetan el bean de forma automática. El resto de directorio comprende los paquetes que definen beans.

2.3 Aplicaciones clientes

2.3.1 Cliente Java

Un cliente puede acceder a un bean de sesión o bean de entidad a través de los métodos definidos en las interfaces del bean. Estas interfaces definen la vista que el cliente tiene del bean. El resto de aspectos del bean, como implementaciones de los métodos, características definidas por los descriptores de despliegue, esquemas abstractos o llamadas de acceso a las bases de datos, se esconden de los clientes.

Los clientes que acceden a los enterprise beans pueden ser aplicaciones Java usando JNDI y Java RMI-IIOP, componentes Web (páginas JSP o servlets) o también otros beans. En todos los casos el funcionamiento es el mismo:

Es fundamental esforzarse en realizar un buen diseño de las interfaces. El desarrollo y el mantenimiento de las aplicaciones J2EE dependen de ello. Unos interfaces limpios y claros permitirán ocultar a las aplicaciones clientes las complejidades internas de la capa EJB y también permitirán internamente cambiar la implementación de los beans sin afectar a esas aplicaciones. Por ejemplo, si se cambia el método de persistencia de persistencia gestionada por el bean a persistencia gestionada por el contenedor, no será necesario modificar el código de las aplicaciones clientes. Pero si se cambia la definición de los métodos de las interfaces, entonces será necesario modificar también el código de las aplicaciones clientes. Por ello, para aislar las aplicaciones clientes de posibles cambios en los beans, es importante que se diseñen las interfaces de forma cuidadosa.

HelloWorldClient.java

  mport java.io.*;
  import java.text.*;
  import java.util.*;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import javax.naming.*;
  import javax.rmi.*;
 
  public class HelloWorldClient {
 
     public static void main(String [] args) {
        try {
           Context jndiContext = getInitialContext();
           Object ref = jndiContext.lookup("HelloWorldEJB");
           HelloWorldRemoteHome home = (HelloWorldRemoteHome)
           PortableRemoteObject.narrow(ref, HelloWorldRemoteHome.class);
           HelloWorldRemote hw = home.create();
           System.out.println("Voy a llamar al bean");
           System.out.println(hw.sayHello());
           System.out.println("Ya he llamado al bean");
        } catch (Exception e) {e.printStackTrace();}
  }

  public static Context getInitialContext()
  throws javax.naming.NamingException {
     Properties p = new Properties();
     p.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
     p.put(Context.PROVIDER_URL, "t3://localhost:7001");
     return new javax.naming.InitialContext(p);
  }
}

2.3.2 Clientes Web: Servlet y JSP

La diferencia fundamental entre un cliente Web (Servlet y JSP) y un cliente Java es que, en general, los clientes web se ejecutan en el mismo servidor de aplicaciones en donde reside en el EJB. Por ello, cambia la forma de localizar el bean: en lugar de usar el contexto genérico JNDI, se usa un contexto específico llamado JNDI ENC (Environment Naming Context). Para colocar una referencia al bean en este contexto se usa la entrada <ejb-ref> en el fichero de descripción de despliegue de la aplicación web.

HelloWorldServlet.java

import java.io.*;
import java.text.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.naming.*;
import javax.rmi.*;
import HelloWorldSLBean.*;

public class HelloWorldServlet extends HttpServlet {
private HelloWorld hw = null;
public HelloWorldServlet() throws NamingException {
  try {
     Context jndiContext = getInitialContext();
     Object ref = jndiContext.lookup("java:comp/env/ejb/HelloWorldEJB");
     HelloWorldHome home = (HelloWorldHome) 
     PortableRemoteObject.narrow(ref, HelloWorldHome.class);
     this.hw = home.create();
  } catch (java.rmi.RemoteException re){re.printStackTrace();}
    catch (javax.naming.NamingException ne){ne.printStackTrace();}
    catch (javax.ejb.CreateException ce){ce.printStackTrace();}
  }

public void doGet(HttpServletRequest request, HttpServletResponse response)
  throws IOException, ServletException {
  response.setContentType("text/html");
  PrintWriter out = response.getWriter();
  out.println("<html>");
  out.println("<head>");
  out.println("<title>Hola</title>");
  out.println("</head>");
  out.println("<body bgcolor=\"white\">");
  out.println("<h1> HelloWorldEJB dice: ");
  out.println(this.hw.hi());
  out.println("</h1>");
  out.println("</body>");
  out.println("</html>");
  }

public static Context getInitialContext()
  throws javax.naming.NamingException {
  Properties p = new Properties();
  return new javax.naming.InitialContext(p);
  }
}

HelloWorld.jsp 

<%@ page import="HelloWorldSLBean.*, javax.naming.*,
javax.rmi.PortableRemoteObject,java.rmi.RemoteException,
javax.ejb.CreateException" %>
<% response.addHeader("Cache-Control", "no-cache, must-revalidate"); %>
<%@ include file="CommonFunctions.jsp" %>

<%!
  HelloWorld helloWorld = null;
%>

<html>
<head>
<title>HelloWorld></title>
</head>
<body bgcolor="#ffffff" LEFTMARGIN="10" RIGHTMARGIN="10"
  link="#3366cc" vlink="#9999cc" alink="#0000cc">

<%
  try {
     Context jndiContext = getInitialContext();
     Object ref = jndiContext.lookup("java:comp/env/ejb/HelloWorldEJB");
     HelloWorldHome home = (HelloWorldHome)
     PortableRemoteObject.narrow(ref,HelloWorldHome.class);
     helloWorld = home.create();
  } catch (Throwable t) {
  t.printStackTrace();
  out.print(t.getMessage()+"<br>Stacktrace:<br>");
  t.printStackTrace(new PrintWriter(out,true));
  }
%>

<h1> HelloWorld bean dice: <%= helloWorld.hi()%> </h1>
</body> </html> web.xml <web-app> <display-name>Hello World</display-name> <description>Hello World</description> <servlet> <servlet-name>HelloWorldJSP</servlet-name> <jsp-file>HelloWorld.jsp</jsp-file> </servlet> <servlet> <servlet-name>HelloWorldServlet</servlet-name> <servlet-class>HelloWorldServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloWorldServlet</servlet-name> <url-pattern>/HolaMundo</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>HelloWorldJSP</servlet-name> <url-pattern>/HolaMundo.jsp</url-pattern> </servlet-mapping> ... <ejb-ref> <ejb-ref-name>ejb/HelloWorldEJB</ejb-ref-name> <ejb-ref-type>Session</ejb-ref-type> <home>HelloWorldSLBean.HelloWorldHome</home> <remote>HelloWorldSLBean.HelloWorld</remote> </ejb-ref> </web-app> weblogic.xml <weblogic-web-app> <reference-descriptor> <ejb-reference-description> <ejb-ref-name>ejb/HelloWorldEJB</ejb-ref-name> <jndi-name>HelloWorldEJB</jndi-name> </ejb-reference-description> </reference-descriptor> </weblogic-web-app>

2.4 Acceso remoto y local a los beans

Al diseñar aplicaciones J2EE, una de las primeras decisiones que hay que tomar es el tipo de acceso que van a utilizar en los beans: remoto o local.

2.4.1. Acceso remoto

Un cliente remoto de un enterprise bean tiene las siguientes características

Para crear un enterprise bean con un acceso remoto es necesario codificar una interfaz remota y una interfaz home. La interfaz remota define los métodos de negocio que podrán ser respondidos por las instancias del bean. Por ejemplo, la interfaz remota de un bean llamado CuentaBancariaEJB podría tener métodos de negocio como transferir o credito. La interfaz home proporciona los métodos necesarios para gestionar el ciclo de vida de las instancias del bean, como create y remove. Para los beans de entidad, la interfaz home también define métodos de búsqueda y métodos home (equivalentes a los métodos de clase en Java). Los métodos de búsqueda se usan para localizar instancias de beans de entidad a partir de su clave primaria. Los métodos home son métodos de negocio cuya invocación afecta a todas las instancias de un bean.

2.4.2 Acceso local

Un cliente local tiene estas características:

Al igual que en el acceso remoto, para construir un enterprise bean que permita acceso local se debe codificar la interfaz local y la interfaz home local. La interfaz local define los métodos de negocio del bean y la interfaz home local los métodos que gestionan el ciclo de vida de las instancias del bean.

2.4.3. Interfaces locales y relaciones gestionadas por el contenedor

Si un bean de entidad es el objetivo de una relación gestionada por el contenedor, entonces debe tener una interfaz local. La dirección de la relación determina si un bean es un objetivo o no lo es. En la figura 2.1, por ejemplo, ProductoEJB es el objetivo de una relación unidireccional con LineaPedidoEJB. Debido a que LineaPedidoEJB accede a ProductoEJB localmente, ProductoEJB debe tener una interfaz local. El bean LineaPedidoEJB también necesita una interfaz local ya que es el objetivo de una relación con PedidoEJB. Y como la relación entre LineaPedidoEJB y PedidoEJB es bidireccional ambos beans deben tener interfaces locales.

Todos los beans que participan en un grupo de relaciones manejadas por el contenedor deben residir en el mismo fichero JAR, ya que todos requieren interfaces locales.

El beneficio principal de las interfaces locales es una mejora en la eficiencia de las invocaciones entre beans, debido a que los parámetros no tienen que serializarse.