|
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
|