JavaBeans Enterprise

La especificaci�n 1.1 de JavaBeans Enterprise (EJB) define una arquitectura para el desarrollo y despliegue de aplicaciones basadas en objetos distribuidos transacionales, software de componentes del lado del servidor. Las organizaciones pueden construir sus propios componentes o comprarlos a vendedores de terceras partes. Estos componentes del lado del servidor, llamados beans enterprise, son objetos distribuidos que est�n localizados en contenedores de JavaBean Enterprise y proporcionan servicios remotos para clientes distribuidos a lo largo de la red.

.�Tecnolog�a de JavaBeans Enterprise

La especificaci�n de JavaBeans Enterprise define una arquitectura para un sistema transacional de objetos distribuidos basado en componentes. La especificaci�n manda un modelo de programaci�n; es decir, convenciones o protocolos y un conjunto de clases e interfaces que crean el API EJB. Este modelo de programaci�n proporciona a los desarrolladores de Beans y a los vendedores de servidores EJB un conjunto de contratos que definen una plataforma de desarrollo com�n. El objetivo de estos contratos es asegurar la portabilidad a trav�s de los vendedores y el soporte de un rico conjunto de funcionalidades.

.�El Contenedor EJB

Los Beans Enterprise son componentes de software que se ejecutan en un entorno especial llamado un contenedor EJB. El contenedor contiene y maneja un Bean enterprise de igual forma que el Servidor Web Java contiene un servelt o un servidor Web contiene un applet Java. Un Bean Enterprise no puede funcionar fuera de un contenedor EJB. El contenedor EJB controla cada aspecto del bean enterprise en tiempo de ejecuci�n incluyendo accesos remotos al bean, seguridad, persistencia, transaciones, concurrencia, y accesos a un almacen de recursos.

El contenedor aisla al bean enterprise de accesos directos por parte de aplicaciones cliente. Cuando una aplicaci�n cliente invoca un m�todo remoto de un bean enterprise, el contenedor primero intercepta la llamada para asegurar que la persistencia, las transaciones, y la seguridad son aplicadas apropiadamente a cada operaci�n que el cliente realiza en el Bean. El contenedor maneja estos aspectos de forma autom�tica, por eso el desarrollador no tiene que escribir este tipo de l�gica dentro del propio c�digo del bean. El desarrollador de beans enterprise puede enfocarse en encapsular la reglas del negocio, mientras el contenedor se ocupa de todo lo dem�s.

Los contenedores manejan muchos Beans simult�neamente de igual forma que un Java WebServer maneja muchos servlets. Para reducir el consumo de memoria y de proceso, los contenedores almacenan los recursos y manejan los ciclos de vida de todos los beans de forma muy cuidadosa. Cuando un Bean no est� siendo utilizado, un contenedor lo situar� en un almac�n para ser reutilizado por otros clientes, o posiblemente lo sacar� de la memoria y s�lo lo traer� de vuelta cuando sea necesario. Como las aplicaciones cliente no tienen acceso directo a los beans --el contenedor trata con el cliente y el bean-- la aplicaci�n cliente se despreocupa completamente de las actividades de control de recursos del contenedor. Por ejemplo, un bean que no est� en uso, podr�a ser eliminado de la memoria del servidor, mientras que su referencia remota en el cliente permanece intacta. Cuando un cliente invoca a un m�todo de la referencia remota, el contenedor simplemente re-activa el bean para servir la petici�n. La aplicaci�n cliente se despreocupa de todo el proceso.

Un bean enterprise depende del contenedor para todo lo que necesite. Si un bean enterprise necesita acceder a un conexi�n JDBC o a otro bean enterprise, lo hace a trav�s del contenedor; si un bean enterprise necesita acceder a la identidad de su llamador, obtiene una referencia a s� mismo, o accede a las propiedades a trav�s e su contenedor. El bean enterprise interact�a con su contenedor a trav�s de uno de estos tres mecanismos.

  • M�todos de Retrollamada

    Todo bean implementa un subtipo del interface EnterpriseBean que define muchos m�todos, llamados m�todos de retrollamada. Cada uno de estos m�todos alerta al bean sobre un evento diferente en su ciclo de vida y el contenedor llamar� a estos m�todos para notificar al bean cuando lo va a activar, persistir su estado a la base de datos, finalizar la transaci�n, eliminar el bean de la memoria, etc. Los m�todos de retrollamada le dan al bean la oportunidad de hacer alg�n trabajo dom�stico inmediatamente antes o despu�s de alg�n evento. Estos m�todos se describen con m�s detalle es una secci�n posterior.

  • EJBContext

    Todo bean obtiene un objeto EJBContext, que es una referencia directa a su contenedor. El interface EJBContext proporciona m�todos para interactuar con el contenedor para que el bean pueda solicitar informaci�n sobre su entorno como la identidad de sus clientes, el estado de una transaci�n, o para obtener referencias remotas a s� mismo.

  • Java Naming and Directory Interface (JNDI)

    El Inteface Java de Nombres y Directorios (JNDI) es una extensi�n est�ndard de la plataforma Java para acceder a sistemas de nombrado como LDAP, NetWare, sistemas de ficheros, etc. Todo bean tiene autom�ticamente acceso a un sistema de nombrado especial llamado Environment Naming Context (ENC). El ENC est� controlado por el contenedor y los bean acceden a �l usando JNDI. El JNDI ENC permite al bean acceder a recursos como conexiones JDBC, otros beans enterprise, y a propiedades espec�ficas para ese bean.

La especificaci�n EJB define un contrato bean-contenedor, que incluye los mecanismos (retrollamadas, EJBContext, JNDI ENC) descritos arriba as� como un estricto conjunto de reglas que describe c�mo se comportar�n los beans enterprise y sus contenedores en tiempo de ejecuci�n, como se comprobar�n los accesos de seguridad, c�mo se manejar�n las transaciones, c�mo se aplicar� la persistencia, etc. El contrato bean-contenedor est� dise�ado para hacer portables los beans enterprise entre contenedores EJB para que los beans enterprise puedan ser desarrollados una s�la vez y puedan ejecutarse en cualquier contenedor EJB. Los vendedores como BEA, IBM, y GemStone venden aplicaciones servidores que incluyen contenedores EJB. Idealmente, cualquier bean enterprise que cumpla la especificaci�n deber�a poder ejecutarse en cualquier contenedor compatible EJB.

La portabilidad es el principal valor que EJB pone encima de la mesa. La portabilidad asegura que un bean desarrollado para un contenedor puede migrarse a otro si ese otro ofrece mejor rendimiento, caracter�sticas, o ahorros. Portabilidad tambi�n significa que la destreza del desarrollador de beans puede influenciarse a trav�s de varios contenedores EJB, proporcionando mejores oporturnidades para las organizaciones y los desarrolladores.

Adem�s de la portabilidad, la simplicidad del modelo de programaci�n EJB hace que este sea muy valioso. Como el contenedor tiene cuidado de manejar las complejas tareas como la seguridad, las transaciones, la persistencia, la concurrencia y el control de recursos, el desarrollador de beans es libre para enfocar su atenci�n en las reglas del negocio y en un modelo de programaci�n muy sencillo. Esto quiere decir que los beans pueden desarrollarse r�pidamente sin necesidad de profundos conocimientos en objetos distribuidos, transaciones y otros sistemas enterprise.

.�Beans Enterprise

Para crear un componente EJB del lado del servidor, un desarrollador de bean enterprise proporciona dos interfaces que definen los m�todos de negocio del bean, adem�s de la implementaci�n real de la clase bean. Entonces el cliente usa un interface p�blico del bean para crear, manipular, y eliminar beans del servidor EJB. La clase de implementaci�n, ser� llamada clase del bean, es ejemplarizada en tiempo de ejecuci�n y se convierte en un objeto distribuido.

Los beans enterprise viven en un contenedor EJB y son accedidos por aplicaciones clientes a trav�s de la red usando sus interfaces remoto y home. Estos interfaces exponen las capacidades del bean y proporcionan todos los m�todos necesarios para crear, actualizar, borrar e interactuar con el bean. Un bean es un componente del lado del servidor que representa un concepto de negocio como un Cliente o un Dependiente de Hotel.

Interfaces Remoto y Home

Los interfaces remoto y home representan al bean, pero el contenedor aisla a los beans de accesos directos desde aplicaciones cliente. Cada vez que un bean es solicitado, creado, o borrado, el contenedor maneja todo el proceso.

El interface home representa los m�todos del ciclo-de-vida del componente (crear, destruir, encontrar) mientras que el interface remoto representa los m�todos de negocio del bean. Los interfaces remoto y home extienden los interfaces javax.ejb.EJBObject y javax.ejb.EJBHome respectivamente. Estos tipos de interfaces EJB definen un conjunto est�ndard de m�todos de utilidad y proporcionan tipos base comunes para todos los interfaces remotos y home.

Los clientes usan el interface home del bean para obtener referencias al interface remoto del bean. El interface remoto define los m�todos del negocio como m�todos accesores o modificadores para cambiar el nombre del cliente, o m�todos de negocio que realizan tareas como usar el bean HotelClerk para reservar una habitaci�n del hotel. Abajo tenemos un ejemplo de como un bean Customer podr�a ser accedido por una aplicaci�n cliente. En este caso el interface home es el tipo CustomerHome y el interface remoto es el tipo Customer.

CustomerHome home = // ... obtain a reference that
                    // implements the home interface.


// Use the home interface to create a
// new instance of the Customer bean.

Customer customer = home.create(customerID);

// using a business method on the Customer.

customer.setName(someName);

El interface remoto define los m�todos de negocio del bean; los m�todos que son espec�ficos para el concepto de negocio que representa. Los interfaces remotos son subclases del interface javax.ejb.EJBObject que es una subclase del interface java.rmi.Remote. La importancia del �rbol de herencias de los interfaces remotos se explica m�s adelante. Por ahora, nos enfocaremos en los m�todos del negocio y su significado. Abajo tenemos la definici�n de un interface remoto para un bean Customer.

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

public interface Customer extends EJBObject {

    public Name getName() 
                throws RemoteException;
    public void setName(Name name) 
           throws RemoteException;
    public Address getAddress() 
             throws RemoteException;
    public void setAddress(Address address) 
                      throws RemoteException;

}

