Untitled Document
   
 
Semplifichiamo lo sviluppo di EJB con EJB 3.0
di Debu Panda, traduzione di Angela Del Chiaro

Discussione
Enterprise JavaBeans (EJB) fu introdotto per assemblare componenti distribuiti. Quando fu introdotto giunse con la promessa di risolvere tutti i problemi e le complessità di CORBA. EJB essendo il cuore di J2EE è passato attraverso parecchie revisioni generali ed è stato ampliato con molte nuove caratteristiche. All'inizio, la maggior parte degli sviluppatori si innamorò di EJB e lo usò nelle applicazioni perfino dove non aveva alcun senso usarlo. "Colpa di EJB" era il modo di pensare di molti sviluppatori quando i loro progetti non raggiungevano una buona scalabilità e avevano fatto uso di EJB.
L'evoluzione di EJB non è mai stata semplice ed è diventata sempre più complessa dopo ogni aggiornamento delle specifiche EJB. EJB è stato paragonato a un elefante a causa della sua complessità e della sua natura da "peso massimo". Molti sviluppatori ritengono EJB come uno strato extra di zucchero sciroppato su un bombolone. In un'epoca dove le diete a basso contenuto di carboidrati e le diete Atkins sono una mania, il comitato di esperti EJB non ha possibilità se non quella di produrre una versione a bassi carboidrati di EJB così da semplificare lo sviluppo di EJB. Il comitato di esperti EJB ha dato una breve illustrazione del modello snellito durante il JavaOne 2004, quando è stata annuncitata la prima versione pubblica della bozza delle Specifiche di EJB 3.0.
Alla prima fugace apparizione il nuovo modello di EJB appare interesante e in questo articolo discuteremo come EJB 3.0 sta provando a vestirsi con una mise di dimensioni più ridotte per diventare più attraente per gli sviluppatori. In un prossimo articolo discuteremo di come EJB 3.0 stia semplificando il modello di persistenza.

 

Facciamo il pulizia...
Andiamo a prendere visione delle complesità del modello EJB corrente prima di tuffarci dentro la discussione dei nuovi dettagli introdotti da EJB 3.0.

  • L'attuale modello EJB richiede la creazione di molte interfacce per i componenti e l'implementazione di molti metodi di callback superflui.
  • Le interfacce dei componenti richiedono l'implementazione di EJBObject o EJBLocalObject e la gestione molte eccezioni superflue.
  • Il descrittore di deploy EJB è complesso e propenso agli errori.
  • La persistenza gestita dal container essendo basata sul modello EJB è altrettanto troppo complessa da sviluppare e gestire. Ci sono diverse caratteristiche di base mancanti come un modo standard di definire la chiave primaria usando una sequenza del database, ed EJBQL è molto limitato.
  • I componenti EJB non assomigliano al loro modello Object Oriented poiché essi hanno restrizioni nell'uso dell'ereditarietà e del polimorfismo.
  • Uno dei maggiori svantaggi degli EJB è che non si possono testare i moduli EJB fuori da un container EJB, e fare il debug di EJB dentro il container rappresenta un incubo per gli sviluppatori.
  • Se avete usato EJB conoscerete le complessità del look-up e dell'invocazione. Sembra sia necessario proprio conoscere i minimi dettagli di JNDI per usare EJB in una applicazione.

 

Semplifichiamo il punto di vista degli sviluppatori
Se avete sviluppato un EJB con le più recenti specifiche comprenderete come è difficoltoso sviluppare un semplice EJB tipo HelloWord EJB. Avete la necessità di almeno due interfacce, di una classe bean e di un descrittore di deploy. La maggior parte degli sviluppatori si è sempre meravigliata del perché ci sia la necessità di tutto questo. Gli ambienti di sviluppo integrati (IDE) come Oracle Jdeveloper, Eclipse e XDoclet hanno reso la vita semplice per lo sviluppatore nel fare questi compiti usuali, tuttavia era ancora responsabilità dello sviluppatore compilare queste classi e impacchettare il descrittore di deploy prima che l'EJB potesse essere pronto per il deploy nel container scelto.
EJB 3.0 sta cercando di risolvere le complessità:

  • Rimuovendo la necessità di interfacce e di descrittori di deploy: questi potrebbero essere generati dal contenitore usando delle annotazione di metadati;
  • Usando classi Java regolari come EJB, e regolari interfacce business per EJB.

