EJB

 

Gli EJB si dividono in Session, Entity e dalla versione 2.0 in Message Driven Bean.

I session a sua volta si dividono in Stateful e Stateless.

Per gli stateful dato che si deve mantenere l’istanza con le proprie proprieta’ vale che per ogni create() corrisponde sempre una nuova istanza lato server, anche se chi invoca la create() e’ lo stesso client.

Per gli stateless invece dato che non c’e’ necessita’ di mantenere uno stato di proprieta’ legato al client che ha fatto la create, non e’ detto che una create() generi una nuova istanza e ad una stessa chiamata allo stesso ejb non e’ detto che risponda la stessa istanza della precedente.

Quindi per gli stateful le transazioni possono nascere in un metodo e finire in un altro, per gli stateless una transazione deve iniziare e fiinire nello stesso metodo.

Gli Entity si dividono in Bean Manager Persistence (BMP) e Container Manager Persistence (CMP).

Gli Entiy sono sostanzialmente una rappresentazione di dati persistent i(DB,Files etc..) sottoforma di classi.

Il loro uso permette di garantire le applicazioni che eventuali crash del sistema non influenzino la consistenza dei dati, in quanto espongono i propri attributi solo che c’e’ stata la certezza che il dato sia stato correttamente inserito.

La differenza tra BMP e CMP, sta a chi e’ delegato il compito di gestire la persistenza dei dati,  se il programmatore tramite i metodi dell’ejb o il container.

Piu’ client possono interagire con gli entity, in quanto e’ a carico del container gestire la concorrenza.

Infine gli ejb di tipo Message driven sono quelli che permettono l’interazione con i servizi di messaging asincrono tramite jms.

 

Per vedere il tipo di EJB occorre vedere il tag <session-type> nel ejb-jar.xml

Session EJB

 

Per poter creare un EJB occorre creare tre oggetti (due interfacce e una classe) :

 

1)       Classe suffisso “Bean” che racchiude la logica applicativa e implementa l’interfaccia SessionBean.

2)      Interfaccia con suffisso “Home” con definito il metodo create e deve estendere EJBHome
public Convertitore create() throws CreateException, RemoteException;

3)      Interfaccia (No suffisso) con dichiarati i metodi di logica applicativa implementati nella Classe al punto 1, ed estende EJBObject

 

In realta’ per creare un EJB occorrono anche dei file XML di configurazione (creati automaticamente dagli strumenti RAD) :

 

1)       ejb-jar.xml il cui DTD e’ reperibile all’url http://java.sun.com/dtd/ejb-jar_2_0.dtd

2)      un file XML per la gestione e il comportamento dell’EJB (purtroppo per ancora mancata standardizzazione di questo punto ogni application server lo usa con un nome differente (Bea WebLogic: weblogic-ejb-jar.xml, Oracle OC4J: orion.xml, Jboss : jboss.xml, WebSphere : ibm-ejb-jar-bnd.xmi)

 

Una volta arrivati a questo punto (in realtà e’ senza il punto 2 relativo al file xml vendor-dependent), si parla di Naked EJB per arrivare ad un Deployable EJB occorre generare una serie di classi Stub e Skeleton che sono necessarie per le applicazioni distribuite).

Quindi per deployare un EJB su vari Application Server occorre sempre partire da un Naked EJB per poi arrivare a un Deployable EJB tramite i tools appositi per quel AS.

 

Lato client il procedimento e’ il seguente :

1)       Recuperare l’InitialContext per cercare in JNDI il riferimento a Costruttore Home.

2)      Fare una lookup facendo il casting di Home

3)      Con la home eseguire il metodo create che ritorna l’oggetto (stub) che poi colloquiera’ con il relativo Skeleton sul server e quindi con EJB

4)      Chiamare il metodo come un normale metodo di un oggetto.

Importante : Nel Classpath del client occorre che ci siano le interfaccie e gli stub generati, altrimenti un errore verra’ generato, in fase di recupero dell’oggetto.

Es. :

String jndiURL = "iiop://localhost:2809/";

String jndiFactory = "com.ibm.websphere.naming.WsnInitialContextFactory";

java.util.Hashtable properties = new java.util.Hashtable(2);

properties.put(Context.PROVIDER_URL, jndiURL);

properties.put(Context.INITIAL_CONTEXT_FACTORY, jndiFactory);

InitialContext lIC = new InitialContext(properties);

ConversioneHome home = (ConversioneHome) lIC.lookup("ejb/test/ConversioneHome");

