Il bean con scope richiesta JSF continua a ricreare nuovi bean di sessione Stateful su ogni richiesta?

Sto costruendo la mia prima applicazione Java EE usando JSF, PrimeFaces, Glassfish e Netbeans. Perché sono nuovo, è ansible che mi sto avvicinando al problema principale sbagliato.

Problema principale: desidero mantenere le informazioni dell’utente in modo sicuro. Sembra che vi siano idee contrastanti sulla necessità di mantenerlo in un bean di sessione JSF o in un bean EJB di sessione stateful. Sto cercando di utilizzare un bean di sessione con stato perché è più sicuro in questo modo.

Il problema è che la mia applicazione sembra creare più istanze di quel bean quando mi aspetto che ne crei una e la riutilizzi. Se @PostConstruct la pagina, esegue @PostConstruct e @PostActivate 3 volte, tutte con istanze diverse. Poi vengono tutti distrutti quando re-distribuisco l’applicazione.

Ho frainteso come dovrebbe funzionare o se qualcosa è configurato male?

Proverò a mostrare un esempio di codice ridotto:

basic.xhtml :

     Facelet Title   Hello from Facelets  Authenticated   Authenticated   Authenticated    

LoginController :

 @Named(value = "loginController") @RequestScoped public class LoginController implements Serializable { @EJB private UserBeanLocal userBean; public boolean isAuthenticated() { return userBean.isAuthenticated(); } } 

UserBean (esclusa interfaccia UserBeanLocal )

 @Stateful public class UserBean implements UserBeanLocal, Serializable { boolean authenticated = false; @PostConstruct @PostActivate public void setup(){ System.out.println("##### Create user Bean: "+this.toString()); } @Override public boolean isAuthenticated() { System.out.println("########## Authentication test is automatically passing."); authenticated = true;//hard coded for simplicity. return authenticated; } @PrePassivate @PreDestroy public void cleanup(){ System.out.println("##### Destroy user Bean"); } } 

Infine, ecco l’output Glassfish dopo averlo rinfrescato tre volte:

 INFO: ##### Create user Bean: boundary._UserBean_Serializable@2e644784 INFO: ########## Authentication test is automatically passing. INFO: ########## Authentication test is automatically passing. INFO: ########## Authentication test is automatically passing. INFO: ##### Create user Bean: boundary._UserBean_Serializable@691ae9e7 INFO: ########## Authentication test is automatically passing. INFO: ########## Authentication test is automatically passing. INFO: ########## Authentication test is automatically passing. INFO: ##### Create user Bean: boundary._UserBean_Serializable@391115ac INFO: ########## Authentication test is automatically passing. INFO: ########## Authentication test is automatically passing. INFO: ########## Authentication test is automatically passing. 

I bean di sessione con stato (SFSB) non sono esattamente ciò che si pensa di essere. Sembra che pensi che si comportino in qualche modo come i bean gestiti JSF con scope di sessione. Questo non è vero. Il termine “sessione” in EJB ha un significato completamente diverso rispetto alla sessione HTTP che avevi in ​​mente.

La “sessione” in EJB deve essere interpretata nel contesto transazionale. La transazione (fondamentalmente, la sessione DB) vive in caso di SFSB fino a quando il cliente vive. Il client di SFSB è nell’esempio in particolare non il browser Web, ma l’istanza di bean gestita da JSF stessa, esattamente quella in cui è stato iniettato l’SFSB. Dato che hai inserito il bean gestito JSF nell’ambito della richiesta, l’SFSB verrà ricreato su ogni richiesta HTTP insieme al bean gestito JSF.

Ad esempio, provare a inserire il bean gestito JSF nell’ambito della vista. L’ambito di visualizzazione è utile per un modulo a più fasi sulla stessa pagina, ad esempio. Ogni volta che la vista viene reinserita su se stessa, viene riutilizzata la stessa istanza di bean gestita da JSF e questa istanza consente di accedere alla stessa istanza di SFSB, così come avviene quando è stato creato il bean, che non è condiviso altrove. La transazione SFSB dura finché il client (il bean con gestione JSF con scope vista) vive.

Un bean di sessione stateless (SLSB) può essere condiviso altrove, ma ciò non dovrebbe avere importanza in quanto è inteso comunque a essere considerato come stateless . Questa “funzione” salva il tempo e la memoria del contenitore per crearli e memorizzarli. Il contenitore può avere solo un pool di essi. Ancor più, l’istanza SLSB che è stata iniettata in un bean gestito JSF view, session o scope scope non ha necessariamente bisogno di fare riferimento esattamente alla stessa istanza su ogni richiesta HTTP come durante la creazione del bean gestito da JSF. Può anche essere un’istanza completamente diversa, a seconda delle istanze disponibili nel pool del contenitore. La transazione vive (per impostazione predefinita) fino a quando una singola chiamata al metodo su SLSB.

Detto questo, un SFSB non è adatto al tuo particolare caso di “ricordare un utente che ha effettuato l’accesso”. Che sia “più sicuro” non ha davvero senso. Basta inserire il bean gestito JSF nell’ambito della sessione e lasciare che ricordi l’utente che ha effettuato l’accesso da solo e utilizzare un SLSB per eseguire qualsiasi azione aziendale (come l’interazione con il DB) e utilizzare SFSB solo quando si desidera uno stato reale bean di sessione (presumo che tu ora capisca esattamente cosa sono :)).

Guarda anche:

  • Quando è necessario o conveniente utilizzare Spring o EJB3 o tutti insieme?
  • Perché i bean di sessione stateless?
  • Livello servizio JSF

Per quanto ho capito dalle mie ricerche e utilizzo, EJB SFSB non è utile per le applicazioni web poiché JSF, Spring fornisce annotazioni helfull per mantenere la sessione per utente. Ma nel caso in cui l’applicazione richiesta chiamata di richiamo del metodo RPC e webservice sia in esecuzione, EJB SFSB è neccs per mantenere la sessione (trancation) per utente.