El interface remoto define m�todos accesores y modificadores para leer y actualizar informaci�n sobre un concepto de negocio. Esto es t�pico de un tipo de beans llamado bean de entidad, que representan un objeto de negocio persistente; objetos de negocio cuyos datos se almacenan en una base de datos. Los beans de entidad representan datos del negocio en una base de datos y a�aden comportamiento espec�fico para esos datos.

M�todos de Negocio

Los m�todos de negocio tambi�n pueden representar tareas que un bean realiza. Aunque los beans de entidad frecuentemente tienen m�todos orientados a tareas, las tareas son m�s t�picas en un tipo de beans llamados beans de sesi�n. Los beans de sesi�n no representan datos como los beans de entidad. Representan procesos del negocio o agentes que realizan un servicio, como hacer una reserva en el hotel. Abajo tenemos una definici�n del interface remoto para un bean HotelClerk, que es un tipo de bean de sesi�n.

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

public interface HotelClerk 
               extends EJBObject {
   
    public void reserveRoom(Customer cust, 
                 RoomInfo ri,
Date from, Date to)
                          throws RemoteException;

    public RoomInfo availableRooms(
         Location loc, Date from, Date to)
                    throws RemoteException;
}

Los m�todos de negocio definidos en el interface remoto HotelClerk representan procesos en vez de simples accesores. El Bean HotelClerk act�a como un agente en el sentido en que realiza tareas en beneficio del usuario, pero no persiste �l mismo en la base de datos. Nosotros no necesitamos informaci�n sobre el HotelClerk, necesitamos que el dependiente del hotel realice tareas por nosotros. Este es un comportamiento t�pico de un bean de sesi�n.

Hay dos tipos b�sicos de beans enterprise: beans de entidad, que representan datos en una base de datos, y beans de sesi�n, que representan procesos o act�an como agentes que realizan tareas. Cuando construyamos aplicaciones EJB crearemos muchos beans enterprise, cada uno representando un concepto diferente del negocio. Cada concepto del negocio ser� manifestado como un bean de entidad o de sesi�n. Elegiremos el tipo de bean bas�ndonos en lo que se espera que haga el bean.

Beans de Entidad

Por cada interface remoto hay una clase de implementaci�n; un objeto de negocio que realmente implementa los m�todos de negocio definidos en el interface remoto. Esta es la clase bean; el elemento clave del bean. Abajo tenemos una definici�n parcial de la clase bean Customer.

import javax.ejb.EntityBean;

public class CustomerBean 
               implements EntityBean {
    
    Address    myAddress;
    Name       myName;
    CreditCard myCreditCard;

    public Name getName() {
         return myName;
    }

    public void setName(Name name) {
         myName = name;
    }

    public Address getAddress() {
         return myAddress;
    }

    public void setAddress(Address address) {
         myAddress = address;
    }

    ...
}

CustomerBean es la implementaci�n de la clase. Contiene los datos y proporciona m�todos accesores y otros m�todos del negocio. Como bean de entidad, el CustomerBean proporciona un objeto view de los datos del cliente. En lugar de escribir la l�gica de acceso a la base de datos en una aplicaci�n, la aplicaci�n simplemente puede usar el interface remoto hacia el bean Customer para acceder a los datos del cliente. Los beans de entidad implementan el tipo javax.ejb.EntityBean que define un conjunto de m�todos de notificaci�n que el bean usa para interact�ar con su contenedor.

Beans de Sesi�n

El Bean HotelClerk es un bean se sesi�n, que son muy similiares a los beans de entidad. Los beans de sesi�n representan un proceso o tarea, que se realizan en beneficio de la aplicaci�n cliente. Los beans de sesi�n podr�an usar otros beans para realizar tareas o acceder directamente a bases de datos. Un poco m�s de c�digo muestra a un bean de sesi�n haciendo ambas cosas. El m�todo reserveRoom() mostrado abajo usa otros beans para realizar una tarea, mientras que el m�todo availableRooms() usa JDBC para acceder directamente a una base de datos.

import javax.ejb.SessionBean;

public class HotelClerkBean 
            implements SessionBean {
   
    public void reserveRoom(
          Customer cust, RoomInfo ri,
                    Date from, Date to) {
        CreditCard card = cust.getCreditCard();
        RoomHome roomHome = 
        // ... get home reference
        Room room = 
         roomHome.findByPrimaryKey(ri.getID());
        double amount = room.getPrice(from,to);
        CreditServiceHome creditHome = 
            // ... get home reference
        CreditService creditAgent = 
                      creditHome.create();
        creditAgent.verify(card, amount);
        ReservationHome resHome = 
             // ... get home reference
        Reservation reservation = 
           resHome.create(cust,room,from,to);
    }

    public RoomInfo[] availableRooms(
                  Location loc,
                  Date from, 
                  Date to) {
        // Make an SQL call to find 
        //available rooms
        Connection con = // ... get database 
        //connection
        Statement stmt = con.createStatement();
        ResultSet results = 
             stmt.executeQuery("SELECT ...");
        ...
        return roomInfoArray;
    }
}

Podr�as haber observado que las clases bean definidas arriba no implementan los interfaces remoto o home. EJB no requiere que la clase bean implemente estos interfaces; de hecho est� desaconsejado que lo haga porque los tipos bases de los interfaces remoto y home (EJBObject y EJBHome) definen muchos otros m�todos que son implementados autom�ticamente por el contenedor. Sin embargo, la clase bean no proporciona implementaciones para todos los m�todos de negocio definidos en el interface remoto.

>M�todos de Ciclo de Vida

Adem�s de un interface remoto, todos los beans tienen un interface home. El interface home proporciona m�todos de ciclo de vida para crear, destruir o localizar beans. Estos comportamientos de ciclo de vida est�n separados del interface remoto porque los comportamientos que representa no son espec�ficos para un s�lo ejemplar bean. Abajo tenemos la definici�n de un interface home para el bean Customer. Observa que extiende el interface javax.ejb.EJBHome que a su vez extiende el interface java.rmi.Remote.

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

public interface CustomerHome 
                  extends EJBHome {
    
    public Customer create(Integer 
                     customerNumber)
                    throws RemoteException, 
                            CreateException;
   
    public Customer findByPrimaryKey(Integer 
                              customerNumber) 
                    throws RemoteException, 
                             FinderException;

    public Enumeration findByZipCode(int zipCode) 
                       throws RemoteException, 
                               FinderException;
}

El m�todo create() se utiliza para crear una nueva entidad. Esto resultar� en un nuevo registro de la base de datos. Un interface home podr�a tener muchos m�todos create(). El n�mero y tipo de los argumentos de cada create() se deja para el desarrollador del bean, pero el tipo de retorno debe ser el mismo tipo del interface remoto. En este caso, llamar a create() sobre el interface CustomerHome devolver� un ejemplar de Customer. Los m�todos findByPrimaryKey() y findByZipCode() se usan para localizar ejemplares espec�ficos del bean Customer. De nuevo, podremos definir tantos m�todos de estos tipos como necesitemos.

Vuelta a los Interfaces Remoto y Home

Los interfaces remoto y home son usados por las aplicaciones para acceder a los beans enterprise en tiempo de ejecuci�n. El interface home permite a la aplicaci�n crear o localizar un bean, mientras que el interface remoto permite a la aplicaci�n invocar m�todos de negocio del bean.

CustomerHome home = 
// Get a reference to the 
//CustomerHome object 

Customer customer = 
  home.create(new Integer(33));

Name name = new Name("Richard", 
       "Wayne", "Monson-Haefel");
customer.setName(name);

Enumeration enumOfCustomers = 
          home.findByZip(55410);

Customer customer2 = 
     home.findByPrimaryKey(
               new Integer(33));

Name name2 = customer2.getName();

// output is "Richard Wayne 
//Monson-Haefel"
System.out.println(name);

El interface javax.ejb.EJBHome tambi�n define otros m�todos que CustomerBean hereda autom�ticamente, incluyendo un conjunto de m�todos remove() que permite a la aplicaci�n destruir ejemplares del bean.

.�Beans Enterprise como Objetos Distribuidos

Los interfaces remoto y home son tipos de interface "Java RMI Remote" . El interface java.rmi.Remote se usa con objetos distribuidos para representar el bean en un espacio de direccionamiento diferente (proceso o m�quina). Un bean enterprise es un objeto distribuido, esto significa que la clase bean es ejemplarizada y vive en un contenedor pero puede ser accedida por aplicaciones que viven en otros espacios de direccionamiento.

Para hacer que un ejemplar de un objeto en un espacio de direccionamiento est� disponible para otros requiere un peque�o truco que involucra sockets de red. Para hacer que el truco funcione, envolvemos el ejemplar en un objeto especial llamado esqueleto (skeleton) que tiene una conexi�n de red con otro objeto especial llamado tal�n (stub). El stub implementa el interface remoto por eso se parece a un objeto de negocio. Pero el stub no contiene la l�gica del negocio; contiene una conexi�n socket con el skeleton. Cada vez que se invoca un m�todo de negocio sobre el interface remoto del stub, �ste env�a un mensaje de red al skeleton dici�ndole qu� m�todo ha sido invocado. Cuando el skeleton recibe un mensaje de red desde el stub, identifica el m�todo invocado y los argumentos, y luego invoca al m�todo correspondiente del ejemplar actual. El ejemplar ejecuta el m�todo de negocio y devuelve el resultado al skeleton, que lo env�a de vuelta al stub. Este diagrama lo ilustra un poco.

El stub devuelve el resultado a la aplicaci�n que invoc� este m�todo del interface remoto. Desde la perspectiva de la aplicaci�n que usa el stub, es como si el stub no trabajara localmente. Realmente, el stub es s�lo un objeto de red mudo que env�a peticiones a trav�s de la red al skeleton, que en invoca al m�todo del ejemplar real. El ejemplar hace todo el trabajo, el stub y el skeleton s�lo pasan la identidad del m�todo y los argumentos de vuelta a trav�s de la red.

