Pregunta

¿Es posible acceder a un frijol de sesión con estado dentro de un frijol sin estado?

Mi problema es que tengo un bean de sesión llamado usuario y quiero acceder a la información del usuario dentro de un frijol sin estado ...

Estoy tratando así:

Lado de EJB:

@Stateless
public class OfferManagerBean implements OfferManagerLocal, OfferManager
{
    @Resource 
    private SessionContext context;
    @EJB
    private ro.project.ejb.interfaces.User user;
    public String getUsername()
    {
        user = (ro.project.ejb.interfaces.User) context.lookup("java:global/project/projectEJB/User!ro.project.ejb.interfaces.User");
        return user.getUsername();
}

Lado del cliente

 User user = (User) ctx.lookup("java:global/project/projectEJB/User!ro.project.ejb.interfaces.User");
 user.setUsername("Alex");

 OfferManager offerManager = (OfferManager) ctx.lookup("java:global/project/projectEJB/OfferManagerBean!ro.project.ejb.interfaces.OfferManager");
 assertEquals(offerManager.getUsername(), "Alex");

El resultado de este caso de prueba es java.lang.AssertionError: expected:<null> but was:<Alex>

falla ... Parece que cómo estoy solicitando que el frijol con estado me devuelva una nueva instancia ...

  1. Sé por qué esto no funciona. Porque mi prueba falla: p. Tengo una nueva instancia ..
  2. Quiero verificar ciertos permisos del usuario iniciado en EJB porque no quiero contar con el lado del cliente porque podría cometer un error allí o les diré a otros desarrolladores que hagan una GUI para mi proyecto.
  3. No quiero usar la seguridad de Java EE, no sé cómo hacer el inicio de sesión en una aplicación RCP
  4. Mi pregunta principal es: ¿Cómo accedo a un bean de sesión (el mismo que posee el cliente) dentro de un EJB .. ¿Es posible? ¿Y cómo?

Estoy preguntando casi lo mismo que este tipo está preguntando: Concepto para la sesión de inicio de sesión reutilizable en las llamadas RMI EJB

Quiero hacer eso pero no con Jaas ...

Gracias de antemano

¿Fue útil?

Solución

Debería nunca inyectar un @Stateful frijoles (sfsb) en un @Stateless frijoles (SLSB). Un SFSB vive mientras su cliente viva (el cliente es la instancia en la que se inyecta el SFSB, que en este caso es el SLSB en sí). Sin embargo, los SLSB tienen la intención de ser apátrida Y la mayoría de los contenedores los tienen en una piscina. Entonces, cada vez que el SLSB regrese a la piscina después de su uso, se reutilizará completamente en otro lugar, ¡pero tiene la misma instancia de SFSB que fue cuando se creó el SLSB por primera vez! Esto puede conducir a resultados indeseables.

Además, cada vez que obtenga el SFSB de JNDI, obtendrá un Para estrenar instancia que es diferente a SLSB no compartido en otro lugar. El cliente de SFSB es la instancia de clase de cliente actual en la que tiene el SFSB de JNDI. Se supone que debe mantener esta instancia usted mismo y reutilizar la misma instancia hasta que haya terminado de realizar la transacción. Una de las formas es almacenarlo en la sesión HTTP usted mismo o en una sesión de frijoles administrados del marco MVC que está utilizando.

El requisito funcional no es del todo claro para mí, por lo que es difícil dar una respuesta adecuada sobre cómo resolver su problema particular, pero tengo la impresión de que usted Realmente Necesita almacenar al usuario en la sesión HTTP, no en un SFSB. El error de principiante más común en cuanto a la sesión de los frijoles es que interpretan incorrectamente la "sesión" en el contexto de EJB como la sesión HTTP.

Vea también esta respuesta relacionada sobre una pregunta del mismo tipo para una explicación más profunda: ¿Solicitud de JSF Bean Scoped Bean sigue recreando nuevos frijoles de sesión con estado en cada solicitud? Según su historial de preguntas, está familiarizado con JSF, por lo que esta respuesta debería ser fácil de entender.

Otros consejos

En general, es posible acceder a ciertos bean de sesión estestados existentes dentro del frijol apáculo. Se puede dar como argumento como argumento al método comercial de Stacune Session Bean.

Pero lo que estás intentando no puede funcionar. La razón es que tanto la inyección dependiente (@EJB) como la búsqueda (ctx.lookup ...) están garantizadas que llamen a NewInstance y, como consecuencia, tendrá una nueva instancia.

Esto se explica en especificación con las siguientes palabras:

La vida de una instancia de Bean de sesión comienza cuando un cliente obtiene una referencia a una instancia de Bean de sesión con estado a través de la inyección de dependencia o la búsqueda JNDI, o cuando el cliente invoca un método Crear en la interfaz de inicio de Session Bean. Esto hace que el contenedor invoque NewInstance en la clase Session Bean para crear una nueva instancia de Session Bean.

En caso de que los demás ya no fueran lo suficientemente claros: ¡lo estás haciendo mal! ;)

