Backing bean (@ManagedBean) o CDI Beans (@Named)?


109

Ho appena iniziato a leggere Core JavaServer Faces, 3a edizione. e dicono questo (enfasi mia):

È un incidente storico che ci siano due meccanismi separati, bean CDI e bean gestiti JSF, per i bean che possono essere utilizzati nelle pagine JSF. Si consiglia di utilizzare i bean CDI a meno che l'applicazione non debba funzionare su un semplice servlet runner come Tomcat.

Perché? Non forniscono alcuna giustificazione. Ho usato @ManagedBeanper tutti i fagioli in un'applicazione prototipo in esecuzione su GlassFish 3 e non ho notato alcun problema con questo. Non mi dispiace particolarmente migrare da @ManagedBeana @Named, ma voglio sapere perché dovrei preoccuparmi .



4
@ Bozho: questa domanda è abbastanza simile, ma dopo aver letto alcune volte la risposta di Pascal, ancora non capisco perché CDI sia di gran lunga superiore. Non conosco CDI e sono felice di apprenderlo visto che è "migliore". Perché è meglio?
Matt Ball

"a meno che la tua applicazione non debba funzionare su un semplice servlet runner come Tomcat" Uso solo tomcat e consiglio vivamente CDI. Tomcat può supportarlo bene
Karl Kildén

1
@ KarlKildén "semplice servlet runner" si riferisce a un servlet container non compatibile con CDI. Al momento in cui scrivo Tomcat non supportava CDI se non con un po 'di magia.
Thorbjørn Ravn Andersen

Risposte:


64

CDI è preferito rispetto a JSF semplice perché CDI consente l'iniezione di dipendenze a livello di JavaEE. Puoi anche iniettare POJO e lasciarli essere gestiti. Con JSF puoi iniettare solo un sottoinsieme di ciò che puoi con CDI.


Quindi, fondamentalmente, posso iniettare un'istanza di quasi tutte le classi (a condizione che abbia "la roba giusta" - che cos'è, solo un costruttore senza argomenti? ) Con CDI, mentre devo usare @ManagedBeanse voglio iniettarlo con plain JSF?
Matt Ball

3
@ MattBall Matt dopo anni, puoi commentare questa migrazione?
Koray Tugay

5
@KorayTugay Non ho toccato questo codice da giugno 2011 ma sono passato a CDI e le cose hanno funzionato bene. Sono felice di rispondere a qualsiasi domanda specifica al meglio della mia memoria, se le hai.
Matt Ball

170

Usa CDI.

Secondo JSF 2.3, @ManagedBeanè deprecato . Vedere anche il problema delle specifiche 1417 . Questo significa che non c'è più un motivo per scegliere @ManagedBeansopra @Named. Questo è stato implementato per la prima volta in Mojarra 2.3.0 versione beta m06.

inserisci qui la descrizione dell'immagine


Storia

La differenza principale è che @ManagedBeanè gestito dal framework JSF ed è @ManagedPropertydisponibile solo tramite un altro bean gestito JSF. @Namedè gestito da server di applicazione (il contenitore) tramite quadro CDI ed è via @Injectdisponibile per qualsiasi tipo di un contenitore artefatto gestita come @WebListener, @WebFilter, @WebServlet, @Path, @Stateless, ecc e anche un JSF @ManagedBean. Dall'altro lato su, @ManagedPropertynon non funzioneranno dentro @Namedo qualsiasi altro contenitore artefatto gestiti. Funziona davvero solo all'interno @ManagedBean.

Un'altra differenza è che CDI inietta effettivamente i proxy che delegano all'istanza corrente nell'ambito di destinazione in base alla richiesta / thread (come il modo in cui sono stati iniettati gli EJB). Questo meccanismo consente di iniettare un bean di uno scope più ristretto in un bean di uno scope più ampio, cosa che non è possibile con JSF @ManagedProperty. JSF "inietta" qui l'istanza fisica direttamente invocando un setter (che è anche esattamente il motivo per cui è richiesto un setter, mentre quello non è richiesto con @Inject).

Sebbene non sia direttamente uno svantaggio - ci sono altri modi - la portata di @ManagedBeanè semplicemente limitata. Dall'altro punto di vista, se non vuoi esporre "troppo" per @Inject, puoi anche mantenere i tuoi fagioli gestiti @ManagedBean. È come protectedcontro public. Ma questo non conta davvero.

Almeno, in JSF 2.0 / 2.1, il principale svantaggio della gestione dei backing bean JSF da parte di CDI è che non esiste un equivalente CDI di @ViewScoped. Si @ConversationScopedavvicina, ma richiede ancora l'avvio e l'arresto manuali e aggiunge un brutto cidparametro di richiesta agli URL dei risultati. MyFaces CODI rende tutto più semplice collegando in modo completamente trasparente i JSF javax.faces.bean.ViewScopeda CDI in modo da poterlo fare @Named @ViewScoped, tuttavia ciò aggiunge un brutto windowIdparametro di richiesta agli URL dei risultati, anche sulla semplice navigazione da pagina a pagina. OmniFaces risolve tutto questo con un vero CDI @ViewScopedche lega realmente l'ambito del bean allo stato di visualizzazione JSF invece che a un parametro di richiesta arbitrario.

