2010-02-28 44 views
81

Estoy siguiendo el tutorial de Java EE 6 y estoy tratando de entender la diferencia entre beans de sesión sin estado y stateful. Si los beans de sesión sin estado no retienen su estado entre las llamadas al método, ¿por qué mi programa está actuando como está?Enterprise Beans Stateless and Stateful Beans

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()); 
    } 

} 

que estaba esperando para volver obtieneNumero 0 cada vez pero vuelve 1 y recargas del servlet en mi navegador aumentarlo 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?

+6

Relacionado: http://stackoverflow.com/questions/8887140/jsf-request-scoped-bean-keeps-recreating-new-stateful-session-beans-on-every-req Esta respuesta es quizás más simple de entender. Tenga en cuenta que los servlets son básicamente de ámbito de aplicaciones (solo hay 1 instancia de servlet en toda la aplicación que se comparte/reutiliza en todas las solicitudes/sesiones HTTP. – BalusC

+0

hola, primero se incrementa y luego se obtiene el valor .... por lo que no se puede esperar un valor de 0 – rzur2004

+0

Solo quiero agradecerle por preguntar esto, mi problema está solucionado en este momento. No podría haberlo preguntado mejor –

Respuesta

88

La diferencia importante no son las variables de miembros privados, sino la asociación de 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é!

Así que 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.

+0

¿Puede proporcionar en un comentario una respuesta explícita? ¿Por qué siempre el frijol sin estado en este ejemplo retiene el valor y aumente cada vez? Porque solo hay un usuario? – arjacsoh

+2

El contador aumentará independientemente del número de usuarios. Por lo tanto, si el usuario 1 entra e incrementa el contador a 1 y al mismo tiempo el usuario2 entra y lo incrementa, el valor será 2. En realidad, debe mostrar que el usuario 1 tiene 1 y el usuario 2 tiene 1 (si eso es lo que pretende hacer. Ejemplo de carrito de compras como el anterior). – Krishna

16

Stateless y con estado en este contexto no significan lo que cabría esperar.

Statefulness con EJB se refiere a lo que llamo estado conversacional. El ejemplo clásico es una reserva de vuelo. Si consiste en tres pasos:

  • Reserva de asiento
  • tarjetas de crédito cobran
  • emisión del billete

Imagínese que cada uno de ellos es una llamada a un método de 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 las 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

125

Frijoles sin estado de sesión (SLSB) se no atadas a un cliente y no hay ninguna garantía para un cliente para obtener la misma instancia con cada invocación de métodos (algunos contenedores puede crear y destruir los frijoles con cada sesión de invocación de métodos , 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 dependen de ellos entre llamadas remotas.

Por el contrario, los beans con estado de sesión (SFSB) se dedicados a un cliente para toda la vida, no hay intercambio o el agrupamiento de los casos (que puede ser desalojado de la memoria después de pasivación para ahorrar recursos, pero eso es otra historia) y mantienen 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, entonces 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 así:

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

Gracias por la aclaración. Cuando uso un programa de línea de comando independiente para el cliente, es obvio que veo la diferencia. –

+0

Gracias por esta aclaración: esta era exactamente la información que estaba buscando. –

+0

gracias por sus comentarios, son más esclarecedores. Primero, proporcione la definición abstracta, luego especifique algunos casos de uso para cada situación y luego señale algunas trampas. Excelente +1 – arthur

4

Esto ocurre porque el contenedor solo tiene una instancia de bean en la agrupación 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.

1

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".

3

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

Frijoles sin estado

  1. Frijoles sin estado de sesión son los que no tienen un estado conversacional con el cliente que ha pedido 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 con buen rendimiento son mejores ya que no tienen estados por cliente.
  3. Pueden manejar múltiples solicitudes de varios clientes en paralelo.

beans con estado

  1. beans de sesión con estado pueden mantener el estado de conversación con varios clientes al mismo tiempo y la tarea no es compartida entre los clientes.
  2. Después de completar la sesión, el estado no se conserva.
  3. El contenedor puede serializar y almacenar el estado como a estado para uso futuro. Esto se hace para guardar recursos del servidor de aplicaciones y para admitir fallas de beans.
Cuestiones relacionadas