En EJB, el skeleton para los interfaces remoto y home est�n implementados por el contenedor, no por la clase bean. Esto es para asegurar que cada m�todo invocado sobre estos tipos de referencia por una aplicacion cliente son manejados primero por el contenedor y luego delegados al ejemplar del bean. El contenedor debe interceptar aquellas peticiones que vayan al bean para poder aplicar la persistencia (beans de entidad), las transaciones, y controlar los accesos autom�ticamente.

Los protocolos de objetos distribuidos definen el formado de mensajes de red enviados entre espacios de direccionamiento. Estos protocolos son bastantes complicados, pero afortunadamente no tenemos que preocuparnos de ellos, ya que son manejados autom�ticamente. La mayor�a de los servidores EJB soportan "Java Remote Method Protocol" (JRMP) o el "Internet Inter-ORB Protocol" (IIOP) de CORBA. El programador de beans y aplicaciones s�lo ve la clase del bean y su interface remoto, los detales de la comunicaci�n de red est�n ocultos.

Con respecto al API EJB, al programador no le importa si el servidor EJB usa JRMP o IIOP -- el API es el mismo. La especificaci�n EJB requiere que usemos una versi�n especializada del API Java RMI, cuando trabajos con un bean de forma remota. Java RMI es un API para acceder a objetos distribuidos y de alguna forma es un protocolo agn�stico -- de la misma forma que JDBC es una base de datos agn�stica. Por eso, un servidor EJB puede soportar JRMP o IIOP, pero el desarrollador de beans y aplicaciones siempre usa el mismo API Java RMI. Para que el servidor EJB pueda tener la opci�n de soportar IIOP, una versi�n especializada de Java RMI, llamada Java RMI-IIOP. Java RMI-IIOP usa IIOP como protocolo y el API Java RMI. Los servidores EJB no tienen que usar IIOP, pero tienen que respetar las restricciones Java RMI-IIOP, por eso EJB 1.1 usa las convenciones Java RMI-IIOP y los tipos especializados, pero el protocolo oculto puede no ser ninguno de ellos.

.�Beans Enterprise del Tipo Entidad

El bean de entidad es uno de los dos tipos de beans primarios: entidad y sesi�n. El bean de entidad es usado para representar datos en un base de datos. Proporciona un interface orientado a objeto a los datos que normalmente ser�an accedidos mediante el JDBC u otro API. M�s que eso, los beans de entidad proporcionan un modelo de componentes que permite a los desarrolladores de beans enfocar su atenci�n en la l�gica de negocio del bean, mientras el contenedor tiene cuidado de manejar la persistencia, las transaciones, y el control de accesos.

Hay dos tipos de beans de entidad: Persistencia Manejada por el Contenedor (CMP) y Persistencia Manejada por el Bean (BMP). Con CMP, el contenedor maneja la persistencia del bean de entidad. Las herramientas de los vendedores se usan para mapear los campos de entidad a la base de datos y no se escribe ning�n c�digo de acceso a las bases de datos en la clase del bean. Con BMP, el bean de entidad contiene c�digo de acceso a la base de datos (normalmente JDBC) y es responsable de leer y escribir en la base de datos su propio estado. Las entidades BMP tienen mucha ayuda ya que el contenedor alertar� al bean siempre que sea necesario hacer una actualizaci�n o leer su estado desde la base de datos. El contenedor tambi�n puede manejar cualquier bloqueo o transaci�n, para que la base de datos se mantenga �ntegra.

.�Persistencia Manejada por Contenedor

Los beans con persistencia manejada por contenedor son los m�s simples para el desarrollador y los m�s complicados para que los soporte el servidor EJB. Esto es porque toda la l�gica de sincronizaci�n del estado del bean con la base de datos es manejada autom�ticamente por el contenedor. Esto significa que el desarrollador del bean no necesita escribir ninguna l�gica de acceso a datos, mientras que se supone que el servidor EJB tiene cuidado de toda la persistencia que necesita autom�ticamente -- un gran pedido de cualquier vendedor. La mayor�a de los vendedores EJB soportan la persistencia autom�tica a un base de datos relacional, pero el nivel de soporte var�a. Algunos proporcionan un mapeo Objeto-a-Relacional muy sofisticado, mientras que otros est�n muy limitados.

En esta secci�n, ampliaremos el CustomerBean desarrollado anteriormente para una completa definici�n de un bean de persistencia manejada por contenedor. En la siguiente secci�n de bean con persistencia manejada por el bean modificaremos el CustomerBean para que maneje su propia persistencia.

La Clase Bean

Un bean enterprise es un componente completo que est� compuesto de al menos dos interfaces y una clase de implementaci�n del bean. Primero veamos la clase del bean.

import javax.ejb.EntityBean;

public class CustomerBean 
             implements EntityBean {

    int        customerID;
    Address    myAddress;
    Name       myName;
    CreditCard myCreditCard;

    // CREATION METHODS
    public Integer ejbCreate(Integer id) {
        customerID = id.intValue();
        return null;
    }

    public void ejbPostCreate(Integer id) {
    }

    public Customer ejbCreate(Integer id, Name name) {
        myName = name;
        return ejbCreate(id);
    }

    public void ejbPostCreate(Integer id, Name name) {
    }
    
    // BUSINESS METHODS
    public Name getName() {
        return myName;
    }

    public void setName(Name name) {
        myName = name;
    }

    public Address getAddress() {
        return myAddress;
    }

    public void setAddress(Address address) {
        myAddress = address;
    }

    public CreditCard getCreditCard() {
        return myCreditCard;
    }

    public void setCreditCard(CreditCard card) {
        myCreditCard = card;
    }

    // CALLBACK METHODS
    public void setEntityContext(EntityContext cntx) {
    }

    public void unsetEntityContext() {
    }
    
    public void ejbLoad() {
    }

    public void ejbStore() {
    }

    public void ejbActivate() {
    }

    public void ejbPassivate() {
    }

    public void ejbRemove() {
    }
}

Este es un buen ejemplo de un bean de entidad CMP bastante simple. Observa que no hay l�gica de acceso a base de datos en el bean. Esto es porque el vendedor del EJB proporciona herramientas para mapear los campos del CustomerBean a la base de datos. La clase CustomerBean, por ejemplo, podr�a ser mapeada a cualquier base de datos proporcionando los datos que contienen y que son muy similares a los campos del bean. En este caso lo campos de ejemplar del bean est�n comprendidos por un int y unos sencillos objetos dependientes (Name, Address, y CreditCard) con sus propios atributos. Abajo tenemos las definiciones de estos objetos dependientes.

// The Name class
public class Name 
        implements Serializable {

    public String lastName, 
            firstName, middleName;

    public Name(String lastName, String firstName,
                String middleName) {
        this.lastName   = lastName;
        this.firstName  = firstName;
        this.middleName = middleName;
    }

    public Name() {}
}

// The Address class
public class Address 
      implements Serializable {

    public String street, 
                city, state, zip;

    public Address(String street, 
         String city,
String state, 
                       String zip) {
        this.street = street;
        this.city   = city;
        this.state  = state;
        this.zip    = zip;
    }

    public Address() {}
}

// The CreditCard class
public class CreditCard 
     implements Serializable {

    public String number, 
            type, name;
    public Date expDate;

    public CreditCard(String 
         number, String type,
String name, 
                          Date expDate) {
        this.number  = number;
        this.type    = type;
        this.name    = name;
        this.expDate = expDate;
    }

    public CreditCard() {}
}

Estos campos se llaman campos manejados por contenedor porque el contenedor es el responsable de sincronizar su estado con la base de datos; el contenedor maneja los campos. Estos campos pueden ser cualquier tipo de dato primitivo o tipo serializable. Este caso usa tanto un tipo primitivo int (customerID) y objetos serializables (Address, Name, CreditCard). Para mapear los objetos dependientes a la base de datos necesitar�amos usar una herramienta de mapeado muy sofisticada. No todos los campos del bean son autom�ticamente campos manejados por el contenedor; algunos de ellos son s�lo campos de ejemplar para el uso temporal del bean. Un desarrollador de beans distingue un campo manejado por conetenedor de un campo de ejemplar normal indicando los campos manejados por el contenedor en el descriptor de desarrollo.

Los campos manejados por contenedor deben tener sus tipos correspondientes (columnas en RDBMS) en la base de datos bien directamente o a trav�s de mapeo Objeto-Relacional. El CustomerBean podr�a, por ejemplo, mapear una tabla CUSTOMER en la base de datos que tenga la siguiente definici�n.

CREATE TABLE CUSTOMER 
{
    id            INTEGER PRIMARY KEY,
    last_name     CHAR(30),
    first_name    CHAR(20),
    middle_name   CHAR(20),
    street        CHAR(50),
    city          CHAR(20),
    state         CHAR(2),
    zip           CHAR(9),
    credit_number CHAR(20),
    credit_date   DATE,
    credit_name   CHAR(20),
    credit_type   CHAR(10)
}

Con la persistencia controlada por contenedor, el vendedor debe tener alguna clase de herramienta propietaria que pueda mapear los datos manejados por el contenedor del bean a sus correspondientes columnas en la tabla espec�fica, CUSTOMER en este caso.

Una vez que los campos del bean se han mapeado a la base de datos, y se ha desarrollado el bean CustomerBean, el contenedor manejar� la creacci�n de registros, el borrado, la carga y la actualizaci�n de registros en la tabla CUSTOMER en respuesta a los m�todos invocados en los interfaces home y remoto del bean Customer.

Un subconjunto (uno o m�s) de los campos manejados por el contenedor ser� identificado como la clave primaria del bean. Esta clave primaria es el �ndice o puntero a un �nico registro(s) en la base de datos que crea el estado del bean. En el caso de CustomerBean, el campo id es el campo clave primario y ser� usado para localizar los datos de los beans en la base de datos. Los campos clave de un campo sencillo primitivo se representa como su correspondiente objeto envoltura. La clave primaria del bean CustomerBean por ejemplo es un int primitivo en la clase bean pero los clientes del bean la manifestar�n como del tipo java.lang.Integer. Las claves primarias que se componen de varios campos, llamadas claves primarias compuestas, ser�n representadas por un clase especial definida por el desarrollador del Bean.

>Interface Home

Para crear un nuevo ejemplar de un bean de entidad CMP, y por lo tanto insertar los datos en la base de datos, se debe llamar al m�todo create() del interface home del bean. Abajo tenemos la definici�n del interface CustomerHome.

