Ejemplo de Session Bean con EJB 3
Un contenedor de aplicaciones JEE (JBoss, Glassfish, ..) puede controlar el ciclo de vida de una serie de clases java que lleven las anotaciones adecuadas. Entre estas clases, conocidas como Enterprise Java Beans o simplemente EJB, están los session beans, en concreto, Singleton, Statefull y Stateless. Vamos a explicar aquí y ver un ejemplo sencillo de estos tres tipos de EJB
Tienes el código de ejemplo de estos EJB en Github. Para ejecutarlo, tendrás que montar un proyecto EJB en tu IDE favorito y necesitarás algún contenedor de aplicaciones. En el proyecto, además de los tres EJB que comentamos aquí, hay uno de nombre MainBean, que no explicaremos. Este MainBean sólo es un bean que hacer "cosas" con los otros tres EJB que sí explicaremos aquí. MainBean está solo por si se te ocurre descargar y desplegar el proyecto en un contenedor de aplicaciones, para que veas que hace algo.
Stateless bean[editar]
Un Stateless bean es una clase java sin estado, es decir, no debería tener atributos, sólo métodos a los que se pueda llamar de forma independiente. Para que el contenedor de aplicaciones lo maneje, únicamente hay que ponerle la anotación @Stateless, como en el siguiente ejemplo
import javax.ejb.LocalBean; import javax.ejb.Stateless; @Stateless @LocalBean public class StatelessBean { public void saySomething(String somethingToSay){ System.out.println(somethingToSay); } }
Es una clase con un método al que se le pasas un texto y lo saca por pantalla. La anotación @Stateless es la que lo convierte en un EJB y le indica al contenedor de aplicaciones que debe encargarse de manejarlo. La anotación @LocalBean indica que a esta clase no se va a acceder de forma remota (desde fuera de nuestra aplicación). La anotación es opcional, puesto que por defecto se entiende que el bean no va a ser accedido de forma remota.
¿Qué quiere decir que lo manejará el contenedor de aplicaciones?. En el caso de Stateless beann, el contenedor de aplicaciones creará varias instancias de estas clase (se encargará de hacer los new) y le pasará estas instancias a quien las necesite. Como son clases sin estado, el contenedor dará cualquiera de las instancias que tiene al que la necesite y no se preocupará de entregar siempre la misma al mismo. Veremos más adelante, con la inyección de dependencias, como se entrega una instancia a otra clase que la necesite.
Statefull bean[editar]
Un Statefull bean no es más que una clase en la que sí hay atributos cuyo valor es importante y debe conservarse entre llamadas a métodos. El contenedor de aplicaciones instanciará, al igual que con los Stateless bean, un número determinado de ellos y los reaprovechará. La diferencia es que el contenedor de aplicaciones se asegurará de dar siempre al mismo cliente/usuario la misma instancia. De esta forma, ese cliente/usuario puede guardar en él datos que sean particulares de él y que necesiten conservarse mientras está trabajando con la aplicación. Un ejemplo típico es el carrito de la compra de una web. Los productos que el usuario va añadiendo al carrito se guardarían en un Statefull bean.
En código, la siguiente clase
import javax.ejb.EJB; import javax.ejb.LocalBean; import javax.ejb.Remove; import javax.ejb.Stateful; @Stateful @LocalBean public class StatefullBean { @EJB StatelessBean statelessTalker; // Estado de la clase, un texto. private String someText; // Se pasa el texto y debe conservarlo para la siguiente llamada public void setText(String someText){ this.someText = someText; } // Usa el texto que se ha pasado previamente. @Remove public void sayText(){ statelessTalker.saySomething(someText); } }
A esta clase, para convertirla en un EJB, le hemos puesto la anotación @Stateful. La anotación @LocalBean, al igual que antes, es opcional e indica que este bean no se va a utilizar de forma remota.
El atributo someText hace las veces de estado de esta clase. Un método setText() le da un valor y este texto debe conservarse para la llamada a sayText(). Por eso este bean es Statefull, lo que hace sayText() depende de la llamada previa a setText().
La anotación @Remove en el método sayText() debe ponerse para indicar al contenedor que ya hemos terminado de usar este Statefull bean. A partir de esta llamada, el contenedor sabe que este bean ya ha sido utilizado completamente y que puede dárselo a otro que lo necesite.
¿Y qué es el atributo @EJB StatelessBean statelessTalker;. Queremos que nuestro Statefull bean utilice la clase StatelessBean para sacar por pantalla el texto. Como StatelessBean es un EJB controlado por el contenedor de aplicaciones, no hacemos nosotros el new de esta clase. Simplemente la anotamos con @EJB y el contenedor se encargará de pasarnos una de las instancias que tiene de StatelessBean y podremos usarla. Esto es lo que comentábamos de "inyección de dependencias". Nuestra clase EJB necesita otra clase EJB, así que nos basta con declarar el atributo y añadirle al anotación @EJB. El contenedor de aplicaciones se encargará de pasárnosla.
Singleton bean[editar]
Un Singleton bean es una clase Java que el contenedor de aplicaciones instanciará una única vez y será compartida por todo el mundo. Está pensada para guardar los datos que son comunes a todos los usuarios o clientes de nuestra aplicación.
El siguiente código de ejemplo tiene un Singleton bean
import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.ejb.Singleton; import javax.ejb.Startup; @Singleton @Startup public class SingletonBean { @PostConstruct public void init() { System.out.println("SingletonBean started"); } @PreDestroy public void destroy() { System.out.println("SingletonBean is going to be destroyed"); } }
La anotación @Singleton convierte a esta clase Java en un Singleton bean. No hemos puesto la anotación @LocalBean puesto que por defecto el bean el local (no se puede acceder a él remotamente) si no se pone.
Hemos puesto la anotación @Startup para indicar al contenedor de aplicaciones que debe arrancar este bean al inicio. Si no ponemos la anotación, el bean no será arrancado hasta que alguien lo necesite. Habitualmente no se pone @Startup, salvo que este bean realice algo que necesite ser hecho en el momento de arrancar el contenedor de aplicaciones/nuestra aplicación.
¿Y qué es lo que va a ejecutar este bean cuando lo arranquen?. Pues lo que tenga el método que anotemos con @PostConstruct. Si no hay ningún método con esta anotación, no se hará nada en el arranque, pero si hay algún método anotado de esta manera, se ejecutará después de cargar el bean, pero antes de que empiece a usarse. Viene a ser como un constructor o método de inicialización de la clase.
Si queremos realizar alguna acción cuando el bean se vaya a destruir (al finalizar nuestra aplicación), debemos anotar el método que queramos que se ejecute con @PreDestroy.
Bueno, esto es todo. Sólo pretende ser una pequeña introducción a estos tres tipos de EJBs. Desde luego, hay muchas más anotaciones que se pueden poner y posibilidades por explorar, pero no vamos a enrollarnos aquí....