You are on page 1of 51

Capa de presentación

Capa de Negocio

Capa de Negocio

• Se ha elegido la versión de EJB 3.0 debido a las siguientes características:
– Tiene una API de persistencia simplificada – Anotaciones de metadatos – Lenguaje de consultas mejorado – Uso de defaulting – Inyección de dependencias – Simplificación de los beans de sesión

Sin embargo. para configurar componentes EJB y especificar mapeos objeto/relacional con entidades. . Las anotaciones de metadatos podrán utilizarse como una alternativa a los descriptores de deployment XML. Las anotaciones de metadatos fueron introducidas en Java 5.• La principal diferencia entre EJB3 y EJB2.x es el manejo de la persistencia. de forma que cuando se desarrollen EJB 3 se utilizará esa versión de Java o una posterior. En EJB 3 un bean de entidad es un objeto Java verdadero. No era posible la herencia y el polimorfismo. los descriptores de deployment pueden seguir utilizándose. • La otra principal innovación de EJB 3 es la introducción de anotaciones de metadatos. Antes de EJB 3 existía un mapeo objeto/relacional limitado entre beans de entidad y tablas relacionales.

En particular JPQL proporciona las siguientes mejoras: – – – – – – – Proyecciones Cláusulas GROUP BY y HAVING Joins Subqueries Queries Dinámicas Queries con parámetros Actualización en lote y operaciones delete.• El EJB Query Language (EJBQL) disponible en versiones anteriores fue más limitado en comparación con JPQL de JPA. .

• El uso extensivo de defaults es hecho en EJB 3. el comportamiento esperado usualmente es el común por default. Los elementos anotación son usualmente necesarios solo cuando queremos configurar comportamientos excepcionales. la mayoría de las anotaciones de metadatos no requieren que le sean especificados elementos o parámetros. Por ejemplo. .

ha sido introducido a EJB 3 como una alternativa a JNDI para localizar recursos administrados por el contenedor.• La inyección de dependencias que caracterizó al framework Spring. . Ya no necesitamos especificar componentes e interfaces home. Además la clase bean de sesión ya no tiene que implementar muchas interfaces callback aún cuando estas no son requeridas por la aplicación. En EJB3 estos métodos de callback de ciclo de vida son implementados por los beans de sesión sólo cuando se requieren. • Los bean de sesión han sido simplificados.

los descriptores de deployment son leídos por el servidor de aplicaciones cuando el EJB es deployado. Las anotaciones de metadatos fueron introducidas en Java SE 5. En las notas se presenta un descriptor de deployment ejemplo junto con una interface y bean de sesión. . • En EJB 2. Por esta razón EJB 3 debe usarse en conjunción con Java SE 5 o posterior.x en vez de anotaciones se utilizaban descriptores de deployment. Como su nombre lo sugiere.Anotaciones • La opción de anotaciones es una de las características más importantes que distingue a EJB 3 de versiones anteriores.

las anotaciones son opcionales en EJB 3.• Las anotaciones son por mucho más fáciles de usar que los descriptores de deployment. Cualquier archivo descriptor de deployment no trivial necesita una herramienta para lectura y escritura. no muy legibles por humanos y tienden a errores cuando se editan de forma manual. Los descriptores de deployment siempre sobrescriben a las anotaciones. Sin embargo. aún se puede usar descriptores de deployment si lo deseamos. El uso de anotaciones significa recompilar un bean cuando sólo queremos cambiar un aspecto de deployment. modificar un descriptor de deployment no requiere recompilación. . Los descriptores de deployment suelen ser verbosos. Además los descriptores de deployment se pueden mezclar con las anotaciones en EJB3.

.• Un enfoque podría ser usar anotaciones para aquellos aspectos de un EJB que raramente van a cambiar entre deployments.

El siguiente diagrama muestra el ciclo de vida de un bean de sesión sin estado: .Ciclo de vida de un bean de sesión statefull • Es importante subrayar que el ciclo de vida de un bean de sesión sin estado es controlado por el contenedor y no por la aplicación.

el contenedor puede decidir en cualquier momento crear tales instancias. Cuando el contenedor inicia. Con el fin de crear tal instancia en el method-ready pool. Sin embargo. por ejemplo.• El estado inicial de un bean de sesión es el estado no-existe. el contenedor ejecuta los siguientes pasos: . Este sería el caso antes de que un contenedor inicie. típicamente crea un número de instancias de bean de sesión sin estado en el method-ready pool. El sig estado es el method-ready pool.

