Domanda

È possibile accedere a un fagiolo statale all'interno di un fagiolo apolide?

Il mio problema è che ho un bean di sessione chiamato utente e desidero accedere alle informazioni dell'utente all'interno di un fagiolo apolido ...

Sto provando così:

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

Dalla parte 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");

Il risultato di questo caso di test è java.lang.AssertionError: expected:<null> but was:<Alex>

fallisce .. sembra che come sto chiedendo che il fagiolo statale mi stia restituendo una nuova istanza ...

  1. So perché questo non funziona. Perché il mio test fallisce: p. Ottengo una nuova istanza ..
  2. Voglio controllare alcune autorizzazioni dell'utente accesso in EJB perché non voglio contare sul lato cliente perché potrei fare un errore lì o dirò ad altri sviluppatori di fare una GUI per il mio progetto ..
  3. Non voglio usare la sicurezza Java ee Beucause non so come effettuare l'accesso in un'applicazione RCP
  4. La mia domanda principale è: come posso accedere a un fagiolo di sessione (lo stesso che il cliente possiede) all'interno di un EJB .. è possibile? E come?

Chiedo quasi la stessa cosa che questo ragazzo sta chiedendo: Concetto per la sessione di accesso riutilizzabile nelle chiamate EJB RMI

Voglio farlo ma non con Jaas ...

Grazie in anticipo

È stato utile?

Soluzione

Dovresti mai iniettare a @Stateful bean (sfsb) in a @Stateless Bean (SLSB). Un SFSB vive fintanto che il suo cliente vive (il cliente è l'istanza in cui è stato iniettato SFSB, che è in questo caso SLSB stesso). Gli SLSB sono comunque intenzionati ad essere apolide E la maggior parte dei contenitori li hanno in una piscina. Quindi ogni volta che lo SLSB torna in piscina dopo l'uso, verrà riutilizzato completamente altrove, ma contiene la stessa istanza SFSB come lo è stato quando lo SLSB è stato creato per la prima volta! Ciò può portare a risultati indesiderati.

Inoltre, ogni volta che otterrai l'SFSB da JNDI, otterrai un nuovo di zecca istanza che è diversa dagli SLSB non condiviso altrove. Il client di SFSB è quindi l'istanza della classe client corrente in cui hai l'SFSB da JNDI. Dovresti tenere te stesso questa istanza e riutilizzare la stessa istanza fino a quando non hai finito con l'esecuzione della transazione su di essa. Uno dei modi è la memorizzazione nella sessione HTTP da soli o in una sessione ASCOPED Managed Bean del framework MVC che stai utilizzando.

Il requisito funzionale non è del tutto chiaro per me, quindi è difficile dare una risposta adatta come risolvere il tuo problema particolare, ma ho l'impressione che tu in realtà È necessario archiviare l'utente nella sessione HTTP, non in un SFSB. L'errore del principiante più comune per quanto riguarda i fagioli di sessione è vale a dire che interpretano erroneamente la "sessione" nel contesto EJB come la sessione HTTP.

Vedi anche questa risposta correlata su una domanda dello stesso tipo per una spiegazione più approfondita: La richiesta JSF SCOPED BEan continua a ricreare nuovi fagioli di sessione statale su ogni richiesta? Secondo la storia della tua domanda hai familiarità con JSF, quindi questa risposta dovrebbe essere facile comprensibile.

Altri suggerimenti

In generale, è possibile accedere a alcuni fagioli di sessione statale esistenti all'interno degli apolidi. Può essere ad esempio dato come argomento al metodo aziendale del bean di sessione apolidi.

Ma ciò che stai cercando non può funzionare. Il motivo è che sia l'iniezione dipendente (@EJB) che la ricerca (CTX.Lookup ...) sono garantite per chiamare NewInstance e come conseguenza avrai una nuova istanza.

Questo è spiegato nelle specifiche con le seguenti parole:

La vita di una sessione dell'istanza del bean inizia quando un client ottiene un riferimento a un'istanza di sessione statale attraverso l'iniezione di dipendenza o una ricerca JNDI, o quando il client invoca un metodo di creazione sull'interfaccia domestica del fagiolo di sessione. Ciò fa invocare il contenitore per la nuova istanza della classe di sessione per creare una nuova istanza di fagioli di sessione.

Nel caso in cui gli altri non fossero già abbastanza chiari: stai sbagliando! ;)

