Con la nuova versione della specifica, Sun ha finalmente eseguito una radicale operazione di reingegnerizzazione volta a semplifare e razionalizzare il lavoro del programmatore. Cominciamo una serie di articoli in cui tratteremo i diversi aspetti di EJB 3.0, dalla teoria alla pratica, descrivendo innovazioni e punti di forza di Enterprise JavaBeans versione 3.0.
Introduzione
Il lento ma inesorabile aumento della complessità di una tecnologia è uno dei problemi maggiormente sentiti da chiunque debba utilizzarla in qualche modo.
Con l‘avvento di Internet questa tendenza è di fatto aumentata tanto velocemente da portare alcuni strumenti e tecnologie a livelli inimmaginabili fino a poco tempo fa.
Lo scenario si è complicato sia in senso orizzontale (sono aumentati gli strumenti tecnologici in competizione tra loro e adatti per una determinato obiettivo) sia in verticale (ogni tecnologia, framework, tool è cresciuto in modo esponenziale tanto da offrire moltissime potenzialità in più rispetto a prima).
La storia recente insegna che una tecnologia è vincente se la crescita delle funzionalità e delle potenzialità , è accompagnata da un costante sforzo di reingegnerizzazione e riorganizzazione dei vari livelli al fine di rendere il tutto omogeneo, coerente e quindi più semplice da utilizzare.
Un caso evidente portato spesso come esempio nelle chiacchiere da bar è quello dei videoregistratori (ma si potrebbe facilmente adattare ai televisori, telefoni cellulari e molti oggetti di consumo): programmare un videoregistratore nei primissimi anni Novanta richiedeva molta pazienza e conoscenze ai limiti della ingegneria del software.
Per questo non è difficile comprendere il motivo del successo di oggetti come l‘iPod, il Tivo, o di taluni software tanto potenti quanto semplici da utilizzare.
Anche nel settore Java Enterprise si è potuto assistere a un fenomeno del tutto analogo: da un lato si può senza dubbio registrare l‘importante lavoro di Sun (e dei partner) per offrire sempre nuovi strumenti e tecnologie.
È altrettanto evidente il successo di soluzioni,che hanno permesso di incrementare lo step tecnologico senza introdurre un elevato coefficiente di complessità , oppure di alternative che pur non presentando alcun nuovo concetto, hanno permesso di fare in maniera molto più semplice, veloce, economica le cose che già si facevano prima.
La specifica EJB da questo punto di vista è uno degli esempi più evidenti del costante conflitto fra potenzialità e semplicità di utilizzo e mostra come in questi casi la concorrenza abbia di fatto giovato all‘elemento centrale.
Con la versione 2.1 ai programmatori era stato dato uno strumento molto potente ma al tempo stesso eccessivamente complesso per essere utilizzato (vedi Web Services Bean) o troppo macchinoso per essere adottato con successo (vedi CMP 2.0 che pur essendo tecnologicamente corretto non ha avuto successo a causa delle alternative più semplici e performanti).
In questa miniserie di articoli mostreremo in modo sintetico le principali innovazioni della tecnologie EJB 3.0, dando rilievo allo sforzo compiuto per semplificare lo scenario. Prima di iniziare a scrivere questo documento, ho trascorso un bel po‘ di tempo nel cercare di capire quale fosse il modo migliore per implementare una applicazione EJB 3.0 ponendomi come obiettivo di rifare una applicazione reale (ovvero in produzione) già fatta in passato. Per questo ho concentrato la mia attenzione non tanto sull‘analisi e sullo studio di tutte le caratteristiche della specifica 3.0 (per l‘elenco delle quali un buon libro o reference può sempre venire in aiuto), ma piuttosto sul modo in cui implementare il processo di sviluppo, su come realizzare quelle cose che tipicamente servono su un progetto e, soprattutto, su quali strumenti utilizzare.
Per forza di cose l‘approcio è incompleto: speriamo nella buona volontà del lettore nel voler colmare le lacune e nell‘apprezzare invece la volontà di fornire contenuti alternativi ai classici che si trovano in Internet.
La visione alla POJO
La specifica EJB si basa su un principio base che vede il dualismo Container-Bean centrale rispetto a tutta la logica server side.
Un session bean o un entity vivono all‘interno di un container il quale regola il ciclo di vita, gli attributi transazionali, il pooling e la sicurezza.
La grossa rivoluzione introdotta da questo nuovo paradigma consiste nel togliere al programmatore un carico di lavoro gravoso volto a risolvere problematiche tipiche che compaiono nella maggior parte delle applicazioni enterprise. In questo nuovo modello, lo sviluppatore può finalmente concentrarsi sullo sviluppo e messa a punto della business logic, trascurando aspetti complessi e costosi (in termini di tempi di sviluppo) che sono passati al controllo del container.
Il nuovo modo di vedere le cose ha sconvolto radicalmente la maniera di lavorare di migliaia di sviluppatori in tutto il mondo.
Per poter ottenere questo risultato, il prezzo da pagare è stato il naturale aumento della complessità generale dei vari strumenti coinvolti e dei concetti di base. Sviluppare una applicazione EJB è un compito non banale dato che per rispettare il contratto container-bean si devono seguire precise regole legate al naming, alle interfacce da implementare, alla logica relativa al ciclo di vita dei beans.
Dopo aver appurato che la strada intrapresa da Sun è quella giusta, la comunità ha chiesto un primo consolidamento per poter disporre anzitutto di strumenti stabili, performanti, sicuri, affidabili. Questo primo step si è avuto con il rilascio della release 2.1 e con strumenti di lavoro come Eclipse, JBuilder e JDeveloper.
Il passo successivo indispensabile è stato quello di riconsiderare tutto il lavoro fatto riportandolo nell‘ottica di semplificazione. La prima trasformazione è consistita nello spostare la complessità dentro l‘application server, lasciando fuori solamente componenti che a prima vista sono semplici classi Java e non Enterprise Beans.
Questo passaggio prende spunto in parte dal lavoro fatto dal team di JBoss (il plugin JBoss IDE già da tempo utilizzava annotazioni e doclet per definire il comportamento di un session e di un entity), in parte facendo propria la filosofia adottata dai moderni framework di mapping come Hibernate.
Un session bean quindi diventa un semplice POJO (Plain Old Java Object) ovvero un bean che contiene metodi e attributi relativi al suo funzionamento non enterprise. Un POJO è quindi, in prima battuta, un componente che non ha nessun legame con il container (nessuna interfaccia da implementare, nessun metodo di ciclo di vita e nessun file XML che lega i due).
Questa grossa rivoluzione si è resa possibile grazie all‘utilizzo delle annotazioni (introdotte ufficialmente con Java 5) che descrivono il comportamento del bean in ottica enterprise.
Per comprendere l‘importanza di questo nuovo modo di sviluppare EJB, vediamo subito un semplicissimo session bean:
@Stateless(name="MySession")
public class MySessionBean implements MySessionLocal, MySessionRemote {
public MyFirstSessionBean() {}
public String helloWorld(){
return "Hello World!";
}
esso implementa un paio di interfacce che possono essere definite in questo modo
@Remote
public interface MySessionRemote {
public String helloWorld ();
}
@Local
public interface MySessionLocal {
}
Come si può notare il session è prima di tutto un semplice bean che non contiene nessun riferimento alla logica EJB; il fatto di implementare le interfacce (che per convenzione stilistica terminano con il suffisso “Local” e “Remote”, ma la specifica non lo obbliga) ha lo scopo di pubblicare nel container le interfacce remota e locale: dentro il container quindi l‘oggetto diviene un session bean, ma al di fuori è un POJO a tutti gli effetti e niente vieta di scrivere
MySessionBean myBean = new MySessionBean();
myBean.helloWorld();
Questo passaggio è la vera rivoluzione di EJB 3.0: adesso è infatti possibile utilizzare il componente sia come oggetto semplice che nella sua versione Enterprise. Ecco come un client può ricavare e invocare il session bean in esecuzione nel container
try{
final Context context = getInitialContext();
MySessionRemote mySession = (MySessionRemote)context.lookup("ejbApp/MySession/remote");
System.out.println("Ecco la risposta dallo strato server:"+ mySession.helloWorld());
} catch (Exception ex) {
ex.printStackTrace();
}
Si noti come, pur rimanendo concettualmente inalterata, l‘operazione di lookup risulta semplificata nella parte del cast (non più narrowing) che è molto simile a un banale lookup e cast che si eseguiva con RMI.
Quindi la nuova specifica semplifica e riporta a una dimesione più umana la definizione e l‘utilizzo dei vari componenti.Particolarmente interessante la parte relativa al nome utilizzato per identificare il bean all‘interno del container, di cui si parlerà poco più avanti in questo articolo.
Riconsiderando il codice del session bean si sarà certamente notata la presenza di annotazioni caratterizzate dalla classica chiocciola: queste note (il compilatore le gestisce i fase di prepropressing come avviene con le direttive C) sono trasformate in codice Java in maniera trasparente agli occhi del programmatore.
Di fatto non è necessario conoscere quando e come sia gestita (se non per fini strettamente culturali), dato che è sufficiente sapere che la seguente annotazione
@Stateless(name="MySession")
“etichetta” un POJO per diventare nel container un session bean.
Parallelamente le due annotazioni @Local e @Remote definiscono quelle che saranno poi le interfacce remota e locale.Per chi fosse interessato ad approfondire la conoscenza e il funzionamento del meccanismo delle annotations, consiglio la lettura dell‘articolo [ANNOT].
La specifica non impone nessun regola particolare sull‘organizzazione del codice del bean o delle interfacce: valgono le stesse considerazioni relative alle eccezioni (vedi [EJB-EXC]) per la firma dei metodi, mentre la regola base che deve guidare il session bean è quella delle specifiche dei JavaBeans (obbligo della presenza del costruttore pubblico di default, metodi get/set, etc.).
E dove va a finire l‘XML?
Con grande sollievo di tutti i programmatori, costretti alla lettura, gestione e manutenzione di tonnellate di XML (in alcuni casi i file descrittori di una applicazione EJB 2.1 possono risultare veramente complessi e altrettanto grossi) la specifica non fa più uso dei file descrittori in formato XML.
In una applicazione EJB che non abbia bisogno di esigenze particolari, saranno presenti il file relativo alla configurazione per l‘application server (per esempio il file “jboss.xml”) che però in genere è vuoto, il file di organizzazione dell‘archivio .ear (“application.xml” che specifica cosa contiene l‘archivio) e un file di configurazione del motore di mapping (dal contenuto veramente molto semplice) di cui parleremo prossimamente. Anche in questo caso si tratta di una grossa semplificazione.
La gestione del contesto JNDI
Sulla carta la ricerca di un componente remoto è stata sgravata di tutte le complicazioni relative alla definizioni dei nomi nel JNDI context (per i quali, personalmente, ho avuto sempre pochissima simpatia).
Leggendo un qualsiasi manuale o tutorial si trova scritto che la procedura di ricerca parte dalla individuazione del nome con il quale è stato effettuato il deploy del bean.
In prima battuta il nome è dato dall‘attributo della annotazione @session. Quindi nell‘esempio di poco sopra partendo da
@Stateless(name="MySession")
dovrebbe essere necessario scrivere
MySessionRemote mySession = (MySessionRemote) context.lookup("MySession");
In JBoss (che resta al momento la piattaforma di riferimento per questo genere di applicazioni) questa istruzione non funziona (il bean non viene trovato dalla procedura di lookup) se il bean è impacchettato in un JAR e poi il tutto è a sua volta inserito in un EAR.
Il problema è legato alla modalità attuale con la quale JBoss, che per primo si adegua a nuove specifiche, gestisce il proxy dinamico delle chiamate (sistema utilizzato già dalla versione 3 dell‘application server): in questo caso quindi si deve includere il nome della applicazione (ossia il nome del file .ear, se non specificato altrimenti in META-INF/application.xml):
MySessionRemote mySession = ( MySessionRemote) context.lookup("EJB30App/MySession");
Putroppo anche questa soluzione potrebbe non funzionare: nel caso in cui si verifichi una ClassCastException alla esecuzione del cast, significa che si sta utilizzando una versione di JBoss recente in cui sono state ulteriormente cambiate alcune parti relative al marshalling e al sistema del dynamic proxy (problema che si verifica in particolare passando dalla versione 4.0.3 alla 4.0.4). In questo caso si deve utilizzare la seguente sintassi:
MySessionRemote mySession = ( MySessionRemote) context.lookup("EJB30App/MySession/remote");
specificando l‘interfaccia da utilizzare (remota o locale).
Lavorare con EJB 3.0
Per poter lavorare con la release 3.0, si devono effettuare attentamente alcune considerazioni circa la scelta dell‘application server e dell‘ambiente di sviluppo integrato.
Per l‘application server, in questo particolare momento, non ci sono molte alternative credibili a JBoss 4.0.4+ (in realtà anche OC4J di Oracle supporta EJB 3.0, ma non consiglio di legarsi in questa fase storica a tale ambiente meno diffuso e meno aperto).
Per quanto concerne l‘IDE, invece, è bene tenere presente che praticamente ogni mese esce una nuova release di uno dei vari concorrenti, e quindi questa valutazione deve essere costantemente aggiornata.
Le prove, durante la fase di studio sono state fatte su JDeveloper (10.1.3.1.0), su Netbeans 5.5 preview (non è stabile come dovrebbe, ma da questo punto di vista sicuramente migliorerà , visto che per ora si tratta di una release non finale) e su Eclipse con plugin di JBoss.
Per tutti gli ambienti si potrebbe dire che in alternativa alle funzioni RAD, ai wizard e alle finestre visual programming, si può lavorare manualmente scrivendo tutte le annotazioni e il codice senza i wizard: in questo caso si perderebbe la potenza di EJB 3.0 (un po‘ come scrivere pagine JSF a mano senza un IDE RAD)
Dopo le varie prove ho dato la palma del miglior ambiente attualmente in circolazione (e sottolineo “attualmente”) a JDeveloper del quale fortunatamente è stata rilasciata una nuova versione proprio mentre stavo facendo le prove con i vari IDE.
JDeveloper è sufficientemente stabile, corretto nel funzionamento e offre il giusto livello di “visual” che si sposa con la filosofia della semplificazione di EJB 3.0.
Ha ancora scarso supporto per application server esterni, mentre predilige quello embedded (OC4J di Oracle); con Ant si riesce comunque a sopperire bene a questa carenza.
Contiene ancora alcuni bizzarri bug che hanno fatto perdere tempo prezioso alla ricerca di un apice che si era perso.
Netbeans parrebbe essere sulla carta l‘ambiente migliore, con un buon approccio visuale. Purtroppo al momento le promesse sono solo sulla carta e molte cose ancora non funzionano.
Se in Sun lavoreranno parecchio per chiudere i bug e renderlo RAD (o simil RAD), operando al contempo per integrarlo, come silenziosamente annunciato, con gli ambienti Sun (Studio Creator e Sun Studio Enterprise) forse verrà fuori la “killer application”. Però – non me ne vogliano i fan della casa madre di Java, nà© i programmatori che ci hanno lavorato – mi verrebbe ironicamente da dire che per adesso l‘applicazione è killer solo nei confronti del programmatore che la usa…
Eclipse (con JBoss plugin) non mi ha convinto per tale utilizzo e soprattutto non mi ha fatto comprendere perché ci siano persone che si ostinano a voler usare Eclipse per lavorare in ambito enterprise.
È un ambiente per niente visuale (in ambito EJB, ma esulando dal contesto di questo articolo, le cose vanno anche peggio per quello che concerne JSF) e tutto il lavoro deve essere fatto a mano.
Di fatto già con la versione precedente del plugin (allineata a EJB 2.1) si poteva lavorare con le annotations in una modalità pseudo POJO: tutto doveva (e deve essere tutt‘ora) scritto a mano e questo rende impraticabile l‘utilizzo di questo strumento in contesti reali se ci sono scenari complessi da gestire (relazioni n-m fra tutti); di fatto ogni applicazione enterprise di produzione si scontra con questi aspetti.
Le prove sono state effettuate con la nuova versione del plugin rilasciata proprio nel periodo della preparazione di questo articolo.
Purtroppo in questo momento la documentazione allegata è ancora inesistente e la cosa ha fatto propendere per rimandare l‘emozione di provare questo ambiente. Per chi fosse interessato ad utilizzare questo sistema è certo che a breve il supporto migliorerà .
Conclusione
Termina questa prima parte della serie dedicata a EJB 3.0: la nuova release è stata annunciata da molto tempo ma solamente adesso gli ambienti di deploy e di sviluppo sono sufficientemente maturi (complice anche il rilascio in versione finale della specifica) per iniziare a fare delle prove e anche per realizzare le prime applicazioni complete.
Non ci sono al momento note e case history che possano giustificarne l‘uso in scenari complessi e di produzione.
Il fatto che di recente, notizia di pochi giorni fa, JBoss abbia rilasciato la prima versione definitiva del container aggiornato alla EJB 3.0, fa ben sperare per considerare i tempi pronti al passaggio.
Il prossimo mese parleremo ancora di POJO (e del perché sia così importante il loro utilizzo) e inizieremo a parlare dei servizi di contorno per finire a trattare la nuova modalità di persistenza.
Riferimenti
[EJB] – Home page Sun della specifica: http://java.sun.com/products/ejb/docs.html
[ANNOT] Andrea Gini, “Java 5. IV parte: le annotazioni”, MokaByte 94, marzo 2005
https://www.mokabyte.it/2005/03/java5_annotations.htm
[EJB-EXC] Giovanni Puliti, “EJB e la gestione delle eccezioni. Interazione fra le eccezioni e le transazioni all‘interno di un container EJB”, MokaByte 80, dicembre 2003 https://www.mokabyte.it/2003/12/ejbexceptions.htm