Crear un Bean Dirigido a Mensaje
Esta capítulo cubre cómo crear un Bean Dirigido por Mensaje (MDB). Creará dos beans MDB, DeliverItems y RequestItems. El primero rellenará los stocks de varios ítems de MyStore, y RequestItems enviará peticiones a varios proveedores para que que envíen ítems que están fuera de stock. El manager de MyStore generará/enviará esta petición.
Nota:
Ambos beans dirigidos por mensajes acceden al bean StoreAccessBean a través de su interface remoto, incluso aunque están en la misma JVM. Esto es porque hemos implementado StoreAccessBean como un bean Remoto, y sólo expone su interface remoto. Sin embargo, en los accesos a los beans Manager y Item, que también son utilizados por estos beans dirigidos por mensaje si podemos utilizar sus interfaces locales ya que están en la misma JVM, y hemos expuesto sus interfaces locales.
|
Crear el Bean MDB RequestItems:
- Ve a Package Explorer expande el nodo del proyecto Mystore, selecciona src y pulsa el botón derecho.
- En el menú que aparece elige New > Lomboz EJB Creation Wizard.
- Introduce au.com.tusc.mdb como el nombre del paquete, RequestItems como el nombre del bean y selecciona el tipo como Message Drive Bean (Queue):
- Pulsa Finish.
Esto creará un paquete llamado au.com.tusc.mdb en src y el bean RequestItemsBean dentro de ese paquete:
Nota:
Los beans dirigidos por mensajes escuchan los mensajes de un productor JMS, que obtiene información de un productor (quizás otro bean) y la trasfieren al bean consumidor. Como es el único responsable de procesar dichos mensajes, no necesita ninguna clase de ayuda del tipo de los interfaces Remote y RemoteHome, las clases de utilidad, las clases DAO, etc. La únicas clases de ayuda que tiene que crear son "objetos de valor inmutable", que son los responsables de contener la información extraída de los mensajes y trasmitirla a los beans.
|
Se crea una etiqueta @ejb.bean que asigna el nombre, el tipo de transación, el tipo de destino y algunas otras propiedades que puedes ver abajo:
Al contrario que los beans anteriores éste tiene un método setMessageContext para configurar el contexto:
Tiene los métodos ejbCreate y ejbRemove al igual que los otros tipos de beans:
Tiene un nuevo método llamado onMessage que es uno de los más importantes para nosotros, es donde escribiremos toda la lógica de negocio:
Una vez que se recibe un mensaje del productor JMS como un objeto Message, se extraen sus datos y se rellena un objeto de valor inmutable con esos datos y luego se transfiere al bean principal. Esto lo cubriremos más tarde.
Ahora, antes de añadir cualquier funcionalidad, crearemos una clase u objeto de valor inmutable para extraer información del mensaje.
Crear un Objeto de Valor Inmutable para RequestItem:
Ya está completo el constructor de RequestItem, ahora nos falta implementar el método onMessage del bean RequestItem.
Implementar el método onMessage:
Este método es responsable de extraer información del mensaje y transferirla al bean principal. Un Manager de MyStore chequeará los ítems que están fuera de stock y genera una petición a los proveedores especificando el itemID y la cantidad necesaria.
- Primero importa los paquetes java.util.ArrayList y java.util.Iterator.
- Añade las siguientes variables para almacenar referencias:
ArrayList outOfStockItems = null;
Iterator itemsIterator = null;
private StoreAccessHome storeAccess = null;
private SupplierLocalHome suppLocalHome = null;
private ItemLocalHome itemLocalHome = null;
- Extrae los datos del mensaje en el objeto de valor inmutable como se muestra abajo:
RequestItem ri = (RequestItem) ((ObjectMessage) message).getObject();
- Añade estas líneas de código para que el manager pueda hacer el login:
StoreAccess access = StoreAccessUtil.getHome().create();
String mgrAccessID = access.loginUser(ri.getUsername(),ri.getPasswd());
- Obtén los ítems con stock 0, llamando a getOutOfStockItems() del bean StoreAccess (que devuelve una Collection):
outOfStockItems = access.getOutOfStockItems();
- Ahora, itera sobre cada ítem, obtén el supplierId asociado con él llamando a los métodos finder del bean Supplier, y finalmente envía el mensaje a ese proveedor llamando al método de negocio requestItem() sobre el bean Supplier:
itemsIterator = outOfStockItems.iterator();
while ( itemsIterator.hasNext() ) {
ItemData itemData= ( ItemData ) itemsIterator.next();
String suppID = itemData.getSupplierID();
SupplierLocal supplier = this.suppLocalHome.findByPrimaryKey(suppID);
Integer quantity = new Integer (ri.getQuantity());
String itemID = ri.getItemID();
supplier.requestItem( itemID, quantity);
}
Abajo puedes ver el código del método onMessage:
Nuestro bean está completo, y sólo nos faltan los descriptores de despliegue para el bean.
Desplegar el Bean RequestItems:
Para desplegar este bean tenemos que añadir unos cuantos descriptores de despliegue. Como se ve abajo, se han añadido cinco etiquetas:

