Tengo un bean de sesión sin estado que contiene un método público, varios métodos privados, y algunos instancia de las variables de nivel. A continuación es un pseudo código de ejemplo.

private int instanceLevelVar

public void methodA(int x) { 
  this.instanceLevelVar = x;
  methodB();
}

private void methodB() {
  System.out.println(instanceLevelVar);
}

Lo que yo estoy viendo es que methodB es la impresión de los valores que no pasa en MethodA. Lo mejor que me puede decir que es la impresión de los valores de otras instancias de la misma bean. Lo que haría que este?

Debo señalar que el código funciona como se esperaba el 99,9% del tiempo. Sin embargo, el .01% está causando serios problemas /preocupaciones para mí.

Entiendo que si yo había públicas de diferentes métodos, a continuación, yo no lo podría conseguir el mismo bean de la espalda, entre las llamadas, lo que podría provocar este comportamiento. Sin embargo, en este caso, la única convocatoria es el único método público. Será el contenedor (Glassfish en este caso) aún intercambio de los granos entre privados llamadas de método?

(editar) he cambiado el nombre de «nivel» a «nivel de instancia», ya que esto estaba causando cierta confusión.

Eso es bastante extraño. Está usted seguro de que su pseudocódigo realmente refleja lo que el código real?
Cuando se llama a methodB() de methodA(), no hay ninguna llamada remota por lo que este debe comportarse como cualquier clase normal en mi humilde opinión. En realidad, no tendría sentido para intercambiar granos por un método privado, los métodos privados no son ni siquiera remoto…
de acuerdo, esto debería funcionar. No puedo ver ningún problema.
Es preciso en que sólo tengo 1 método público. Yo tengo varios de la clase de las variables de nivel y múltiples métodos privados. Sin embargo, todas las variables se establecen desde dentro de un método público. Es como si el contenedor se suspende el procesamiento de la mitad y deja que el otro cliente de inicio de tratamiento con el mismo bean, que suspende y devuelve el control al cliente. Ahora todas las variables de clase han cambiado.
también, «a nivel de clase de la variable» – si es una variable de clase que tiene que ser declarada con «estática» de la palabra clave. Que podría explicar este comportamiento. El código y el nombre de la variable se contradicen unos a otros.

OriginalEl autor Preston | 2009-10-27

