Mostrando entradas con la etiqueta ejb. Mostrar todas las entradas
Mostrando entradas con la etiqueta ejb. Mostrar todas las entradas

jueves, 13 de junio de 2013

Ejercicios de clase. Clase 11: implementando un Timer

Los métodos de los EJB pueden ser etiquetados con @Schedule para que sean invocados en intervalos regulares de tiempo. La sintaxis empleada para especificar esa periodicidad es similar a la de cron de UNIX. Puedes consultarla aquí

 

El método myTimer() se ejecutará cada 10 segundos imprimiendo en la consola del servidor la hora del sistema. El atributo persistent si se establece a "true" hace que el Timer se guarde después de un reinicio o una caida del servidor para que continúe invocándose nada más ser reiniciado.
Puedes descargar el código de las clases NewTimerSessionBean y su auxiliar ServicioHora aquí

Salida del Timer de ejemplo en la consola del servidor GlassFish, ejecutándose cada 10 segundos


Ejercicios de clase. Clase 11: implementando un Interceptor

Un Interceptor es una clase especial que dispone de un método que es ejecutado cuando se  invoca un método de un EJB, bien porque el método invocado está anotado específicamente para ser interceptado o bien porque la clase entera está anotada para ser interceptada, de manera, que este hecho afectará a todos sus métodos. En resumen, los Interceptors permien hacer procesamientos anteriores y posteriores a la ejecución de un método de un EJB.

Clase correspondiente a un Interceptor. El método tiene que ser anotado con @AroundInvoke y debe respetar la signatura mostrada en la figura, aunque su nombre es indiferente. El parámetro context encapsula todos los metadatos correspondientes a la clase y el método interferidos. Así, en este ejemplo, se emplea el parámetro de tipo InvocationContext para imprimir el nombre del método interferido. El método proceed() permite ejecutar el método interferido, por lo que todo el código anterior corresponde a preprocesamiento y el posterior a postprocesamiento.

Puedes descargar el código de InterceptorSimple aquí
Puedes acceder a la API de la clase InvocationContext aquí


Por su parte, el componente intercepado, tiene que ser anotado con @Interceptors para indicar qué clases de tipo Interceptor tiene asociadas
Esta es la salida generada por el interceptor de ejemplo en la consola del servidor GlassFish cuando es interceptado el método onMessage() del EJB NewMessage.


miércoles, 12 de junio de 2013

Diapositivas. Clase 11: Transacciones en EJBs

Las transacciones manejadas por el contenedor EJB soportan distintos valores para su anotación @TransactionAttribute:

  •     TransactionAttributeType.REQUIRED: se trata del valor por defecto si no se emplea la anotación para indicar el atributo transaccional. Se interpreta como que el método anotado con este valor tiene que ser ejecutado dentro de una transacción. Más especificamente, cuando existe una transacción activa y el método es invocado desde esa transacción, automáticamente entra a formar parte de la misma. Si por el contrario, es invocado desde un contexto no transaccional, se crea una nueva transacción para ejecutar el método. En caso de fallo, cuando se revierte la transacción, el rollback siempre afectará a los métodos anotados como "REQUIRED".
    Supongamos que antes de llamar a crearDetalleEmpleado() para crear un ojbeto DetalleEmpleado se crea un objeto Empleado general. Tanto si se produce un error antes como después de haber creado un objeto DetalleEmpleado con la llamada a crearDetalleEmpleado(), el objeto DetalleEmpleado jamás se construirá porque la operación entra a formar parte de la transacción original de crearEmpleado(), de tal manera que si ya hubiera sido instanciado se revertirá la operación y se eliminará la instancia.
  •     TransactionAttributeType.REQUIRES_NEW: implica que siempre se creará una nueva transacción para el método anotado con este valor de atributo independientemente de si se invoca desde un contexto transaccional o no.
    Supongamos que se crea un objeto Empleado antes de invocar a crearDepartamento(). Al invocar a crearDepartamento() se crea una instancia de Departamento que posteriormente será encapsulada en el objeto Empleado. Si se produjese algún fallo en el método crearEmpleado() justo después de la llamada a crearDepartamento(), la instacia de Departamento no se eliminaría porque ha sido creada en una transacción independiente a la de crearEmpleado() que ha culminado con éxito.
  •     TransactionAttributeType.SUPPORTS: supone la propagación del estado transaccional del contexto que invoca al método anotado con este valor. Esto es, si el método es invocado desde una transacción activa, entonces entrará a formar parte de esa transacción y también se verá afectado por el rollback en caso de fallo. En cambio, si el método es invocado normalmente, sin un contexto transaccional, entonces su código también se ejecutará normalmente sin formar parte de ninguna transacción.
  •     TransactionAttributeType.NOT_SUPPORTED: se emplea en situaciones donde determinadas tareas no pueden ejecutarse dentro de una transacción. Así, si el método anotado con este valor de atributo es invocado desde una transacción activa, la transacción es pausada justo antes de la invocación del método y reanudada tras su ejecución. En caso de una invocación desde un contexto no transaccional, el método se ejecutará normalmente fuera de cualquier transacción.
    El ejemplo más ilustrativo de operaciones que no pueden ser incluidas en una transacción es el envío de un email, por tratarse de una tarea de naturaleza asíncrona. En este caso, la operación de registro del usuario debe ser pausada antes de enviar el email y reanudada justo después, pero en ningún caso el envío del email entra a formar parte de la transacción de registerUser()
  •     TransactionAttributeType.MANDATORY: sirve para asegurarse de que el método anotado con este valor va a ejecutarse dentro de una transacción pero a diferencia de otros valores del atributo lanza una excepción si es invocado desde un contexto no transaccional.
    Si llevamos a cabo una transferencia de capital que supone dos operaciones: deducir el capital de una cuenta origen y añadirlo a una cuenta destino, ambas operaciones deben necesariamente ejecutarse formando parte de una transacción; en caso contrario, se lanzará una excepción.
  •     TransactionAttributeType.NEVER: se emplea en raras ocasiones. Permite que cuando desde una transacción activa se invoca un método anotado con este valor de atributo, automáticamente se lance una excepción.