Annotazioni di metadati
EJB 3.0 utilizza molto le annotazioni di metadati. L'annotazione dei metadati è stata standardizzata secondo JSR 175 e farà parte di J2SE 5.0. L'annotazione è un tipo programmazione orientata agli attributi e simile a XDoclet. Tuttavia, al contrario di XDoclet che richiede la pre-compilazione, le annotazioni sono compilate in classi (a seconda del valore a cui @Retention è impostata) dal compilatore Java a tempo di compilazione. Dal punto di vista dello sviluppatore, le annotazioni sono trattate come pubbliche e possono essere usate in classi, campi, metodi, parametri, variabili locali, costruttori, enumeratori e package. Potete usare le annotazioni nel vostro codice Java specificando gli attributi che possono essere usati sia per i generatori di codice, di documentazione oppure per fornire speciali servizi come un migliore livello di sicurezza business o speciale logica business durante l'esecuzione. L'obiettivo di J2EE 1.5 (5.0) è di semplificare lo sviluppo usando le annotazioni, e a causa di ciò uscirà con il suo insieme di annotazioni. Le annotazioni sono marcate con @ come segue:

@Author("Debu Panda")
@Bean
public class MySessionBean

Il fine di EJB 3.0 è di semplificare lo sviluppo, e deriva da questo l'uso delle annotazioni dei metadati per generare alcuni oggetti come le interfacce e usare le annotazioni invece che i descrittori di deploy.
Utilizzo di POJO e di POJI
In termini canonici, i JavaBeans e le interfacce spesso sono denominati rispettivamente Plain Old Java Object (POJO) e Plain Old Java Interface (POJI). Le classi e le interfacce EJB assomiglieranno da ora in poi rispettivamente a POJO e POJI. La necessità di oggetti inutili come le interfacce home sarà eliminata. Lo sviluppatore deve implementare una delle interfacce EJB (SessionBean, EntityBean o MessageDrivenBean) del package javax.ejb oppure usare le annotazioni nelle classi di implementazione dei bean. Potete usare Stateless, Stateful, MessageDriven o Entity per annotare le vostre classi bean. Per esempio, se definite un EJB stateless come HelloWord definirete l'EJB come segue:

@Remote
@Stateless public class HelloWorldBean {
public String sayHello(String s)
{ System.out.println("Hello: "+s; }
}

Le interfacce dell'EJB, locali o remote, non devono implementare EJBObject o EJBLocalObject. È possibile fornire l'interfaccia business per il vostro EJB e implementare tale interfaccia nella classe del bean oppure ottenerle generandole durante il deploy. Le interfacce sono facoltative per gli entity bean, ma sono comunque richieste per SessionBean e MessageDrivenDriven. Se non implementate un'interfaccia per il vostro session bean, una interfaccia del bean sarà generata per voi. Il tipo di interfaccia generata, locale o remota, dipende dalle annotazioni che avete usato nella classe del bean. Se guardate il codice sopra nell'esempio, è molto chiaro che @Remote viene usata per generare una interfaccia remota per il bean HelloWorld. Se ne avete bisogno, potete avere sia l'interfaccia remota che locale per il vostro EJB.
Dall'esempio sopra, è molto chiaro che lo sviluppatore non ha molti degli usuali compiti come quello di definire le interfacce e implementare i metodi di ritorno.
Il nome dell'interfaccia generata è derivato dal nome della classe bean implementata. Le interfacce generate sono ottime per gli sviluppatori. Comunque, io non vedo alcun beneficio nel generare interfacce poichè la maggior parte degli ambienti di sviluppo integrati (IDE), come Oracle Jdeveloper, le generano al volo.
Quello che non è chiaro dalla bozza sono i requisiti lato client per il lookup dell'EJB e il modo in cui si prende il controllo delle interfacce richieste per invocare questo EJB. Raccomanderei di non usare un'interfaccia generata, per alcune ragioni:

