Frijoles Java Enterprise sin estado y con estado

Estoy repasando el tutorial de Java EE 6 y estoy tratando de entender la diferencia entre beans de sesión sin estado y con estado. Si los beans de sesión sin estado no retienen su estado entre las llamadas al método, ¿por qué mi progtwig está actuando como está?

package mybeans; import javax.ejb.LocalBean; import javax.ejb.Stateless; @LocalBean @Stateless public class MyBean { private int number = 0; public int getNumber() { return number; } public void increment() { this.number++; } } 

El cliente

 import java.io.IOException; import javax.ejb.EJB; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.WebServlet; import mybeans.MyBean; import java.io.PrintWriter; @WebServlet(name = "ServletClient", urlPatterns = { "/ServletClient" }) public class ServletClient extends HttpServlet { private static final long serialVersionUID = 1L; @EJB MyBean mybean; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter out = response.getWriter(); mybean.increment(); out.println(mybean.getNumber()); } } 

Esperaba que getNumber devolviera 0 cada vez, pero devuelve 1 y las recargas del servlet en mi navegador lo aumentan más. El problema está en mi comprensión de cómo funcionan los beans de sesión sin estado y no con las bibliotecas o el servidor de aplicaciones, por supuesto. ¿Alguien puede darme un simple ejemplo de hello world type de un bean de sesión sin estado que se comporta de manera diferente cuando lo cambias a stateful?

La diferencia importante no son las variables de miembros privados, sino la asociación del estado con un usuario en particular (piense en “carrito de compras”).

La parte con estado del bean de sesión con estado es como la sesión en servlets. Los beans de sesión con estado permiten que su aplicación aún tenga esa sesión, incluso si no hay un cliente web. Cuando el servidor de aplicaciones extrae un bean de sesión sin estado del grupo de objetos, sabe que se puede usar para satisfacer CUALQUIER solicitud, porque no está asociado con un usuario en particular.

Un bean de sesión con estado debe ser entregado al usuario que lo obtuvo en primer lugar, porque la información de su carrito de compras debe ser conocida solo por ellos. El servidor de aplicaciones se asegura de que esto sea así. ¡Imagina lo popular que sería tu aplicación si pudieras comenzar a comprar y luego el servidor de la aplicación me dio tu bean de sesión con estado cuando yo llegué!

Entonces su miembro de datos privados es de hecho “estado”, pero no es “carrito de compras”. Intenta volver a hacer tu (muy bueno) ejemplo para que la variable incrementada esté asociada a un usuario en particular. Increméntelo, cree un nuevo usuario y vea si aún puede ver el valor incrementado. Si se hace correctamente, cada usuario debería ver solo su versión del contador.

Los beans de sesión sin estado (SLSB) no están vinculados a un cliente y no hay garantía de que un cliente obtenga la misma instancia con cada invocación de método (algunos contenedores pueden crear y destruir beans con cada sesión de invocación de método, esta es una decisión específica de la implementación , pero las instancias generalmente se agrupan, y no menciono los entornos en clúster). En otras palabras, aunque los beans sin estado pueden tener variables de instancia, estos campos no son específicos de un cliente, por lo que no debe confiar en ellos entre llamadas remotas.

Por el contrario, Stateful Session Beans (SFSB) están dedicados a un cliente para toda su vida, no hay intercambio o agrupamiento de instancias (puede ser desalojado de la memoria después de la pasivación para ahorrar recursos, pero esa es otra historia) y mantener el estado conversacional . Esto significa que las variables de instancia del bean pueden mantener los datos relativos al cliente entre las invocaciones de métodos. Y esto hace posible tener llamadas a métodos interdependientes (los cambios realizados por un método afectan las llamadas a métodos posteriores). Los procesos de varios pasos (un proceso de registro, un carrito de compras, un proceso de reserva …) son casos típicos de uso para SFSB.

Una cosa más. Si está utilizando SFSB, debe evitar inyectarlos en clases de naturaleza multiproceso, como Servlets y beans administrados JSF (no desea que todos los clientes lo compartan). Si desea utilizar SFSB en su aplicación web, debe realizar una búsqueda JNDI y almacenar la instancia EJB devuelta en el objeto HttpSession para futuras actividades. Algo como eso:

 try { InitialContext ctx = new InitialContext(); myStateful = (MyStateful)ctx.lookup("java:comp/env/MyStatefulBean"); session.setAttribute("my_stateful", myStateful); } catch (Exception e) { // exception handling } 

Apátridas y con estado en este contexto no significan lo que cabría esperar.

La plenitud de estado con los EJB se refiere a lo que yo llamo estado conversacional . El ejemplo clásico es una reserva de vuelo. Si consta de tres pasos:

  • Asiento de reserva
  • Cargar tarjeta de crédito
  • Boleto de emisión

Imagine que cada una de ellas es una llamada a un bean de sesión. Un bean de sesión con estado puede mantener este tipo de conversación para que recuerde lo que sucede entre llamadas.

Los beans de sesión sin estado no tienen esa capacidad para el estado conversacional.

Las variables globales dentro de un bean de sesión (sin estado o con estado) son algo completamente diferente. Los beans de sesión con estado tendrán un conjunto de beans creados (ya que un bean solo se puede usar en una conversación a la vez) mientras que los beans de sedición sin estado a menudo solo tendrán una instancia, lo que hará que la variable global funcione, pero no creo esto es necesariamente garantizado

Esto ocurre porque el contenedor solo tiene una instancia de bean en el grupo que se reutiliza para todas las llamadas. Si ejecuta los clientes en paralelo, verá un resultado diferente porque el contenedor creará más instancias de beans en el grupo.

Las principales diferencias entre los dos tipos principales de beans de sesión son:

Frijoles sin estado

  1. Los beans de sesión sin estado son los que no tienen ningún estado conversacional con el cliente que ha llamado a sus métodos. Por esta razón, pueden crear un conjunto de objetos que se pueden usar para interactuar con múltiples clientes.
  2. Los beans sin estado de rendimiento son mejores ya que no tienen estados por cliente.
  3. Pueden manejar múltiples solicitudes de múltiples clientes en paralelo.

Frijoles con estado

  1. Los beans de sesión con estado pueden mantener el estado conversacional con múltiples clientes a la vez y la tarea no se comparte entre los clientes.
  2. Una vez completada la sesión, el estado no se conserva.
  3. El contenedor puede serializar y almacenar el estado como un estado obsoleto para su uso futuro. Esto se hace para guardar recursos del servidor de aplicaciones y para admitir fallas de beans.

Tiene buenas respuestas. Me gustaría agregar una pequeña respuesta. Stateless Bean no debería usarse para contener datos de clientes. Se debe usar para “modelar acciones o procesos que se pueden hacer de una vez”.