La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

Tema 6 - Enterprise JavaBeans Dr. Diego Lz. de Ipiña Gz. de Artaza

Presentaciones similares


Presentación del tema: "Tema 6 - Enterprise JavaBeans Dr. Diego Lz. de Ipiña Gz. de Artaza"— Transcripción de la presentación:

1 Tema 6 - Enterprise JavaBeans Dr. Diego Lz. de Ipiña Gz. de Artaza http://paginaspersonales.deusto.es/dipina http://paginaspersonales.deusto.es/dipina/cursos/J2EECesine.zip dipina@eside.deusto.es

2 Enterprise JavaBeans Tecnología por excelencia para el desarrollo de componentes en la parte servidora con la plataforma J2EE Deben de conformar a la especificación de J2EE y sólo se pueden ejecutar en un contenedor de EJBs Última especificación EJB 2.1 disponible en: http://java.sun.com/products/ejb/docs.html http://java.sun.com/products/ejb/docs.html Los contenedores de EJBs son lo que hacen a esta tecnología tan atractiva, ya que ofrecen soporte para: Transacciones Seguridad Persistencia … tanto de manera programática como declarativa

3 Beneficios de EJBs Aplicaciones basadas en EJBs son difíciles de desarrollar (tecnología difícil de asimilar), sin embargo: Aplicaciones basadas en EJBs nos permiten concentrarnos en la lógica de negocio, sin preocuparnos de transacciones y connection pooling provista por contenedor Los EJBs son componentes  REUTILIZACIÓN Clara separación entre desarrollo, explotación y administración de una aplicación EJB El contenedor de EJBs gestiona transacciones, detalles de manejo de estado, multi-threading, connection pooling, seguridad y otros detalles de bajo nivel que el desarrollador no necesita conocer.

4 Puesto de EJB container en una aplicación de empresa Web Application Web Container Enterprise Bean EJB Container Browser Database

5 ¿Cuando usar EJBs? No siempre, para simples aplicaciones web con servlets y JSPs sobra Si necesitas alta disponibilidad y escalabilidad entonces usa EJBs JDO y Hibernate

6 Tecnologías usadas por EJBs EJBs hacen uso: RMI RMI-IIOP JNDI (Java Naming and Directory Interface) JMS (Java Messaging Service)

7 Categorías de EJBs 3 tipos de Enterprise JavaBeans: Entity Beans: representan datos de negocio y proveen acceso a datos a través de métodos Session Beans: modelan procesos de negocio que son accedidos de manera síncrona Message-driven Beans: modelan procesos de negocio que son accedidos de manera asíncrona, permiten el uso de JMS desde EJBs

8 Contenedores de EJBs JBoss: http://www.jboss.orghttp://www.jboss.org Contenedor más popular en el mundo y open source Download: http://prdownloads.sourceforge.net/jboss/jboss- 3.2.3.zip?download http://prdownloads.sourceforge.net/jboss/jboss- 3.2.3.zip?download Documentación: http://www.jboss.org/modules/html/docs/jbossj2e e.pdf http://www.jboss.org/modules/html/docs/jbossj2e e.pdf Otros muy conocidos y muy usados comercialmente: BEA WebLogic, IBM Websphere o Oracle10g

9 Escribiendo tu primer EJB Seleccionar un contenedor de EJBs: vamos a usar jboss-4.0.1sp1 disponible en http://www.jboss.org http://www.jboss.org Pasos a seguir para desarrollar un EJB: Escribir la clase del bean Escribir el descriptor de explotación (deployment descriptor) Crear un fichero de explotación Desarrollar el bean Escribir la aplicación cliente para probar el bean Ejemplo  “EJB que suma dos números”

10 Escribiendo el bean Adder I Crea un directorio con el nombre de la aplicación ( adder ) y crea un subdirectorio en él llamado es/deusto/ejb donde guardarás los ficheros AdderHome.java, Adder.java y AdderBean.java y otro llamado META-INF donde guardaras un fichero de configuración XML. package es.deusto.ejb; import java.rmi.RemoteException; import javax.ejb.CreateException; import javax.ejb.EJBHome; public interface AdderHomeRemote extends EJBHome { AdderRemote create() throws RemoteException, CreateException; }

11 Escribiendo el bean Adder II package es.deusto.ejb; import javax.ejb.EJBObject; import java.rmi.RemoteException; public interface AdderRemote extends EJBObject { public int add(int a, int b) throws RemoteException; }

12 Escribiendo el bean Adder III package es.deusto.ejb; import java.rmi.RemoteException; import javax.ejb.SessionBean; import javax.ejb.SessionContext; public class AdderBean implements SessionBean { public int add(int a, int b) { System.out.println("from AdderBean"); return (a + b); } public void ejbCreate() {} public void ejbRemove() {} public void ejbActivate() {} public void ejbPassivate() {} public void setSessionContext(SessionContext sc) {} }

13 Escribiendo el deployment descriptor: META-INF/ejb-jar.xml Your first EJB application Adder Application AdderEJB es.deusto.ejb.AdderHomeRemote es.deusto.ejb.AdderRemote es.deusto.ejb.AdderBean Stateless Bean

