lunes julio 17, 2006
EJB3 - Conceptos Basicos
Introducción
Por todos es sabido que el modelo de programación propuesto por la versión 2.1 de EJB conllevaba una serie de inconvenientes que limitaron mucho el uso de esta especificación y conllevó la aparición de soluciones open source que suplían las carencias que presentaba EJB 2.1. Bajo mi punto de vista las soluciones open source que más han marcado el desarrollo empresarial dentro de la plataforma Java han sido Hibernate y Spring Framework, y en la nueva versión de Java Enterprise Edition se han incorporado muchas de las características de estos frameworks para procurar a los desarrolladores una plataforma de desarrollo bastante más sencilla que su predecesora versión 1.4. En este post voy a tratar de explicar cuáles son los distintos tipos de Enterprise Java Bean y cuáles son los propósitos de cada uno de ellos : Stateless Session Bean, Stateful Session Bean, Entity Bean y Message Driven Bean. Debido a que éste pretende ser una breve explicación a los tipos de Entreprise Bean existentes, no voy a entrar en detalles tales como ciclo de vida de los mismos y otros tipos de características.Stateless Session Bean
Un bean de sesión sin estado es aquél que no dispone de variables de instancia en las cuales se guarden datos que puedan ser compartidos entre los distintos métodos del bean. Es decir, se trata de un bean que por lo general contará con una serie de métodos que realizarán un trabajo determinado e independiente y que el resultado de las operaciones realizadas dentro de cada uno de los métodos no dependerá de ningún ?estado? relativo a la conversación que mantiene el cliente con el bean. Como puede ser que a través de mis palabras no quede suficientemente claro a qué me refiero creo que va a ser mejor que veamos un ejemplo. Tomemos como ejemplo un bean que se encarga de gestionar las operaciones básicas que podemos realizar con un cliente, como son consultar un cliente, guardar un cliente y borrarlo. En primer lugar tendríamos que crear una interface :
public interface CustomerServiceLocal {
public void saveCustomer( Customer customer );
public Customer getCustomer( Long id );
public Collection getAllCustomers();
public void deleteCustomer( Long id );
}
Podemos ver que se trata de una simple interface que no tiene ninguna característica particular. Todo bean de sesión sin estado es necesario que disponga de una interface y la que hemos definido arriba es perfectamente válida para nuestro servicio de clientes. Si no la hubiéramos creado y hubiéramos definido directamente el bean sin la creación de la interface, hubiera sido el propio contenedor quién la hubiera creado por nosotros. La intefaz debiera de tener una anotación, que le indicara si se trata de una interface Local o Remote. Si el bean va a ser utilizado por una clase que se ejecute dentro de la misma JVM en la que se ejecuta el bean de sesión entonces la interface podría ser Local, y si el bean va a ser llamado por una clase que se ejecuta en una JVM distinta entonces la interface tendría que ser Remote. Por defecto, si no se indica nada, será tratada como una interface Local.
Ejemplo de interface local :
@Local
public interface CustomerServiceLocal {
public void saveCustomer( Customer customer );
public Customer getCustomer( Long id );
public Collection getAllCustomers();
public void deleteCustomer( Customer customer );
}
Ejemplo de interface remota :
@Remote
public interface CustomerServiceRemote{
public void saveCustomer( Customer customer );
public Customer getCustomer( Long id );
public Collection getAllCustomers();
public void deleteCustomer( Customer customer );
}
Ahora nos faltaría crear el bean propiamente dicho :
@Stateless
public class CustomerService implements CustomerServiceLocal {
@PersistenceContext()
private EntityManager em;
public void saveCustomer( Customer customer ) {
em.persist( customer );
}
public Customer getCustomer( Long id ) {
Query q = em.createQuery( "SELECT c FROM Quiz c WHERE c.id = :id" ).
setParameter( "id", id );
return (Customer)q.getSingleResult();
}
public Collection getAllCustomers() {
return em.createQuery( "SELECT c from Customer c" ).getResultList();
}
public void deleteCustomer( Customer customer ) {
em.remove( customer );
}
}
Stateful Session Bean
Al contrario que en los beans de sesión sin estado, los stateful session bean, como su nombre indica, sí tienen estado. Lo que esto significa es que dentro de la sesión del usuario estos beans van a almacenar datos en variables de instancia, y esos datos van a tener un significado concreto durante toda la convesación mantenida entre el cliente y el bean. Un ejemplo típico de bean de sesión con estado es un carro de la compra, en el cual, durante la sesión de usuario, éste va agregando productos en el carro a través de una lista. Tras ir agregando productos llegará un momento en el que el usuario quiera efectuar la compra, para lo cuál tendrá que realizar previamente un registro de sus datos, especificar la dirección de entrega, indicar el número de su tarjeta de crédito, etcétera, y finalmente confirmará la compra de los productos seleccionados. Como vemos, todos estos datos hay que almacenarlos en unas variables, que son las que conforman el estado del bean. Al igual que los Stateless Session Bean, los Stateful también deben de implementar una interface que puede ser Local o Remote :
@Local
public interface CartServiceLocal {
public void addProduct( Product product );
public void removeProduct( Product product );
public Collection getProducts();
}
Y la implementación de esta interface sería el Stateful Session Bean :
@Stateful
public class CartService implements CartServiceLocal {
private List products;
public void addProduct( Product product ) {
products.add( product );
}
public void removeProduct( Product product ) {
products.remove( product );
}
public Collection getProducts() {
return products;
}
}
Entity Bean
Un Entity Bean es una clase ( POJO ) que representa una tabla de una base de datos, y cada instancia de esta clase representa un registro de la tabla, es decir, con los entity beans lo que conseguimos es crear un mapeo entre las propiedades de una clase y los campos de una tabla. Además de este mapeo también vamos a poder especificar las relaciones que tienen las clases entre sí ( uno a uno, uno a muchos, muchos a uno y muchos a muchos ). Todo Entity Bean debe de tener una clave primaria que identifica a ese registro de forma única dentro de la tabla. Todas estas configuraciones las vamos a realizar a través de anotaciones, y el API que se encarga de gestionar todos los aspectos relativos a la persistencia es JPA ( Java Persistent API ). Vamos a ver un ejemplo. Vamos a crear una entidad llamada Team, para lo cual veremos que lo único que vamos a tener en cuenta es establecer una anotación @Entity al principio de la clase, una anotación @Id para indicar cuál es la propiedad que representa la clave primaria, y por último una anotación @OneToMany para indicar que un equipo puede estar compuesto por muchos jugadores y que éstos sólo pueden pertenecer a un equipo :
@Entity
public class Team {
private int id;
private String name;
private Date foundationDate;
private Collection players;
@Id
public int getId() {
return id;
}
public void setId( int value ) {
id = value;
}
public String getName() {
return name;
}
public void setName( String value ) {
name = value;
}
public Date getFoundationDate() {
return foundationDate;
}
public void setFoundationDate( Date value ) {
foundationDate = value;
}
@OneToMany
public Collection getPlayers() {
return players;
}
public void setPlayers( Collection value ) {
players = value;
}
}
A continuación vamos a crear la Entidad Player, que al igual que la entidad anterior va a tener una anotación @Entity, otra anotación @Id, y por último una anotación @ManyToOne para establecer una relación bidireccional entre las dos entidades :
public class Player {
private int id;
private String name;
private Team team;
@Id
public int getId() {
return id;
}
public void setId( int value ) {
id = value;
}
public String getName() {
return name;
}
public void setName( String value ) {
name = value;
}
@ManyToOne
public Team getTeam() {
return team;
}
public void setTeam( Team value ) {
team = value;
}
}
Message Driven Bean
Este tipo de beans ( MDB ) permite a las aplicaciones procesar mensajes de forma asíncrona a través del servicio JMS ( Java Messaging Service ). Este servicio funciona a través de colas de mensajes, que es donde los clientes envían sus peticiones, y estas colas son controladas por los Message Driven Beans, los cuales procesan los mensajes que hay en ellas y ejecutan ciertos servicios dependiendo del mensaje procesado. Este tipo de beans se aproximan más a la forma conceptual de los Stateless Session Bean en el sentido que son beans que no deben almacenar estado alguno. Cuando un mensaje llega a la cola el contenedor hace una llamada al método onMessage del Message Driven Bean y en este método el bean debería invocar a métodos de otros sesión bean o realizar la lógica de negocio de debiera ejecutar ( es más conveniente no tener aquí lógica de negocio, sino hacer invocaciones a métodos de otras clases que sí se encarguen de realizar lógica de negocio ). Para declarar un MDB sólo hemos de establecer la anotación @MessageDriven a una clase que implemente la interface MessageListener, e indicar el nombre de la cola del contenedor ( la cuál es accesible vía JNDI ) que va a controlar el MDB. Veamos un ejemplo :
@MessageDriven( mappedName = "jms/Queue" )
public class AsynchronousService implements MessageListener {
public void onMessage( Message message ) {
TextMessage textMessage = (TextMessage)message;
System.out.println( textMessage.getText() );
}
}
Conclusión
Estos son los cuatro tipos de beans existentes en la plataforma JEE, y cada uno de ellos cuenta con unas características determinadas que hacen que cada bean sea más apropiado para unas situaciones determinadas. En el próximo artículo intentaré explicar cómo desarrollar una aplicación JEE que haga uso de Stateless Session Beans, Entity Beans y que éstos sean utilizados a través de una aplicación web.Posted at 08:59PM jul 17, 2006 by Jose Luis Monteagudo in General | Comentarios[9]
Hola,
Solo quisiera aportar diciendo que el bean stateless no guarda ningun valor entre llamada y llamada por que el server siempre te proporciona un bean "limpio" en cada invocacion a un metodo. Las variables de instancia que pudieras usar para guardar un estado ya estan inicializadas cuando comienza la ejecucion del metodo.
Saludos.
Enviado por jose luis en julio 24, 2006 a las 04:26 PM GMT-01:00 #
hola
Enviado por 201.104.42.88 en agosto 23, 2006 a las 04:53 PM GMT-01:00 #
Hola haber si me mandan informacion sobre Spring FrameWork porfa lo necesito aprender.........
Enviado por Edwin en septiembre 04, 2006 a las 07:52 PM GMT-01:00 #
Hola,
tengo una duda sobre los Stateful Session Bean:
Cuando decis 'Lo que esto significa es que dentro de la sesión del usuario estos beans van a almacenar datos en variables de instancia, y esos datos van a tener un significado concreto durante toda la convesación mantenida entre el cliente y el bean' a que os referis con lo de 'sesión del usuario', por que esto no es una HttpSession supongo. Y si no es asi como lo almacenaria en una HttpSession?
Gracias y un saludo.
Enviado por anonimo en octubre 25, 2006 a las 09:28 AM GMT-01:00 #
Hola anónimo,
en efecto, cuando hablamos de la sesión de usuario en el contexto de los Stateful Session Beans (SFSB) no estamos hablando de una HpptSession. El ciclo de vida de un SFSB es gestionado por el Servidor de Aplicaciones.
Cuando un cliente invoca un método de un SFSB, el servidor de aplicaciones comprueba si ya existe un SFSB de ese mismo tipo asociado al cliente. En el supuesto de que no exista entonces el servidor de aplicaciones crea uno nuevo, pero si ya existía va a seguir utilizando ese SFSB que ya existía (teniendo en cuenta el estado de las variables de instancia de ese SFSB asociado al cliente que realiza la invocación).
¿Hasta cuándo va a existir ese SFSB en el servidor de aplicaciones? Va a existir hasta que se realice una invocación a un método del SFSB que esté anotado con @Remove, o bien hasta que el servidor de aplicaciones lo elimine después de alcanzar un timeout.
No sé si ha quedado claro, pero ese es el funcionamiento de los SFSB a grosso modo. Faltaría comentar que los SFSB pueden entrar en un estado "pasivo" y que desde este estado pueden volver a "activarse", pero ese es otro tema que no está relacionada con la pregunta que hacías.
Saludos,
jl_monteagudo
Enviado por jl_monteagudo en octubre 31, 2006 a las 01:14 PM GMT-01:00 #
Sobre lo de SFSB como maneja el server el tema de los clientes, es decir, como identifica de quien estan viniendo los datos, supongmaos q tengo clientes swing accesando via RMI, es correcto no?
Enviado por Bruno en enero 26, 2007 a las 07:29 PM GMT-01:00 #
d
Enviado por d en junio 09, 2007 a las 04:49 PM GMT-01:00 #
Como respuesta al primer comentarios quiero aclarar que la especificacion no dice que el bean que se entrega esta limpio, solo dice que "NO SE GARANTIZA QUE CONSERVE EL ESTADO" es muy simple realizar la prueba y se ve que si existe solo un cliente de un stateless (en jboss por ejemplo) el bean retornado (si es que este tiene estado) tiene siempre los mismos valores. Esto es debido al pool de conexiones y al ciclo de vida de los SLSB
Mas info en :
http://gpitech.wordpress.com/
Enviado por 200.41.46.178 en junio 22, 2007 a las 03:16 PM GMT-01:00 #
0
Enviado por 200.54.67.41 en mayo 28, 2008 a las 02:38 PM GMT-01:00 #