Estoy de acuerdo en que podría ser confuso, pero la única sesión en EJB Session Beans se mantiene en el bean proxy que obtiene del inititalcontext.

Los diferentes frijoles que obtienes de este contexto no comparten ningún tipo de sesión común. En EJB, los frijoles no se almacenan en una sesión de EJB, pero son esta sesión.

En otras palabras, el initialContext (CTX en su código) no es la equivalencia de EJB para la httpsession.

Peor peor quizás es que en su código el usuario es un frijol EJB. Esto está mal.

Un usuario es un sustantivo en su aplicación. Estos están representados por entidades JPA o frijoles Java 'normales' simples. Los EJB son para implementar el verbos En su aplicación: Servicios, DAOS, Repositorios, etc.

Se supone que el estado en los frijoles de sesión con estado debe resistir los datos del modelo durante un proceso comercial (para almacenar en caché, bloqueo, reservas, etc. En ninguna situación debería ser este estado los datos del modelo.

Mi consejo: deja ir tu 'diseño' actual. No intentes solucionarlo, no intentes justificarlo. Déjelo ir, elimine su código, no mire hacia atrás. Lea algunos buenos libros sobre EJB y luego comience de nuevo.

¡Buena suerte!

No estoy validando si está haciendo lo correcto/incorrecto en el uso de SFSB y SLSB. Pero a continuación se encuentra la respuesta a su problema

Opción-1: desde su servlet, realice JNDI Buscar para SFSB. Esto debería ser una vez. Almacene la referencia devuelta de SFSB en su httpsession. Cuando llame al método SLSB que necesita la instancia SFSB para almacenar los detalles del usuario, pase el objeto de referencia SFSB anterior como parámetro al método SLSB. Luego acceda a él desde el método SLSB y almacene los datos del usuario.

Problema con la opción 1: está vinculando a la pareja de su mecanismo de persistencia (SFSB) a su código de IU (ya que lo almacena en httpsession y lo pasa). Mañana, si quieres cambiar a otro mecanismo de persistencia como un caché, deberás hacer mucho trabajo. Nuevamente, si desea exponer su método SLSB como servicio web, no podrá hacerlo, ya que no puede xML-tamaño la referencia del objeto SFSB. En resumen, una mala opción.

Opción-2: Tenga un hashmap estático en alguna clase en el nivel de negocios. Suponga que tiene algunos atributos de transacción únicos para cada transacción, algo así como una ID. Cuando comience la transacción, desde su nivel comercial, cree el SFSB, almacene su referencia en el hashmap estático con ID como clave. Cuando llame al método de servicio SLSB, pase esta ID (supongo que cada transacción puede tener una ID única). Desde el método SLSB, use la ID para buscar la referencia SFSB almacenada en el hashmap estático. Úselo para su almacenamiento. En esta opción, su UI y SFSB no está acoplado. Mañana, si desea anotar su mecanismo de persistencia, puede hacer sin afectar a los clientes, ya que sus cambios serán limitados dentro de BC Tier.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top