Esta p�gina cubre como crear un componente EJB con Persistencia Manejada por el contenedor (CMP). Crearemos dos beans CMP, Item y Supplier. El bean Item ser� responsable de almacenar los detalles de los �tems, como su disponibilidad o precio. El bean Supplier almacena detalles de los provedores de MyStore. Ambos beans interact�an con las correspondientes tablas de la base de datos. En CMP est� interacci�n la controla el contenedor, en este caso el contenedor JBOSS CMP.

A todos los �tems se les ha asignado un �nico itemId igual que a los proveedores se les ha asignado un �nico supplierID adem�s de su username que es lo que usar�n para acceder a los servicios de MyStore.
Nota:
La pr�ctica usual para acceder a los m�todos de negocio de beans CMP, es utilizar un bean de sesi�n, que encapsule la l�gica de negocio y act�e como interface para otros componentes EJB. En este caso se puede acceder a Items y a Supplier mediante StoreAccess. |
�Crear el Bean de Entidad CMP Items:
- Ve a Package Explorer y expande el nodo Mystore, selecciona src, pulsa el bot�n derecho y aparecer� un men� desplegable.
- En el men� pulsa New > Lomboz EJB Creation Wizard.
- Introduce au.com.tusc.cmp como el nombre del paquete, Item como el nombre del bean, y selecciona el tipo del bean como Container Manged Entity:
- Pulsa Next y aparecer� una nueva ventana.
- Introduce MyStoreItem como el Schema Name.
- Introduce Item como el nombre de la tabla.
- Bajo Persistent Fields primero introduce itemID como el Field, con un tipo de campo de java.lang.String, ITEMID como su columna Database, y VARCHAR para su tipo SQL.
- Pulsa Add.. y se a�adir� este campo a la secci�n Fields, selecciona este nuevo campo y pulsa Make Primary Key:
- De forma similar a�ade el resto de los campos de la tabla items:
- Add .. Field: supplierID, Field Type: java.lang.String, Database Column: SUPPLIERID, SQL Type: VARCHAR.
- Add .. Field: description, Field Type: java.lang.String, Database Column: DESCRIPTION, SQL Type: VARCHAR.
- Add .. Field: quantity, Field Type: java.lang.Integer, Database Column: QUANTITY, SQL Type: INTEGER.
- Add .. Field: price, Field Type: java.lang.Float, Database Column: PRICE, SQL Type: DECIMAL.
- Despu�s de a�adir estos campos, pulsa Finish.
Esto crear� un paquete llamado au.com.tusc.cmp bajo src, y se crear� ItemBean dentro de ese paquete:

Nota:
En comparaci�n con nuestros anteriores Beans de Entidad BMP, ahora se han generado m�s etiquetas a nivel de clase. Observa tambi�n que el CMP no requiere un interface DAO, ya que la comunicaci�n entre el bean y la base de datos la controla el contenedor. |
Primero generamos las clases EJB y luego examinaremos esas etiquetas:
- Ve al nodo ItemBean en au.com.tusc.cmp > LombozJ2EE > Add EJB to Module, selecciona MyStoreMgr y pulsa Ok.
- Ve al nodo MyStoreMgr y selecciona LombozJ2EE > Generate EJB classes.
Ahora veamos qu� ficheros ha generado Xdoclet. Como puedes ver abajo, los ficheros son casi los mismos que para BMP, excepto que no hay clases de clave primaria o de DAO, y ahora hay un ItemCMP que extiende la clase ItemBean. El resto son los mismos que para los beans de entidad BMP:

Examinemos esas nuevas etiquetas, algunas de las cuales hemos visto en p�ginas anteriores:
- @ejb.bean; proporciona informaci�n sobre el EJB. Es la �nica etiqueta obligatoria para todos los EJBs.
- @ejb.persistence; se utiliza a dos niveles, a nivel de clase y de m�todo. A nivel de clases proporciona informaci�n sobre la persistencia de un bean de entidad CMP, es decir la tabla de la base de datos con la que va a interact�ar, y que le proporcionar� la persistencia. A nivel de m�todo proporciona informaci�n del mapeo de los atributos persistentes del bean a columnas en la tabla de la base de datos.
- @ejb.finder; define un m�todo finder para el interface home. Este requiere la consulta EJB QL para comparar los datos y la firma del m�todo. Esta etiqueta se puede utilizar para varios m�todos finder.
- @ejb.persistence-field; etiqueta a nivel de m�todo que ha quedado obsoleta en favor de @ejb.persistence, proporciona informaci�n sobre los campos persistentes.
- @ejb.pk-field; define la clave primaria.
El siguiente fragmento de c�digo muestra como se declaran los atributos persistentes en un bean de entidad CMP:

