Come si confrontano CDI ed EJB? interagire?


106

Faccio fatica a capire come interagiscono i due e dove si trova il confine tra loro. Si sovrappongono? Ci sono licenziamenti tra di loro?

So che ci sono annotazioni associate a entrambi, ma non sono riuscito a trovare un elenco completo per entrambi con brevi descrizioni. Non sono sicuro se questo aiuterebbe a chiarire come differiscono o dove si sovrappongono.

Davvero solo confuso. Io (penso di) capire EJB ragionevolmente bene, immagino di avere difficoltà a capire esattamente cosa porta CDI in tavola e come soppianta o migliora ciò che EJB già offre.


3
Questa domanda ordina superiore sulla ricerca "differenza EJB CDI" di Google, ma ho trovato la risposta a stackoverflow.com/questions/13487987/... più chiara
matt Freake

Risposte:


50

CDI: si tratta di iniezione di dipendenza. Significa che puoi iniettare l'implementazione dell'interfaccia ovunque. Questo oggetto può essere qualsiasi cosa, non può essere correlato a EJB. Ecco un esempio di come iniettare un generatore casuale utilizzando CDI. Non c'è niente su EJB. Utilizzerai CDI quando desideri iniettare servizi non EJB, diverse implementazioni o algoritmi (quindi non hai affatto bisogno di EJB).
EJB: capisci, e probabilmente sei confuso @EJBdall'annotazione: ti consente di iniettare l'implementazione nel tuo servizio o qualsiasi altra cosa. L'idea principale è che la classe, dove si inietta, dovrebbe essere gestita dal contenitore EJB. Sembra che CDI capisca cos'è EJB, quindi nel server compatibile con Java EE 6, nel tuo servlet puoi scrivere entrambi

@EJB EJBService ejbService;

e

@Inject EJBService ejbService;

questo è ciò che può creare confusione, ma probabilmente è l'unica cosa che è il ponte tra EJB e CDI.

Quando parliamo di CDI, puoi iniettare altri oggetti nelle classi gestite da CDI (dovrebbero essere creati solo da framework compatibili con CDI).

Cos'altro offre CDI ... Ad esempio, usi Struts 2 come framework MVC (solo un esempio) e sei limitato qui, anche usando EJB 3.1 - non puoi usare l' @EJBannotazione nell'azione Struts, non è gestita dal contenitore. Ma quando aggiungi il plugin Struts2-CDI, puoi scrivere lì @Injectannotazioni per la stessa cosa (quindi non è più necessaria la ricerca JNDI). In questo modo aumenta la potenza di EJB, ma come ho detto prima, ciò che inietti con CDI - non importa se è correlato a EJB o meno, e questo è il suo potere.

PS. collegamento aggiornato all'esempio


@EJB e @Inject sono davvero equivalenti dal punto di vista funzionale? Penso che sia stata la sovrapposizione dei metodi di iniezione tra CDI e alcuni degli altri acronimo Java EE che mi ha confuso. Più letture sembrano indicare che c'è speranza di allineare le annotazioni.
Tim

@Maxym Quando si utilizza @ Inject, come si può garantire che @ Stateless o qualsiasi altro componente lato server di EJB utilizzi ancora le funzionalità come il pooling o la concorrenza offerte dal contenitore. Spero che questo non sia offerto da CDI, giusto?
Bala

1
@Bala: CDI non offre il pooling ... guarda CDI con o senza EJB3.1 , spero che risponda alla tua domanda ..
Maxym

@KorayTugay: CDI è una funzionalità Java EE, quindi qualsiasi server compatibile con Java EE 6 ce l'ha (Glassfish 3.0.1+ non è sbagliato, JBoss 6+ ecc.) Puoi dare un'occhiata a JBoss Weld, un'implementazione CDI di riferimento che tu può usare ad esempio Tomcat ...
Maxym

191

Attualmente è davvero un po 'confuso in quanto ora ci sono più modelli di componenti in Java EE. Sono CDI , EJB3 e JSF Managed Beans .