El contenedor entonces invoca un método callback PostConstruct.1. El contenedor inyecta el SessionContext del bean. Por ejemplo. el bean de sesión puede hacer uso de una queue JMS para enviar mensajes. si hay uno presente en el bean. El bean es instanciado. 3. 4. El método PostConstruct sería usado para inicializar cualquier recurso utilizado por el bean. si aplica. 2. El SessionContext es usado por un bean para consultarle al contenedor sobre el estatus o contexto del bean. cuando se transita de un estado no-existe al method-ready pool . Un método PostConstruct es llamado solo una vez en la vida de una instancia. La queue de conexión usada por JMS podría ser inicializada en el método PostConstruct. El contenedor ejecuta cualquier otra inyección de dependencias que es especificada en el metadato del bean.

El contenedor luego llama un método de negocio en el bean. cuando un cliente invoca un método de negocio en un bean de sesión sin estado cualquier instancia en el method ready pool puede ser elegido por el contenedor para ejecutar el método. Después de que un método de negocio ha sido invicado. Inversamente. Cada llamada al método de negocio podría originarse desde un cliente diferente. el contenedor puede decidir destruir la instancia del bean (típicamente si el contenedor decide que hay demasiadas instancias del method-ready pool) o reutilizar la instancia en nombre de cualquier cliente que invoque su método de negocio. .

cuando está por transicionar al estado no-existe. El método PreDestroy sería usado para poner en orden actividades.• Cuando el contenedor decide destruir la instancia primero invoca el método callaback PreDestroy si hay uno presente en el bean. Un método PreDestroy es llamado sólo una vez en la vida de una instancia. tal como cerrar conexiones que pudieron haber sido abiertas en el método PostConstruct. • Estas características de agrupamiento de instancias y compartición de instancias significa que los beans de sesión sin estado se escalan bien ante un número grande de clientes. .

Ciclo de vida de un bean de sesión stateful • El siguiente diagrama muestra el ciclo de vida de un bean de sesión sin estado .

Así que este paso es instanciado por el cliente y no por el contenedor. . el contenedor ejecuta los mismos pasos que con un method-ready de un bean de sesión sin estado. Una vez que un bean de sesión stateful está en un estado method-ready.• El ciclo de vida de un bean de sesión stateful es diferente del de un bean de sesión sin estado en muchas cosas. debido a que cada instancia sirve a un solo cliente. No hay agrupamiento de instancias de bean idénticos. Un bean de sesión stateful transita de un estado no-existe a un estado method-ready tan pronto como un cliente ejecuta una búsqueda de la interfaz de negocio o una inyección de dependencia de un bean.

si aplica. 4. 3. si hay uno presente en el bean. 2. El bean es instanciado. • El contenedor luego llama un método de negocio en el bean . El contenedor entonces invoca un método callback PostConstruct. El contenedor ejecuta cualquier otra inyección de dependencias que es especificada en el metadato del bean. El contenedor inyecta el SessionContext del bean.1.

Este proceso es llamado passivation e involucra serialización de la instancia del bean. La caché del contenedor podría llegar a estar completa de instancias de beans de sesión stateful. o ejecutar otras actividades. pero esto es seguro.• Recalcamos que un bean de sesión puede involucrar considerable tiempo ocioso si un cliente decide esperar. Cuando el cliente decide invocar un método en el bean pasivado. el contenedor deserializa el estado guardado e invoca el método solicitado. . Este proceso es conocido como activation. Para limitar tales instancias. de forma en que en la activación restauramos el estado que fue guardado en la activación. entre llamadas a métodos. Nota que el método puede no estar en la instancia del bean original. el contenedor puede cambiar estos de la caché hacia afuera del disco u otro almacenamiento.

y la política de selección de víctima del contenedor. . el máximo tiempo ocioso del bean. y típicamente depende de factores como el máximo número de beans que pueden ser contenidos en la caché del contenedor. La política de selección de víctima de glassfish tiene las siguientes opciones: Menos Recientemente Usado(LRU). y Primero en Entrar Primero en Salir(FIFO). Todos estos factores pueden ser configurados por el administrador del contenedor. No Recientemente Usado(NRU).• El algoritmo de pasivación es dependiente del contenedor.

el cual es ejecutado inmediatamente después de la activación. . y un método @PostActivate. En estos casos el recurso será cerrado en el método @Prepassivate y reabierto en el método @PostActivate. que no pueden ser manejadas por el contenedor durante la pasivación. el cual es ejecuta inmediatamente antes de la pasivación.• El bean puede proporcionar un método callback @Prepassivate. conexiones JMS o a base de datos. Un bean de sesión stateful puede contener recursos abiertos como sockets abiertos.