14 Creando un archivo (.jar) de explotación 1. cd 2. adder-dir>set CLASSPATH= \server\default\lib\jboss-j2ee.jar;. 3. adder-dir>javac es\deusto\ejb\*.java 4. adder-dir>jar cvf adder.jar es/deusto/ejb/* META-INF/ejb-jar.xml¡ 5. adder-dir>copy adder.jar \server\default\deploy

15 Explotación del EJB adder Al copiar el fichero.jar a: \server\default\deploy, la siguiente información será visualizada si JBoss es arrancado: 18:08:57,970 INFO [MainDeployer] Starting deployment of package: file:%JBOSS_HOME%/server/default/deploy/adder.jar 18:08:58,140 INFO [EjbModule] Creating 18:08:58,160 INFO [EjbModule] Deploying AdderEJB 18:08:58,280 INFO [EjbModule] Created 18:08:58,280 INFO [EjbModule] Starting 18:08:58,341 INFO [EjbModule] Started 18:08:58,341 INFO [MainDeployer] Deployed package: file:/F:/DocMan/tools/jboss-3.0.6_tomcat- 4.1.18/server/default/deploy/adder.jar 18:08:58,341 INFO [MainDeployer] Starting deployment of package: file:/F:/DocMan/tools/jboss-3.0.6_tomcat- 4.1.18/server/default/deploy/ejb-management.jar 18:08:58,451 INFO [EjbModule] Creating 18:08:58,491 INFO [EjbModule] Deploying MEJB 18:08:58,511 INFO [EjbModule] Created 18:08:58,511 INFO [EjbModule] Starting 18:08:58,531 INFO [EjbModule] Started …

16 EJBs en detalle Un Enterprise Java Bean no consta de una sola clase sino que también tiene dos (realmente cuatro, si contamos que pueden ser locales y remotos) interfaces: HomeRemote/HomeLocal interfaces Remote/Local interfaces Se puede implementar o bien una tupla HomeRemote/Remote, o HomeLocal/Local o las 4 a la vez Los interfaces locales fueron añadidos en EJB 2.0 La clase bean contiene la implementación de las reglas de negocio Las clases home y remote sirven como entrada a un bean de empresa desde un cliente Todo EJB se construye implementando o extendiendo clases del paquete javax.ejb.

17 El interfaz Home Lleva a cabo operaciones de ciclo de vida: crear, buscar y eliminar un EJB Debe extender la interfaz javax.ejb.EJBHome o javax.ejb.EJBLocalHome EJBHome deriva de java.rmi.Remote, es usado para identificar interfaces cuyos métodos pueden ser invocados desde una virtual machine no local

18 El interfaz Remote Ofrece los métodos de negocio disponibles a clientes remotos Un interfaz remoto debe extender el interfaz javax.ejb.EJBObject, el cual a su vez también deriva de java.rmi.Remote La versión local de Remote deriva de javax.ejb.EJBLocalObject

19 La clase del bean de empresa Provee la implementación de los métodos de ciclo de vida en la interfaz home así como los métodos de negocio en la interfaz remota Un EJB puede ser: Session bean que implementa javax.ejb.SessionBean Entity bean que implementa javax.ejb.EntityBean Message-driven bean implementa javax.ejb.MessageDrivenBean Un EJB debe ofrecer la implementación de los métodos callback invocados por el contenedor y definidos en javax.ejb.SessionBean o javax.ejb.EntityBean ( ejbCreate, ejbPostCreate, ejbFind, etc.)

20 Descriptor de explotación Especifica meta-información para el contenedor de EJB Contiene la siguiente información: El nombre del EJB El tipo El nombre completo del home interface El nombre completo del remote interface El nombre completo de la clase que implementa el bean

21 Escribiendo aplicaciones cliente Un cliente de un EJB no invoca métodos directamente en el bean Solamente puede ver los interfaces home y remote Las aplicaciones cliente acceden al bean de empresa a través de JNDI Vamos a ver dos ejemplos de aplicación cliente: Clase simple llamada BeanClient JSP que demuestra como usar un bean de empresa desde un servlet o JSP

22 Java Naming and Directory Interface (JNDI) I Un servicio de nombre permite encontrar un objeto dado su nombre DNS: nombres dominio  direcciones IP EJB: nombre EJB  referencia a EJB Para comunicarse con un EJB una aplicación cliente sólo necesita saber el nombre Un servicio de directorio extiende un servicio de nombres puesto que asocia atributos que describen el objeto El paquete javax.naming ofrece la funcionalidad de JNDI

23 Java Naming and Directory Interface (JNDI) II javax.naming.Context Ofrece el método: public Object lookup (String name) throws javax.naming.NamingException javax.naming.InitialContext Implementa la interfaz Context, nos permite desde un programa buscar un EJB

24 Obteniendo una referencia a un EJB I 1. Crear un objeto java.util.Properties 2. Añadir las propiedades (la clase que implementa la factoría del naming service y su localización) a java.util.Properties 3. Construcción de un objeto javax.naming.InitialContext 4. Uso del método lookup de javax.naming.Context para obtener una referencia al home del bean, pasándole el nombre del bean

25 Obteniendo una referencia a un EJB II Properties properties = new Properties(); properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); properties.put(Context.PROVIDER_URL, "localhost:1099"); try { // Get an initial context InitialContext jndiContext = new InitialContext(properties); // Get a reference to the Bean Object ref = jndiContext.lookup("AdderEJB"); } catch (NamingException e) { }

26 Creando una instancia de un bean Usando JNDI hemos obtenido una referencia al home interface del bean Para llamar al método create del home interface de Adder tenemos que hacer un downcast Para conformar con RMI-IIOP en vez de (AdderHomeRemote) se utiliza el método narrow de la clase javax.rmi.PortableRemoteObject : AdderHomeRemote home = (AdderHomeRemote)PortableRemoteObject.n arrow(ref, AdderHomeRemote.class); Una vez obtenido el objeto home podemos crearlo usando el método create : AdderRemote adder = home.create(); Finalmente podemos usar ese bean: int i = adder.add(2, 5);

27 Una clase cliente para Adder I package es.deusto.client; import javax.naming.*; import javax.rmi.PortableRemoteObject; import java.util.Properties; import es.deusto.ejb.AdderRemote; import es.deusto.ejb.AdderHomeRemote; public class BeanClient { public static void main(String[] args) { // preparing properties for constructing an InitialContext object Properties properties = new Properties(); properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); properties.put(Context.PROVIDER_URL, "localhost:1099"); try { // Get an initial context InitialContext jndiContext = new InitialContext(properties); System.out.println("Got context");

28 Una clase cliente para Adder II // Get a reference to the Bean Object ref = jndiContext.lookup("AdderEJB"); System.out.println("Got reference"); // Get a reference from this to the Bean's Home interface AdderHomeRemote home = (AdderHomeRemote) PortableRemoteObject.narrow (ref, AdderHomeRemote.class); // Create an Adder object from the Home interface AdderRemote adder = home.create(); System.out.println ("2 + 5 = " + adder.add(2, 5)); } catch(Exception e) { System.out.println(e.toString()); }

29 Compilando y ejecutando BeanClient 1. adder-dir>set CLASSPATH= \client\jbossall-client.jar; \client\log4j.jar;. 2. adder-dir>javac es\deusto\client\BeanClient.java 3. adder-dir>java es.deusto.client.BeanClient 4. Respuesta: Got context Got reference 2 + 5 = 7

30 Llamando a adder desde un JSP I <% // preparing a Properties object for constructing // an initial context Properties properties = new Properties(); properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); properties.put(Context.PROVIDER_URL, "localhost:1099"); try { // Get an initial context InitialContext jndiContext = new InitialContext(properties); System.out.println("Got context");

31 Llamando a adder desde un JSP II // Get a reference to the Bean Object ref = jndiContext.lookup("Adder"); System.out.println("Got reference"); // Get a reference from this to the Bean's Home interface AdderHome home = (AdderHome) PortableRemoteObject.narrow (ref, AdderHome.class); // Create an Adder object from the Home interface Adder adder = home.create(); out.println ("2 + 5 = " + adder.add(2, 5)); } catch(Exception e) { System.out.println(e.toString()); } %>

32 Instalando adder.ear en Jboss I Necesario crear un ‘enterprise archive’.ear que contiene: Adder.war  parte web de nuestra aplicación (servlets/jsps) Adder-ejb.jar  parte de los EJBs Application.xml  deployment descriptor que documenta la relación entre el.war y el.jar de esta aplicación

33 Instalando adder.ear en Jboss II Adder This is the implementaion of the Adder application adder-ejb.jar adder.war /

34 Instalando adder.ear en Jboss III adder-ejb.jar  contiene todas las clases correspondientes a los EJBs + ejb-jar.xml (deployment descriptor de EJBs) adder.war  contiene todos los JSPs y servlets + web.xml + clases clientes para comunicarse con EJBs

35 Instalando adder.ear en Jboss IV Usamos magia de Ant para generar el fichero.ear

36 Session Beans Es un bean de empresa que implementa lógica de negocio para sus clientes Puede realizar operaciones Procesar ordenes Encriptar y desencriptar datos, Buscar datos en una base de datos, etc. Siguiendo patrón de diseño Fachada, los sesión beans son los componentes con los que se comunican servlets y JSPs Los beans de sesión viven tanto tiempo como el cliente que los usa Incluso a veces más tiempo dado que el contenedor los coloca en un pool de beans

37 Stateful y Stateless Session Beans Un stateful session bean está asociado con un cliente único Retiene información específica a un cliente Mantiene “estado conversacional” Análogo a javax.servlet.http.HttpSession Passivation es el proceso a través del cual el estado conversacional de un stateful session bean es transferido a almacenamiento secundario Activation es el proceso opuesto Un stateless session bean NO es específico a un cliente Son muy buenos para conseguir aplicaciones escalables, se guardan en un pool y son reutilizables por cualquier cliente

38 Escribiendo un Session Bean Necesitamos las siguientes clases: El home interface El remote interface La clase sesión bean La razón de existencia de los interfaces home y remote es que el cliente no crea el bean directamente, y tampoco invoca el método de un sesión bean directamente.

39 Interfaz javax.ejb.SessionBean Los cuatro métodos que provee son: public void ejbActivate throws javax.ejb.EJBException, java.rmi.RemoteException El contenedor invoca este método cuando activa un sessión bean que había sido ‘pasivado’ public void ejbPassivate() throws javax.ejb.EJBException, java.rmi.RemoteException El contenedor lo invoca cuando el bean se pasiva public void ejbRemove() throws javax.ejb.EJBException, java.rmi.RemoteException; El contenedor invoca este método cuando el cliente invoca en Remote remove() o un time-out en el session object es alcanzado public void setSessionContext(SessionContext context) throws javax.ejb.EJBException, java.rmi.RemoteException El contenedor invoca este método después de que una instancia del bean se crea. Suele ser conveniente cachear este objeto en una variable del bean

40 El interfaz javax.ejb.SessionContext Provee algunos métodos útiles para obtener información acerca de: el cliente realizando una invocación, el objeto home asociado, el entorno, etc: getEJBHome(), getEJBLocalHome(), getPrimaryKey(), isIdentical(), getEJBLocalObject(), getEJBObject(), getMessageContext()

41 Como guardar referencias a un stateful session bean desde un JSP Usar objeto HttpSession HttpSession session = request.getSession(true), Session.setAttribute(“cart”, cartBean); … Cart cartBean = (Cart)session.getAttribute(“car t”)

42 El deployment descriptor de un session bean Toda aplicación EJB debe tener un deployment descriptor, cuyo elemento raiz es y contiene un nodo llamado del que cuelgan todos los beans declarados en un aplicación Cada session bean se registra debajo del elemento, pudiendo contener los siguientes subelementos: description, display-name, small-icon, large-icon ejb-name  nombre dado al EJB home/local-home  el nombre completo del home/local interfaz del bean remote/local  el nombre completo del home/local interfaz del bean ejb-class  el nombre completo de la clase implementando el bean transaction-type, env-entry, etc.

43 Deployment descriptor de la aplicación I The Search Bean for Tassie Online Bookstore Search Bean Search es.deusto.bookstore.ejb.SearchHomeRemote es.deusto.bookstore.ejb.SearchRemote es.deusto.bookstore.ejb.SearchBean Stateless Bean

44 Deployment descriptor de la aplicación II BookDetails es.deusto.bookstore.ejb.BookDetailsHomeRemote es.deusto.bookstore.ejb.BookDetailsRemote es.deusto.bookstore.ejb.BookDetailsBean Stateless Bean Cart es.deusto.bookstore.ejb.CartHomeRemote es.deusto.bookstore.ejb.CartRemote es.deusto.bookstore.ejb.CartBean Stateful Bean

45 Entity Beans I Es un componente de datos que persiste datos permanentemente a almacenamiento secundario, e.j. BD Contiene campos y métodos Guarda datos en los campos Realiza operaciones sobre los campos con los métodos Vista de un registro en una tabla de una base de datos Aísla el desarrollo de aplicaciones del acceso a BD

46 Entity Beans II El contenedor de EJBs lleva a cabo la sincronización y otras tareas para mantener los datos Provee servicios que hacen mucho más sencillo manejar datos representados por entity beans Mientras que un session mean modela un proceso de negocio, un entity bean modela datos de negocio Además un entity bean sobrevive una caída del servidor Dos tipos: Bean-managed persistence (BMP) Container-managed persistence (CMP) Los ficheros necesarios para construir un entity bean son: Interfaz Remote/Local Interfaz HomeRemote/HomeLocal La clase primaria La clase que implementa el entity bean El deployment descriptor

47 La interfaz remota/local Esta interfaz permite a un cliente acceder a la instancia de un bean de entidad Debe extender: javax.ejb.EJBObject para interfaces remotos javax.ejb.EJBLocalObject para interfaces locales El cliente puede usar esta interfaz para hacer: Obtener la interfaz home para el bean de entidad Eliminar el bean de entidad Obtener su clave primaria Ejemplo: public interface ProductRemote extends javax.ejb.EJBObject { double getPrice(int productId) throws java.rmi.RemoteException; int getCategory(int productId) throws java.rmi.RemoteException; }

48 La interfaz home I Un cliente puede utilizar esta interfaz para: Crear un bean de entidad Eliminarlo Buscar un bean de entidad Esta interfaz provee métodos de creación, eliminación y búsqueda Una interfaz home ( javax.ejb.EJBHome o javax.ejb.EJBHomeLocal ) puede definir varios métodos create : public interface ProductHomeRemote extends javax.ejb.EJBHome { public ProductRemote create(int productId, String productName, String description, double price) throws java.rmi.RemoteException, javax.ejb.CreateException; }

49 La interfaz home II Como un bean de entidad representa una pieza de datos, una de las operaciones más frecuentes es encontrar un bean de datos: Para eso se usan los métodos finder Al menos el método findByPrimaryKey debe definirse Otros métodos también pueden definirse El método findAll Si un método finder devuelve varios resultados el tipo de datos devuelto deberá ser java.util.Collection public interface ProductHomeLocal extends javax.ejb.EJBLocalHome { public ProductLocal findByPrimaryKey(Integer productId) throws javax.ejb.EJBException, javax.ejb.FinderException; public Collection findByProductName(String productName) throws javax.ejb.EJBException, javax.ejb.FinderException; public Collection findAll() throws FinderException, EJBException; } El método remove permite borrar una bean de entidad: void remove(Object primaryKey) throws jajvax.ejb.EJBException, javax.ejb.RemoveException;

50 El bean de entidad Debe implementar el interfaz javax.ejb.EntityBean Implementa los métodos de ciclo de vida definidos en la interfaz home Y métodos callback llamados por el contenedor

51 La interfaz javax.ejb.EntityBean Los métodos a definir son: public void ejbActivate()  invocado por el contenedor cuando la entidad es recuperada del pool pasa a asociarse con un objeto entidad específico public void ejbPassivate()  invocado por el contenedor cuando la asociación entre una instancia de un bean con su objeto entidad está a punto de romperse public void ejbLoad()  invocado por el contenedor para sincronizar el estado del bean de los datos subyacentes public void ejbStore()  opuesto a ejbLoad public void ejbRemove()  invocado por el contenedor cuando una instancia de un bean está a punto de borrarse public void setEntityContext(EntityContext context)  invocado después de que la instancia del bean haya sido creada public void unsetEntityContext()  opuesto a setEntityContext Los métodos ejbStore y ejbLoad permiten la pasivación y activación del estado de un bean de entidad a y desde una BD

52 Métodos Create/Find/remove en un bean de entidad I Todo método create/find/remove en una interfaz home es transformado en un método ejbCreate/ejbFind/ejbRemove en la clase que implementa el bean Los métodos ejbCreate/ejbFind devuelven un valor correspondiente a la clave primaria de un bean (o colección con claves primarias en métodos find) en vez de una referencia a la interfaz remota/local del bean como en la interfaz home Todos los métodos definidos en el interfaz remote o local tienen los mismos tipos de datos de retorno y listas de argumentos en la implementación del bean

53 Métodos Create/Find/remove en un bean de entidad II public class ProductBean implements javax.ejb.EntityBean { public ProductPK ejbCreate(int productId, String productName, String description, double price) throws javax.ejb.EJBException, javax.ejb.CreateException { this.productId = new Integer(productId) this.productName = productName; this.description = description; this.price = price; return this.productId; } public ProductPK ejbFindByPrimaryKey(ProductPK primaryKey) throws EJBException, FinderException {... } public void ejbRemove() throws EJBException, RemoveExcepton {... } public double getPrice() { return this.price; }... }

54 La interfaz javax.ejb.EntityContext Define dos métodos: javax.ejb.EJBObject getEJBObject() throws IllegalStateException Devuelve una refencia al objecto de empresa asociado con una instancia del bean de entidad Object getPrimaryKey() throws IllegalStateException Devuelve la clave primaria de un bean

55 Dos tipos de bean de entidad Dependiendo del modo en que los datos son hechos persistentes encontramos: Bean de entidad con bean-managed persistence (BMP) El programador tiene que escribir el código SQL necesario para guardar/recuperar estado bean Bean de entidad con container-managed persistence (CMP) La tarea de guardar/recuperar datos es llevada a cabo por el contenedor de EJBs Instrucciones sobre cómo llevar a cabo esa tarea son dados al contenedor en el deployment descriptor

56 Escribiendo un bean de entidad BMP Crear un BMP que representa a un producto Pasos a seguir: 1. Crear una tabla de una base de datos, con los campos ProductId ( int ), ProductName ( string ), Description ( string ) y Price ( string )  ProductsBD 2. Obtener un driver JDBC para tu base de datos. En nuestro caso usaremos el ODBC-JDBC bridge para acceder a Access 3. Configurar JBoss para usar tu base de datos preferida (lo haremos con el ejemplo en CMP) Dado que usamos un driver que viene con la distribución estándar de J2SE, no es necesario ninguna configuración adicional 4. Preparar la estructura de directorio adecuada para tu proyecto. es.deusto.ejb en nuestro caso

57 La interfaz remota ProductRemote package es.deusto.ejb; import javax.ejb.EJBObject; import java.rmi.RemoteException; /* this is the remote interface for Product */ public interface ProductRemote extends EJBObject { public Integer getProductId() throws RemoteException; public void setProductId(Integer productId) throws RemoteException; public double getPrice() throws RemoteException; public void setPrice(double price) throws RemoteException; public String getProductName() throws RemoteException; public void setProductName(String productName) throws RemoteException; public String getDescription() throws RemoteException; public void setDescription(String desc) throws RemoteException; }