Conversione conversione = (Conversione) home.create(); 

double euro = conversione.converti(8500); 

System.out.println("EURO : " + euro) ;    

 

Nelle specifiche il recupero da jndi dovrebbe essere fatto tramite l’oggetto PortableRemoteObject.narrow, quindi :

ConversioneHome home = (ConversioneHome) PortableRemoteObject.narrow(lIC.lookup("ejb/test/ConversioneHome")

Considerazioni su Session Bean (Stateful)

 

Il Concetto degli stateful e’ che il client parla con un’istanza che ha (e mantiene nel corso della vita del bean) determinate proprietà quindi facendo il create del bean viene creata un’istanza ejb che rimane in vita fino a quando non viene fatto il remove() da parte del client o non si attiva il meccanismo del timeout/passivazione.

 

Il ciclo di vita di un EJB Stateful e’ il seguente.

1)       Create da parte del client (creazione nuova istanza EJB) e esecuzione del metodo ejbCreate()

2)      Chiamata al metodo setSessionContext(SessionContext c) (riserva un’area di memoria riservata dal container a quell’istanza di ejb, e serve per le transazioni)

3)      L’istanza se non viene usata per un determinato periodo va in passivazione quindi l’AS lo serializza e lo scarica su disco, prima pero’ chiama  ejbPassivate(), dove il programmatore ha il compito di chiudere gli oggetti non serializzabili, (la passivazione puo’ avvenire anche in caso di scarsita’ di risorse dell’AS. La passivazione e’ possibile solo se nessun client lo sta invocando e non ha transazioni in corso. (un oggetto per essere serializzabile deve implementare l’interfaccia Serializable.

4)      Se viene richiamata dopo la passivazione, il container richiama il metodo ejbActivate(), in questo metodo il programmatore deve preoccuparsi di riaprire e reinstanziare gli oggetti presenti prima della passivazione.

5)      Se il client richiama il metodo remove() o se dopo la passivazione arriva il secondo timeout, l’EJB eliminato.

 

A differenza degli stateless dove le proprieta’ non hanno significato, per gli stateful e’ possibile definire piu’ metodi create con diversi parametri, in modo da cambiare lo stato dell’istanza EJB.

Considerazioni su Session Bean (Stateless)

 

Il funzionamento degli stateless e’ sostanzialmente lo stesso tranne, per il fatto che :

1)       Gli EJB stanno in un pool, quindi ad ogni richiesta puo’ corrispondere un’stanza differente, quindi c’e’ da stare attenti a l’uso di variabili di classe.

2)      I metodi ejbActivate() e ejbPassivate() vengono scatenati rispettivamente quando un ejb viene tolto dal pool e rimesso nel pool a disposizione di nuove richieste.

Entity EJB

 

Tali tipi di EJB non servono tutte le volte che siamo in presenza di un DB, ma solo se dobbiamo gestire una pesante concorrenzialita’ di accessi ai dati, in quanto il container in presenza di Entity EJB, gestisce gli accessi in caso di richieste contemporanee sulla stessa entita’ dati.

Ogni volta che le proprieta’ dell’EJB vengono modificate (tramite metodi get/set), il sistema di persistenza su cui sono inseriti i dati viene automaticamente aggiornato da parte del container.

Ogni volta che da parte del client viene interrogata una proprietà del ejb, il container richiama ejbLoad() che prende il valore dal DB.

 

I principali metodi degli EJB Entity sono :

 

ejbCreate()

Inserisce il dato nel DB e crea un’istanza dell’ejb, verifica che non ci siano primary key duplicate e ritorna l’istanza di una Primary Key. (INSERT)

ejbPostCreate()

