Sì, puoi mescolare liberamente sia CDI che EJB e ottenere ottimi risultati. Sembra che tu stia usando @WebService
e @Schedule
, che sono buone ragioni per aggiungere EJB al mix.
C'è molta confusione là fuori, quindi ecco alcune informazioni generali su EJB e CDI in quanto si riferiscono a ciascuno insieme.
EJB> = CDI
Notare che gli EJB sono bean CDI e quindi hanno tutti i vantaggi di CDI. Il contrario non è (ancora) vero. Quindi sicuramente non prendere l'abitudine di pensare "EJB vs CDI" poiché quella logica si traduce davvero in "EJB + CDI vs CDI", che è una strana equazione.
Nelle future versioni di Java EE continueremo ad allinearle. Cosa significa allineare sta permettendo alle persone di fare quello che già possono fare, basta senza la @Stateful
, @Stateless
o @Singleton
di annotazione in alto.
EJB e CDI nei termini di implementazione
In definitiva, EJB e CDI condividono lo stesso design fondamentale di essere componenti proxy. Quando ottieni un riferimento a un bean EJB o CDI, non è il vero bean. Piuttosto l'oggetto che ti viene dato è un falso (un proxy). Quando si invoca un metodo su questo oggetto falso, la chiamata va al contenitore che invierà la chiamata tramite intercettori, decoratori, ecc., Oltre a occuparsi di qualsiasi transazione o controllo di sicurezza. Una volta fatto tutto ciò, la chiamata va finalmente all'oggetto reale e il risultato viene ritrasmesso al chiamante attraverso il proxy.
La differenza sta solo nel modo in cui viene risolto l'oggetto da richiamare. Per "risolto" intendiamo semplicemente dove e come il contenitore cerca l'istanza reale da invocare.
In CDI il contenitore guarda in un "ambito", che sarà fondamentalmente una hashmap che vive per un periodo di tempo specifico (per richiesta @RequestScoped
, per sessione HTTP @SessionScoped
, per applicazione @ApplicationScoped
, conversazione JSF @ConversationScoped
o per l'implementazione dell'ambito personalizzato).
In EJB il contenitore guarda anche in una hashmap se il bean è di tipo @Stateful
. Un @Stateful
bean può anche utilizzare una qualsiasi delle annotazioni dello scope sopra riportate facendolo vivere e morire con tutti gli altri bean nello scope. In EJB @Stateful
è essenzialmente il bean "any scoped". L' @Stateless
è fondamentalmente un pool di istanze - si ottiene un'istanza dal pool per la durata di un invocazione. Il @Singleton
è essenzialmente@ApplicationScoped
Quindi, in un livello fondamentale, qualsiasi cosa tu possa fare con un bean "EJB" dovresti essere in grado di farlo con un bean "CDI". Sotto le coperte è terribilmente difficile distinguerli. Tutto l'impianto idraulico è lo stesso con l'eccezione di come vengono risolte le istanze.
Al momento non sono gli stessi in termini di servizi che il contenitore offrirà quando si esegue questo proxy, ma come ho detto ci stiamo lavorando a livello di specifica Java EE.
Nota sulle prestazioni
Ignora qualsiasi immagine mentale "leggera" o "pesante" che potresti avere. È tutto marketing. Hanno lo stesso design interno per la maggior parte. La risoluzione dell'istanza CDI è forse un po 'più complessa perché è leggermente più dinamica e contestuale. La risoluzione dell'istanza EJB è piuttosto statica, stupida e semplice al confronto.
Posso dirti da una prospettiva di implementazione in TomEE, c'è circa zero differenza di prestazioni tra invocare un EJB e invocare un bean CDI.
L'impostazione predefinita è POJO, quindi CDI, quindi EJB
Ovviamente non utilizzare CDI o EJB quando non ci sono vantaggi. Aggiungi CDI quando inizi a desiderare iniezione, eventi, intercettori, decoratori, monitoraggio del ciclo di vita e cose del genere. Quella è la maggior parte del tempo.
Al di là di queste basi, ci sono una serie di servizi utili container si ha solo la possibilità di utilizzare, se fate il vostro CDI fagiolo anche un EJB con l'aggiunta @Stateful
, @Stateless
o @Singleton
su di esso.
Ecco un breve elenco di quando rompo gli EJB.
Utilizzando JAX-WS
Esporre un JAX-WS @WebService
. Sono pigro. Quando @WebService
è anche un bean, non è necessario elencarlo e mapparlo come servlet nel web.xml
file. Questo è lavoro per me. Inoltre ho la possibilità di utilizzare una qualsiasi delle altre funzionalità menzionate di seguito. Quindi è un gioco da ragazzi per me.
Disponibile @Stateless
e @Singleton
solo.
Utilizzando JAX-RS
Esporre una risorsa JAX-RS tramite @Path
. Sono ancora pigro. Quando il servizio RESTful è anche un EJB, di nuovo si ottiene il rilevamento automatico e non è necessario aggiungerlo a una Application
sottoclasse JAX-RS o qualcosa del genere. Inoltre posso esporre lo stesso identico bean di un, @WebService
se lo desidero o utilizzare una delle fantastiche funzionalità menzionate di seguito.
Disponibile @Stateless
e @Singleton
solo.
Logica di avvio
Carica all'avvio tramite @Startup
. Attualmente non esiste un equivalente a questo in CDI. In qualche modo ci siamo persi l'aggiunta di qualcosa come un AfterStartup
evento nel ciclo di vita del container. Se lo avessimo fatto, avresti semplicemente potuto avere un @ApplicationScoped
bean che lo ascoltasse e che sarebbe effettivamente lo stesso di un @Singleton
con @Startup
. È sulla lista per CDI 1.1.
Disponibile @Singleton
solo per.
Lavorare in parallelo
@Asynchronous
invocazione del metodo. L'avvio di thread è un no-no in qualsiasi ambiente lato server. Avere troppi thread è un serio killer delle prestazioni. Questa annotazione ti consente di parallelizzare le cose che fai usando il pool di thread del contenitore. Questo e spettacolare.
Disponibile per @Stateful
, @Stateless
e @Singleton
.
Pianificazione del lavoro
@Schedule
o ScheduleExpression
è fondamentalmente un cron o una Quartz
funzionalità. Anche molto impressionante. La maggior parte dei contenitori usa solo Quartz sotto le coperte per questo. La maggior parte delle persone non sa, tuttavia, che il lavoro di pianificazione in Java EE è transazionale! Se aggiorni un database, pianifichi un lavoro e uno di essi non riesce, entrambi verranno automaticamente ripuliti. Se la EntityManager
chiamata persistente non riesce o si verifica un problema di scaricamento, non è necessario annullare la pianificazione del lavoro. Sì, transazioni.
Disponibile @Stateless
e @Singleton
solo.
Utilizzo di EntityManagers in una transazione JTA
La nota sopra sulle transazioni ovviamente richiede di utilizzare un file JTA
managed EntityManager
. È possibile utilizzarli con un semplice "CDI", ma senza le transazioni gestite dal contenitore può diventare davvero monotono duplicare la UserTransaction
logica di commit / rollback.
Disponibile a tutti i componenti Java EE tra cui CDI, JSF @ManagedBean
, @WebServlet
, @WebListener
, @WebFilter
, ecc L' @TransactionAttribute
annotazione, tuttavia, è a disposizione @Stateful
, @Stateless
e @Singleton
solo.
Mantenere JTA gestito EntityManager
Il EXTENDED
gestito EntityManager
consente di mantenere EntityManager
aperto tra le JTA
transazioni e di non perdere i dati memorizzati nella cache. Buona caratteristica per il momento e il luogo giusti. Usa responsabilmente :)
Disponibile @Stateful
solo per.
Facile sincronizzazione
Quando è necessaria la sincronizzazione, le annotazioni @Lock(READ)
e @Lock(WRITE)
sono piuttosto eccellenti. Ti consente di ottenere la gestione degli accessi simultanei gratuitamente. Salta tutti gli impianti idraulici ReentrantReadWriteLock. Nello stesso bucket c'è @AccessTimeout
, che ti consente di dire quanto tempo un thread deve attendere per avere accesso all'istanza del bean prima di arrendersi.
Disponibile @Singleton
solo per i fagioli.