Sì, puoi mescolare liberamente sia CDI che EJB e ottenere ottimi risultati. Sembra che tu stia usando @WebServicee @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, @Statelesso @Singletondi 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 @ConversationScopedo per l'implementazione dell'ambito personalizzato).
In EJB il contenitore guarda anche in una hashmap se il bean è di tipo @Stateful. Un @Statefulbean 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, @Statelesso @Singletonsu 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.xmlfile. 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 @Statelesse @Singletonsolo.
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 Applicationsottoclasse JAX-RS o qualcosa del genere. Inoltre posso esporre lo stesso identico bean di un, @WebServicese lo desidero o utilizzare una delle fantastiche funzionalità menzionate di seguito.
Disponibile @Statelesse @Singletonsolo.
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 AfterStartupevento nel ciclo di vita del container. Se lo avessimo fatto, avresti semplicemente potuto avere un @ApplicationScopedbean che lo ascoltasse e che sarebbe effettivamente lo stesso di un @Singletoncon @Startup. È sulla lista per CDI 1.1.
Disponibile @Singletonsolo per.
Lavorare in parallelo
@Asynchronousinvocazione 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, @Statelesse @Singleton.
Pianificazione del lavoro
@Scheduleo ScheduleExpressionè fondamentalmente un cron o una Quartzfunzionalità. 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 EntityManagerchiamata persistente non riesce o si verifica un problema di scaricamento, non è necessario annullare la pianificazione del lavoro. Sì, transazioni.
Disponibile @Statelesse @Singletonsolo.
Utilizzo di EntityManagers in una transazione JTA
La nota sopra sulle transazioni ovviamente richiede di utilizzare un file JTAmanaged EntityManager. È possibile utilizzarli con un semplice "CDI", ma senza le transazioni gestite dal contenitore può diventare davvero monotono duplicare la UserTransactionlogica di commit / rollback.
Disponibile a tutti i componenti Java EE tra cui CDI, JSF @ManagedBean, @WebServlet, @WebListener, @WebFilter, ecc L' @TransactionAttributeannotazione, tuttavia, è a disposizione @Stateful, @Statelesse @Singletonsolo.
Mantenere JTA gestito EntityManager
Il EXTENDEDgestito EntityManagerconsente di mantenere EntityManageraperto tra le JTAtransazioni e di non perdere i dati memorizzati nella cache. Buona caratteristica per il momento e il luogo giusti. Usa responsabilmente :)
Disponibile @Statefulsolo 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 @Singletonsolo per i fagioli.