Sono d'accordo sul fatto che potrebbe essere confuso, ma l'unica sessione nei fagioli di sessione EJB è mantenuta nel fagiolo proxy che si ottiene dall'InitalContext.

I fagioli diversi che ottieni da questo contesto non condividono alcun tipo di sessione comune. In EJB, i fagioli non sono archiviati in una sessione EJB ma sono questa sessione.

In altre parole, InitialContext (CTX nel codice) non è l'equivalenza EJB per HTTPSESSION.

Ancora peggio forse è che nel tuo codice l'utente è un fagiolo EJB. Questo è sbagliato.

Un utente è un sostantivo nella tua applicazione. Questi sono rappresentati da entità JPA o fagioli java "normali" semplici. Gli EJB sono per l'implementazione del Verbi Nella tua domanda: servizi, DAOS, repository, ecc.

Lo stato in fagioli di sessione statale dovrebbe aggrapparsi ai dati del modello durante un processo aziendale (per memorizzazione nella cache, bloccaggio, prenotazioni, ecc.). In nessuna situazione questo stato dovrebbe essere i dati del modello.

Il mio consiglio: lascia andare il tuo attuale "design". Non provare a risolverlo, non cercare di giustificarlo. Lascialo andare, elimina il tuo codice, non guardare indietro. Leggi alcuni buoni libri su EJB e poi ricomincia.

Buona fortuna!

Non sto convalidando se stai andando bene/sbagliato nell'uso di SFSB e SLSB. Ma di seguito è la risposta al tuo problema

Opzione-1: dal tuo servlet, esegui la ricerca JNDI per SFSB. Questa dovrebbe essere una volta. Conserva il riferimento restituito di SFSB nella tua HTTPSESSION. Quando si chiama il metodo SLSB che necessita dell'istanza SFSB per la memorizzazione dei dettagli dell'utente, passare l'oggetto di riferimento SFSB sopra come parametro al metodo SLSB. Quindi accedilo dal metodo SLSB e archivia i dati utente.

Problema con l'opzione-1: stai legando la coppia il tuo meccanismo di persistenza (SFSB) al tuo codice dell'interfaccia utente (poiché lo memorizzi in httpSession e lo passiamo in giro). Domani, se vuoi passare a un altro meccanismo di persistenza come una cache, dovrai fare molta rielaborazione. Ancora una volta, se vuoi esporre il tuo metodo SLSB come servizio Web, non sarai in grado di farlo in quanto non è possibile XML-Ize il riferimento dell'oggetto SFSB. In breve, una cattiva opzione.

Opzione-2: avere un hashmap statico in qualche classe nel livello commerciale. Supponiamo di avere alcuni attributi di transazione univoci per ogni transazione, qualcosa come un ID. Quando si avvia la transazione, dal tuo livello commerciale, crea SFSB, memorizza il suo riferimento nell'hashmap statico con ID come chiave. Quando si chiama il metodo di servizio SLSB, passare questo ID (presumo che ogni transazione possa avere un ID univoco). Dal metodo SLSB, utilizzare l'ID per cercare riferimento SFSB memorizzato nell'hashmap statico. Usalo per il tuo spazio di archiviazione. In questa opzione, l'interfaccia utente e SFSB non sono accoppiati. Domani, se vuoi cogliere il tuo meccanismo di persistenza, puoi fare senza imparare i clienti poiché le tue modifiche saranno limitate all'interno di BC Tier.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top