Java Beans de Empresa sin estado y con Estado


Estoy pasando por el tutorial de Java EE 6 y estoy tratando de entender la diferencia entre los frijoles de sesión sin estado y con estado. Si los frijoles de sesión sin estado no conservan su estado entre las llamadas a los métodos, ¿por qué mi programa está actuando de la manera en que 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 está devolviendo 1 y las recargas del servlet en mi navegador lo aumentan más. El problema es con mi comprensión de cómo sesión sin estado los frijoles funcionan y no con las bibliotecas o el servidor de aplicaciones, por supuesto. ¿Puede alguien darme un ejemplo simple del tipo hello world de un bean de sesión sin estado que se comporta de manera diferente cuando lo cambia a stateful?

Author: dit, 2010-02-28

6 answers

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

La pieza con estado de session bean es como la sesión en servlets. Los beans de sesión con estado permiten que tu app siga teniendo 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 usuario particular.

Un bean de sesión con estado debe repartirse 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 así sea. Imagine lo popular que sería su aplicación si pudiera comenzar a comprar y luego el servidor de aplicaciones me dio su bean sesión con estado cuando llegué!

Así que su miembro de datos privados es de hecho "estado", pero no es "carrito de compras". Trate de rehacer su (muy bueno) ejemplo a hacer que la variable incrementada se asocie con un usuario en particular. Incremente, cree un nuevo usuario y vea si todavía puede ver el valor incrementado. Si se hace correctamente, cada usuario debe ver solo su versión del contador.

 88
Author: duffymo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-28 13:57:09

Stateless Session Beans (SLSB) son no atado para un cliente y hay ninguna garantía por un cliente para obtener la misma instancia con cada invocación de método (algunos envases pueden crear y destruir los frijoles con cada invocación del método de la sesión, esta es una implementación específica de la decisión, pero los casos son generalmente agrupados y no quiero mencionar entornos de clúster). En otras palabras, aunque los frijoles sin estado pueden tener variables de instancia, estos campos no son específicos de uno cliente, así que no confíes en ellos entre llamadas remotas.

En contraste, los Frijoles de sesión con estado (SFSB) están dedicados a un cliente durante toda su vida, no hay intercambio o agrupación de instancias (puede ser desalojado de la memoria después de la pasivación para ahorrar recursos, pero eso es otra historia) y mantener el estado conversacional. Esto significa que las variables de instancia de bean pueden mantener datos relativos al cliente entre 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). 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, entonces debe evitar inyectarlos en clases que son de naturaleza multiproceso, como Servlets y JSF managed beans (no desea que sea compartido por todos los clientes). Si desea utilizar SFSB en su aplicación web, entonces usted necesita realizar una búsqueda JNDI y almacenar la instancia EJB devuelta en el objeto HttpSession para actividades futuras. 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
}
 129
Author: Pascal Thivent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-28 15:32:39

Apátrida y con estado en este contexto no significa exactamente lo que podría esperar.

Statefulness con EJBs 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
  • Tarjeta de crédito de cargo
  • Emitir ticket

Imagine que cada uno de ellos es una llamada de 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 pasa entre llamadas.

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

Las variables globales dentro de un session bean (stateless o stateful) son algo completamente distinto. Los frijoles de sesión con estado tendrán un grupo de frijoles creados (ya que un frijol solo se puede usar en una conversación a la vez), mientras que los frijoles de sesión sin estado a menudo solo tendrán una instancia, lo que hará que la variable global funcione, pero no creo que esto esté necesariamente garantizado.

 16
Author: cletus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-28 13:59:06

Esto sucede porque el contenedor solo tiene una instancia de bean en el pool que se está reutilizando 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.

 4
Author: Neyma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-28 22:25:29

Las principales diferencias entre los dos tipos principales de session beans son:

Judías sin estado

  1. Los frijoles de sesión sin estado son los que no tienen estado de conversación con el cliente que ha llamado a sus métodos. Por esta razón, pueden crear un grupo de objetos que se pueden usar para interactuar con varios clientes.
  2. Los frijoles sin estado en cuanto al 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 de conversación con varios clientes a la vez y la tarea no se comparte entre los clientes.
  2. Una vez finalizada la sesión, el estado no se conserva.
  3. El contenedor puede serializar y almacenar el estado como un estado obsoleto para uso futuro. Esto se hace para ahorrar recursos del servidor de aplicaciones y para soportar bean fallo.
 3
Author: Pritam Banerjee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-20 20:08:31

Tiene buenas respuestas. Quisiera añadir una pequeña respuesta. Bean sin estado no debe usarse para almacenar datos de clientes. Se debe utilizar para "modelar acciones o procesos que se pueden hacer de una sola vez".

 2
Author: malatesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-27 05:26:22