58 La interfaz home ProductHomeRemote package es.deusto.ejb; import java.rmi.RemoteException; import javax.ejb.FinderException; import javax.ejb.CreateException; import javax.ejb.EJBHome; import java.util.Collection; public interface ProductHomeRemote extends EJBHome { public ProductRemote create(int productId, String productName, String description, double price) throws RemoteException, CreateException; public ProductRemote findByPrimaryKey(Integer key) throws RemoteException, FinderException; public Collection findByName(String name) throws RemoteException, FinderException; public Collection findAll() throws RemoteException, FinderException; }

59 El bean de entidad ProductBean I package es.deusto.ejb; import java.sql.*; import java.util.Properties; import java.util.Collection; import java.util.Vector; import java.rmi.RemoteException; import javax.ejb.EntityBean; import javax.ejb.EntityContext; import javax.ejb.CreateException; import javax.ejb.FinderException; import javax.ejb.ObjectNotFoundException; import javax.naming.InitialContext; import javax.naming.Context; import javax.naming.NamingException; public class ProductBean implements EntityBean { EntityContext context; Integer productId; String productName; String description; double price; Connection conn = null; public Integer getProductId() { System.out.println("getProductId: " + this.productId); return this.productId; } public void setProductId(Integer id) { this.productId = id; }

60 El bean de entidad ProductBean II public String getProductName() { System.out.println("getProductName " + this.productName); return this.productName; } public void setProductName(String productName) { this.productName = productName; } public String getDescription() { System.out.println("getDescription: " + this.description); return this.description; } public void setDescription(String description) { this.description = description; } public double getPrice() { System.out.println("getPrice: " + this.price); return this.price; } public void setPrice(double price) { this.price = price; }

61 El bean de entidad ProductBean III public Integer ejbCreate(int productId, String productName, String description, double price) throws RemoteException, CreateException { System.out.println("ejbCreate"); this.setProductId(new Integer(productId)); this.setProductName(productName); this.setDescription(description); this.setPrice(price); Connection con = null; PreparedStatement ps = null; try { String sql = "INSERT INTO Products" + " (ProductId, ProductName, Description, Price)" + " VALUES" + " (?, ?, ?, ?)"; con = getConnection(); ps = con.prepareStatement(sql); ps.setInt(1, this.getProductId().intValue()); ps.setString(2, this.getProductName()); ps.setString(3, this.getDescription()); ps.setDouble(4, this.getPrice()); ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally { try { if (ps != null) ps.close(); if (con != null)con.close(); } catch (SQLException e) {} } return this.getProductId(); }

62 El bean de entidad ProductBean IV public void ejbPostCreate(int productId, String productName, String description, double price) throws RemoteException, CreateException { System.out.println("ejbPostCreate"); } public Integer ejbFindByPrimaryKey(Integer primaryKey) { throws RemoteException, FinderException { System.out.println("ejbFindByPrimaryKey"); Connection con = null; PreparedStatement ps = null; ResultSet rs = null; try { String sql = "SELECT ProductName" + " FROM Products" + " WHERE ProductId=?"; con = getConnection(); ps = con.prepareStatement(sql); ps.setInt(1, primaryKey.intValue()); rs = ps.executeQuery(); if (rs.next()) { rs.close(); ps.close(); con.close(); return primaryKey; } } catch (SQLException e) { e.printStackTrace(); } finally { try { if (rs != null) rs.close(); if (ps != null) ps.close(); if (con != null) con.close(); } catch (SQLException e) {} } throw new ObjectNotFoundException(); }

63 El bean de entidad ProductBean V public Collection ejbFindByName(String name) throws RemoteException, FinderException { System.out.println("ejbFindByName"); Vector products = new Vector(); Connection con = null; PreparedStatement ps = null; ResultSet rs = null; try { String sql = "SELECT ProductId " + " FROM Products" + " WHERE ProductName=?"; con = getConnection(); ps = con.prepareStatement(sql); ps.setString(1, name); rs = ps.executeQuery(); while (rs.next()) { int productId = rs.getInt(1); System.out.println("Añadiendo producto: " + productId); products.addElement(new Integer(productId)); } } catch (SQLException e) { e.printStackTrace(); } finally { try { if (rs != null) rs.close(); if (ps != null) ps.close(); if (con != null) con.close(); } catch (SQLException e) {} } return products; }

64 El bean de entidad ProductBean VI public Collection ejbFindAll() throws RemoteException, FinderException { System.out.println("ejbFindAll"); Vector products = new Vector(); Connection con = null; PreparedStatement ps = null; ResultSet rs = null; try { String sql = "SELECT * " + " FROM Products"; con = getConnection(); ps = con.prepareStatement(sql); rs = ps.executeQuery(); while (rs.next()) { int productId = rs.getInt(1); System.out.println("**********+Product id retrieved: " + productId); products.addElement(new Integer(productId)); } } catch (SQLException e) { e.printStackTrace(); } finally { try { if (rs != null) rs.close(); if (ps != null) ps.close(); if (con != null) con.close(); } catch (SQLException e) {} } return products; }

65 El bean de entidad ProductBean VII public void ejbRemove() throws RemoteException { System.out.println("ejbRemove"); Connection con = null; PreparedStatement ps = null; try { String sql = "DELETE FROM Products" + " WHERE ProductId=?"; Integer key = (Integer) context.getPrimaryKey(); con = getConnection(); ps = con.prepareStatement(sql); ps.setInt(1, key.intValue()); ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally { try { if (ps != null) ps.close(); if (con != null) con.close(); } catch (SQLException e) {} } public void ejbActivate() {System.out.println("ejbActivate");} public void ejbPassivate() {System.out.println("ejbPassivate");}

66 El bean de entidad ProductBean VIII public void ejbLoad() { System.out.println("ejbLoad"); Connection con = null; PreparedStatement ps = null; ResultSet rs = null; try { String sql = "SELECT ProductName, Description, Price" +" FROM Products" + " WHERE ProductId=?"; con = getConnection(); ps = con.prepareStatement(sql); Integer primaryKey = (Integer)context.getPrimaryKey (); ps.setInt(1, primaryKey.intValue()); rs = ps.executeQuery(); if (rs.next()) { this.productName = rs.getString(1); System.out.println("Product name: " + this.productName); this.description = rs.getString(2); System.out.println("Description: " + this.description); this.price = rs.getDouble(3); System.out.println("Price: " + this.price); } } catch (SQLException e) { e.printStackTrace(); } finally { try { if (rs != null) rs.close(); if (ps != null) ps.close(); if (con != null) con.close(); } catch (SQLException e) {} }

67 El bean de entidad ProductBean IX public void ejbStore() { System.out.println("ejbStore"); Connection con = null; PreparedStatement ps = null; try { String sql = "UPDATE Products" + " SET ProductName=?, Description=?, Price=?" + " WHERE ProductId=?"; Integer key = (Integer) context.getPrimaryKey(); con = getConnection(); ps = con.prepareStatement(sql); ps.setString(1, this.productName); ps.setString(2, this.description); ps.setDouble(3, this.price); ps.setInt(4, key.intValue()); ps.executeUpdate(); } catch (SQLException e) {e.printStackTrace();} finally { try { if (ps != null) ps.close(); if (con != null) con.close(); } catch (SQLException e) { } } public void setEntityContext(EntityContext context) { System.out.println("setEntityContext"); this.context = context; } public void unsetEntityContext() { System.out.println("unsetEntityContext"); context = null; }

68 El bean de entidad ProductBean X public Connection getConnection() { String dbUrl = null; String userName = null; String password = null; Context initialContext; Context environment; Connection connection = null; try { initialContext = new InitialContext(); environment = (Context) initialContext.lookup("java:comp/env"); dbUrl = (String) environment.lookup("dbUrl"); userName = ((String) environment.lookup("dbUserName")).trim(); password = ((String) environment.lookup("dbPassword")).trim(); } catch (NamingException e) { e.printStackTrace(); } try { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); } catch (ClassNotFoundException cnfe) { System.out.println("ClassNotFoundException: " + cnfe.getMessage()); cnfe.printStackTrace(System.out); } try { System.out.println("Obtaining connection: " + dbUrl + ": " + userName + ": " + password); connection = DriverManager.getConnection(dbUrl, userName, password); System.out.println("Connection obtained: " + connection); } catch (SQLException e) { e.printStackTrace(); } return connection; }

69 El bean de entidad ProductBean IX La url, nombre de usuario, contraseña usados para conectarse a la base de datos son recuperados del deployment descriptor Para ello usamos JNDI, y recuperamos los valores especificados en el fichero XML a través del objeto InitialContext initialContext = new InitialContext() Environment = (Context) initialContext.lookup(“java:comp/env”); dbUrl = (String)environment.lookup(“dbUrl”); Hay tres métodos de búsqueda: findByPrimaryKey, findByName y findAll ejbFindByPrimaryKey devuelve el objeto identificado por la clave primaria pasada o javax.ejb.ObjectNotFoundException ejbFindByName devuelve una colección de productos donde el nombre contiene la clave dada ejbFindAll devuelve una lista con todos los productos

70 Deployment Descriptor Your first EJB application Products Application BMPProduct es.deusto.ejb.ProductHomeRemote es.deusto.ejb.ProductRemote es.deusto.ejb.ProductBean Bean java.lang.Integer false dbUrl java.lang.String jdbc:odbc:ProductsBD dbUserName java.lang.String dbPassword java.lang.String

71 Aplicación cliente I package es.deusto.client; import javax.naming.*; import javax.rmi.PortableRemoteObject; import java.util.Properties; import java.util.Collection; import java.util.Iterator; import es.deusto.ejb.ProductRemote; import es.deusto.ejb.ProductHomeRemote; public class BMPProductClient { public static void main(String[] args) { // preparing properties for constructing an InitialContext object Properties properties = new Properties(); properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); properties.put(Context.PROVIDER_URL, "localhost:1099"); try { // Get an initial context InitialContext jndiContext = new InitialContext(properties); System.out.println("Got context"); // Get a reference to the Bean Object ref = jndiContext.lookup("BMPProduct"); System.out.println("Got reference");

72 Aplicación cliente II // Get a reference from this to the Bean's Home interface ProductHomeRemote home = (ProductHomeRemote) PortableRemoteObject.narrow(ref, ProductHomeRemote.class); // Create an Interest object from the Home interface home.create(11, "Franklin Spring Water", "400ml", 2.25); home.create(12, "Franklin Spring Water", "600ml", 3.25); home.create(13, "Choco Bar", "Chocolate Bar 200g", 2.95); home.create(14, "Timtim Biscuit", "Biscuit w. mint flavor, 300g", 9.25); ProductRemote product = home.create(15, "Supermie", "Instant Noodle", 1.05); product.remove(); Collection products = home.findByName("Franklin Spring Water"); //Collection products = home.findAll(); for (Iterator iter=products.iterator(); iter.hasNext();) { product = (ProductRemote) iter.next(); System.out.println("Id: " + product.getProductId()); System.out.println("Product Name: " + product.getProductName()); System.out.println("Description: " + product.getDescription()); System.out.println("Price: " + product.getPrice()); } } catch (Exception e) { System.out.println(e.toString()); }

73 Compilación/ejecución de EJB Product Utilizar ant para generar un product.ear que se copiará a %JBOSS_HOME%\server\default\deploy Ejecutar cliente: set CLASSPATH=%JBOSS_HOME%\client\jbossall- client.jar;%PRODUCT_APP_HOME%\build\products-ejb.jar;. java es.deusto.client.BMPProductClient Resultado: Got context Got reference Id: 11 Product Name: Franklin Spring Water Description: 400ml Price: 2.25 Id: 12 Product Name: Franklin Spring Water Description: 600ml Price: 3.25

74 Escribiendo un bean de entidad CMP Son más fáciles de escribir que BMPs Un bean de entidad CMP delega todas las tareas relacionadas con el acceso a una BD al contenedor No hay necesidad de implementar métodos ejbStore y ejbLoad Incluso los métodos finder son implementados por el contenedor en base a los datos especificados en el deployment descriptor Menos trabajo de codificación pero más de declaración Es necesario configurar tu contenedor de EJBs con tu base de datos de preferencia En este caso vamos a usar hsqldb

75 Hypersonic SQL (hsqldb) I Url: http://hsqldb.sourceforge.net/http://hsqldb.sourceforge.net/ La fuente de datos configurada por defecto con Jboss es hsqldb Ficheros de configuración de fuentes de datos en JBoss: %JBOSS_HOME%\server\default\deploy\hsqldb-ds.xml %JBOSS_HOME%\server\default\conf\standardjbosscmp- jdbc.xml Para ver contenidos de DB ejecutar: java -cp hsqldb.jar org.hsqldb.util.DatabaseManager Conectarse como: jdbc:hsqldb:%JBOSS_HOME%/server/default/data/hypersonic/localDB Type: Database engine standalone

76 Hypersonic SQL (hsqldb) II

77 Pasos para desarrollar un CMP 1. Declarar interfaz remota/local que define contrato entre los clientes y el EJB 2. Declarar interfaz home remota o local para acceder a los métodos de ciclo de vida del EJB 3. Implementar EJB 4. Actualizar ejb-jar.xml with metadata para el EJB creado

78 CMPProductRemote package es.deusto.ejb; import javax.ejb.EJBObject; import java.rmi.RemoteException; /* this is the remote interface for Product */ public interface CMPProductRemote extends EJBObject { public void setProductId(Integer productId) throws RemoteException; public Integer getProductId() throws RemoteException; public void setPrice(double price) throws RemoteException; public double getPrice() throws RemoteException; public void setProductName(String productName) throws RemoteException; public String getProductName() throws RemoteException; public void setDescription(String description) throws RemoteException; public String getDescription() throws RemoteException; }

79 CMPProductHomeRemote package es.deusto.ejb; import java.rmi.RemoteException; import javax.ejb.FinderException; import javax.ejb.CreateException; import javax.ejb.EJBHome; import java.util.Collection; public interface CMPProductHomeRemote extends EJBHome { public CMPProductRemote create(int productId, String productName, String description, double price) throws RemoteException, CreateException; public CMPProductRemote findByPrimaryKey(Integer productId) throws RemoteException, FinderException; public Collection findByProductName(String productName) throws RemoteException, FinderException; public Collection findAll() throws RemoteException, FinderException; }

80 CMPProductBean I package es.deusto.ejb; import java.sql.*; import java.util.Properties; import java.util.Enumeration; import java.util.Vector; import java.rmi.RemoteException; import javax.ejb.EntityBean; import javax.ejb.EntityContext; import javax.ejb.CreateException; import javax.ejb.FinderException; import javax.ejb.ObjectNotFoundException; import javax.naming.InitialContext; import javax.naming.Context; import javax.naming.NamingException; public abstract class CMPProductBean implements EntityBean { private EntityContext context; public abstract void setProductId(Integer productId); public abstract Integer getProductId(); public abstract void setProductName(String productName); public abstract String getProductName(); public abstract void setDescription(String description); public abstract String getDescription(); public abstract void setPrice(double price); public abstract double getPrice();

81 CMPProductBean II public Integer ejbCreate(int productId, String productName, String description, double price) throws RemoteException, CreateException { System.out.println("ejbCreate"); this.setProductId(new Integer(productId)); this.setProductName(productName); this.setDescription(description); this.setPrice(price); return null; } public void ejbPostCreate(int productId, String productName, String description, double price) throws RemoteException, CreateException { System.out.println("ejbPostCreate"); } public void ejbRemove() throws RemoteException { System.out.println("ejbRemove"); }

82 CMPProductBean III public void ejbActivate() { System.out.println("ejbActivate"); } public void ejbPassivate() { System.out.println("ejbPassivate"); } public void ejbLoad() { System.out.println("ejbLoad"); } public void ejbStore() { System.out.println("ejbStore"); } public void setEntityContext(EntityContext context) { System.out.println("setEntityContext"); this.context = context; } public void unsetEntityContext() { System.out.println("unsetEntityContext"); context = null; }

83 ejb-jar.xml CMPProductEJB es.deusto.ejb.CMPProductHomeRemote es.deusto.ejb.CMPProductRemote es.deusto.ejb.CMPProductBean Container java.lang.Integer False 2.x Product productId productName price description productId

84 Ejb-jar.xml II findByProductName java.lang.String SELECT OBJECT( p ) FROM Product AS p WHERE p.productName = ?1 Para definir consultas a bases de datos complejas EJB 2.0 define Enterprise JavaBeans Query Language (EJB QL), un lenguaje similar a SQL.

85 ejb-jar.xml III This role represents everyone who is allowed full access to the beans. everyone everyone CMPProductEJB * CMPProductEJB * Required

86 Configurando interfaces locales y remotos SequenceSessionEJB com.pelikon.docman.util.ejb.keygenerator.SequenceSessionHomeRemote com.pelikon.docman.util.ejb.keygenerator.SequenceSessionRemote com.pelikon.docman.util.ejb.keygenerator.SequenceSessionHomeLocal com.pelikon.docman.util.ejb.keygenerator.SequenceSessionLocal com.pelikon.docman.util.ejb.keygenerator.SequenceSessionBean Stateless Container retryCount java.lang.Integer 5

87 Buscando local/remote homes public static synchronized Object getRemoteHome(String jndiName, Class narrowTo) throws NamingException { Object ref = remoteHomes.get(jndiName); if(ref == null) { ref = getContext().lookup(jndiName); ref = PortableRemoteObject.narrow(ref, narrowTo); remoteHomes.put(jndiName, ref); } return ref; } public static synchronized Object getLocalHome(String jndiName) throws NamingException { Object ref = localHomes.get(jndiName); if(ref == null) { ref = getContext().lookup(jndiName); localHomes.put(jndiName, ref); } return ref; }

88 Sintáxis EJB QL I Una query en EJB QL tiene la forma: select_clause from_clause [where_clause] select_clause select [DISTINCT] {single_valued_path_expression | OBJECT(identification_variable)} SELECT DISTINCT OBJECT(p) FROM Product AS p

89 Sintáxis EJB QL II from_clause FROM identification_variable_declaration [, identification_variable_declaration]* identification_variable_declaration::=collecti on_member_declaration|range_variable_declarati on collection_member_declaration::= IN (collection_valued_path_expression) [AS] identifier range_variable_declaration::=abstract_schema_nam e [AS] identifier SELECT DISTINCT OBJECT(o) FROM Order o, IN(o.lineItems) l WHERE l.product.category=‘book’

90 Sintáxis EJB QL III where_clause WHERE conditional_expression Donde la expresión condicional puede ser: Literal (TRUE, FALSE, 9E2) Variable, debe haber sido declarada en la parte FROM Parámetros de entrada, de ?1 en adelante Operadores:., *, /, +, -, =, >, >=,, NOT, AND, OR Expresiones BETWEEN: BETWEEN arithmetic-expr AND arithmetic-expr Expresiones IN Expresiones LIKE Comparaciones IS NULL Funciones: CONCAT, SUBSTRING, LOCATE, LENGTH, ABS, SQRT

91 Ejemplos EJB QL SELECT OBJECT(u) FROM User AS u WHERE LCASE(u.userName) = LCASE(?1) SELECT OBJECT(p) FROM Project AS WHERE p.projectCategory.id = ?1 En el ejb-jar.xml aparecerían las queries en el siguiente formato: = ?3 and d.creationDate

92 Message-driven Beans (MDB) EJB El módelo MDB permite a un EJB ser invocado asíncronamente para procesar las peticiones que llegan en la forma de mensajes JMS Para un cliente un MDB EJB es un consumidor asíncrono de mensajes Similar a stateless session bean en que no tiene estado conversacional asociado No tienen interfaces home y remote como los session o entity beans Un cliente de un MDB EJB accede a él enviando mensajes a un destino JMS

93 Java Message Service (JMS) Un servicio de mensajería es un servicio que provee comunicación entre aplicaciones o componentes software En un servicio de mensajería el emisor y el receptor pueden estar desconectados Emisor envía a un destino y el receptor recoge el mensaje del destino

94 La API de JMS Las aplicaciones que usan JMS se denominan JMS clients Los servicios de mensajería que manejan el ruteamiento y envío de mensajes son los JMS providers Un cliente que envía se denomina JMS producer Un cliente que recibe se denomina JMS receiver Dos características: Asíncrono: un cliente JMS no tiene que requerir un mensaje para recibirlo Robusto: un sistema JMS puede asegurar que un mensaje se recibe, uno y sólo una vez Objetivo JMS: integrarse con plataformas MOM (Message Oriented Middleware)  IBM MQSeries, TIBCO RV

95 Cuándo usar JMS Los clientes tienen que estar desacoplados unos de otros El intercambio de mensajes se debe permitir incluso cuando alguno de los clientes no está activo El módelo de negocio requiere que los componentes se envíen mensajes sin necesidad de tener que recibir una respuesta inmediatamente

96 Dominios de JMS Publish/Subscribe (pub/sub) Un cliente envía un mensaje a un tema y el mensaje es recibido por todos los clientes subscritos a ese tema Modelo one-to-many Point-to-point (PTP) Un emisor envía un mensaje a una cola y el receptor extrae el mensaje de la cola cuando más le convenga La cola mantiene el mensaje hasta que éste sea recogido o expire Modelo one-to-one

97 Modelo de objetos de JMS I Los objectos más importantes en JMS son: 1. ConnectionFactory  sirve para crear una conexión con un proveedor JMS Tiene dos subinterfaces: TopicConnectionFactory y QueueConnectionFactory Para conseguir una conexión para un proveedor JMS punto-a-punto: Context jndiContext = new InitialContext(); QueueConnectionFactory factory = (QueueConnectionFactory) jndiContext.lookup("ConnectionFactory"); 2. Destination  encapsula la dirección de un proveedor de JMS Topic en pub/sub Queue en PTP Queue queue = (Queue) context.lookup(queueName); 3. Connection  representa una conexión activa a un proveedor JMS Dos tipos de conexiones: QueueConnection TopicConnection Después de crear una conexión se queda en modo ‘stop’ y es necesario arrancarla cuando se quieren enviar o recibir mensajes

98 Modelo de objetos de JMS II Los objectos más importantes en JMS son: 4. Session  contexto para producir y recibir mensajes Dos subinterfaces: TopicSession QueueSession Los métodos createTopicSession y createQueueSession tienen como parámetros: transacted  indica si hay transacciones en la sesión acknowledgeMode  indica si el consumidor indicará la recepción de un mensaje: AUTO_ACKNOWLEDGE CLIENT_ACKNOWLEDGE

99 Modelo de objetos de JMS III Los objectos más importantes en JMS son: 5. MessageConsumer  objeto usado para recibir mensajes Dos subtipos: QueueReceiver TopicSubscriber 6. Message  los siguientes tipos de mensajes son soportados: TextMessage MapMessage BytesMessage StreamMessage ObjectMessage

100 MDB EJB API I Un MDB debe implementar los interfaces: javax.ejb.MessageDrivenBean y javax.jms.MessageListener La interfaz javax.ejb.MessageDrivenContext es también utilizada MessageDrivenBean define los métodos: public void setMessageDrivenContext (MessageDrivenContext context) throws EJBException  asocia un contexto al MDB public void ejbRemove() throws EJBException  invocado por el contenedor al destruir un MDB

101 MDB EJB API II MessageDrivenContext define los métodos: getRollbackOnly getUserTransaction isCallerInRole setRollbackOnly getCallerPrincipal, getEJBHome, getEJBLocalHome

102 Acceso a un MDB Desde un cliente ha de accederse a un javax.jms.Queue : Context context = new InitialContext(); Queue queue = (Queue)context.lookup( “queue/MyQueue”;

103 Escribiendo un MDB 1. Crear la clase del message driven bean 2. El ejb-jar.xml 3. Configurar Jboss para explotar un message-driven bean ( jboss.xml ) 4. Compilar código 5. Ejecutar clientes JMS

104 MyMDB.java I import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageListener; import javax.jms.Queue; import javax.jms.QueueConnection; import javax.jms.QueueConnectionFactory; import javax.jms.QueueSender; import javax.jms.QueueSession; import javax.jms.TextMessage; import javax.naming.InitialContext; import javax.naming.NamingException; public class MyMDB implements MessageDrivenBean, MessageListener { MessageDrivenContext context = null; QueueConnection connection; QueueSession session; Queue responseQueue;

105 MyMDB.java II public void ejbCreate() throws EJBException { System.out.println("ejbCreate"); try { InitialContext initContext = new InitialContext(); String queueName = "queue/B"; this.responseQueue = (Queue) initContext.lookup(queueName); QueueConnectionFactory qcf = (QueueConnectionFactory) initContext.lookup("java:comp/env/jms/QueueFactory"); connection = qcf.createQueueConnection(); session = connection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE); connection.start(); } catch (Exception e) { throw new EJBException("Failed to initialize MyMDB", e); }

106 MyMDB.java III public MyMDB() { System.out.println("Constructing MyMDB"); } public void setMessageDrivenContext(MessageDrivenContext context) { this.context = context; System.out.println("setMessageDrivenContext"); } public void ejbRemove() { System.out.println("ejbRemove"); context = null; try { if (session != null) session.close(); if (connection != null) connection.close(); } catch (JMSException e) { e.printStackTrace(); }

107 MyMDB.java III public void onMessage(Message msg) { System.out.println("onMessage"); try { TextMessage message = (TextMessage) msg; System.out.println("*******+message received: " + msg); //Queue queue = (Queue) msg.getJMSReplyTo(); //QueueSender sender = session.createSender(queue); QueueSender sender = session.createSender(this.responseQueue); TextMessage message2 = session.createTextMessage(message.getText()); sender.send(message2); sender.close(); } catch (Exception e) { e.printStackTrace(); }

108 ejb-jar.xml MyMDB es.deusto.ejb.MyMDB Container AUTO_ACKNOWLEDGE javax.jms.Queue jms/QueueFactory javax.jms.QueueConnectionFactory Container

109 jboss.xml MyMDB queue/MyQueue jms/QueueFactory java:/JmsXA

110 jbossmq-mymdb-service.xml <mbean code="org.jboss.mq.server.jmx.Queue" name="jboss.mq.destination:service=Queue,name=M yQueue"> jboss.mq:service=Dest inationManager

111 MessageSender.java I package es.deusto.client; import javax.jms.*; import javax.naming.*; public class MessageSender { public static void main(String[] args) { QueueConnection queueConnection = null; try { Context context = new InitialContext(); QueueConnectionFactory queueConnectionFactory = (QueueConnectionFactory)context.lookup ("ConnectionFactory"); String queueName = "queue/MyQueue"; Queue queue = (Queue) context.lookup(queueName); queueConnection = queueConnectionFactory.createQueueConnection(); QueueSession queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); QueueSender queueSender = queueSession.createSender(queue); TextMessage message = queueSession.createTextMessage(); message.setText("This is a TextMessage"); queueSender.send(message); System.out.println("Message sent.");

112 MessageSender.java II } catch (NamingException e) { e.printStackTrace(); System.out.println("Naming Exception"); } catch (JMSException e) { System.out.println("JMS Exception"); } finally { if (queueConnection != null) { try { queueConnection.close(); } catch (JMSException e) {} }

113 MessageReceiver.java package es.deusto.client; import javax.jms.*; import javax.naming.*; public class MessageReceiver { public static void main(String[] args) { QueueConnection queueConnection = null; try { Context context = new InitialContext(); QueueConnectionFactory queueConnectionFactory = ( QueueConnectionFactory) context.lookup("ConnectionFactory"); String queueName = "queue/MyQueue"; Queue queue = (Queue) context.lookup(queueName); queueConnection = queueConnectionFactory.createQueueConnection(); QueueSession queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); QueueReceiver queueReceiver = queueSession.createReceiver(queue); queueConnection.start(); System.out.println("Receiving message");

114 MessageReceiver.java Message message = queueReceiver.receive(0); System.out.println("Message received: " + message); if (message != null) { if (message instanceof TextMessage) { TextMessage textMessage = (TextMessage) message; System.out.println(textMessage.getText()); } catch (NamingException e) { System.out.println("Naming Exception"); } catch (JMSException e) { System.out.println("JMS Exception"); } finally { if (queueConnection != null) { try { queueConnection.close(); } catch (JMSException e) {} }

115 Configurando un BMP para que use una fuente de datos I <!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd"> This bean represents a cruise ship. ShipEJB com.titan.ship.ShipHomeRemote com.titan.ship.ShipRemote com.titan.ship.ShipBean Bean java.lang.Integer False DataSource for the Titan database jdbc/titanDB javax.sql.DataSource Container

116 Configurando un BMP para que use una fuente de datos II This role represents everyone who is allowed full access to the Ship EJB. everyone everyone ShipEJB * ShipEJB * Required

117 Configurando un BMP para que use una fuente de datos III Standard BMP EntityBean A C ShipEJB ShipHomeRemote jdbc/titanDB java:/DefaultDS Standard BMP EntityBean

118 Configurando un BMP para que use una fuente de datos IV private Connection getConnection () throws SQLException { try { Context jndiCntx = new InitialContext (); DataSource ds = (DataSource)jndiCntx.lookup("java:comp/env/jdbc/titanDB"); return ds.getConnection (); } catch (NamingException ne) { throw new EJBException (ne); }

119 Extendiendo una query de EJB QL: jbosscmp-jdbc.xml I TrigUIEJB TRIGUI id ID name NAME version VERSION

120 Extendiendo una query de EJB QL: jbosscmp-jdbc.xml II size SIZE_ numTrigSpaces NUM_TRIGSPACES author AUTHOR company COMPANY description DESCRIPTION

121 Extendiendo una query de EJB QL: jbosscmp-jdbc.xml III price PRICE timestamp TIMESTAMP userName USERNAME password PASSWORD counter

122 Extendiendo una query de EJB QL: jbosscmp-jdbc.xml IV ejbSelectOrderedKeys <![CDATA[ SELECT t.id FROM TrigUI t ORDER BY t.id DESC ]]>

123 Extendiendo una query de EJB QL: jbosscmp-jdbc.xml V findByNameOrderedByVersionDesc java.lang.String <![CDATA[ SELECT OBJECT(t) FROM TrigUI t WHERE t.name = ?1 ORDER BY t.version DESC ]]>

124 Configurando Jboss con MySQL I Instalar MySQL Download MySQL de: http://www.mysql.com/downloads/mysql-4.0.html http://www.mysql.com/downloads/mysql-4.0.html Para Windows elegir ‘Windows downloads, installer option’ Descomprimir el.zip resultante y hacer doble click en Setup.exe Ejecutar: %MYSQL_INSTALL_DIR%\bin\winmysqladmin Hará que el servicio de mysql comience, y un icono con un semáforo aparecerá en la parte derecha barra de tareas

125 Configurando Jboss con MySQL II Añadir soporte para transacciones a MySQL Probar si existe soporte para transiciones: Hacer click con el botón derecho del ratón en el semáforo y mostrar el administador de MySQL Hacer click en pestaña myini setup Asegurarse que el contenido de ese fichero es el que sigue (reemplazando 'c:\mysql' por la localización real de MySQL en tu máquina): #This File was made using the WinMySQLAdmin 1.4 Tool #12/11/2002 15:06:27 #Uncomment or Add only the keys that you know how works. #Read the MySQL Manual for instructions [mysqld] basedir=c:\mysql #bind-address=10.0.0.194 datadir=c:\mysql\data #language=c:\mysql\share\your language directory #slow query log#= #tmpdir#= #port=3306 #set-variable=key_buffer=16M default-table-type=InnoDB max_allowed_packet=12M

126 Configurando Jboss con MySQL III [WinMySQLadmin] Server=c:\mysql\bin\mysqld-max-nt.exe user=starbase1 password=starbase1 # Uncomment the following if you are using Innobase tables innodb_data_file_path = ibdata1:100M:autoextend innodb_data_home_dir = c:\mysql\ibdata innodb_log_group_home_dir = c:\mysql\iblogs innodb_log_arch_dir = c:\mysql\iblogs set-variable = innodb_mirrored_log_groups=1 set-variable = innodb_log_files_in_group=3 set-variable = innodb_log_file_size=5M set-variable = innodb_log_buffer_size=8M innodb_flush_log_at_trx_commit=1 innodb_log_archive=0 set-variable = innodb_buffer_pool_size=16M set-variable = innodb_additional_mem_pool_size=2M set-variable = innodb_file_io_threads=4 set-variable = innodb_lock_wait_timeout=50

127 Configurando Jboss con MySQL IV Asegurate que el botón de radio mysqld-max- nt es seleccionado Haz click en el botón 'Save Modification' button Para y rearranca el servicio MySQL yendo a Setting-->Control Panel-->Administrative Tools-->Services http://www.mhoehme.de/java/ejb.html#jbos s-mysql provee detalles sobre cómo configurar JBoss y MySQL http://www.mhoehme.de/java/ejb.html#jbos s-mysql

128 Configurando Jboss con MySQL V Obtener ejemplo de configuración de base de datos de: %JBOSS_HOME%\docs\examples\jca\mysql-ds.xml Copiarlo a %JBOSS_HOME%\server\default\deploy Modificar los elementos: jdbc:mysql://localhost:3306/deusto com.mysql.jdbc.Driver deusto Modificar el fichero %JBOSS_HOME%\server\default\conf\ standardjbosscmp- jdbc.xml Substituir java:/DefaultDS por java:/MySqlDS Copiar driver de MySQL downloads\mysql4.1\mysql- connector-java-3.1.6-bin.jar a %JBOSS_HOME%\server\default\lib

129 Configurando Jboss con MySQL V Para crear la base de datos deusto con username deusto y password deusto Guardar en fichero creardbdeusto.sql el siguiente código: CREATE DATABASE deusto; GRANT ALTER, SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ON deusto.* TO deusto@'%' IDENTIFIED BY 'deusto'; GRANT ALTER, SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ON deusto.* TO deusto@localhost IDENTIFIED BY 'deusto'; Ejecutar el comando: mysql –uroot –p < creardbdeusto.sql

130 EJB 3.0 Futuro de EJB: Orientado a simplificar el desarrollo de aplicaciones escalables Mejorando aún más su rendimiento

131 Middlegen http://boss.bekk.no/boss/middlegen/

132 Referencias La mejor fuente de documentación sobre Jboss es la Jboss Wiki: http://www.jboss.org/wiki/Wiki.jsp http://benmira.free.fr/en/j2ee/ejb.htm


Descargar ppt "Tema 6 - Enterprise JavaBeans Dr. Diego Lz. de Ipiña Gz. de Artaza"

Presentaciones similares


Anuncios Google