- Primero añade la siguiente etiqueta a nivel de clase en el bean RequestItems, para obtener una referencia a StoreAccessBean, para poder invocar a sus métodos:
@ejb.ejb-ref
ejb-name="StoreAccess"
view-type="remote"
ref-name="StoreAccess"
Esta etiqueta generará los descriptores de despliegue en ejb-jar.xml cuando generes tus clases EJB, ya que este bean de mensaje tiene que autenticarse, antes de transferir la información al bean principal. Generará los siguientes descriptores de despliegue:
- Añade esta otra etiqueta, para obtener una referencia al bean Supplier en este bean:
@ejb.ejb-ref
ejb-name="Supplier"
view-type="local"
ref-name="SupplierLocal"
Esta etiqueta generará los descriptores de despliegue en ejb-jar.xml cuando generes tus clases EJB, ya que este bean de mensaje transfiere información al bean Supplier. Se generarán estos descriptores de despliegue:
Nota:
Otro descriptor que se ha generado es <ejb-name>, que ha sido generado por la etiqueta @ejb.bean que añadió el EJB creation wizard.
Esta etiqueta genera los siguientes descriptores de despliegue en ejb-jar.xml:
|
- Añade la siguiente etiqueta. Esta etiqueta es específica de JBOSS, y se utiliza para registrar el bean dirigido por mensaje con un nombre JNDI, utilizando el formato "queue/name":
@jboss.destination-jndi-name
name="queue/MdbQueue"
Esta etiqueta genera los siguientes descriptores de despliegue en jboss.xml:
- Añade esta otra etiqueta, necesaria para que JBOSS pueda encontrar el bean Supplier utilizando su nombre JNDI:
@jboss.ejb-ref-jndi ref-name="SupplierLocal"
jndi-name="SupplierLocal"
Nota:
Como se explicó en páginas anteriores, esta etiqueta genera descriptores incorrectos dentro de jboss.xml. Para view-type="local" genera una etiqueta <ejb-ref> en vez de <ejb-local-ref>.
|
- Corrige las siguientes etiquetas:
Busca estas etiquetas en jboss.xml y cambialas como <ejb-local-ref> según la siguiente figura:
- Ahora añde esta última etiqueta en el bean StoreAccess, para referenciarlo utilizando su nombre JNDI:
@jboss.ejb-ref-jndi ref-name="StoreAccess"
jndi-name="StoreAccessBean"
Esta etiqueta generará los siguientes descriptores de despliegue en jboss.xml:
Ahora ya está completo nuestro bean RequestItems, añade tu bean y genera las clases EJB:
- Ve al nodo RequestItemsBean en el paquete au.com.tusc.mdb, pulsa con el botón derecho y selecciona Lomboz J2EE... > Add EJB to Module y pulsa Ok.
- Ve al nodo MyStoreMgr en el explorador de paquetes, pulsa con el botón derecho, y selecciona Lomboz J2EE... > Generate EJB classes.
Nota:
Como has regenerado tus clases de nuevo, tendrás que corregir los descriptores de despliegue incorrectos de jboss.xml, dentro de <message-driven> y <session>.
|
- Ahora para desplegar el bean, ve a Lomboz J2EE View, arranca el servidor si no lo está y despliega el bean.
Los mensajes de la consola te dirán el estado del despliegue. Ahora nos falta crear nuestro test de cliente.
Crear el Test de Cliente:
En este caso no nos servirá el Test Client Wizard para crear el test de cliente, porque requiere que seleccionemos un interface Home y un interface EJB, y los beans dirigidos por mensaje no tienen este tipo de interfaces.
Por eso tenemos que escribir una clase y los métodos necesarios para llamar a las operaciones sobre el bean RequestItems.
- Añade una clase llamada RequestMDBClient al paquete au.com.tusc.mdb
- Añade un método llamado getContext con la siguiente firma:
private InitialContext getContext() throws NamingException
- Añade las siguientes líneas de código para obtener el ejemplar de IntialContext:
- Añade un método llamado testMDBBean con la siguiente firma:
public void testMDBBean()
- Ahora implementa este método, utilizando estos pasos:
- Añade un Data Object que se enviará como mensaje.
- Crea una referencia al contexto inicial.
- Crea una referencia a la factoría conexiones.
- Utiliza este contexto para realizar la búsqueda, donde el string de búsqueda es "queue/MdbQueue".
- Crea la QueueConnection.
- Crea el QueueSender.
- Crea la QueueSession para el bean.
- Crea el objeto Message para el Data Object en el mensaje.
- Envía el mensaje.
- Finalmente, envía la sesión, y luego cierra tanto la sesión como la conexión.
Aquí puedes ver un fragmento de código del método testMDBean:
El test de cliente ya está completo, vamos a probarlo!
Probar el Cliente:
- Para probar el cliente, selecciona el nodo RequestMDBClient, ve al menú superior y selecciona el icono del "hombre corriendo".
- En él, selecciona Run as y luego Java Application.
- Ahora, en la consola deberías obtener los siguientes mensajes:
Este mensaje no nos dice si se ha enviado o no el mensaje al bean principal. Para verificar esto, ve a la base de datos utilizando JMX Management Console View > Hypersonic > Invoke Database Manager y ejecuta una consulta sobre la tabla supplier para ver si se ha añadido un mensaje a algún proveedor.
Nota:
Los detalles de cómo acceder a este Database Manager se vieron en la primera página de este tutorial.
|
Como un proveedor llamado Sebastian ha recibido nuestro mensaje, significa que nuestro bean funciona correctamente.
Ejercicio:
Ahora para seguir progresando, por favor completa el siguiente ejercicio para implementar DeliverItems como un bean MD. Aquí tienes la lista de tareas:
- Crea un bean MD lamado DeliverItems en el paquete au.com.tusc.mdb.
- Crea un objeto de valor inmutable llamado DeliverItem en el paquete au.com.tusc.mdb. Añadele algunos atributos e implementa sus métodos accesores y mutadores:
private String username
private String passwd
private String itemID
private int quantity
- Implementa el método onMessage en DeliverItems:
- Añade estas dos variables para almacenar referencias:
private StoreAccessHome storeAccess = null;
private ItemLocalHome itemLocalHome = null;
- Extrae los datos del mensaje en tu objeto de valor inmutable de esta forma:
DelieverItem di = (DeliverItem) ((ObjectMessage) message).getObject();
- Obtén las referencias de los beans StoreAccess e Item:
StoreAccess access = StoreAccessUtil.getHome().create();
itemLocalHome = ItemUtil.getLocalHome();
- LLama al método loginUser de supplier para obtener su userid(accessID) y luego encontrar la ID del proveedor llamado al método getSupplierData:
String suppAcessID = access.loginUser(di.getUsername(), di.getPasswd());
SupplierData sd = access.getSupplierData(suppAccessID);
String suppID = sd.getSupplierID();
- Si suppID no es null, llama al método finder del bean Item para obtener los detalles de los ítems a entregar, extrayendo itemID del mensaje:
ItemLocal item = this.itemLocalHome.findByPrimaryKey(di.getItemID());
- Obtén la ID del proveedor asociada con el ítem encontrado, para poder actualizar el stock:
String itemSuppID = item.getSupplierID();
-
Compara itemSuppID e ItemID, si son iguales actualiza el stock de ese ítem llamado al método fillStock del bean Item:
if ( suppID.equals(itemSuppID)) {
System.out.println ("Delivering items in store now... :");
Integer quantity = new Integer (di.getQuantity());
item.fillStock(quantity);
System.out.println ("Stock of iten after dleivery is :" + item.getItemData());
}
- Añade las siguientes etiquetas para el despliegue a nivel de clase para enlazar/referenciar a Supplier:
1. @ejb.ejb-ref
ejb-name="StoreAccess"
view-type="remote"
ref-name="StoreAccess"
2. @ejb.ejb-ref
ejb-name="Item"
view-type="local"
ref-name="ItemLocal"
3. @jboss.ejb-ref-jndi ref-name="ItemLocal"
jndi-name="ItemLocal"
4. @jboss.ejb-ref-jndi ref-name="StoreAccess"
jndi-name="StoreAccessBean"
5. @jboss.destination-jndi-name
name="queue/DelMdbQueue"
- Despliega el bean DeliverItems.
- Crea un test de cliente llamado DeliverMDBClient en le paquete au.com.tusc.mdb.
- añade un método llamado testMDBBean con la siguiente firma:
public void testMDBBean
- Implementa testMDBBean; aquí tienes unas pistas:
- Añade un Data Object que se envié como mensaje.
- Crea el contexto inicial.
- Crea una factoría de conexiones.
- Utiliza este contexto para realizar la búsqueda JNDI con el string "queue/DelMdbQueue".
- Crea la QueueConnection.
- Crea el QueueSender.
- Crea la QueueSession para el bean.
- Crea el objeto Message y pasále el Data Object en el mensaje.
- Envía el mensaje.
- Finalmente, envía la sesión y cierra la sesión y la conexión.
- Ejecuta el cliente y prueba el bean:
Nota:
Todos estos pasos ya los has realizado para implementar el bean RequestItems. 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:
|