public interface CustomerHome 
               extends javax.ejb.EJBHome {
 
    public Customer create(
           Integer customerNumber) 
             throws RemoteException,CreateException;
   
    public Customer create(Integer customerNumber, 
                                        Name name) 
            throws RemoteException,CreateException;

    public Customer findByPrimaryKey(Integer 
                                customerNumber) 
          throws RemoteException, FinderException;

    public Enumeration findByZipCode(int zipCode) 
          throws RemoteException, FinderException;
}

Abajo tenemos un ejemplo de c�mo se usar�a el interface home en una aplicaci�n cliente para crear un nuevo cliente.

CustomerHome home = 
// Get a reference to the 
//CustomerHome object 

Name name = 
   new Name("John", "W", "Smith");

Customer customer = 
   home.create(
      new Integer(33), name);

Un interface home de un bean podr�a declarar cero o m�s m�todos create(), cada uno de los cuales debe tener sus correspondientes m�todos ejbCreate() y ejbPostCreate() en la clase del bean. Estos m�todos de creacci�n son enlazados en tiempo de ejecuci�n, para que cuando se llame a un m�todo create() del interface home, el contenedor delegue la invocaci�n a los correspondientes m�todos ejbCreate() y ejbPostCreate() de la clase Bean.

Cuando se invoca al m�todo create() de un interface home, el contenedor delega esta llamada al correspondiente m�todo ejbCreate() en el bean. Estos m�todos se usan para inicializar el estado del ejemplar antes de que el registro sea insertado en la base de datos. En este caso, inicializa los campos customerID y Name. Cuando el m�todo ejbCreate() ha finalizado (devuelven null en CMP) el contenedor lee los campos manejados por el contenedor e inserta un nuevo registro en la tabla CUSTOMER indexado por la clave primaria, en este caso customerID que se mapea a la columna CUSOTMER.ID.

En EJB un bean de entidad no existe t�cnicamente hasta despu�s de que sus datos hayan sido insertados en la base de datos, lo que ocurre durante el m�todo ejbCreate(). Una vez que los datos han sido insertados, el bean de entidad existe y puede acceder a su propia clave primaria y a referencias remotas, lo que no es posible hasta que se complete el m�todo ejbCreate() y que los datos est�n en la base de datos. Si el bean necesita acceder a su propia clave primaria o a una referencia remota despu�s de haber sido creado, pero antes de servir a cualquier m�todo de negocio, puede hacerlo en el m�todo ejbPostCreate(). Este m�todo permite al bean realizar cualquier proceso post-creacci�n antes de empezar a servir peticiones de clientes. Por cada ejbCreate() debe haber un m�todo ejbPostCreate() correspondiente (con los mismos argumentos).

Los m�todos del interface home que empiezan con "find" son llamados m�todos de b�squeda. Se usan para consultar al servidor EJB sobre beans de entidad espec�ficos, bas�ndose en el nombre del m�todo y los argumentos pasados. Desafortunadamente, no hay un lenguaje de consultas est�ndard definido para los m�todos de b�squeda, por eso cada vendedor implementar� estos m�todos de forma diferente. En los beans de entidad CMP, los m�todos de b�squeda no est�n implementados con los m�todos correspondientes en la clase del bean; los contenedores los implementan cuando el bean se desarrolla de una forma espec�fica del vendedor. El desarrollador usar� las herramientas espec�ficas del vendedor para decirle al contenedor c�mo se deber�a comportar un m�todo de b�squeda particular. Algunos vendedores usaran herramientas de mapeo Objeto-Relacional para definir el comportamiento de un m�todo de b�squeda mientras que otros s�lo requeriran que el desarrollador introduzca el comando SQL apropiado.

Hay dos clases b�sicas de m�todos de b�squeda: m�todos de b�squeda uni-entidad y multi-entidad. Los m�todos de b�squeda uni-entidad devuelven una referencia remota a un bean de entidad espec�fico que corresponda con la b�squeda solicitada. Si no se encuentra un bean de entidad, el m�todo lanza una excepci�n ObjectNotFoundException. Todo bean de entidad debe definir el m�todo de b�squeda uni-entidad con el nombre del m�todo findByPrimaryKey(), que toma el tipo de la clave primaria del bean como argumento.

Los m�todos de b�squeda multi-entidad devuelven una colecci�n (tipo Enumeration o Collection) de entidades que corresponden con la b�squeda solicitada. Si no se encuentran entidades, estos m�todos devuelven una colecci�n vac�a. (Observa que una colecci�n vac�a no es lo mismo que una referencia nula).

>Interface Remoto

Cada bean de entidad debe definir una interface remoto en adici�n del interface home. El interface remoto define los m�todos de negocio del bean de entidad. Abajo tenemos la definici�n del interface remoto del bean CustomerBean.

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

public interface Customer 
          extends EJBObject {

    public Name getName()
                throws RemoteException;

    public void setName(Name name)
                throws RemoteException;

    public Address getAddress()
                   throws RemoteException;

    public void setAddress(
                 Address address)
                throws RemoteException;

    public CreditCard getCreditCard()
                      throws RemoteException;

    public void setCreditCard(CreditCard card)
                throws RemoteException;
}

Abajo tenemos un ejemplo de c�mo una aplicaci�n cliente podr�a usar el interface remoto para interactuar con un bean.

Customer customer = 
// ... obtain a remote 
//reference to the bean

// get the customer's address
Address addr = customer.getAddress();

// change the zip code
addr.zip = "56777";

// update the customer's address
customer.setAddress(addr);

Los m�todos de negocio en el interface remoto se delegan a los correspondientes m�todos de negocio en el ejemplar del bean. En el bean Customer, los m�todos de negocios son todos simples accesores y modificadores, pero podr�an ser m�s complicados. En otras palabras, los m�todos de negicio de una entidad no est�n limitados a leer y escribir datos, tambi�n pueden realizar tareas de c�lculo.

Si, por ejemplo, los clientes tuvieran un programa de fidelidad que premiara el uso frecuente, podr�a haber un m�todo para mejorar los premios en el programa, basado en una acumulaci�n de estancias superiores a una noche.

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

public interface Customer extends EJBObject {
    
    public MembershipLevel addNights(int nights_stayed)
                           throws RemoteException;
    
    public MembershipLevel upgradeMembership()
                           throws RemoteException;

    public MembershipLevel getMembershipLevel()
                           throws RemoteException;

    ... Simple accessor business methods go here
}

Los m�todos addNights() y upgradeMembership() son m�s sofisticados que los sencillos m�todos accesores. Aplican reglas de negocio para cambiar el nivel del premio y van m�s all� de leer y escribir datos.

M�todos de RetroLlamada

La clase bean define m�todos create que corresponden con m�todos del interface home y m�todos de negocio que corresponden con m�todos del interface remoto. La clase bean tambi�n implementa un conjunto de m�todos callback que permiten al contenedor notificar al bean los eventos de su ciclo de vida. Los m�todos de retrollamada est�n definidos en el interface javax.ejb.EntityBean que es implementado por todos los beans de entidad, incluyendo la clase CustomerBean. El interface EntityBean tiene la siguiente definici�n. Observa que la clase del bean implementa estos m�todos.

public interface javax.ejb.EntityBean {

    public void setEntityContext();

    public void unsetEntityContext();
    
    public void ejbLoad();

    public void ejbStore();

    public void ejbActivate();

    public void ejbPassivate();

    public void ejbRemove();
}

El m�todo setEntityContext() proporciona al bean un interface con el contenedor llamado el EntityContext. Este interface contiene m�todos para obtener informaci�n sobre el contexto bajo el que opera el bean en un momento particular. El interface EntityContext se usa para acceder a informaci�n de seguridad sobre su llamador; para determinar el estado de la transaci�n actual o para forzar a deshacer una transaci�n; o para obtener una referencia al propio bean, su interface home o su clave primaria. Este interface s�lo se configura una vez en la vida de un ejemplar de bean de entidad, por eso su referencia deber�a ponerse en uno de los campos de ejemplar del bean si la vamos a necesitar m�s tarde.

El bean Customer de arriba no usa EntityContext, pero podr�a hacerlo. Por ejemplo, podr�a usarlo para validad al llamador en un rol de seguridad particular. Abajo tenemos un ejemplo, donde se usa el EntityContext para validad que el llamador es un Manager, el �nico rol (indentidad de seguridad) que puede seleccionar el tipo de la tarjeta de cr�dito de un cliente para que sea una tarjeta mundial, no una tarjeta limitada. (A los clientes con esta tarjeta se le ofrecen servicios especiales).

import javax.ejb.EntityBean;

public class CustomerBean 
         implements EntityBean {

    int           customerID;
    Address       myAddress;
    Name          myName;
    CreditCard    myCreditCard;
    EntityContext ejbContext;
    
    // CALLBACK METHODS
    public void setEntityContext(
                        EntityContext cntx) {
        ejbContext = cntx
    }

    public void unsetEntityContext() {
        ejbContext = null;
    }

    // BUSINESS METHODS
    public void 
         setCreditCard(CreditCard card) {
        if (card.type.equals("WorldWide"))
            if (ejbContext.isCallerInRole(
                                 "Manager"))
                myCreditCard = card;
            else
                throw new SecurityException();
        else
            myCreditCard = card;
    }

    public CreditCard getCreditCard() {
        return myCreditCard;
    }
    ...
}

El m�todo unsetEntityContext() se usa al final del ciclo de vida del bean -- antes de que el ejemplar sea sacado de la memoria -- para desrefenciar el EntityContext y realizar cualquier peque�a tarea de limpieza.

Los m�todos ejbLoad() y ejbStore() en entidades CMP se invocan cuando el estado del bean de entidad est� siendo sincronizado con la base de datos. El ejbLoad() se invoca justo despu�s de que el contenedor haya refrescado los campos del bean manejados por contenedor con su estado desde la base de datos. El m�todo ejbStore() se invoca justo antes de que el contenedor escriba los campos del bean manejados por contenedor en la base de datos. Estos m�todos se usan para modificar datos que est�n siendo sincronizados. Los m�todos podr�an usarse, por ejemplo, para comprimir los datos antes de almacenarlos y descomprimirlos cuando son recuperados de la base de datos.

