Java EE 6 @ javax.annotation.ManagedBean vs. @ javax.inject.Named vs. @ javax.faces.ManagedBean


107

Penso che ci sia un po 'di confusione nelle specifiche Java EE 6. Esistono diversi gruppi di annotazioni.

Abbiamo javax.ejbannotazioni come @Statefule@Stateless per la creazione di EJB.

C'è anche un @javax.annotation.ManagedBean per creare un bean gestito.

Ci sono annotazioni in javax.enterprise.contextlike @SessionScopede@RequestScoped .

Inoltre ci sono anche @ManagedBeane @SessionScoped/ @RequestScopedannotazioni injavax.faces.bean pacchetto.

E per rendere le cose più complicate c'è un pacchetto javax.injectcon@Named annotazioni.

Qualcuno può descrivere come sono collegati gli uni agli altri?

Dove posso usare @EJB, @Injecto @ManagedProperyper iniettare altri fagioli?


Risposte:


194

Prima di tutto lasciatemi fare alcune precisazioni:

Definizione di bean gestito : generalmente un bean gestito è un oggetto il cui ciclo di vita (costruzione, distruzione, ecc.) È gestito da un contenitore.

In Java ee abbiamo molti contenitori che gestiscono il ciclo di vita dei loro oggetti, come il contenitore JSF, il contenitore EJB, il contenitore CDI, il contenitore Servlet, ecc.

Tutti questi contenitori funzionano in modo indipendente, si avviano nell'inizializzazione del server delle applicazioni e scansionano le classi di tutti gli artefatti inclusi i file jar, ejb-jar, war e ear durante la distribuzione e raccolgono e archiviano alcuni metadati su di essi, quindi quando è necessario un oggetto di una classe in fase di esecuzione ti daranno istanze di quelle classi e dopo aver terminato il lavoro, le distruggeranno.

Quindi possiamo dire che abbiamo:

  • Fagioli gestiti da JSF
  • Fagioli gestiti da CDI
  • Bean gestiti da EJB
  • E anche i servlet sono bean gestiti perché vengono istanziati e distrutti da un contenitore, che è un contenitore servlet.

Quindi, quando vedi la parola Managed Bean, dovresti chiedere informazioni sul contesto o sul tipo di essa (JSF, CDI, EJB, ecc.)

Quindi potresti chiederti perché abbiamo molti di questi contenitori: AFAIK, i ragazzi di Java EE volevano avere un framework di iniezione delle dipendenze, ma non potevano raccogliere tutti i requisiti in una specifica perché non potevano prevedere i requisiti futuri e hanno creato EJB 1.0 e poi 2.0 e poi 3.0 e ora 3.1 ma l'obiettivo di EJB era solo per alcuni requisiti (transazione, modello di componenti distribuiti, ecc.).

Allo stesso tempo (in parallelo) si sono resi conto che dovevano supportare anche JSF, poi hanno realizzato bean gestiti da JSF e un altro contenitore per bean JSF e lo hanno considerato un contenitore DI maturo, ma ancora non era un contenitore completo e maturo.

Dopo di che Gavin King e altri bravi ragazzi;) hanno creato CDI che è il contenitore DI più maturo che abbia mai visto. CDI (ispirato a Seam2, Guice e Spring) è stato creato per colmare il divario tra JSF ed EJB e molte altre cose utili come l'iniezione di pojo, i metodi di produzione, gli intercettatori, i decoratori, l'integrazione SPI, molto flessibile, ecc. E può anche fare cosa stanno facendo i bean gestiti EJB e JSF, allora possiamo avere un solo contenitore DI maturo e potente. Ma per qualche retrocompatibilità e ragioni politiche i ragazzi di Java EE vogliono mantenerli !!!

Qui puoi trovare la differenza e i casi d'uso per ciascuno di questi tipi:

Fagioli gestiti JSF, Fagioli CDI e EJB

JSF è stato inizialmente sviluppato con il proprio meccanismo di iniezione delle dipendenze e dei bean gestiti che è stato migliorato per JSF 2.0 per includere i bean basati sull'annotazione. Quando CDI è stato rilasciato con Java EE 6, era considerato il framework bean gestito per quella piattaforma e, naturalmente, gli EJB li superavano tutti essendo in circolazione da oltre un decennio.

Il problema ovviamente è sapere quale usare e quando usarli.

Cominciamo con i bean gestiti JSF più semplici.

Fagioli gestiti JSF

In breve, non usarli se stai sviluppando per Java EE 6 e stai usando CDI. Forniscono un semplice meccanismo per l'inserimento delle dipendenze e la definizione dei bean di supporto per le pagine web, ma sono molto meno potenti dei bean CDI.

Possono essere definiti utilizzando il @javax.faces.bean.ManagedBean annotazione che accetta un parametro name opzionale. Questo nome può essere utilizzato per fare riferimento al bean dalle pagine JSF.

L'ambito può essere applicato al bean utilizzando uno dei diversi ambiti definiti nel javax.faces.beanpacchetto che includono la richiesta, la sessione, l'applicazione, la vista e gli ambiti personalizzati.