Nota en este caso que cualquier método anotado @PreDestroy no será invocado .• Un bean puede moverse desde un estado method-ready a un estado no-existe si un método anotado @Remove es invocado. En tal caso. • Un bean pasivado también puede moverse a un estado no existe si un periodo de timeout ha sido alcanzado. un método anotado @PreDestroy es invocado antes. Un bean puede hacer esto también si el periodo de timeout configurado del contenedor ha sido alcanzado.

. Este bean invocado únicamente retornará Que tengas un buen día. Pasar por valor significa que un objeto pasado por el cliente al bean remoto. y luego deserializado. o viceversa. Este protocolo estipula que los argumentos del método son pasados por valor y no por referencia. primero es serializado. como nuestro TimeServiceBean original. Los argumentos de los métodos son pasados por referencia y no por valor de forma que mejoran el performance. luego pasado sobre la red. Por esta razón la tecnología EJB proporciona una opción de interfaz local para beans de sesión. Todo esto tiene un impacto en términos de performance. primero definimos la interfaz del bean BuenDiaService. una interfaz remota utiliza el protocolo RMI-IIOP para operaciones de red. • Para ilustrar esto creemos un bean de sesión que será invocado y ejecutado en el mismo contenedor EJB.Interfaces locales • Tras las escenas. Aún si nuestro cliente es un bean de sesión que invoca a otro en el mismo contenedor hay una sobrecarga en el performance si usamos una interfaz remota debido a que se produce una serialización y deserialización.