En el bean Customer los m�todos ejbLoad() y ejbStore() podr�an usarse para converitir objetos dependientes (Name, Address, CreditCard) a sencillos objetos String y tipos primitivos, si el contenedor EJB no es lo suficientemente sofisticado para mapear los objetos dependientes a la tabla CUSTOMER. Abajo tenemos un ejemplo de como se podr�a modificar el Bean.

import javax.ejb.EntityBean;

public class CustomerBean 
                  implements EntityBean {

    //container-managed fields
    int    customerID;
    String lastName;
    String firstName;
    String middleName;
    ...
    
    // not-container-managed fields
    Name       myName;
    Address    myAddress;
    CreditCard myCreditCard;

    
    // BUSINESS METHODS
    public Name getName() {
        return myName;
    }

    public void setName(Name name) {
        myName = name;
    }
    ...

    public void ejbLoad() {
        
        if (myName == null) 
            myName = new Name();

        myName.lastName = lastName;
        myName.firstName = firstName;
        myName.middleName = middleName;     
        ...
    }

    public void ejbStore() {
         
        lastName   = myName.lastName;
        firstName  = myName.firstName;
        middleName = myName.middleName;
        ...
    }
}

Los m�todos ejbPassivate() y ejbActivate() se invocan sobre el bean justo antes de que el bean sea "pasivizado" o justo despu�s de que se activado, respectivamente. "Pasivizado" en un bean de entidad significa que el ejemplar del bean ha sido des-asociado con su referencia remota para que el contenedor pueda eliminarlo de la memoria o reutilizarlo. Es una medida de conservaci�n de recursos que emplea el contenedor para reducir el n�mero de ejemplares en memoria. Un bean podr�a ser "pasivizado" si no ha sido utilizado durante un tiempo o como una operaci�n normal realizada por el contenedor para maximizar la reutilizaci�n del los recursos. Algunos contenedores eliminar�n los beans de la memoria, mientras que otros reutilizar�n ejemplares para otros interfaces remotos m�s activos. Los m�todos ejbPassivate() y ejbActivate() proporcionan al bean una notificaci�n cuando est� apunto de ser "pasivizado" (des-asociado con la referencia remota) o activado (asociado con un referencia remota).

.�Persistencia Controlada por el Bean

En un bean enterprise con la persistencia manejada por el Bean (BMP) maneja la sincronizaci�n de su estado con la base de datos directamente . El Bean usa el API de bases de datos (normalmente JDBC) para leer y escribir sus campos en la base de datos, pero el contenedor le dice cuando hacer cada operaci�n de sincronizaci�n y maneja las transaciones por el bean autom�ticamente. La persistencia manejada por el bean le da al desarrollador de bean la flexibilidad de realizar operaciones de persistencia que son demasiado complicadas para el contenedor o para usar una fuente de datos que no est� soportada por el contenedor -- por ejemplo bases de datos legales y personalizadas.

En esta secci�n, modificaremos la clase CustomerBean para crear un bean con persistencia manejada por el Bean (BMP). Esta modificaci�n no impactar� en absoluto en los interfaces home o remoto. De hecho, no modificaremos directamente el CustomerBean original. En su lugar, lo cambiaremos a persistencia manejada por el bean extendiendo el bean y sobreescribiendo la clase para crear una entidad BMP. En la mayor�a de los casos, no extenderemos el bean para hacerlo BMP, s�lo implementaremos el bean como BMP directamente. Esta estrategia (extender el bean CMP) se hace por dos razones: permite al bean ser un bean CMP o BMP; y acorta significativamente la cantidad de c�digo a mostrar. Abajo tenemos la definici�n de la clase BMP.

public class CustomerBean_BMP 
          extends CustomerBean {
    public void ejbLoad() {
        // override implementation
    }
    public void ejbStore() {
        // override implementation
    }
    public void ejbCreate() {
        // override implementation
    }
    public void ejbRemove() {
        // override implementation
    }
    private Connection getConnection() {
        // new helper method
    }
}

Con beans BMP, los m�todos ejbLoad() y ejbStore() los usa el contenedor de forma diferente a como lo hac�a con un bean CMP. En BMP, estos m�todos contienen c�digo para leer los datos de la base de datos y para escribir los cambios en la base de datos, respectivamente. Estos m�todos se llaman sobre el bean cuando el servidor EJB decide que es un buen momento para leer o escribir los datos.

El bean CustomerBean_BMP maneja su propia persistencia. En otras palabras, los m�todos ejbLoad() y ejbStore() deben incluir l�gica de acceso a base de datos para que el bean pueda cargar y almacenar sus datos cuando el contenedor EJB se lo diga. El contenedor ejecutar� autom�tiamente los m�todos ejbLoad() y ejbStore() cuando crea apropiado.

El m�todo ejbLoad() se invoca normalmente al principio de una transaci�n, justo antes de que el contenedor delege un m�todo de negocio del bean. El c�digo mostrado abajo muestra c�mo implementar el m�todo ejbLoad() usando JDBC.

import java.sql.Connection;