@ManagedBean(name="someBean")
@RequestScoped
public class SomeBean {
    ....
    ....
}

I bean JSF non possono essere combinati con altri tipi di bean senza un qualche tipo di codifica manuale.

Fagioli CDI

CDI è il framework per la gestione dei bean e l'inserimento delle dipendenze rilasciato come parte di Java EE 6 e include una funzionalità bean completa e completa. I bean CDI sono molto più avanzati e flessibili dei semplici bean gestiti JSF. Possono fare uso di intercettori, ambito di conversazione, eventi, type safe injection, decoratori, stereotipi e metodi di produzione.

Per distribuire i bean CDI, è necessario posizionare un file denominato bean.xml in una cartella META-INF sul classpath. Una volta fatto questo, ogni bean nel pacchetto diventa un bean CDI. Ci sono molte funzionalità in CDI, troppe per essere trattate qui, ma come riferimento rapido per funzionalità simili a JSF, puoi definire l'ambito del bean CDI utilizzando uno degli ambiti definiti nel javax.enterprise.contextpacchetto (vale a dire, richiesta, conversazione , sessioni e ambiti dell'applicazione). Se si desidera utilizzare il bean CDI da una pagina JSF, è possibile assegnargli un nome utilizzando l' javax.inject.Namedannotazione. Per iniettare un bean in un altro bean, annotare il campo con javax.inject.Injectannotation.

@Named("someBean")
@RequestScoped
public class SomeBean {

    @Inject
    private SomeService someService;
}

L'iniezione automatica come quella definita sopra può essere controllata tramite l'uso di qualificatori che possono aiutare ad abbinare la classe specifica che si desidera iniettare. Se disponi di più tipi di pagamento, potresti aggiungere un qualificatore per indicare se è asincrono o meno. Sebbene sia possibile utilizzare l' @Namedannotazione come qualificatore, non dovresti in quanto è fornita per esporre i bean in EL.

CDI gestisce l'iniezione di bean con ambiti non corrispondenti tramite l'uso di proxy. Per questo motivo è possibile iniettare un bean con ambito di richiesta in un bean con ambito di sessione e il riferimento sarà ancora valido su ogni richiesta perché per ogni richiesta, il proxy si riconnette a un'istanza live del bean con ambito di richiesta.

CDI supporta anche gli intercettori, gli eventi, il nuovo ambito di conversazione e molte altre caratteristiche che lo rendono una scelta molto migliore rispetto ai bean gestiti JSF.

EJB

Gli EJB sono anteriori ai bean CDI e sono in qualche modo simili ai bean CDI e per altri versi molto diversi. In primo luogo, la differenza tra i bean CDI e gli EJB è che gli EJB sono:

  • transazionale
  • Remoto o locale
  • Capace di passivare i bean stateful liberando risorse
  • In grado di utilizzare i timer
  • Può essere asincrono

I due tipi di EJB sono chiamati stateless e stateful. Gli EJB senza stato possono essere pensati come bean monouso thread-safe che non mantengono alcuno stato tra due richieste web. I bean con stato mantengono lo stato e possono essere creati e rimanere in attesa per tutto il tempo necessario fino a quando non vengono eliminati.

La definizione di un bean è semplice, basta aggiungere un'annotazione javax.ejb.Statelesso javax.ejb.Statefulalla classe.

@Stateless
public class BookingService {

  public String makeReservation(Item Item, Customer customer) {
    ...
    ...
  }
}

I bean senza stato devono avere un ambito dipendente mentre un bean di sessione con stato può avere qualsiasi ambito. Per impostazione predefinita, sono transazionali, ma è possibile utilizzare l'annotazione dell'attributo di transazione.

Sebbene gli EJB e i bean CDI siano molto diversi in termini di funzionalità, scrivere il codice per integrarli è molto simile poiché i bean CDI possono essere iniettati negli EJB e gli EJB possono essere iniettati nei bean CDI. Non è necessario fare alcuna distinzione quando si inietta l'uno nell'altro. Anche in questo caso, i diversi ambiti vengono gestiti da CDI tramite l'uso del proxy. Un'eccezione è che CDI non supporta l'iniezione di EJB remoti ma può essere implementata scrivendo un semplice metodo produttore per esso.

L' javax.inject.Namedannotazione e qualsiasi qualificatore possono essere utilizzati su un bean per abbinarlo a un punto di iniezione.

Quando usare quale fagiolo

Come fai a sapere quando usare quale fagiolo? Semplice.

Non utilizzare mai bean gestiti JSF a meno che non si lavori in un contenitore servlet e non si voglia provare a far funzionare CDI in Tomcat (sebbene ci siano alcuni archetipi Maven per questo, quindi non ci sono scuse).

In generale, è necessario utilizzare i bean CDI a meno che non sia necessaria la funzionalità avanzata disponibile negli EJB come le funzioni transazionali. Puoi scrivere il tuo intercettore per rendere transazionali i bean CDI, ma per ora è più semplice usare un EJB finché CDI non ottiene i bean CDI transazionali che sono proprio dietro l'angolo. Se sei bloccato in un servlet container e stai usando CDI, allora le transazioni scritte a mano o il tuo interceptor di transazione sono l'unica opzione senza EJB.