Ejercicios de clase. Clase 10: aplicación web de noticias (EJB Message-Driven + EJB de sesión Singleton + JPA + Servlets)

 

Sigue los pasos del proyecto propuesto por la documentación de NetBeans Creating an Enterprise Application with EJB 3.1 consistente en una sencilla aplicación web que permite añadir noticias (título + contenido) a un listado que se almacena en una base de datos. Asimismo, dispone de un contador para saber en cada momento el número de sesiones abiertas. La aplicación dispone de los siguientes elementos:

 

  • Una clase de entidad NewsEntity para soportar la persistencia de las noticias.
  • Un EJB Message-Driven llamado NewMessage que se encarga de leer los mensajes que uno de los servlets (PostMessage) va depositando en una cola gestionada por JMS, para luego guardarlos en la base de datos.
  • Una clase abstracta AbstractFacade y una clase derivada de ella, NewsEntityFacade, que nos proporciona una instancia de EntityManager para permitir las operaciones habituales sobre la base de datos a nuestra clase entidad.
  • Un EJB de sesión singleton, SessionManagerBean, que actúa como escuchador de los eventos de creación y destrucción de sesiones para mantener actualizado un contador. (Los beans de sesión singleton son una novedad en EJB 3.1 así como que se permita que este EJB esté incluido en el módulo web en lugar de situarse en el módulo EJB)
  • Un servlet ListNews que genera la interfaz principal de la aplicación donde se muestra el listado de las noticias almacenadas actualmente, un enlace que nos lleva a comunicarnos con otro servlet (PostMessage) para añadir una noticia nueva y el número de sesiones abiertas actualmente.
  • Un servlet PostMessage que se encarga de mostrar el formulario para que el usuario pueda enviar una nueva noticia al servidor. El modo de envío es asíncrono, agregándolo a la cola de mensajes que el EJB Message-Driven luego irá procesando.
(Puedes descargar el proyecto empleando el enlace de la propia documentación)


Ejercicios de clase. Clases 9 y 10: Ampliar la funcionalidad del chat

A partir de la solución al ejercicio anterior de implementar un chat empleando un EJB de sesión, amplía su funcionalidad habilitando en la interfaz del cliente un botón "Eliminar mensajes" que sea capaz de borrar todos los mensajes que se hayan guardado hasta ese momento en la base de datos.

Pasos:


  • Inserta un nuevo botón en la interfaz gráfica del cliente para eliminar los mensajes.  

  • Añade a la interfaz remota un nuevo método para que el cliente pueda solicitar al EJB que vacíe la tabla de mensajes.
  • El manejador del evento Action debe ahora invocar el método de la interfaz para borrar los mensajes valiéndose de la referencia al bean que ya había sido empleada con anterioridad para listar y enviar mensajes. Además limpiará el área de texto donde se visualizan todos los mensajes.
  • En la clase entidad Post debe declararse una nueva consulta con nombre que permita borrar todos los registros de la tabla correspondiente.
  • El bean tendrá que implementar el método de borrado de la interfaz remota valiéndose de la referencia al EntityManager que ejecutará la consulta con nombre de la entidad que creamos en el apartado anterior.


martes, 11 de junio de 2013

Ejercicios de clase. Clase 9: aplicación de escritorio + EJB de sesión + JPA

 

Crea una aplicación Java EE para que múltiples usuarios se puedan comunicar y que sus mensajes queden almacenados en una base de datos. La aplicación constará de:

  • Una GUI Java Swing actuando como cliente desde la que los usuarios pueden introducir su nombre y enviar mensajes. Cada vez que el cliente envíe un mensaje podrá ver la lista de mensajes ya almacenados, precedidos del nombe del usuario que los ha enviado.

  • Un EJB de sesión que manejará la persistencia.

  • Una tabla en una base de datos Java donde se almacenará un identificador, el nombre de usuario y el contenido de cada mensaje enviado. El identificador se generará de forma automática y actuará como campo clave. La longitud máxima de los mensajes será de 2000 caracteres.