  • Il nome dell'interfaccia generate deriverà dal nome del bean
  • Magari non si desidera esporre alcuni metodi dell'EJB nell'interfaccia mentre l'interfaccia generata potrebbe esporre tutti i metodi in maniera predefinita.
  • C'è bisogno dell'interfaccia lato client per invocare l'EJB.

 

Rimuovere la necessità dei metodi di callback
EJB 2.1 e le precedendi versioni richiedono l'implementazione di parecchi metodi del ciclo di vita come ejbPassivate, ejbActivate, ejbLoad, ejbStore, ecc. per ogni EJB anche se lo sviluppatore non ne ha effettiva necessità. Per esempio, ejbPassivate non è richiesto per un session bean stateless, ma è richiesto di implementare questo metodo nella vostra classe bean. Poichè EJB 3.0 adesso assomiglia alle classi Java vere e proprie, l'implementazione di questi metodi del ciclo di vita è diventata facoltativa. Se si implementa qualche metodo di ritorno nell'EJB, poi il container invocherà questo metodo.
L'unica eccezione è per il metodo ejbRemove nei session bean stateful dove è possibile usare l'annotazione Remove per annotare un metodo business del session bean stateful. Se usate questo tipo di annotazione ciò suggerirà al container di rimuovere l'istanza del session bean stateful dopo il compimento (normale o anormale) del metodo dell'annotazione. Per esempio, potete specificare quanto scritto di seguito, per rimuovere l'istanza del session bean stateful dopo che il metodo checkOut è stato eseguito.

@Stateful public class Cart {
...
...
@Remove public void checkOut() {
...
}
}

 

Confronto fra annotazioni e descrittori di deploy
Come abbiano esposto precedentemente, i descrittori di deploy non saranno più richiesti per gli EJB mentre le annotazioni saranno usate al loro posto. Saranno scelti, i valori di default per ogni attributo nel descrittore di deploy e gli sviluppatori non dovranno specificare questi attributi, a meno che essi non vogliano un valore diverso rispetto a quello predefinito. Ciò può essere specificato usando le annotazioni all'interno delle classi bean. Le specifiche EJB 3.0 definiscono un insieme di annotazioni per metadati usabili dagli sviluppatori, quali tipo del bean, tipo delle interfacce, riferimenti alle risorse, attributi per le transazioni, sicurezza, ecc. Per esempio, se vogliamo collegare una risorsa a un particolare EJB, allora la definiremo come segue

@Resource (name="jdbc/OracleDS", resourceType="javax.sql.DataSource")

I produttori J2EE come Oracle, BEA, IBM aggiungeranno le annotazioni per gli attributi nei descrittori di deploy nei loro prodotti specifici e gli sviluppatori useranno queste annotazioni per evitare di usare i descrittori di deploy. Ciò sembra molto attraente per gli sviluppatori così gli sgradevoli descrittori XML che la maggior parte di essi detestano usciranno dalla loro vita; ma questo introduce alcuni problemi e dobbiamo stare attenti prima di accogliere a braccia aperte le annotazioni.