CDI è il nuovo ragazzo sul blocco. Fagioli CDI dispongono dependency injection, scopinged una event bus. I bean CDI sono i più flessibili rispetto a injection e scoping. Il bus degli eventi è molto leggero e molto adatto anche per le applicazioni web più semplici. Oltre a questo, CDI espone anche una funzionalità molto avanzata chiamata portable extensions, che è una sorta di meccanismo di plug-in per i fornitori per fornire funzionalità extra a Java EE che possono essere rese disponibili su tutte le implementazioni (Glassfish, JBoss AS, Websphere, ecc.) .

I bean EJB3 sono stati adattati dal vecchio modello di componenti EJB2 legacy * e sono stati i primi bean in Java EE a essere gestiti tramite un'annotazione. Fagioli EJB3 dispongono dependency injection, declarative transactions, declarative security, pooling, concurrency control, asynchronous executione remoting.

L'inserimento delle dipendenze nei bean EJB3 non è flessibile come nei bean CDI ei bean EJB3 non hanno il concetto di scoping. Tuttavia, i bean EJB3 sono transazionali e raggruppati per impostazione predefinita ** , due cose molto utilizzabili che CDI ha scelto di lasciare nel dominio di EJB3. Anche gli altri elementi menzionati non sono disponibili in CDI. Tuttavia EJB3 non ha alcun bus di eventi proprio, ma ha un tipo speciale di bean per ascoltare i messaggi; il bean message driven. Può essere utilizzato per ricevere messaggi da Java Messaging System o da qualsiasi altro sistema che disponga di un adattatore di risorse JCA. L'uso della messaggistica completa per eventi semplici è molto più pesante del bus di eventi CDI ed EJB3 definisce solo un ascoltatore, non un'API del produttore.

I Managed Beans JSF sono esistiti in Java EE da quando è stato incluso JSF. Anche loro presentano dependency injectione scoping. JSF Managed Beans ha introdotto il concetto di scoping dichiarativo. Originariamente gli ambiti erano piuttosto limitati e nella stessa versione di Java EE in cui i bean EJB3 potevano già essere dichiarati tramite annotazioni, JSF Managed Beans doveva ancora essere dichiarato in XML. La versione corrente di JSF Managed Beans viene infine dichiarata tramite un'annotazione e gli ambiti vengono espansi con un ambito di visualizzazione e la possibilità di creare ambiti personalizzati. L'ambito della visualizzazione, che ricorda i dati tra le richieste alla stessa pagina, è una caratteristica unica di JSF Managed Beans.

A parte l'ambito di visualizzazione, c'è ancora molto poco da fare per JSF Managed Beans in Java EE 6. L'ambito di visualizzazione mancante in CDI è sfortunato, poiché altrimenti CDI sarebbe stato un super set perfetto di ciò che offre JSF Managed Beans. Aggiornamento : in Java EE 7 / JSF 2.2 è stato aggiunto un @ViewScoped compatibile CDI , rendendo CDI davvero quel super set perfetto. Aggiornamento 2 : in JSF2.3 i bean gestiti JSF sono stati deprecati a favore dei bean gestiti CDI.

Con EJB3 e CDI la situazione non è così chiara. Il modello dei componenti EJB3 e l'API offrono molti servizi che CDI non offre, quindi in genere EJB3 non può essere sostituito da CDI. D'altra parte, CDI può essere utilizzato in combinazione con EJB3, ad esempio aggiungendo il supporto dell'ambito agli EJB.

Reza Rahman, membro del gruppo di esperti e implementatore di un'implementazione CDI chiamata CanDI, ha spesso accennato al fatto che i servizi associati al modello dei componenti EJB3 possono essere adattati come set di annotazioni CDI. Se ciò dovesse accadere, tutti i bean gestiti in Java EE potrebbero diventare bean CDI. Ciò non significa che EJB3 scompaia o diventi obsoleto, ma solo che la sua funzionalità verrà esposta tramite CDI invece che tramite le annotazioni di EJB come @Stateless e @EJB.

Aggiornare

David Blevins della fama di TomEE e OpenEJB spiega molto bene le differenze e le somiglianze tra CDI ed EJB sul suo blog: CDI, quando far scoppiare gli EJB