ejb. . Esto indica al contenedor EJB que este bean sólo puede ser invocado por un cliente local que corre en el mismo contenedor.Stateless. import java. La interfaz consiste de tan sólo la definición de un método. } } Todo esto es correcto. A continuación veremos la implementacion del bean BuenDiaServiceBean: package ejb30. @Stateless public class NiceDayServiceBean implements NiceDayService { public String getMessage() { return " – Que tengas un Buen Dia".session.*.• La definición de interface anterior se prefijó con la anotación @Locale. getMessage(). notamos que el bean de sesión es sin estado y el método getMessage() retorna la cadena Que tengas un buen día. import javax.util.

Calendar cal = Calendar.getMessage().Stateless. fmt.*. import javax. import java.ejb.EJB.format("%tr". El TimeServiceBean agregará el mensaje BuenDiaService a la hora actual.session. public String getTime() { Formatter fmt = new Formatter(). Aquí está el código modificado para TimeServiceBean: package ejb30.getInstance(). } } .toString() + niceDay. cal). return fmt.util.ejb. @Stateless public class TimeServiceBean implements TimeService { private @EJB NiceDayService niceDay.• Vamos a ver cómo podríamos modificar TimeServiceBean para invocar BuenDiaService. import javax.

Recordamos que este es un ejemplo de inyección de campo. Una alternativa a la inyección de campo es la inyección de setter. Luego podemos invocar el método niceDay.getMessage(). La siguiente versión de TimeServiceBean usa inyección de setter. luego invoca al método setNiceDay() pasándole la referencia del bean BuenDiaService como parámetro a setNiceDay() . En este caso es anotado un método más que un campo. • Anotando el método setNiceDay() con la anotación @EJB estamos instruyendo al contenedor que busque el bean BuenDiaService.• Usamos la anotación @EJB para instruir al contenedor que busque el bean BuenDiaService. e inyectar una referencia al bean en el campo niceDay.

Veremos los siguientes temas: • • • • • • • • Entidades EJB 3 API de persistencia Java Mapear una entidad a una tabla de base de datos Metadatos defaults Introducción al entity manager Empaquetar y deployar entidades Generar llaves primarias Sobrescribir metadatos defaults .ENTIDADES • Las entidades son clases que necesitan ser persistidas. generalmente en una base de datos relacional.

Consecuentemente los aspectos de persistencia de EJB3 han sido empaquetados como una especificación separada –la Java Persistece API (JPA). • La especificación EJB 3 reconoce que muchas aplicaciones tienen las necesidades de persistencia anteriores sin requerir los servicios (seguridad. queremos consultar. las entidades las entidades no tienen lógica de negocio diferente que la validación. La mayoría de los ejemplos asumen que el motor de persistencia existe sin un contenedor EJB 3 como Glass Fish o Jboss. actualizar. su estado es almacenado fuera de la aplicación. . De igual forma que el almacenamiento de tales entidades. transacciones) de un contenedor EJB de servidor de aplicación.ENTIDADES • Las entidades son clases que necesitan ser persistidas. A diferencia de los beans de sesión. JPA no asume que tenemos un contenedor y podemos utilizarla aún en una aplicación Java SE. típicamente en una base de datos relacional. y eliminarlas.

o propietarios como Oracle Toplink han implementado estas tecnologías de persistencia desde hace años. situándose en lo alto de JDBC. . el engine de persistencia convierte sentencias JPA en sentencias JDBC de bajo nivel.ENTIDADES • Productos de mapeo objeto/relacional exitosos como un Hibernate open source. Bajo la cubierta. Los creadores de Oracle Toplink y Hibernate han influído en el desarrollo de la especificación JPA. • JPA puede considerarse como un alto nivel de abstracción.

y nombre y apellido. El siguiente código muestra una entidad Cliente. .java con atributos id. que es único para una instancia de un cliente.ENTIDADES • Entidades EJB 3 En JPA cualquier clase o POJO puede ser convertido a JPA con pocas modificaciones.

en este caso Cliente. .ENTIDADES La clase sigue las reglas de JavaBean usuales. pero describe como es persistida una entidad. Las variables de instancia son no públicas y son accesadas por clientes a través de métodos de acceso getters y setters de forma apropiada. No hay una parte intrínseca de una entidad. La anotación es inmediatamente colocada antes de la definicipon de la clase y es un ejemplo de anotación a nivel de clase. Las anotaciones especifican metadatos de entidad. o cómo una entidad está relacionada con otras entidades. También podemos tener anotaciones basadas en propiedades y basadas en campos. Solo un par de anotaciones han sido agregadas para distinguir esta entidad de un POJO. como podemos ver. es una entidad. La anotación @Entity indica al engine de persistencia que la clase anotada.

Esto no es esencial. getId(). debido a que la entidad cliente tiene el potencial de llegar a ser una entidad suelta (detached). Una anotación basada en propiedad debe ser colocada inmediatamente antes del método setter correspondiente. diferentes que las anotaciones a nivel de clase. pero es una buena práctica. Nota que todas las anotaciones en una entidad. Donde las anotaciones basadas en propiedad son utilizadas. Nuestra entidad Cliente también implementa la interfaz Serializable. deben ser todas basadas en propiedad o todas basadas en campo. El atributo id es una llave primaria candidata. Este es un ejemplo de anotación basada en propiedad.ENTIDADES La anotación @Id especifica la llave primaria de la entidad. Una alternativa a las anotaciones basadas en propiedad son las anotaciones basadas en campos. Las entidades sueltas deben implementar la interfaz Serializable. el engine de persistencia usa los métodos getters y setters para accesar y asignar el estado de la entidad. . Nota que se ha colocado la anotación inmediatamente antes del método getter correspondiente. y no al método getter.

la clase bean de entidad contiene métodos callback como ejbCreate(). ejbPassivate().ENTIDADES •Comparación con los beans de entidades EJB 2.x la construcción correspondiente es un componente bean de entidad con los mismos artefactos que un bean de sesión. y setEntityContext(). una interfaz home o localhome. La interfaz local o remota contiene definiciones de métodos setter y getter. a saber. ejbActivate(). y opcionalmente otras definiciones de métodos de búsqueda. un archivo descriptor de deployment. de forma que se es referido como una entidad y no como un bean de entidad. Como con los beans de sesión. En EJB 2. una interfaz local o remota. y la misma clase del bean. ejbLoad().x Una entidad EJB 3 es un POJO y no un componente. . ejbRemove(). La interfaz local o home contiene definiciones para los métodos create() y findByPrimaryKey().

CMP) o por la aplicación (Application Managed Persistence. Además del ejbCreate(). el bean de entidad es definido como una clase abstracta con definiciones de métodos getters y setters abstractos.x. En el caso de BMP. Consecuentemente. El bean de entidad EJB 2. BMP).ENTIDADES La entidad EJB 3 siendo un POJO. ejbStore(). En EJB 2. ejbFIndByPrimaryKey(). y cualquier otro método de búsqueda. necesita ser codificado usando JDBC.x necesitamos decidir si los aspectos de persistencia de un bean de entidad son manejados por el contenedor (Container Managed Persistence. En el caso de CMP. sus clientes siempre son locales a la JVM. pero puede tener clientes desde fuera de su JVM. puede correr fuera de un contenedor. . el bean de entidad es definido como una clase. En el deployment el contenedor crea una implementación concreta de esta clase de bean de entidad abstracta. los métodos getters y setters necesitan ser codificados.x es un objeto distribuido que necesita un contenedor para correr. las entidades EJB 3 son más reutilizables y más fáciles de probar que los beans de entidad EJB 2. ejbLoad().

xml. dígase Oracle. Estos pasos no se requieren si vamos a usar la fuente de datos Derby default. nuestro nombre de la tabla es CLIENTE. EJB 3 hace fuerte uso de defaulting para describir metadatos de entidades. Si queremos que Glasfish accese a otra base de datos relacional . Primero. En todos los ejemplo usaremos la base de datos Derby. Así. En esta sección describiremos algunos de estos defaults. Si queremos mapear la entidad CLIENTE a otra tabla necesitaremos usar la anotación @Table. el engine de persistencia mapea el nombre de la entidad a un nombre de tabla relacional. entonces necesitamos usar la consola de administración Glasfish para configurar una fuente de datos Oracle. . por default. Glassfish incluye una base de datos relacional Derby embebida.ENTIDADES • Mapeando una entidad a una tabla de base de datos Podemos mapear entidades en casi cualquier base de datos relacional. También necesitamos referirnos a esta base de datos Oracle en el archivo persistence.

Si queremos cambiar este comportamiento default. son los nombres de columnas correspondientes a los atributos de la entidad id. nombre y apellido. y VARCHAR2(255) para Oracle. Un int será mapeado a INTEGER para una base de datos Derby y NUMBER para una base de datos ORACLE.ENTIDADES Por default los nombres de propiedades o campos son mapeados a nombres de columnas. VARCHAR(255) para Derby. necesitaremos usar la anotación @Column. una String será mapeada a VARCHAR para una base de datos Derby y VARCHAR2 para una base de datos Oracle. APELLIDO. NOMBRE. Así ID. De esta forma. necesitamos usar el elemento length de la anotación @Column. SI queremos cambiar este tamaño de columna. . Las reglas JDBC son usadas para mapear primitivos Java a tipos de datos relacionales. El tamaño de una columna mapeada de una String por default es 255.

La interface se lista en las notas. y métodos de negocio addCliente() y findCliente(). Así mismo después de la interfaz se muestra la implementación del bean de sesión.ENTIDADES • Introducción al EntityManager Usaremos un bean de sesión sin estado remoto para operaciones de negocio en la entidad Cliente. Llamaremos a nuestra interface del bean de sesión BankService. Mas adelante agregaremos mas entidades y operaciones de negocio que típicamente son usadas por una aplicación bancaria. . En esta etapa nuestra aplicación bancaria trata con una entidad –Cliente. BankServiceBean. que respectivamente agregan un cliente a la base de datos y retoman una entidad cliente dados los identificadores de los clientes.

xml. tendremos 10 contextos de persistencia. consultar. por decir. La sentencia define: @PersistenceContext(unitName="BankService") private EntityManager em. Si tenemos. remover.ENTIDADES El EntityManager es un servicio provisto por el engine de persistencia que proporciona métodos para persistir. Es importante subrayar que un contexto de persistencia está asociado con un conjunto administrado de instancias u objetos de entidad. y actualizar entidades. Asociado con un EntityManager es una unidad de persistencia que especifica información de configuración. El conjunto de instancias de la entidad manejada es conocido como contexto de persistencia. encontrar. define una instancia EntityManager em con un contexto de persistencia asociado llamado BankService. La configuración de la actual unidad de persistencia está especificada en el archivo persistence. . que veremos pronto. 10 clientes accesando el bean.

persist(). crea. Ahora vamos a ver el método addCliente(). Primero la sentencia Cliente cust = new Cliente(). invoca al método EntityManager. La instancia aún no está asociada con un contexto de persistencia. –Inyecte la instancia EntityManager en el campo em. La sentencia em. tras escenas. como se espera. Sin embargo. Las siguientes sentencias invocan los métodos setter de Cliente en la forma usual.ENTIDADES Actualmente. . Las instancias de la entidad administradas también se les refiere como instancias ligadas y las instancias no administradas como instancias sueltas. en esta etapa la instancia de la entidad no está administrada. la anotación @PersistenceContext causa que el contenedor: –Use el EntityManagerFactory para crear una instancia del EntityManager –Enlace la instancia del EntityManager a la unidad de persistencia BankService.persist(cust). una instancia de la entidad Cliente.

ENTIDADES .

ENTIDADES .

ENTIDADES .

ENTIDADES .

ENTIDADES .

ENTIDADES .

ENTIDADES .

ENTIDADES .

ENTIDADES .

ENTIDADES .