JSF 2.2 (che viene rilasciato 3 anni dopo questa domanda / risposta) offre una nuova @ViewScopedannotazione completamente compatibile CDI fuori dagli schemi in sapore di javax.faces.view.ViewScoped. JSF 2.2 arriva anche con un solo CDI @FlowScopedche non ha un @ManagedBeanequivalente, spingendo gli utenti JSF verso CDI. L'aspettativa è che gli @ManagedBeanamici saranno deprecati in base a Java EE 8. Se stai ancora utilizzando @ManagedBean, è quindi fortemente consigliato passare a CDI per essere preparati per futuri percorsi di aggiornamento. CDI è immediatamente disponibile nei contenitori compatibili con Java EE Web Profile, come WildFly, TomEE e GlassFish. Per Tomcat, devi installarlo separatamente, esattamente come hai già fatto per JSF. Vedi anche Come installare CDI in Tomcat?


4
Ho creato beans.xml, convertito @ManagedBeanbacking bean in @Namede convertito @ManagedPropertyin @Inject. Va tutto bene con il mondo. Tuttavia, se cambio le mie @EJBannotazioni in @Inject, la distribuzione non riesce ( org.jboss.weld.exceptions.DeploymentException) con messaggio WELD-001408 Injection point has unsatisfied dependencies. Dovrei effettivamente usare @Injectper iniettare EJB senza interfaccia in un @Namedbean, o dovrei restare @EJB? Gli EJB sono impacchettati in un EJB JAR, nello stesso EAR del WAR che contiene i miei bean CDI.
Matt Ball

Dovrebbe funzionare. Stai ancora affrontando questo problema con l'attuale versione di Weld?
BalusC

Ahimè, non saprei dire. Questa domanda è di 2 datori di lavoro e> 2 anni fa. Sulla base del mio vecchio commento sulla risposta di Bozho, devo essere passato a CDI / @Named.
Matt Ball

"MyFaces CODI rende tutto più semplice collegando in modo completamente trasparente javax.faces.bean.ViewScoped di JSF a CDI in modo da poterlo fare @Named @ViewScoped, tuttavia questo aggiunge un brutto parametro di richiesta windowId agli URL dei risultati, anche sulla semplice navigazione da pagina a pagina." Nota che con DeltaSpike questo non è più vero. Puoi disabilitare entrambi i parametri URL dsId e windowId, se non hai bisogno di Window Scope.
gennaio

1
@ Jan: E nel frattempo, OmniFaces ha anche un JSF 2.2 simile @ViewScopedper JSF 2.0 / 2.1: showcase.omnifaces.org/cdi/ViewScoped
BalusC

16

Con Java EE 6 e CDI hai diverse opzioni per Managed Beans

  • @javax.faces.bean.ManagedBeansi riferisce a JSR 314 ed è stato introdotto con JSF 2.0. L'obiettivo principale era evitare la configurazione nel file faces-config.xml per utilizzare il bean all'interno di una pagina JSF.
  • @javax.annotation.ManagedBean(“myBean”) è definito da JSR 316. Generalizza i bean gestiti JSF da utilizzare altrove in Java EE
  • @javax.inject.Named(“myBean”) sono quasi gli stessi, come quello sopra, tranne per il fatto che è necessario un file bean.xml nella cartella web / WEB-INF per attivare CDI.

1
Qual è la differenza tra i primi due?
Matt Ball

L'obiettivo della prima annotazione è / era sostituire la configurazione del bean in faces-config.xml per l'utilizzo in JSF. Il secondo copia il concetto nel "contenitore java ee 6". Ha più funzioni (come le annotazioni @PostConstruct e @PreDestroy), ma è anche raggiungibile dalla pagina JSF (con Expression Language).
h2mch

1
perché hai bisogno di un beans.xmlfile? È ancora vero oggi?
Thufir

2
No, con JavaEE7 non hai più bisogno di bean.xml. vedi docs.oracle.com/javaee/7/tutorial/doc/cdi-adv001.htm
h2mch

1
Con JavaEE7 non hai bisogno di bean.xml : docs.oracle.com/javaee/7/tutorial/cdi-adv001.htm (link corretto) blogs.oracle.com/theaquarium/entry/… (Default CDI Enablement in Java EE 7)
M. Atif Riaz

2

Stavo usando CDI in GlassFish 3.0.1, ma per farlo funzionare ho dovuto importare il framework Seam 3 (Weld). Ha funzionato abbastanza bene.

In GlassFish 3.1 CDI ha smesso di funzionare e Seam Weld ha smesso di funzionare con esso. Ho aperto un bug su questo ma non l'ho ancora visto risolto. Ho dovuto convertire tutto il mio codice per utilizzare le annotazioni javax.faces. * Ma ho intenzione di tornare a CDI una volta che lo faranno funzionare.

Sono d'accordo che dovresti usare CDI, ma un problema che non ho ancora visto risolto è cosa fare con l'annotazione @ViewScoped. Ho molto codice che dipende da esso. Non è chiaro se @ViewScoped funzioni se non si utilizza @ManagedBean con esso. Se qualcuno può chiarire questo, lo apprezzerei.


-1

Una buona ragione per passare a CDI: potresti avere una risorsa comune con ambito di sessione (ad esempio il profilo utente) @Injectinserita sia nei bean gestiti JSF che nei servizi REST (cioè Jersey / JAX-RS).

D'altra parte, @ViewScopedè un motivo valido per restare con JSF @ManagedBean, specialmente per qualsiasi cosa con AJAX significativo. Non esiste un sostituto standard per questo in CDI.

Sembra che possa avere qualche supporto per @ViewScopedun'annotazione simile a quella per i bean CDI, ma non ci ho giocato personalmente.

http://seamframework.org/Seam3/FacesModule

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.