  • Questo sconfigge il fine della portabilità delle applicazioni perché, se un EJB usa un descrittore di deploy specifico di un produttore, non può essere cambiato senza effettuare ricompilazione e repackaging degli EJB.
  • Il descrittore di deploy forniva una visione olistica dei moduli EJB a chi assemblava / effettuava il deploy (ejb-jar), senza necessità di guardare all'EJB individuale: bastava operare una messa a punto dei descrittori a seconda delle necessità del deploy. Ma, se i descrittori non sono disponibili o non sono generati fino alla fine dell'azione del deploy, questo potrebbe diventare un incubo.
  • I descrittori di deploy erano usati dai vari tool per riconoscere gli EJB in un modulo EJB ed erano molto utili quando si cercava di migrare da un container a un altro. Le specifiche EJB 3.0 propongono anche un modo per sovrascrivere le annotazioni nei descrittori di deploy. Tuttavia i dettagli della sovrascrittura delle annotazioni sono tralasciati nelle specifiche.

Non c'è dubbio che lasciar perdere i descrittori di deploy renderà la vita più facile ai nuovi sviluppatori, ma questo potrebbe diventare un incubo gestionale se non usato prudentemente.

 

Semplificare la persistenza gestita dal container
Gli entity bean a CMP (Container Managed Persistence, "persistenza gestita dal container") hanno subito una notevole revisione in EJB 3.0 per renderli una scelta praticamente obbligata per gli sviluppatori. I framework di persistenza come OracleAS TopLink o, tra gli open source, Hibernate, sono diventate un tesoro per sviluppare delle infrastrutture per la persistenza per le applicazioni J2EE che non amano gli entity bean per la loro complessità e pesantezza intrinseche. EJB 3.0 sta adottando un modello di persistenza leggera come TopLink e Hibernate per semplificare la persistenza gestita dal container e questo dà l'impressione di essere irresistibile per gli sviluppatori. Diamo ora una veloce occhiata ai piani previsti per gli entity bean: discuteremo sui dettagli del miglioramento della persistenza in un altro articolo.

Gli entity bean si stanno reincarnando come come POJO e non ci saranno richieste di interfacce ai componenti per gli entity bean. Gli entity bean sono adesso visti come veri e propri oggetti e come tali supporteranno anche l'ereditarietà e il polimorfismo.

Di seguito trovate il codice sorgente per una entity bean:

@Entity public class Employee{
private Long empNo;
private String empName;
private Address address;
private Hashmap projects = new Hashmap();
private Double salary;
@Id(generate=SEQUENCE) public Long getEmpNo() {
return empNo;
}
protected void setEmpNo(Long empNo) {
this.empNo = empNo;
}
public String getEmpName() {
return EmpName;
}
public void setEmpName(String EmpName){
this.EmpName = EmpName;
}
@Dependent public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Set getProjects() {
return projects;
}
public void setProjects(Set projects) {
this.projects = projects;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
....

}

Se guardate il codice, troverete che la classe del bean è una classe concreta e non una classe astratta come negli entity bean attuali.

Sono stati fatti diversi miglioramenti per ampliare le possibilità delle query in EJB QL e per il supporto delle query SQL negli entity bean. Una nuova API EntityManager simile a Hibernate e una versione semplificata della API Session di TopLink è stata proposta per manipolare gli entity bean, per esempio per la creazione, la rimozione, la ricerca degli entity bean.

In un prossimo articolo esamineremo da vicino i dettagli degli entity bean a CMP che sono stati proposti.
Semplificare la vista client per EJB
L'uso degli EJB ad esempio per la consultazione e l'invocazione è molto complesso anche se l'EJB è collocato nell'applicazione. J2EE 1.4 e le specifiche EJB 3.0 stanno lavorando per semplificare la vista client degli EJB.

Attulmente, se volete usare un EJB dovete definire le ejb-ref, le ejb-local-ref nel descrittore di deploy, ricercare l'EJB e poi invocarlo. Se volete invocare il nostro EJB HelloWorld, di seguito viene riportata la più semplice strada da seguire per invocare un EJB con l'attuale implementazione.

Anzitutto definiamo i riferimenti all'EJB nel descrittore di deploy come di seguito:

<ejb-ref>
<ejb-ref-name>HelloWorldEJB</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home>hello.HelloWorldHome</home>
<remote> hello.HelloWorld</remote>
</ejb-ref>

Poi effettuiamo la lookup dell'EJB come sotto riportato. Le eccezioni devono essere gestite in maniera esplicita per la lookup dell'EJB e la creazione dell'istanza del bean.

try
{
Context context = new InitialContext();
HelloWorldHome helloHome = (HelloWorld)PortableRemoteObject.narrow
                            context.lookup("
                                java:comp/env/ejb/HelloWorldEJB"),
                            HelloWorldHome.class);
HelloWorld hello = helloHome.create();
....
}
catch(RemoteException e)
{
System.err.println("System/communication error: " + e.getMessage());
}
catch(NamingException e)
{
System.err.println("Communication error: " + e.getMessage());
}
catch(CreateException e)
{
System.err.println("Error creating EJB instance: " + e.getMessage());
}

Come alternativa alle variabili di ambiente, EJB 3.0 propone una soluzione che usa l'iniezione dei metodi di set per la lookup e la consultazione degli EJB.

Di seguito viene riportata la soluzione con cui il nostro HelloWorldEJB può essere ricercato in un altro EJB attraverso l'uso dell'iniezione dei metodi di set.

@Inject private void setSessionContext(SessionContext ctx)
{
this.ctx = ctx
}
...
myHello = (HelloWorld)ctx.lookup("java:comp/env/ejb/HelloWorldEJB");

Se esamina attentamente il codice sopra, il metodo setSessionContext è annotato con @Inject per specificare che l'iniezione di dipendenza può essere usata per questo metodo. I metodi immessi saranno invocati dal contenitore per assegnare l'EJBContext prima che nessun metodo business venga chiamato sull'EJB.

Un altro esempio immediato di iniettare il session bean HelloWorld potrebbe essere semplicemente @EJB public HelloWorld myHello e questo comporterebbe che myHello sarebbe "iniettato" con una istanza del bean HelloWorld.

Potete usare le iniezioni di dipendenza per ricercare ogni tipo di ambiente e riferimenti a una risorsa come DataSource, JMS, Mail, Web Service, ecc.
Collaudabilità e usabilità al di fuori del container
Una grossa preoccupazione per gli attuali sviluppatori degli EJB non è solo che lo sviluppo degli EJB è complesso, ma anche collaudarli è un incubo. Per sviluppare e collaudare gli EJB è richiesto un contenitore EJB e gli sviluppatori hanno dovuto prendere familiarità con la piattaforma finale di deploy per compiere il collaudo. Questo può non essere un grosso problema per molti sviluppatori intraprendenti, ma è un problema per i produttori di sofware indipendenti che lavorano supportando numerosi produttori e che devono mantenere molteplici ambienti per effettuare il collaudo dei loro EJB. Le specifiche EJB 3.0 promettono di supportare la capacità di collaudo fuori dal container ma ciò non è ancora compreso nella bozza delle specifiche.

 

Conclusione
Sebbene vi siano un notevole numero di informazioni mancanti relativamente al packaging, all'assemblaggio e a dettagli fondamentali delle API, quanto proposto nelle bozze EJB 3.0 appaiono molto promettenti per gli sviluppatori di applicazioni Java enterprise. Ciò contribuirà certamente nel rimuovere le complessità dal punto di vista dello sviluppatore rimandandole ai produttori dei container. È da vedere come i produttori di container implementeranno tutto ciò e faranno di EJB 3.0 un'irresistibile opzione per sviluppare le applicazioni enterprise.
Per i riferimenti e le ulteriori informazioni leggete "EJB 3.0 Draft Specification"

 

Biografia dell'autore
Debu Panda uno dei principali product manager del gruppo di sviluppo dell'Application Server Oracle, dove egli concentra i suoi sforzi nel contenitore EJB e nel gestore delle transazioni. Con più di tredici anni di esperienza nel settore IT, ha pubblicato articoli in molte riviste e ha presenziato a molte conferenze di tecnologia. Il suo weblog incentrato su J2EE è disponibile all'indirizzo

http://radio.weblogs.com/0135826/.

L'articolo è stato pubblicato originariamente su theServerSide.com