Se hai bisogno di usare @ViewScopedin CDI dovresti

  • utilizzare seam-faces o il modulo CODI di MyFaces . basta aggiungerne uno al proprio classpath e @ViewScopedfunzionerà in CDI. MyFaces CODI ha un supporto ancora più solido di @ViewScoped
  • usa i CODI di MyFaces @ViewAccessScoped, è un'estensione scritta su CDI da Apache, scaricala e usa l' @ViewAccessScopedannotazione invece di @ViewScoped.
  • Usa CDI @ConversationScopede rendilo di lunga durata. Vedi qui per maggiori informazioni .
  • Usa l' annotazione Omnifaces @ViewScoped

Alcune parti sono state rubate da qui .


3
È fantastico! Grazie! Per completare, è sufficiente indicare come iniettare CDI o bean EJB nel bean JSF. È il @ManagedProperty("#{someBean})"modo corretto?
Piotr Gwiazda

2
No! non funzionerà. basta trasformare il bean gestito jsf in bean gestito CDI annotandolo utilizzando @Namede @javax.enterprise.context.RequestScopede utilizzando l'iniezione CDI utilizzando l'annotazione @Inject. non utilizzare bean gestiti jsf se non è necessario;).
Mehdi

3
> I ragazzi di JEE vogliono tenerli !!! - È un po 'più sottile di così. Il CDI è finito piuttosto tardi nel ciclo Java EE 6 e sia JSF 2 che JAX-RS erano già stati completati. Avevano migliorato resp. ha già introdotto il proprio bean facility gestito. Se il CDI fosse stato disponibile un po 'prima, le cose sarebbero potute andare diversamente. In Java EE 7, JSF adotterà CDI e javax.faces.bean alla fine sarà deprecato (la deprecazione è un processo lento in Java EE, il che è sia positivo che negativo).
Arjan Tijms

3
Quando si dice: per distribuire i bean CDI, è necessario inserire un file chiamato bean.xml in una cartella META-INF sul classpath. Una volta fatto questo, ogni bean nel pacchetto diventa un bean CDI. Intendi dire che ogni fagiolo diventa anche un fagiolo CDI oltre a quello che era? Cosa succede se ho JSF ManagedBeans con ManagedBean e ViewScoped. Sono ancora fagioli gestiti JSF, giusto?
Koray Tugay

3
Qualcuno in grado di fare un aggiornamento per Java EE 7 su questo fantastico articolo?
Martijn Burger

7

Sì, questo può creare confusione.

Per alcuni ehm ragioni storiche JSF e CDI stanno usando le stesse annotazioni per scopi, ma da diversi pacchetti.

Come probabilmente stai indovinando, quelli di javax.faces.beanprovengono dalle specifiche JSF e non sono correlati a CDI. Non usarli a meno che tu non abbia un'ottima ragione per farlo. E non mescolarli mai con le annotazioni CDI di javax.ejb. Ciò produrrà un elenco infinito di bug e sottili anomalie.

In genere consiglio di sfogliare le prime (o anche di più) pagine dell'eccellente documentazione di Weld . Questo dovrebbe metterti sulla buona strada per Java EE 6.

E sentiti libero di pubblicare ulteriori domande qui.


In realtà ho due domande: 1. Trovo spesso l'ambito di visualizzazione molto utile. Allora devo usare le annotazioni JSF? 2. Significa che @javax.annotation.ManagedBeanè inutile poiché CDI tratta tutte le classi come bean gestiti, giusto?
Piotr Gwiazda

Non proprio. Sarà necessario collegare gli scope JSF a CDI con, ad esempio, Seam Faces. E sì, @ManagedBeans non è necessario se hai un bean.xml nel file jar pertinente. Oh, e se hai ulteriori domande è meglio iniziare un nuovo thread prima di perderci nella sezione dei commenti.
jan groth

3

Poiché non ci sono risposte specifiche in merito @javax.annotation.ManagedBean, ecco un collegamento alla risposta di una domanda simile: Backing Beans (@ManagedBean) o CDI Beans (@Named)? . La specifica può essere trovata su http://download.oracle.com/otndocs/jcp/managed_beans-1.0-fr-eval-oth-JSpec/ . Quindi a me sembra che @javax.annotation.ManagedBeanfosse una generalizzazione di@javax.faces.bean.ManagedBean .

Da quello che ho raccolto, JSF Managed Beans viene gradualmente eliminato a favore di CDI Beans (forse sarà deprecato da JSF 2.3?), Quindi immagino che @javax.annotation.ManagedBeanstia diventando sempre più obsoleto ora.


@Namedsostituirà @ManagedBeanin futuro?
Thufir

1
Ho letto diverse dichiarazioni da diversi esperti Java EE che prevedono che le CDI @Namedfagioli sostituiranno JSF @ManagedBeans, ad esempio in stackoverflow.com/questions/4347374/... , BalusC dice: "L'aspettativa è che @ManagedBean e gli amici saranno deprecati come per Java EE 8. ".
Hein Blöd
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.