Nota:
Todos los atributos persistentes se declaran con m�todos accesores y mutadores abstract en ItemBean. Observa tambi�n que en el caso de una clave primaria compuesta se tiene que especificar la etiqueta @ejb.pk-field para todos los atributos/propiedades que se combinan para forma la clave compuesta. |
�Implementar el M�todo ejbCreate:
El wizard de Lomboz Bean crea el m�todo ejbCreate, pero a�n tenemos que a�adir algo de c�digo para completarlo. Modificar la firma de ejbCreate, pasar todos los atributos como par�metros y luego seleccionar todos esos atributos utilizando sus m�todos mutadores asociados, como se muestra abajo:
Nota de errata:
Hay un error en la siguiente figura. El atributo Integer llamado 'qunatity' deber�a ser 'quantity'. |

Nota:
El otro aspecto interesante de ejbCreate es su tipo de retorno, ya que debe ser el mismo que el tipo de la clave primaria (es decir, tiene que ser String, Integer, Float, o cualquier otro). En este caso es String -- el tipo de itemID, y cuando lo implementemos deber�a devolver null (puedes ver la especificaci�n 10.5.1 de EJB). |
�A�adir un M�todo Finder:
Nota:
Un interface home de un bean de entidad define uno o m�s m�todos finder, para encontrar un objeto entidad o una colecci�n de ellos. El nombre de cada m�todo finder empieza con el prefijo find, como en findPrice o findQuantity en nuestro caso. Todo m�todo finder, excepto findByPrimaryKey(key) debe estar asociados con un elemento query en el descriptor de despliegue. El preveedor del bean de entidad declara la consulta EJB QL y la asocia con el m�todo finder en el descriptor de despliegue. Un m�todo find normalmente se caracteriza por un string de consulta EJB QL especificado mediante el elemento query. |
Ahora a�adamos un m�todo finder a nuestra clase bean para buscar �tems suministrados por un proveedor particular. Para poder hacer esto tenemos que declarar la etiqueta a nivel de clase que hemos descrito arriba: @ejb.finder.
- A�ade esta etiqueta:
@ejb.finder query="SELECT OBJECT(a) FROM MyStoreItem a where a.supplierID = ?1" signature="java.util.Collection findBySupplierID(java.lang.String supplierID)"
Nota:
En EJB QL, en lugar del nombre de la tabla, se utiliza el nombre del esquema (en este caso MyStoreItem, en vez de especificar Item para una consulta SQL). Lo mismo ocurre con los nombres de columnas que se utilizar�an en SQL, en EJB QL son reemplazados por los correspondientes atributos declarados en el bean. - Regenera tus clases EJB para ver lo que ha creado la etiqueta anterior en el interface Home, tiene que ser algo parecido al siguiente fragmento de c�digo de ItemLocalHome:
Tiene cuatro m�todos, incluyendo los dos m�todos finder generados por las etiquetas declaradas a nivel de clase. Los otros dos, create y findByPrimaryKey los crea Xdoclet (mediante la etiqueta <entitycmp/> en ejbGenerate.xml.
- A�ade otro m�todo finder para encontrar todos los �tems que est�n fuera de stock en MyStore. A�ade la siguiente etiqueta:
@ejb.finder query="SELECT OBJECT(c) FROM MyStoreItem c where c.quantity =0" signature="java.util.Collection findByOutOfStock()"
Abajo puedes ver un fragmento de c�digo de estos m�todos finder en la clase ItemLocalHome despu�s de regenerar las clases EJB:
Ahora, regenera tus clases EJB y analiza las clases importantes. Todos los m�todos finder est�n completos. A�adamos ahora algunos m�todos de negocio.
�A�adir M�todos de Negocio:
- Ahora a�ade un m�todo de negocio con la siguiente firma: public ItemData getItemData() con el tipo de interface local.
Nota:
Ya hemos visto como a�adir m�todos de negocio en las p�ginas anteriores...Estos proporciona la descripci�n de los �tems individuales de MyStore.
- A�ade algunas sentencias de depuraci�n y devuelve un ejemplar de ItemData:
- A�ade otro m�todo de negocio con la siguiente firma: public void fillStock (Integer quantity) con el tipo de interface como local. Esto incrementar� los �tems disponibles en MyStore despu�s de la llegada de m�s �tems. A�ade algunas sentencias de depuraci�n y las siguientes l�neas para completar el m�todo:
Integer qty = new Integer((quantity.intValue() + getQuantity().intValue()) ); setQuantity (qty);
Abajo puedes ver un fragmento del m�todo fillStock de la clase ItemBean:
�A�adir un M�todo de Retrollamada:
Al contrario que en BMP (donde se generar�n autom�ticamente) tenemos que a�adir los m�todos de retrollamadas que se sobreescribir�n en la clase ItemCMP.
- Primero importa el siguiente paquete:
javax.ejb.EntityContext
- A�ade un campo para almacenar el contexto de entidad:
protected EntityContext eContext;
- A�ade un m�todo setEntityContext con entityContext como par�metro y asignalo a tu variable entityContext.
- A�ade un m�todo unsetEntityContext, que ponga a null la variable entityContext.

Ahora ya est�n completos todos los m�todos, es hora de regenerar las clases EJB y examinar la clase ItemCMP generada, que es la m�s interesante.
Al contrario que en nuestro bean BMP todo el comportamiento de persistencia de atributos se ha sobreescrito por m�todos abstractos. Esto es porque el contenedor EJB es el responsable de mantener su persistencia.

Todos los m�todos de retrollamadas que hemos implementado se sobreescribir�n as�:

Nota:
No hay m�todos ejbFinder en esta clase como en los beans BMP, ya que todo esto lo controla el contenedor. Al igual que ya apuntamos antes, tampoco se generan clases PrimaryKey ni se necesita una clase DAO, porque todo lo controla el contenedor. |
Ahora, antes de desplegar nuestro bean, echaremos un vistazo a ejb-jar.xml y jboss.xml para ver que descriptores se han generado.
Nota:
No tenemos que escribir ning�n descriptor para la fuente de datos como hicimos en los beans de sesi�n y BMP, ya que el contenedor EJB es el responsable de esto. |

Como se ve el fragmento anterior, todos los m�todos abstractos se han generado como campos persistentes dento de la etiqueta <cmp-field> debido a la etiqueta @persistence-field declarada en cada m�todo accesor. Tambi�n se han generado el descriptor de la clase primaria dentro de la etiqueta <primary-key-class> y el campo de la clave primaria en la etiqueta <primarykey-field> debido a la etiqueta @field-pk declarada para los atributo(s) importantes.
Los descritores de los m�todos finder se han generado junto con la consulta definida para buscar los datos como se ve abajo. Estas etiquetas finder las ha generado la etiqueta @ejb.finder declaraa a nivel de clase.

Y en el fichero jboss.xml, se han generado los siguiente descritores mediante la etiqueta @ejb.bean declarada a nivel de clase:

Se ha completado la funcionalidad del bean Item y ya est� listo para desplegarlo.
�Desplegar el Bean Item:
- Ve a Lomboz J2EE View y expande los nodos MyStore > MyStoreMgr, selecciona Jboss 3.2.1 ALL.
- Pulsa con el bot�n derecho y selecciona Debug Sever en el men� desplegable.
- Ve al nodo MyStoreMgr en Lomboz J2EE View, pulsa con el bot�n derecho y selecciona Deploy en el men� desplegable:
Nota:
Esto es para arrancar el servidor. Si ya est� ejecut�ndose saltate estos pasos y ve al siguiente. |
Los mensajes de la consola indicar�n si tu bean se ha desplegado con �xito o no.
Ahora modifiquemos StoreAccessBean para llamar a los m�todos de ItemBean.
- A�ade un campo para almacenar nuestra referencia a Item (obtenida mediante JNDI):
private ItemLocalHome itemLocalHome;
- En el m�todo ejbCreate almacena esta referencia en la variable itemLocalHome llamando al m�todo est�tico getLocalHome de la clase ItemUtil:
�A�adir un M�todo de Negocio a StoreAccess:
Ahora a�adiremos otro m�todo de negocio al bean StoreAccess para llamar a los m�todos de negocio de nuestro bean Item.
- A�ade un m�todo de negocio con esta firma: public ItemData getItemData(String itemID), con el tipo de interface local. Como los managers entran en MyStore con su username, una vez autenticados ser�n identificados con su userid. Los managers pueden llamar a los m�todos del bean Item para examinar el inventario.
- Llama a uno de los m�todos finder de Item mediante la variable que hemos creado en el m�todo ejbCreate:
ItemLocal item = itemLocalHome.findByPrimaryKey(itemID)
- Ahora llama a un m�todo de negocio de Item con esta referencia:
ItemData myItem = item.getItemData()
- A�ade otro m�todo de negocio al bean StoreAccess con la firma: public java.util.ArrayList getOutOfStockItems() y con el tipo de interface como remote. Este devolver� los �tems que est�n fuera de stocks en MyStore.
- Crea dos variables de los tipos Collection y ArrayList respectivamente, ya que el m�todo finder de Item devuelve una Collection y este m�todo devolver� un ArrayList, despu�s de rellenarlo con los �tems fuera de stocks de la Collection. devuelta:
Collection items = null; ArrayListItemsOutOfStock = null;
- Ahora llama a uno de lo m�todos finder de Item con la variable que hemos creado en el m�todo ejbCreate:
items = itemLocalHome.findByOutOfStock()
- Itera por la collection de �tems fuera de stock y a�adelos al ArrayList:
ItemLocal myItemLocal = (ItemLocal) iterate.next(); itemsOutOfStock.add(myItemLocal.getItemData());
- A�ade otro m�todo de negocio a StoreAccess con la firma: public java.util.ArrayList getItemBySupplier(String supplierID), con el tipo de interface remote. Este devolver� la lista de �tems suministrados por un proveedor dado.
- >Crea dos variables de los tipos Collection y ArrayList respectivamente, ya que el m�todo finder de Item devuelve una Collection y este m�todo devolver� un ArrayList, despu�s de rellenarlo con los �tems suministrados por un proveedor particular:
Collection suppliedItems = null; ArrayList itemsBySupplier = null;
- Ahora llama a uno de los m�todos finder de Item con la variable creada en el m�todo ejbCreate:
suppliedItems = itemLocalHome.findBySupplierID(supplierID)
- Itera sobre la colecci�n de �tems y a��delos al ArrayList:
ItemLocal myItemsLocal = (ItemLocal) iterate.next(); itemsBySupplier.add(myItemsLocal.getItemData());



Ahora que hemos a�adido a StoreAccess todos los m�todos necesarios para acceder a los m�todos de negocio de Item, lo �nico que nos queda son los descriptores de despliegue requeridos para enlazar/referenciar StoreAccess y Item. Por eso a�adiremos est�s dos etiquetas:

- Primero a�ade esta etiqueta a nivel de clase en StoreAccess:
@ejb.ejb-ref ejb-name="Item" view-type="local" ref-name="ItemLocal"
Esta etiqueta generar� los descriptores de despliegue en ejb-jar.xml, ya que StoreAccessBean tiene que saber a qu� bean se est� referenciando, cu�l es su view-type y su ref-name. Esto generar� los siguientes descriptores de despliegue:
- A�ade una segunda etiqueta a StoreAccess a nivel de clase:
@jboss.ejb-ref-jndi ref-name="ItemLocal" jndi-name="ItemLocal"
Esta etiqueta generar� los descriptores de despliegue en jboss.xml, ya que el servidor de aplicaciones tiene que saber qu� nombre JNDI tiene el bean que se ha registrado. Esto generar� estos descriptores de despliegue:
Nota:
ref-name y jndi-name se utilizan para beans locales (en la misma JVM).
Nota:
Podemos ver en los descriptores de despliegue generados por la etiqueta @jboss, que para los tipos de vista 'local' genera descriptores de despliegue incorrectos, como explicamos en p�ginas anteriores. Por eso, cada vez que utilices esta etiqueta tienes que cambiar el <ejb-ref> por <ejb-local-ref> antes del despliegue. Cuidado: tienes que hacer esto manualmente cada vez que regeneres tus clases EJB, ya que jboss.xml se sobreescribir� en cada regeneraci�n. |
Tras estos cambios nuestro bean Item ya est� completo, ya puedes desplegarlo de nuevo, desde Lomboz J2EE View. La consola te indicar� el estado del despliegue.
Una vez que el bean se ha desplegado con �xito, crea un test de cliente que llame al m�todo loginUser del bean StoreAccess, a getCustomerData del bean Customer, a getManagerData del bean Manager y a getOutOfStockItems del bean Item.
�Crear tu Test de Cliente:
- Ve al nodo del proyecto MytStore selecciona el nodo src y exp�ndelo; selecciona el paquete au.com.tusc.client y pulsa el bot�n derecho.
- Selecciona New en el men� y luego Lomboz EJB Test Client Wizard.
- Pon au.com.tusc.client como nombre de paquete, SessionCMPClient como nombre de sesi�n, au.com.tusc.session.StoreAccessHome como EJB Home y au.com.tusc.session.StoreAccess como EJB Interface.
Esto generar� los m�todos necesarios en tu clase SessionCMPClient y s�lo tendr�s que llamar a loginUser, getCustomerData, getManagerData (el bean Manager se desarroll� como parte del ejercicio de la p�gina anterior) y a getOutOfStockItems.
- Ahora, el �ltimo paso para escribir el c�digo de tu cliente. Para acceder a los �tems fuera de stock necesitaremos un Iterator y un ArrayList. Declara dos variables de estos tipos, e importa los paquetes necesarios(java.util.ArrayList y java.util.Iterator).
Iterator itemsIterator = null; ArrayList items = null;
- Y ahora a�ade esta l�neas de c�digo para llamar a los m�todos mencionados arriba:
System.out.println("Request from client : "); String userID = myBean.loginUser("ANDY","PASSWD"); System.out.println("Reply from Server: Your userid is " + userID ); CustomerData cd = myBean.getCustomerData(userID); System.out.println ("Andy your details with MyStore are " + cd ); String mgrID = myBean.loginUser("RUSTY","PASSWD"); System.out.println("Reply from Server: Your mgrid is " + mgrID ); ManagerData md = myBean.getManagerData(mgrID); System.out.println ("Rusty your details with MyStore are " + md ); System.out.println("Manager Request : List items out of stock "); items = myBean.getOutOfStockItems(); itemsIterator = items.iterator(); System.out.println("List Of Out Of stock Items "); while ( itemsIterator.hasNext() ) { ItemData itemData= ( ItemData ) itemsIterator.next(); System.out.println ("Item Data " + itemData ); }
�Probar tu Cliente:
- Ahora, para poder probar tu cliente, selecciona el nodo SessionCMPClient.
- Ve al men� de la parte superior y selecciona el icono con el 'hombre corriendo'.
- En �l selecciona Run as y elige Java Application, como se ve en la siguiente figura:
Ahora en tu consola, deber�as obtener como repuestas CALCULATOR y CLOCK, exactamente igual que en esta imagen:

�Ejercicio:
Aqu� tienes un ejercicio para t�. Para seguir m�s all�, debes implementar Supplier como un bean de entidad CMP. Aqu� tienes la lista de tareas:
- Crea un bean CMP llamado Supplier en el paquete au.com.tusc.cmp.
- Implementa el m�todo ejbCreate, pasando todos los atributos como argumentos y asignando esos atributos utilizando m�todos mutadores.
- A�ade un m�todo finder llamado findUserID con la consulta:
query "SELECT OBJECT(b) FROM MyStoreSupplier as b where b.userID = ?1"
y la firma:au.com.tusc.cmp.SupplierLocal findUserID(java.lang.String userID)
Nota:
La firma del m�todo es find<cmp attribute> en lugar de findByPrimaryKey, porque los m�todos finder de atributos que no son claves utilizan esta covenci�n. De acuerdo al tipo de retorno para los m�todos finder ser� Collection o <entity type>, seg�n se especifica en la especificaci�n EJB, secciones 10.5.6 y 10.5.2, respectivamente. - A�ade un m�todo de negocio para obtener los detalles del proveedor con la firma:
public SupplierData getSupplierData()
- A�ade un m�todo de negocio para obtener los �tems de varios proveedores con la firma:
public void requestItem(String itemID, Integer quantity)
- A�ade m�todos de retrollamada, necesarios para seleccionar/deseleccionar el contexto del bean con la firma:
public void setEntityContext(EntityContext ctx) public void unsetEntityContext()
- Despliega el bean Supplier.
- A�ade un campo al bean StoreAcess para almacenar su referencia:
private SupplierLocalHome supplierLocalHome
- En el m�todo ejbCreate de StoreAccess almacena una referencia en la variable supplierLocalHome llamando al m�todo est�tico getLocalHome de supplierUtil.
- A�ade un m�todo de negocio al bean StoreAccess con la firma:
public ItemData getItemData(String itemID)
- A�ade las siguientes etiquetas a nivel de clase para el enlace/referencia en el despliegue:
1. @ejb.ejb-ref ejb-name="Supplier" view-type="local" ref-name="SupplierLocal" 2. @jboss.ejb-ref-jndi ref-name="SupplierLocal" jndi-name="SupplierLocal"
- Prueba tu Bean Supplier ejecutando tu test de cliente creado para Item llamado SessionCMPClient.
Nota:
Todos estos pasos ya los has realizado para implementar el bean Item. Es necesario que implementes este bean porque lo utilizaremos en las p�ginas siguientes: En el caso de que tengas dificultades, aqu� te proporcionamos las clases para que las descargues: |