* Sebbene sia solo un incremento nel numero di versione, i bean EJB3 erano per la maggior parte un tipo di bean completamente diverso: un semplice pojo che diventa un "bean gestito" applicando una semplice annotazione singola, rispetto al modello in EJB2 dove un pesante e Per ogni singolo bean era richiesto un descrittore di distribuzione XML eccessivamente dettagliato, oltre al fatto che il bean doveva implementare varie interfacce di componenti estremamente pesanti e per la maggior parte prive di significato.

** I bean di sessione stateless sono in genere pool, i bean di sessione con stato in genere no (ma possono esserlo). Per entrambi i tipi il pooling è quindi facoltativo e la specifica EJB non lo impone in alcun modo.


3
Sono un po 'confuso dalle tue affermazioni che "i bean EJB3 non hanno il concetto di scoping" e che "EJB3 non ha un bus di eventi proprio però". Come si adatta questo con l' affermazione di David Blevin secondo cui "gli EJB sono bean CDI e quindi hanno tutti i vantaggi di CDI"? È cambiato qualcosa in questo senso tra quando hai scritto la tua risposta e quando David ha scritto il suo post sul blog?
Chris

5
È a causa del concetto forse un po 'confuso che in realtà non ci sono realmente "bean CDI", ma ci sono servizi applicati ai bean gestiti. Per motivi di discussione, le persone (e io stesso) li chiamano comunque "bean CDI". Prima di CDI, i bean EJB non avevano uno scoping esplicito. Come spiega David, Stateful è implicitamente uno scope (e quindi nessuno scope in particolare). con CDI disponibile, i bean EJB possono trarre vantaggio dagli ambiti forniti da CDI. Senza la specifica CDI, quindi quando si guarda solo alle specifiche EJB, non ci sono ambiti espliciti.
Arjan Tijms

1
Puoi approfondire cosa intendi con "ci sono servizi applicati ai bean gestiti"? Significa che in realtà non esiste un fagiolo CDI? Sono solo alcuni che forniscono funzionalità extra su un POJO - EJB - o su un Managed Bean JSF? Ti piace poter usare l'annotazione Inject in un Managed Bean JSF?
Koray Tugay

3
@Chris per chiarire ulteriormente dal punto di vista delle specifiche EJB abbiamo preso la decisione deliberata dall'inizio di CDI di richiedere che le implementazioni EJB debbano supportare il 100% delle funzionalità CDI impostate sugli EJB. Ogni aspetto di CDI funziona sugli EJB con l'eccezione degli scope che abbiamo dovuto limitare solo ai bean con stato.
David Blevins

1
Si noti che JSF 2.2 ora fornisce javax.faces.view.ViewScoped, un'estensione CDI che è essenzialmente una porta dell'ambito della vista JSF a CDI. Con questo, CDI è un sostituto completo per JSF Managed Beans.
jdessey

-1

Albert Einstein: If you can't explain it simply, you don't understand it well enough

Ejbs e CDI sono piuttosto semplici da capire.

EJB:

  1. Sarà sempre annotato da qualificatori di ambito, ad esempio @Stateless, @Stateful, @Request ecc
  2. Le istanze di Ejbs sono controllate dal framework Java EE e raggruppate. È dovere del framework EE fornire le istanze per il consumatore.

@Stateless

 public class CarMaker(){
    public void createCar(Specification specs){
        Car car = new Car(specs);
    }
}

Il CarMaker è annotato con un ambito Ejbs specifico, quindi è Ejb

CDI:

  1. Non gestite interamente dal framework EE, le istanze devono essere create da soli.
  2. È sempre dipendente. lasciatemi spiegare "Dipendente" con un esempio:

    class Specification { private String color; private String model; //- Getter and Setter }

La Specificationclasse è CDI, poiché non è annotata con gli ambiti Ejb e anche questo deve essere inizializzato dal tuo codice non dal framework EE. Un punto da notare qui è che poiché non abbiamo annotato la Specificationclasse, per impostazione predefinita è annotata mediante @Dependentannotazione.

@Dependent  <- By default added 
class Specification { ... }

Further reading: È necessario studiare di più tra l'annotazione dell'ambito Ejbs e l'annotazione dell'ambito CDI, che chiarirà ulteriormente il concetto


Einstein ha anche detto: "Tutto dovrebbe essere reso il più semplice possibile, ma non più semplice" puoi (dovresti) sostituire 'fatto' con 'spiegato' qui.
Kukeltje
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.