9 Comentarios

  1. 10

    Yo simplemente no se molestan utilizando la variable de instancia de bean de sesión sin estado. Independientemente de cuál sea la causa del problema que se han encontrado, probablemente no es algo que usted quiere hacer de todos modos. Tratar sólo con las variables locales en todo o definir las variables de instancia en clases de ayuda que usted está llamando desde el bean de sesión sin estado los métodos de negocio.

    uno de los miembros de mi equipo está diciendo la misma cosa.
    Mismo como para los servlets. Puedo contar algunas historias sobre personas que escribir servlets y asumir el contenedor web, se crea una nueva instancia de servlet sólo para «su» hilo. Nyet! De estilo funcional y sólo las variables en la pila son tus amigos aquí.

    OriginalEl autor Rocket Surgeon

  2. 24

    Cuando leí ¿Qué es un Bean de Sesión? sección de J2EE 1.4 tutorial:

    Stateless Session Beans

    Un apátridas sesión bean no mantener una conversación estado para un cliente en particular. Cuando un cliente invoca el método de un apátrida, soya, el frijol de las variables de instancia pueden contener un estado, pero sólo para la duración de la invocación. Cuando el método está terminado, el estado ya no se conservan. Excepto durante la invocación de método, todas las instancias de un estado de frijol son equivalentes, lo que permite el contenedor de EJB para asignar una instancia para cualquier cliente.

    En su caso, la llamada a methodB() de methodA() va a estar en la misma instancia y es equivalente a this.methodB(). Soy por lo tanto tienden a decir que methodB() no pueden salida de algo más que el valor que lo que se pasó a methodA().

    Esto es confirmado por la primera frase en la sección 7.11.8 en el EJB 2.0 especificación: «El contenedor debe asegurarse de que sólo un hilo puede ejecutar una instancia en cualquier momento». Esto significa que usted no puede llegar a una situación donde los datos (en sus variables de instancia) de los diferentes clientes (hilos) será mixta. El que se garantiza un acceso único a las variables de instancia hasta methodA() ha vuelto!

    Que dijo, no estoy diciendo que usted no tiene un problema en algún lugar. Pero no creo que su pseudo código es equivalente.

    (EDIT: después de Haber leído algunos comentarios para el OP pregunta, ahora hay claramente una duda sobre el pseudo código y semántico utilizado. Estoy aclarando las posibles consecuencias de abajo.)

    Subrayadas por Cohete Cirujano, ¿a qué te refieres exactamente por variable de clase? ¿De verdad quieres decir variable de clase frente a variable de instancia? Si sí, el pseudo-código, no se refleja, pero esto claramente provocar un comportamiento impredecible. En realidad, de la sección 24.1.2 (y primer punto) en la especificación EJB 2.0, es claro que no se permite escribir datos a una variable de clase (aunque se puede hacer). Debe haber una buena razón para esto 🙂

    Estoy llamando a un nivel de clase de la variable sólo porque tiene alcance a la clase en comparación con un método de nivel variable. La declaración parece private int x;
    La especificación EJB también dice: «Porque todas las instancias de un bean de sesión sin estado son equivalentes, el contenedor puede elegir a un delegado del cliente invoca el método a cualquier disposición de la instancia. Esto significa, por ejemplo, que el contenedor puede delegar las solicitudes de un mismo cliente, dentro de la misma transacción a diferentes instancias, y que el contenedor puede intercalar las solicitudes de varias transacciones a la misma instancia.» Es la última parte de la frase que me hace pensar. «y que el contenedor puede intercalar las solicitudes de varias transacciones a la misma instancia»
    así que al parecer este es un EJB 3.0 especificación de la pregunta, no 2.1
    Mmm, el OP escribió que «Porque todas las instancias de un bean de sesión sin estado son equivalentes, el contenedor puede elegir a un delegado del cliente invoca el método a cualquier disposición de la instancia. Esto significa, por ejemplo, que el contenedor puede delegar las solicitudes de un mismo cliente, dentro de la misma transacción a diferentes instancias, y que el contenedor puede intercalar las solicitudes de varias transacciones a la misma instancia.» que está en EJB 2.x spec. Pero estoy dudando ahora, me gustaría que el OP para confirmar.
    Este aún mantiene EJB 3.0, el comportamiento es el mismo, la versión de la especificación no es la parte importante.

    OriginalEl autor Pascal Thivent

  3. 5

    La causa probable del problema es que el contenedor es utilizar el mismo objeto en dos solicitudes (por lo tanto dos hilos) al mismo tiempo. Así que el primer hilo llega a la línea que llama a methodB y, a continuación, en el siguiente hilo se pone el código que llama a methodB y, a continuación, el primer hilo ejecuta la llamada a methodB, causando el problema. Eso explicaría el comportamiento, en cualquier caso. No parecen ajustarse a la especificación, pero que podría ser un error.

    En general, incluso si se permite, manteniendo el estado en el grano, no es una gran idea. Esto lleva a la confusión de código y puede fácilmente conducir a errores cuando se le olvida a empezar de nuevo con todo su estado en cada llamada al método.

    Sería mucho mejor para pasar los objetos a su alrededor entre los métodos, y que evitaría todos los problemas.

    OriginalEl autor Yishai

  4. 3

    Probablemente tu no están correctamente la reinicialización de la variable de instancia.

    Variables de instancia

    En general, no debemos mantener el estado de nuestro bean de sesión sin estado. Los objetos referenciados por las variables de instancia, si no anulada después de su uso, se mantienen vivas hasta el final de la petición e incluso más si nuestro contenedor EJB piscinas de los beans de sesión para reutilizar. En el último caso, debemos asegurarnos de que la variable de instancia obtener correctamente reiniciadas en una solicitud posterior. Por lo tanto, el uso de variables de instancia pueden conducir a las siguientes cuestiones:

    • durante la misma solicitud, la variable de instancia compartida entre los diferentes métodos pueden fácilmente conducir a errores donde nos olvidar para volver a empezar con el estado correcto en cada llamada al método
    • en caso de contenedor EJB piscinas de beans de sesión y puede que nuestro código no trata correctamente reinicializar las variables de instancia podemos reutilización rancio estado en una petición anterior
    • variables de instancia han ámbito de la instancia que podría presentar problemas de pérdida de memoria, donde el espacio en el Montón se utiliza para conservar los objetos que no son (o no deberían) a utilizarse.

    Variables de clase

    Como por ejemplo, las variables, las variables de la clase no debe ser usado para mantener el estado compartido en el bean de sesión sin estado. Esto no significa que no se debe utilizar la palabra clave static, sino que debemos usar con precaución (por ejemplo, definir inmutable constantes, algunos de fábrica estáticos de la clase, etc.)

    OriginalEl autor puglieseweb

  5. 2

    Porque esto es muy extraño, he realizado una prueba rápida con Netbeans y mi local Glassfish 2.1.

    1. Crear un nuevo proyecto utilizando Muestras->Java EE->Servlet Apátridas. Esto crea un proyecto de empresa con un simple apátridas bean y un servlet que lo utiliza.
    2. He modificado el apátridas bean para este aspecto, tan cerca de su ejemplo como es posible que yo pienso.

      @Stateless
      public class StatelessSessionBean implements StatelessSession {
      
         String clName;
      
         private void testNa() {
            System.out.println(clName);
         }
      
         public String sayHello(String name) {
            this.clName = name;
            testNa();
            return "Testcase";
         }
      }

    Esto funciona como debería. No sé qué editor usas, pero si es Netbeans puede ser interesante.

    El código se considera como anidada en la lista, necesita 8 espacios en blanco oO
    Muchas gracias Pascal!
    El ejemplo se ve a la derecha. Sin embargo, creo que el problema sólo se produce cuando hay varios granos en uso. Voy a intentar escribir el código de la prueba y el uso de algunas de carga de software para ver si puedo reproducir un éxito.
    Es este EJB 3.0? Creo que la pregunta fue específicamente acerca de EJB 2.1
    como Preston mencionó que trabaja en un servidor GlassFish contenedor yo más o menos asumido 3.0. Yo no veo ninguna referencia a 2.1 en la pregunta original, sólo hay una cita de la 2.1 especificación por Pascal Thivent en otra respuesta.

    OriginalEl autor fvu

  6. 0

    Todo depende de lo que quieres decir por «nivel de clase de la variable». Una variable de clase debe tener el modificador static. Si clName no, entonces cada instancia de su bean de sesión sin estado tiene su propia copia de clName. Su servidor de aplicaciones Java EE probablemente creado un grupo de dos o más instancias del bean de sesión sin estado, y cada una de sus llamadas a testNa() y sayHello() se envía a cualquier instancia.

    Estoy llamando a un nivel de clase de la variable sólo porque tiene alcance a la clase en comparación con un método de nivel variable. La declaración parece private int x;
    Así que estás diciendo que la convocatoria pública para sayHello puede ser manejada por el bean 1 y la llamada privada a testNa puede ser manejada por el bean 2?
    Sí, o en el ejemplo actual, llamada methodA() de un frijol y methodB() de otro, etc. Ya que cada bean (objeto) tiene su propio instanceLevelVar, si estabas esperando instanceLevelVar a ser compartida por todos los granos en su clase, usted se sorprenderá por los resultados.

    OriginalEl autor Jim Ferrans

  7. 0

    Me topé con esta pregunta cuando he experimentado el mismo problema. En mi caso, el método privado que realmente establece la variable de instancia. Lo que he notado es que a veces la variable de instancia, ya que, obviamente de una solicitud anterior.

    @Stateless
    public class MyBean {
      String someString;
    
      public void doSomething() {
        internalDoSomething();
      }
    
      private void internalDoSomething() {
        if (someString != null) {
          System.out.println("oops, someString already contained old data");
        }
    
        this.someString = "foo";
      }
    }

    Supongo que tiene sentido. Cuando el contenedor re-utiliza una caché ejemplo, cómo debe saber cómo borrar las variables…

    Para mí, esto está en línea con y confirma tanto de Pascal referencia a la especificación EJB («variables de instancia son compatibles») y Rocket Cirujano de la recomendación («no lo hagas, el uso de las variables locales en lugar de»).

    OriginalEl autor Hank

  8. 0

    El problema con el uso de las variables de Instancia en apátridas Frijoles.

    De acuerdo a la especificación JEE ese mismo apátridas EJB instancia podría ser compartida con otro cliente así. El pulgar de la regla no es crear las variables de instancia en Apátridas Ejb.

    Podría ser posible que los dos clientes que acceden a la aplicación simultáneamente se proporcionan mismo EJB ejemplo, lo que podría crear problemas, ya que no hay incoherencia de los datos.

    Por lo que no es una buena idea utilizar las variables de instancia en apátridas EJB frijoles .

    OriginalEl autor user2600752

  9. 0

    Tuve problema similar porque yo estática global variable de clase en mi clase ejb y cuando tuve concurrente apátridas EJB ejecución, la variable se ha sobrescrito por otras instancias.

    Campos de clase estática son compartidos entre todas las instancias de una clase particular, pero sólo dentro de una sola Máquina Virtual de Java (JVM). La actualización de una clase estática campo implica un intento de compartir el valor del campo entre todas las instancias de la clase.

    La esperanza de ayudar a alguien 🙂

    OriginalEl autor Bemat

Dejar respuesta

Please enter your comment!
Please enter your name here