Viene chiamata dop la ejbCreate(), prima della commit(, in questo metodo siamo sicuri che tutto e’ andato bene

ejbFindByPrimaryKey()

crea un’istanza di un EJB, ritornando una Primary Key

ejbFind<xxx>()

Altri metodi Finder, ritorna Collection di riferimenti Primary Key

setEntityContext()

Viene chiamato dal Container dopo la ejbCreate()

unsetEntityContext()

Chiamando questo metodo si dice al container di rimuovere l’istanza dal pool senza cacellare il dato

ejbActivate()

Come per gli EJB Session Stateless

ejbPassivate()

Come per gli EJB Session Stateless

ejbLoad()

Carica il dato dal DB e valorizza le proprieta’ di classe (SELECT)

ejbStore()

Inserisce il dato nel DB (UPDATE)

ejbRemove()

Rimuove dal DB il dato e distrugge l’istanza dell’EJB (DELETE)

 

Una caratteristica degli entity’ e’ che sono condivisibili da piu’ client, non che i client accedono alla stessa istanza EJB, ma piuttosto che possono condividenre i dati.

Siccome un Entity deve rappresentare un dato univoco su DB, si usa identificare la Primary key, per legare l’ejb all’entity sul DB. Non e’ necessariamente vero che la primary key dell’ejb deve essere lo stesso di quella di riferimento della tabella del DB.

Le Primari key sono dichiarate nel Deployment descriptor del ejb in XML, e sono rappresentate da una o piu’ proprieta’ della classe.

La dichiarazione della Primary key e’ fatta nel metodo ejbCreate() e se si tenta di creare un ejb con una Primary key di un entity ejb che gia’ esiste, viene rilanciata la DuplicateObjectException.

 

Per vedere se esiste gia’ un ejb che rappresenta il dato desiderato, ci sono diversi metodi di find che possono ritornare un riferimento a un particolare ejb o a una collection.

Tutti gli entity devono avere nella interfaccia home la findByPrimaryKey(PrimaryKeyClass key),

Se vengono creati metodi ejbFind<xxx>() devono fare la throw di RemoteException. Nei BMP ad ogni find….() deve corrispondere il relativo ejbFind….() nella classe Bean.

Gli ejbFind….() devono ritornare l’istanza di una chiave primaria oppure una collection di chiavi primarie, inoltre deve fare il throw ObjectNotFoundException se non viene trovato nessun dato che rispetti i criteri.

Nei metodi find NON si deve preoccuparsi di ricavare e memorizzare i dati nelle proprieta’ della classe, lo scopo e’ solo di localizzare e caricare il valore della primary key. Sara’ poi il container che tramite il metodo ejbLoad() avra’ la responabilita’ di valorizzare le proprieta’ della classe.

EJB Entity BMP [Bean Managed Persistence]

Questi tipi di EJB sono usati quando la persistenza dei dati non si basa su DB o quando e’ su DB ma questo comporta query complesse e join tra tabelle che non permettono una gestione automatica del dato (risolto con EJB 2.0).

EJB Entity CMP [Container Managed Persistence]

Con questo tipo di EJB si delega tutto al container che tramite la mappatura da parte del programmatore sui file di configurazione gestisce la consistenza dei dati.

Questo EJB e’ preferibile rispetto al BMP in quanto e’ piu’ performante e in piu’ non c’e’ da scrivere codice.

I CMP come detto richiedono una mappatura tra le proprieta’ di classe, il file e le regole di mappatura sono dipendenti dall’AS usato. Questo punto e’ molto delicato in quanto una non corretta mappatura porta ad errori che vanni risolti remotamente ; su Websphere e’ possibile attivare il trace che da maggiori dettagli, per fare questo occorre introdurre nella configurazione del Test Environment nella sezione trace : “com.ibm.ws.ejbpersistence.*=all=enabled:”

In questo modo Verra’ creato nella dir .metadata\.plugins\com.ibm.etools.server.core\tmp???\logs\server1 il file di trace.

 

 

Un entity puo’ essere in tre stati particolari :Does not exist, Pooled, ready.

1)       quando un ejb e’ vuoto (con proprieta’ non valorizzate e con nessuna PK), e’ in stato pooled quindi a disposizione del container.

2)      Quando viene richiamato il create() o i Find() o altri metodi della home, il container prende un ejb dal pooled e nel momento in cui ha la necessita’ di valorizzare le proprieta’ diventa in ready. Il processo da pooled a ready e’ chiamato attivazione. (da ready a pooled viene chiamato passivazione)

3)      Da does not exist a pooled dipende dal numero di istanze e dai client che le richiedono.

Message Driver Bean

 

Questi tipi di EJB introdotti dalla versione 2.0 delle specifiche permettono di avere degli EJB con funzione di client JMS. Quindi e’ possibile creare degli ejb che vivono nel container e sono scatenati a seconda del tipo di messaggi che in fase di deploy e’ stato configurato.

Quindi per la loro chiamata, qualunque sistema anche non java, ch puo’ accedere a sistemi MQ puo’ usufruire di questo tipo di EJB inviando messaggi.

 


 

Qui sotto il diagramma dove si inseriscono nel modello 3-tier gli EJB :

 

Diagramma di una richiesta a un EJB :