public class CustomerBean_BMP 
             extends CustomerBean {

  public void ejbLoad() {
    Connection con;
    try {
      Integer primaryKey = 
       (Integer)ejbContext.getPrimaryKey();
      con = this.getConnection();
      Statement sqlStmt = 
      con.createStatement("SELECT * 
                       FROM Customer " +
                       " WHERE customerID = " +
                       primaryKey.intValue());
      ResultSet results = sqlStmt.executeQuery();
      if (results.next()) {
        // get the name information 
        //from the customer table
        myName = new Name();
        myName.first = results.getString("
                                  FIRST_NAME");
        myName.last = results.getString("
                                   LAST_NAME");
        myName.middle = results.getString("
                                 MIDDLE_NAME");
        // get the address information from 
        //the customer table
        myAddress = new Address();
        myAddress.street = 
            results.getString("STREET");
        myAddress.city = 
            results.getString("CITY");
        myAddress.state = 
            results.getString("STATE");
        myAddress.zip = results.getInt("ZIP");
        // get the credit card information 
        //from the customer table
        myCreditCard = new CreditCard();
        myCreditCard.number = 
           results.getString("CREDIT_NUMBER");
        myCreditCard.expDate = 
             results.getString("CREDIT_DATE");
        myCreditCard.type = 
             results.getString("CREDIT_TYPE");
        myAddress.name = 
               results.getInt("CREDIT_NAME");
      }
    }
    catch (SQLException sqle) {
      throw new EJBException(sqle);
    }
    finally {
      if (con!=null)
        con.close();
    }
  }
}

El m�todo ejbLoad(), usa la referencia ejbContext() hacia el EntityContext del bean para obtener la clave primaria del ejemplar. Esto asegura que usamos el �ndice correcto en la base de datos. Obviamente, el CustomerBean_BMP necesitar� usar los m�todos heredados setEntityContext() y unsetEntityContext().

El m�todo ejbStore() es invocado sobre el bean, al final de la transaci�n, justo antes de que el contenedor intente enviar todos los cambios a la base de datos.

import java.sql.Connection;

public class CustomerBean_BMP 
                extends CustomerBean {

  public void ejbLoad() {
    ... read data from database
  }

  public void ejbStore() {
    Connection con;
    try {
      Integer primaryKey = 
        (Integer)ejbContext.getPrimaryKey();
      con = this.getConnection();
      PreparedStatement sqlPrep = 
      con.prepareStatement(
         "UPDATE customer set " +
         "last_name = ?, first_name = ?, 
                     middle_name = ?, " +   
         "street = ?, city = ?, state = ?, 
            zip = ?, " +
         "card_number = ?, card_date = ?, " +
         "card_name = ?, card_name = ?, " +
         "WHERE id = ?"
      );
      sqlPrep.setString(1,myName.last);
      sqlPrep.setString(2,myName.first);
      sqlPrep.setString(3,myName.middle);
      sqlPrep.setString(4,myAddress.street);
      sqlPrep.setString(5,myAddress.city);
      sqlPrep.setString(6,myAddress.state);
      sqlPrep.setString(7,myAddress.zip);
      sqlPrep.setInt(8, myCreditCard.number);
      sqlPrep.setString(9, myCreditCard.expDate); 
      sqlPrep.setString(10, myCreditCard.type);
      sqlPrep.setString(11, myCreditCard.name);
      sqlPrep.setInt(12,primaryKey.intValue());
      sqlPrep.executeUpdate();
    }
    catch (SQLException sqle) {
      throw new EJBException(sqle);
    }
    finally {
      if (con!=null)
        con.close();
    }
  }
}

En ambos m�todos ejbLoad() y ejbStore() el bean sincroniza su propio estado con la base de datos usando JDBC. Si estudiamos el c�digo cuidadosamente podr�amos haber observado que el bean otiene sus conexiones a la base de datos desde una invocaci�n misteriosa al m�todo this.getConnection(). Un m�todo todav�a no implementado. El m�todo getConnection() no es un m�todo est�ndard EJB, s�lo una ayuda privada implementada para ocultar los mecanismos de obtenci�n de conexiones a bases de datos. Abajo tenemos la definic�n del m�todo getConnection().

import java.sql.Connection;

public class CustomerBean_BMP 
    extends CustomerBean {

  public void ejbLoad() {
    ... read data from database
  }

  public void ejbStore() {
    ... write data to database
  }

  private Connection getConnection() 
         throws SQLException {

     InitialContext jndiContext = 
         new InitialContext();
     DataSource source = (DataSource)
                jndiContext.lookup("
           java:comp/env/jdbc/myDatabase");
     return source.getConnection();
  }
}

Las conexiones a bases de datos se obtienen desde el contenedor usando un contexto JNDI por defecto llamado "JNDI Environment Naming Context" (ENC). El ENC proporciona acceso a almacenes de conexiones JDBC transacionales a trav�s de la factor�a de conexiones est�ndard, del tipo javax.sql.DataSource.

En BMP, los m�todos ejbLoad() y ejbStore() los invoca el contenedor para sincronizar el ejemplar del bean con los datos en la base de datos. Para insertar y eliminar entidades en la base de datos, se implementan los m�todos ejbCreate() y ejbRemove() con una l�gica de acceso a bases de datos muy similar. Los m�todos ejbCreate() se implementan para insertar un nuevo registro en la base de datos y los m�todos ejbRemove() para eliminar los datos de una entidad de la base de datos. Estos m�todos de una entidad son invocados por el contenedor en respuesta a invocaciones a sus correspondientes m�todos en los interface home y remoto. Abajo podemos ver las implementaciones de estos m�todos.

  public void ejbCreate(Integer id) {
    this.customerID = id.intValue();
    Connection con;
    try {
      con = this.getConnection();
      Statement sqlStmt = 
      con.createStatement("INSERT INTO 
               customer id VALUES (" +
                          customerID + ")");
      sqlStmt.executeUpdate();
      return id;
    }
    catch(SQLException sqle) {
      throw new EJBException(sqle);
    }
    finally {
      if (con!=null)
        con.close();
    }
  }

  public void ejbRemove() {
    Integer primaryKey = 
     (Integer)ejbContext.getPrimaryKey();
    Connection con;
    try {
      con = this.getConnection();
      Statement sqlStmt = 
      con.createStatement("DELETE FROM 
                    customer WHERE id = " 
                   primaryKey.intValue());
      sqlStmt.executeUpdate();
    }
    catch(SQLException sqle) {
      throw new EJBException(sqle);
    }
    finally {
      if (con!=null)
        con.close();
    }
  }

En BMP, la clase bean es responsable de implementar los m�todos de b�squeda definidos en el interface home. Por cada m�todo de b�squeda definido en el interface home debe haber el correspondiente m�todo ejbFind() en la clase bean. Estos m�todos localizan los registros del bean apropiado en la base de datos y devuelve sus claves primarias al contenedor. El contenedor convierte la clave primara en referencias a beans y los devuelve al cliente. Abajo tenemos un ejemplo de implementaci�n del m�todo ejbFindByPrimaryKey() en la clase CustomerBean_BMP, que corresponde al findByPrimaryKey() definido en el interface CustomerHome.

public Integer ejbFindByPrimaryKey(
                  Integer primaryKey) 
               throws ObjectNotFoundException {
    Connection con;
    try {
        con = this.getConnection();
        Statement sqlStmt = 
            con.createStatement("SELECT * 
                             FROM Customer " +
                             " WHERE customerID = " +
                             primaryKey.intValue());
                            
        ResultSet results = sqlStmt.executeQuery();
        if (results.next())
            return primaryKey;
        else
            throw ObjectNotFoundException();
    }
    catch (SQLException sqle) {
        throw new EJBException(sqle);
    }
    finally {
        if (con!=null)
        con.close();
    }
}

Los m�todos de b�squeda de entidades simples como el de arriba devuelven una s�la clave primara y lanza una ObjectNotFoundException si no se localiza un registro correspondiente. Los m�todos de b�squeda multi-entidad devuelven una colecci�n (java.util.Enumeration o java.util.Collection) de claves primarias. El contenedor convierte la colecci�n de claves primarias en una colecci�n de referencias remotas, que son devueltas al cliente. Abajo tenemos un ejemplo de c�mo el m�todo ejbFindByZipCode() multi-entidad, que corresponde al m�todo findByZipCode() definido en el interface CustomerHome, ser�a implementado en la clase CustomerBean_BMP.

public Enumeration ejbFindByZipCode(
                      int zipCode)  {
    Connection con;
    try {
        con = this.getConnection();
        Statement sqlStmt = 
        con.createStatement("SELECT id 
                     FROM Customer " +
              " WHERE zip = " +zipCode);
                            
        ResultSet results = 
                sqlStmt.executeQuery();
        Vector keys = new Vector();
        while(results.next()){
            int id = results.getInt("id");
            keys.addElement(new Integer(id));
        }
        return keys.elements();
    }
    catch (SQLException sqle) {
        throw new EJBException(sqle);
    }
    finally {
        if (con!=null)
        con.close();
    }
}

Si no se encuentran registros correspondientes, se devuelve una colecci�n vac�a al contenedor, que devuelve una colecci�n vac�a al cliente.

Con la implementaci�n de todos estos m�todos y unos pocos cambios menores en el descriptor de desarrollo del bean, el CustomerBean_BMP esta listo para ser desplegado como una entidad BMP.

.�Beans Enterprise del Tipo Sesi�n

Los beans de sesi�n son usados para manejar las interacciones de entidades y otros beans de sesi�n, accesos a recursos, y generalmente realizan tareas en beneficio del cliente. Los bean de sesi�n no son objetos del negocio persistentes como lo son los beans de entidad. No representan datos en la base de datos. Los beans de sesi�n corresponden al controlador en una arquitectura modelo-vista-controlador porque est�n encapsulando la l�gica de negocio de una arquitectura de tres hilos.

Hay dos clases b�sicas de beans de sesi�n: sin estado y con estado. Los beans de sesi�n sin estado configuran m�todos de negocio que se comportan como procedimientos; operan s�lo sobre los argumentos que se les pasan. Los bean sin estado son temporales; no mantienen el estado del negocio entre llamadas. Los beans de sesi�n con estado encapsulan la l�gica del negocio y el estado espec�fico de un cliente. Los beans con estado si que mantienen es estado de negocio entre llamadas al m�todo, las mentienen en memoria y no es persistente.

.�Beans de Sesi�n sin Estado

Los bean de sesi�n sin estado, como todos los beans de sesi�n, no son objetos de negocio persistentes. No representan datos en la base de datos. En su lugar, representan procesos de negocio o tareas que son realizadas en beneficio del cliente que la usa. Los m�todos del negocio en un bean de sesi�n sin estado act�an como los procedimientos tradicionales en un monitor de procesamiento de transaciones legales. Cada llamada a un m�todo de negocio es independiente de las llamadas anteriores. Los beans de sesi�n sin estado son muy sencillos de manejar por parte el contenedor EJB, por eso tienden a procesar las peticiones muy r�pido y usan menos recursos. Pero esta ventaja de rendimiento tiene un precio; los beans de sesi�n sin estado no recuerdadn nada entre una llamada a m�todo y la siguiente.

Un ejemplo de bean de sesi�n sin estado es un bean CreditService, que representa un servicio de cr�dito que puede validar y procesar cargos en tarjetas de cr�dito. Una cadena de Hoteles podr�a desarrollar un bean CreditService para encapsular el proceso de verificaci�n del n�mero de una tarjeta de cr�dito, hacer un cargo, y grabar el cargo en la base de datos para prop�sitos de contabilidad. Abajo tenemos el interface home y remoto para el bean CreditService.

// remote interface
public interface CreditService 
    extends javax.ejb.EJBObject {
    public void verify(CreditCard 
                card, double amount)
    throws RemoteException, 
          CreditServiceException;
    public void charge(CreditCard 
               card, double amount) 
    throws RemoteException, 
             CreditServiceException;
}

// home interface
public interface CreditServiceHome 
         extends java.ejb.EJBHome {
     public CreditService create()
           throws RemoteException, 
                      CreateException;
}

El interface remoto, CreditService, define dos m�todos, verify() y charge() que se usan para verificar y realizar cargos en tarjetas de cr�dito. El Hotel podr�a usar el m�todo verify() para hacer una reserva, pero no cargar al cliente. El m�todo charge() se usar�a para cargar al cliente una habitaci�n. El interface home, CreditServiceHome proporciona un m�todo create() sin argumentos. Todos los interfaces home de los beans de sesi�n sin estado definir�n s�lo un m�todo, un m�todo create() sin argumento, porque los beans de sesi�n no tienen m�todos de b�squeda y no puden ser inicializados con ning�n argumento cuando son creados. Los beans de sesi�n sin estado no tienen m�todos de b�squeda porque son todos equivalentes y no son persistentes. En otras palabras, no hay beans de sesi�n sin estado �nicos que puedan ser localizados en la base de datos. Como los beans de sesi�n sin estado no son persistentes, son servicios temporales. Cada cliente que usa el mismo tipo de bean de sesi�n sin estado obtiene el mismo servicio.

Abajo tenemos la definici�n de la clase del bean para CreditService. Este bean encapsula el acceso a los servicios de procesamiento de las Tarjetas de Cr�dito Acme. Espec�ficamente, este bean accede a servidor web seguro de Acme y postea una solicitud para validar o realizar un cargo en la tarjeta de cr�dito del cliente.

import javax.ejb.SessionBean;

public class CreditServiceBean 
        implements SessionBean {
    URL acmeURL;
    HttpURLConnection acmeCon;

    public void ejbCreate() {
        try {
            InitialContext jndiContext = 
                  new InitialContext();
            URL acmeURL = (URL)
            jndiContext.lookup("
               java:comp/ejb/env/url/acme");
            acmeCon = 
              acmeURL.openConnection();
        }
        catch (Exception e) {
            throws new EJBException(e);
        }
    }

    public void verify(CreditCard card, 
                         double amount) {
        String response = post("verify:" + 
                       card.postString() +
                            ":" + amount);
        if (response.substring("
                         approved")== -1)
            throw new 
             CreditServiceException("denied");
    }

    public void charge(CreditCard card, 
                              double amount) 
                throws CreditCardException {
        String response = post("charge:" + 
                          card.postString() +
                               ":" + amount);
        if (response.substring("approved")== -1)
            throw new CreditServiceException("
                                      denied");
    }

    private String post(String request) {
        try {
            acmeCon.connect();
            acmeCon.setRequestMethod("
                        POST "+request);
            String response = 
              acmeCon.getResponseMessage();
        }
        catch (IOException ioe) {
            throw new EJBException(ioe);
        }
    }

    public void ejbRemove() {
        acmeCon.disconnect();
    }

    public void setSessionContext(
            SessionContext cntx) {}

    public void ejbActivate() {}

    public void ejbPassivate() {}
}

El bean sin estado CreditService demuestra que un bean sin estado puede representar una colecci�n de servicios independientes pero relacionados. En este caso la validaci�n y los cargos de una tarjeta de cr�dido est�n relacionados pero no son necesariamente interdependientes. Los beans sin estado podr�an usarse para acceder a recursos poco usuales -- como es el caso de CreditService -- a bases de datos o para realizar c�lculos complejos. El bean CreditService se usa para demostrar el servicio natural de los beans sin estado y para proporcionar un contexto para explicar el comportamiento de los m�todos de retrollamada. El uso de beans de sesi�n sin estado no est� limitado al comportamiento ilustrado en este ejemplo; se pueden utilizar para realizar cualquier tipo de servicio.

La clase CreditServiceBean usa una factor�a de recursos URL (acmeURL()) para obtener y mantener una referencia al servidor web de Acme que existe en otro ordenador muy lejano. El CreditServiceBean usa el acmeURL() para obtener una conexi�n al servidor web y postear solicitudes para la validaci�n o el cargo de tarjetas de cr�dito. El bean CreditService lo usan los clientes en lugar de una conexi�n directa para que el servicio pueda ser mejor manejado por el contenedor EJB, que almacenar� conexiones y manejar� las transaciones y la seguirdad autom�tiamente por el cliente.

El m�todo ejbCreate() es invocado al principio de su vida y es invocado s�lo una vez. Este m�todo es un m�todo conveniente para inicializar recursos de conexi�n y variables que ser�n usadas por el bean sin estado durante su vida. En el ejemplo anterior, el CreditServiceBean usa ejbCreate() para obtener una referencia a la factor�a HttpURLConnection, que ser� usada para obtener conexiones al servidor web de Acme.

El CreditServiceBean usa el JNDI ENC para obtener una factor�a de conexiones URL de la misma forma que el CustomerBean usaba el JNDI ENC para obtener una factor�a de recursos DataSource para conexiones JDCB. El JNDI ENC es un contexto JNDI por defecto por que cual todos los beans tienen acceso autom�tico. El JNDI ENC se usa para acceder a propiedades est�ticas, otros beans, y factor�as de recursos como java.net.URL y JDBC javax.sql.DataSource. Adem�s, el JNDI ENC tambi�n proporciona acceso a factorias de recursos como JavaMail y Java Messaging Service.

Los m�todos ejbCreate() y ejbRemove() son invocados s�lo una vez en sus vidas por el contenedor; cuando el bean se crea por primera vez y cuando es destruido. Las invocaciones de los m�todos create() y remove() en sus interface home y remoto por el cliente no resultan en invocaciones de los m�todos ejbCreate() y ejbRemove() en el ejemplar del bean. En su lugar, una invocaci�n al m�todo create() le proporciona al cliente una referencia la tipo de bean sin estado y los m�todos remove() invalidan la referencia. El contenedor decidir� cuando los ejemplares del bean son realmente creados y destruidos e invocar� a los m�todos ejbCreate() y ejbRemove() en esos momentos. Esto permite a los ejemplares sin estado ser compartidos entre muchos clientes sin impactar en las referencias de esos propios clientes.

En el CreditServiceBean, los m�todos ejbCreate() y ejbRemove() son usados para obtener una conexi�n URL al principio de la vida del ejemplar del bean y para desconectarlo al final del ciclo de vida del ejemplar del bean. Durante el tiempo entre que la conexi�n URL es obtenida y es desconectada es usada por los m�todos de negocio. Esta aproximaci�n se usa para reducir el n�mero de veces que se necesita obtener y desconectar una conexi�n, conservando los recursos. Podr�a parecer costoso mantener la conexi�n URL entre llamadas a m�todos, pero los beans de sesi�n sin estado est�n dise�ados para ser compartidos entre muchos clientes, por lo que est�n en uso constantemente. Tan pronto como una ejemplar sin estado completa una llamada de m�todo para un cliente, autom�ticamente puede servir a otro cliente. Idealmente, hay poco tiempo sin utilizaci�n, por lo que tiene sentido mantener la conexi�n URL.

Los m�todos verify() y charge() delegan sus peticiones al m�todo post(), un m�todo privado de ayuda. El m�todo post() usa un HttpURLConnection para enviar informaci�n sobre la tarjeta de cr�dito al servidor web de Acme y devuelve la respuesta al m�todo verify() o charge(). El HttpURLConnection podr�a haber sido desconectado autom�ticamente por el contenedor -- esto podr�a ocurrir si, por ejemplo, ha pasado mucho tiempo desde su �ltimo uso -- por eso el m�todo post() siempre invoca al m�todo connect(), que no hace nada si la conexi�n ya est� establecida. Los m�todos verify() y charge() analizan el valor de retorno buscando la sub-cadena "approved" que indica que la tarjeta de cr�dito no era denegada. Si no se encuentra "approved", se asume que la tarjeta de cr�dito fue denegada y se lanza una excepci�n de negocio.

El m�todo setSessionContext() porporciona al ejemplar del bean una referencia a SessionContext que sirve para el mismo prop�sito que EntityContext lo era para CustomerBean en la secci�n Beans de Entidad. El SessionContext no se usa en este ejemplo.

Los m�todos ejbActivate() y ejbPassivate() no est�n implementados en el bean CreditService porque la "pasivaci�n" no se utiliza en los beans de sesi�n sin estado. Estos m�todos est�n definidos en el interface javax.ejb.SessionBean para los beans de sesi�n con estado, y por eso se debe proporcionar una implementaci�n vac�a para los beans de sesi�n sin estado. Los beans de sesi�n sin estado nunca proporcionar�n nada distinto que una implementaci�n vac�a para estos m�todos.

Los beans de sesi�n sin estado tambi�n pueden usarse para acceder a la base de datos as� como para coordinar la interacion de otros beans para realizar una tarea. Abajo tenemos la definici�n del HotelClerkBean mostrado anteriormente en este tutorial.

import javax.ejb.SessionBean;
import javax.naming.InitialContext;

public interface HotelClerkBean 
          implements SessionBean {

    InitialContext jndiContext;

    public void ejbCreate() {}

    public void reserveRoom(Customer 
                    cust, RoomInfo ri,
                Date from, Date to) {
        CreditCard card = 
                 cust.getCreditCard();

        RoomHome roomHome = (RoomHome)
        getHome("java:comp/env/ejb/RoomEJB", 
                           RoomHome.class);
        Room room = 
          roomHome.findByPrimaryKey(
                           ri.getID());
        double amount = 
               room.getPrice(from,to);

        CreditServiceHome creditHome =
           (CreditServiceHome) getHome(
        "java:comp/env/ejb/CreditServiceEJB",
                    CreditServiceHome.class);
        CreditService creditAgent = 
                        creditHome.create();
        creditAgent.verify(card, amount);

        ReservationHome resHome =
                        (ReservationHome) getHome(
                              "java:comp/env/ejb/ReservationEJB",
                              ReservationHome.class);
        Reservation reservation = resHome.create(cust.getName(),
                                                 room,from,to);
    }

    public RoomInfo[] availableRooms(Location loc,
                              Date from, Date to) {
        // do a SQL call to find available rooms
        Connection con = db.getConnection();
        Statement stmt = con.createStatement();
        ResultSet results = 
                stmt.executeQuery("SELECT ...");
        ...
        return roomInfoArray;
    }

    private Object 
      getHome(String path, Class type) {
        Object ref = 
                jndiContext.lookup(path);
        return 
          PortableRemoteObject.narrow(ref,type);
    }
}

El HotelClerkBean es un bean sin estado. Toda la informaci�n necesaria para precesar una reserva o para consultar una lista de habitaciones disponibles se obtiene desde los argumentos al m�todo. En el m�todo reserveRoom(), las operaciones sobre otros beans (Room, CreditService, y Reservation) est�n coordinadas para ralizar una larga tarea, reservar una habitaci�n para un cliente. Este es un ejemplo de un bean de sesi�n que maneja la interacci�n con otros beans en beneficio del cliente. El m�todo availableRooms() se usa para consultar la base de datos y obtener una lista de habitaciones -- la informaci�n devuelta al cliente es una colecci�n de envolturas de datos definida por la clase RoomInfo. El uso de esta clase, mostrado abajo, es un patr�n de dise�o que proporciona al cliente una envoltura de peso ligero con s�lo la informaci�n necesaria.

public class RoomInfo {
    public int     id;
    public int     bedCount;
    public boolean smoking;
}

Para obtener una referencia a otro bean, como se hace tres veces en el m�todo reserveRoom(), se usa el m�todo de ayuda privado getHome(). Este m�todo usa el JNDI ENC para obtener referencias a otros beans.

private Object getHome(String path, 
                       Class type) {
   Object ref = 
           jndiContext.lookup(path);
   return 
      PortableRemoteObject.narrow(
                          ref,type);
}

En la especificaci�n EJB 1.1, RMI sobre IIOP es el modelo de programaci�n espec�ficado, por eso los tipos de referencia CORBA deben ser soportados. Las referencias CORBA no pueden ser forzadas usando Java nativo. En su lugar se debe usar el m�todo PortableRemoteObject.narrow() para apuntar expl�citamente a una referencia desde un tipo a su subtipo. Como JNDI siempre devuelve un tipo Object, todas las referencias deben apuntar expl�citamente para soportar la portabilidad entre contenedores.

.�Beans de Sesi�n con Estado

Los beans de sesi�n con estado est�n dedicados a un cliente y mantienen un estado-conversacinal entre llamadas de m�todos. Al contrario que los beans de sesi�n sin estado, los clientes no comparten los beans de sesi�n con estado. Cuando un cliente crea un bean con estado, el ejemplar del bean est� dedicado a servir �nicamente a ese cliente. Esto hace posible mantener estado-conversacional, que es un estado de negocio que puede ser compartido por m�todos del mismo bean con estado.

Como ejemplo, el bean HotelClerk puede ser modificado para que sea un bean con estado que pueda mantener estado-conversacional entre llamadas a m�todos. Esto ser�a �til, por ejemplo, si queremos que el bean HotelClerk pueda realizar muchas reservas, pero pueda procesarlas todas juntas bajo una tarjeta de cr�dito. Esto ocurre frecuentemente, cuando las familias necesitan reservar dos o m�s habitaciones o cuando las corporaciones reservan un bloque de habitaciones para alg�n evento. Abajo tenemos el HotelClerkBean modificado para ser un bean con estado.

import javax.ejb.SessionBean;
import javax.naming.InitialContext;

public class HotelClerkBean 
          implements SessionBean {

    InitialContext jndiContext;
    
    //conversational-state
    Customer cust;
    Vector resVector = new Vector();

    public void ejbCreate(Customer 
                       customer) {}
        cust = customer;
    }

    public void addReservation(Name 
                    name, RoomInfo ri,
                               Date 
                      from, Date to) {
        ReservationInfo resInfo =
              new ReservationInfo(name,
                           ri,from,to);
        resVector.addElement(resInfo);
    }

    public void reserveRooms() {
        CreditCard card = 
            cust.getCreditCard();
        Enumeration resEnum = 
             resVector.elements();

        while 
         (resEnum.hasMoreElements()) {

        ReservationInfo resInfo =
                       (ReservationInfo) 
                    resEnum.nextElement();

        RoomHome roomHome = (RoomHome)
        getHome("java:comp/env/ejb/RoomEJB", 
                            RoomHome.class);
        Room room =
             roomHome.findByPrimaryKey(
                 resInfo.roomInfo.getID());
        double amount = room.getPrice(
                 resInfo.from,restInfo.to);

        CreditServiceHome creditHome = 
                      (CreditServiceHome)
        getHome("java:comp/env/ejb/CreditServiceEJB",
                CreditServiceHome.class);
        CreditService creditAgent = creditHome.create();
        creditAgent.verify(card, amount);

        ReservationHome resHome = (ReservationHome)
        getHome("java:comp/env/ejb/ReservationEJB",
                ReservationHome.class);
        Reservation reservation = 
        resHome.create(resInfo.getName(),
        resInfo.roomInfo,resInfo.from,resInfo.to);
    }

    public RoomInfo[] availableRooms(Location loc,
                              Date from, Date to) {
        // Make an SQL call to find available rooms
    }

   private Object getHome(String path, Class type) {
        Object ref = jndiContext.lookup(path);
        return PortableRemoteObject.narrow(ref,type);
   }
}

En esta versi�n con estado de la clase HotelClerkBean, el estado conversacional es la referencia Customer que es obtenerida cuando se crea el bean y el Vector de objetos ReservationInfo. Manteniendo el estado-conversacional en el bean, el cliente est� absuelto de responsabilidades de seguir la pista del estado de la sesi�n. El bean mantiene la pista de las reservas y de procesarlas en un proceso batch cuando se llama el m�todo serverRooms().

Para conservar recursos, los beans de sesi�n con estado podr�an ser "pasivizados" cuando no est�n en uso por el cliente. La "pasivizaci�n" en beans de sesi�n con estado es diferente de los beans de entidad. En los beans con estado, la "pasivizaci�n" significa que el estado-conversacional del bean es escrito en un almacenamiento secundario (en disco, normalmente) y el ejemplar es eliminado de la memoria. La referencia del cliente al bean no se ve afectada por la "pasivizaci�n", permanece viva y utilizable mientras el bean es "pasivizado". Cuando el cliente invoca a un m�todo de un bean que est� "pasivizado", el contenedor activar� el bean ejemplarizando un nuevo ejemplar y rellenandolo con el estado-convsersacional escrito en el almacenamiento secundario.

Los beans de sesi�n con estado, usan los m�todos ejbActivate() y ejbPassivate(). El contenedor invocar� estos m�todos para notificar al bean cuando est� a punto de ser "pasivizado" (ejbPassivate()) e inmediatamente despues de la activaci�n (ejbActivate()). Los desarrolladores de bean deber�an usar estos m�todos para cerrar recursos abiertos y para hacer otras operaciones de limpieza antes de que el estado del ejemplar sea escrito en el almacenamiento secundario y eliminarlo de la memoria.

El m�todo ejbRemove() es invocado sobre el ejemplar con estado cuando el cliente invoca al m�todo remove() del interface home o remoto. El bean deber�a usar el m�todo ejbRemove() para hacer el mismo tipo de limpieza realizada en el m�todo ejbPassivate().

.�Soluciones a la Tecnolog�a de Despliegue de JavaBeans Enterprise

Como se mencion� anteriormente, el contenedor maneja la persistencia, las transaciones, la concurrencia y el control de acceso autom�ticamente para los beans enterprise. La especificaci�n EJB describe un mecanismo declarativo para indicar c�mo se manejaran esas cosas, a trav�s del uso de un descriptor de desarrollo XML. Cuando un bean es desplegado dentro de un contenedor, el contenedor lee el descriptor de desarrollo para encontrar c�mo ser�n manejadas las transaciones, la persistencia (beans de entidad), y el control de acceso. La persona que despliega el bean usa est� informaci�n y especificar� informaci�n adicional para proporcionarle al bean estas facilidades en tiempo de ejecuci�n.

Un descriptor de desarrollo tiene un formato predefinido que deben usar todos los beans compatibles EJB y que todos los servidores EJB deben saber como leer. Este formato se especifica como un "Document Type Definition", o DTD de XML. El descriptor de desarrollo describe el tipo de bean (sesi�n o entidad) y las clases usadas para el interface remoto, home y la clase del bean. Tambi�n especifica los atributos transacionales de cada m�todo del bean, qu� roles de seguridad pueden acceder a cada m�todo (control de acceso), y si la persistencia de un bean de entidad es manejada autom�ticamente o sea manejada por el bean. Abajo tenemos un ejemplo de descriptor de desarrollo usado para describir el bean Customer.

<?xml version="1.0"?>

<!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>
  <enterprise-beans>
    <entity>
      <description>
        This bean represents a customer
      </description>
      <ejb-name>CustomerBean</ejb-name>
      <home>CustomerHome</home>
      <remote>Customer</remote>
      <ejb-class>CustomerBean</ejb-class>
      <persistence-type>Container</persistence-type>
      <prim-key-class>Integer</prim-key-class>
      <reentrant>False</reentrant>

      <cmp-field><field-name>myAddress</field-name></cmp-field>
      <cmp-field><field-name>myName</field-name></cmp-field>
      <cmp-field><field-name>myCreditCard</field-name></cmp-field>
    </entity>
  </enterprise-beans>
 
  <assembly-descriptor>
    <security-role>
      <description>
        This role represents everyone who is allowed full access 
        to the Customer bean.
      </description>
      <role-name>everyone</role-name>
    </security-role>

    <method-permission>
      <role-name>everyone</role-name>
      <method>
        <ejb-name>CustomerBean</ejb-name>
        <method-name>*</method-name>
      </method>
    </method-permission>

    <container-transaction>
      <description>
        All methods require a transaction
      </description>
      <method>
        <ejb-name>CustomerBean</ejb-name>
        <method-name>*</method-name>
      </method>
      <trans-attribute>Required</trans-attribute>
    </container-transaction>
  </assembly-descriptor>
</ejb-jar>

Los servidores de aplicaciones EJB normalmente proporcionan herramientas que pueden ser usadas para construir descriptores de desarrollo; esto simplifica mucho el proceso.

Cuando un bean va ser desplegado, sus ficheros class de los interfaces home y remoto y de la clase del bean y del descriptor de desarrollo deben empaquetarse juntos en un fichero JAR. El descriptor de desarrollo debe almacenarse en el fichero JAR con un nombre especial META-INF/ejb-jar.xml.

Este fichero JAR, llamado un ejb-jar, puede ser deplegado en cualquier contenedor EJB que soporte la especificaci�n EJB. Cuando un bean es desplegado en cualquier contenedor EJB su descriptor de desarrollo XML es le�do desde el fichero JAR para determinar c�mo manejar el bean en tiempo de ejecuci�n. La persona que despliega el bean mapear� los atributos del descriptor de desarrollo al entorno del contenedor. Esto incluir� el mapeo de la seguirdad de accesos al sistema de seguridad del entorno, a�adir el bean al sistema de nombrado del contenedor EJB, etc. Una vez que el desarrollador del bean han finalizado su despligue el bean estar� disponible para que lo utilicen las aplicaciones cliente y otros beans.

.�Clientes de JavaBeans Enterprise

Los clientes de JavaBeans Enterprise podr�an ser aplicaciones solitarias, servlets, applets, o incluso otros beans enterprise. Por ejemplo, el bean de sesi�n HotelClerk mostrado arriba era cliente del bean de entidad Room. Todos los clientes usan el interface home del bean para obtener referencias al servidor del bean. Esta referencia tiene el tipo de dato del interface remoto el bean, por lo tanto el cliente interct�a con el bean del servidor s�lamente a trav�s de los m�todos definidos en el interface remoto.

El interface remoto define los m�todos de negocio, como los m�todos accesores o modificadores para cambiar el nombre de un cliente, o m�todos de negocio que realizan tareas como usar el bean HotelClerk para reservar una habitaci�n en le Hotel. Abajo tenemos un ejemplo de c�mo se podr�a acceder al bean Customer desde una aplicaci�n cliente. En este caso el interface home es CustomerHome y el interface remoto es Customer.

CustomerHome home;
Object       ref;

// Obtain a reference to the CustomerHome
ref  = jndiContext.lookup("java:comp/env/ejb/Customer");

// Cast object returned by the JNDI lookup to the
// appropriate datatype
home = PortableRemoteObject.narrow(ref, CustomerHome.class);

// Use the home interface to create a
// new instance of the Customer bean.
Customer customer = home.create(customerID);

// Use a business method on the Customer.
customer.setName(someName);

Un cliente, primero obtiene una referencia al interface home usando JNDI ENC para buscar el servidor del bean. En EJB 1.1, Java RMI-IIOP es el modelo de programaci�n especificado. Como consecuencia, todas las referencias CORBA deben ser soportadas. Las referencias CORBA no pueden ser forzadas usando Java nativo. En su lugar se debe usar el m�todo PortableRemoteObject.narrow() para apuntar expl�citamente a una referencia desde un tipo a su subtipo. Como JNDI siempre devuelve un tipo Object, todas las referencias deben apuntar expl�citamente para soportar la portabilidad entre contenedores.

Despu�s de obtener el interface home, el cliente usa los m�todos definidos en este interface para crear, buscar, o eliminar el bean servidor. Invocar uno de los m�todos create() del interface home devuelve al cliente una referencia remota al bean servidor, que el cliente usa para realizar su trabajo.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP
SIGUIENTE ARTÍCULO