Estoy revisando 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 llamadas a métodos, ¿por qué mi programa está actuando como lo hace?
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 es 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 ejemplo simple tipo hola mundo de un bean de sesión sin estado que se comporta de manera diferente cuando lo cambia a estado?
java
jakarta-ee
ejb
ejb-3.1
stateful-session-bean
Stanley Kelly
fuente
fuente
Respuestas:
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 pieza con estado del bean de sesión con estado es como la sesión en los 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 obtiene 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 distribuirse 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 la aplicación se asegura de que sea así. ¡Imagínese lo popular que sería su aplicación si pudiera comenzar a comprar y luego el servidor de la aplicación me diera su bean de sesión con estado cuando llegué!
Entonces, su miembro de datos privados es de hecho "estado", pero no es "carrito de compras". Intente rehacer su (muy bueno) ejemplo para que la variable incrementada esté asociada con un usuario en particular. Increméntelo, cree un nuevo usuario y vea si todavía pueden ver el valor incrementado. Si se hace correctamente, cada usuario debería ver solo su versión del contador.
fuente
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 implementación , pero las instancias generalmente se agrupan, y no menciono los entornos agrupados). En otras palabras, aunque los beans sin estado pueden tener variables de instancia, estos campos no son específicos de un cliente, así que no confíe en ellos entre llamadas remotas.
Por el contrario, los Stateful Session Beans (SFSB) están dedicados a un cliente durante toda su vida, no hay intercambio ni agrupación 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 de conversación . Esto significa que las variables de instancia del bean pueden mantener datos relativos al cliente entre invocaciones de métodos. Y esto hace posible tener llamadas de método interdependientes (los cambios realizados por un método afectan las llamadas de método posteriores). Los procesos de varios pasos (un proceso de registro, un carrito de compras, un proceso de reserva ...) son casos de uso típicos para SFSB.
Una cosa más. Si está utilizando SFSB, debe evitar inyectarlos en clases de naturaleza multiproceso, como Servlets y beans administrados por 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
HttpSession
objeto para la actividad futura. Algo como eso:fuente
Sin estado y sin estado en este contexto no significa exactamente lo que podría esperar.
Statefulness con EJB se refiere a lo que yo llamo estado conversacional . El ejemplo clásico es la reserva de un vuelo. Si consta de tres pasos:
Imagine que cada uno de ellos es una llamada a un método a un bean de sesión. Un bean de sesión con estado puede mantener este tipo de conversación para recordar lo que sucede entre llamadas.
Los beans de sesión sin estado no tienen tal 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 grupo de beans creado (ya que un bean solo se puede usar en una conversación a la vez) mientras que los beans de sesión sin estado a menudo solo tendrán una instancia, lo que hará que la variable global funcione, pero no creo esto está necesariamente garantizado.
fuente
Las principales diferencias entre los dos tipos principales de beans de sesión son:
Frijoles sin estado
Frijoles con estado
fuente
Esto sucede 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 bean en el grupo.
fuente
Tiene buenas respuestas. Me gustaría agregar una pequeña respuesta. Stateless Bean no debe utilizarse para almacenar datos de clientes. Debe utilizarse para "modelar acciones o procesos que se pueden realizar de una vez".
fuente
Buena pregunta,
pruebe este código (cambie MyBean Stateful / Stateless.):
Servlet_1
Servlet_2
caso: MyBean - @ Stateless
http: // localhost: 8080 / MYServletDemo / ServletClient
1
http: // localhost: 8080 / MYServletDemo / ServletClient
2
http: // localhost: 8080 / MYServletDemo_war_exploded / newServletClient
3
http: // localhost: 8080 / MYServletDemo / ServletClient
4
caso: MyBean - @ Stateful
http: // localhost: 8080 / MYServletDemo / ServletClient
1
http: // localhost: 8080 / MYServletDemo / ServletClient
2
http: // localhost: 8080 / MYServletDemo / newServletClient
1
http: // localhost: 8080 / MYServletDemo / ServletClient
3
fuente