COMMON
CLIENT INTERFACE (CCI)
CCI definisce un insieme di API per uniformare l'accesso
ad EIS da parte di applicazioni client. I client CCI
possono essere componenti applicativi quali EJB o componenti
d'integrazione come gli stessi Integration Broker.
CCI
fornisce API di alto livello che permettono di astrarsi
dai dettagli e dalle specificità di gestione
delle differenti risorse EIS, operando rispetto a queste
in modo analogo a JDBC rispetto ai DBMS, JMS rispetto
ai sistemi di messaging o JNDI rispetto ai servizi di
Naming e Directory.
L'analogia
è ancora più stretta se si confronta JCA
con JDBC; si può scherzosamente affermare che
JCA è il "cugino di primo grado" [BSTW]
di JDBC.
Le
API CCI astraggono lo sviluppatore dai dettagli di comunicazione
con lo specifico EIS e definiscono uno standard per
accedere a qualsiasi EIS non-relazionale. In modo similare,
le API JDBC astraggono lo sviluppatore dai dettagli
di comunicazione con lo specifico DBMS e definiscono
uno standard per accedere a database relazionali.
Per creare una connessione con JDBC si utilizza javax.sql.DataSource,
dataSource
= (DataSource) ic.lookup("java:comp/env/jdbc/MyDataBase");
in JCA si utilizza javax.resource.cci.ConnectionFactory
factoryJCA = (ConnectionFactory) ic.lookup("java:comp/env/eis/MyHost");
Per
ottenere una connesione con il DBMS in JDBC si utilizza
il metodo getConnection dell'oggetto DataSource
java.sql.Connection con = dataSource.getConnection();
in JCA avviene in modo analogo, invocando il metodo
getConnection sull'oggetto ConnectionFactory
javax.resource.cci.Connection con = cf.getConnection(.
. .);
Come già detto in [JCA1] l'implementazione delle
API CCI non è mandataria. Se l'accesso via CCI
non è disponibile, è necessario utilizzare
direttamente l'interfaccia proprietaria del RA; ovviamente
l'utilizzo diretto di API proprietarie riduce i vantaggi
di astrazione di JCA.
PANORAMICA API CCI
Le API CCI si dividono fondamentalmente in quattro aree
:
- Connection
API: per connettersi all'EIS
- Interaction
API: per eseguire comandi ed invocare azioni sull'EIS
- Record/ResultSet
API: incapsulano il risultato dell'operazione avvenuta
sull'EIS
- Metadata
API: che permettono la descrizione dei tipi di dati
Affinchè
un RA sia CCI-compliant deve implementare un set di
intefacce (presentate nel seguito).
Le interfacce obbligatorie da implementare sono javax.resource.cci.Connection
e javax.resource.cci.Interaction.
Le API CCI sono costituite da sole interfacce, incluse
nel package javax.resource.cci.
clicca per ingrandire
ConnectionFactory (javax.resource.cci.ConnectionFactory)
E' l'interfaccia Factory responsabile della creazione
delle connessioni con l'EIS. Il ConnectionFactory è
pubblicato in un namespace JNDI e quindi reperibile
mediante l'operazione JNDI di lookup.
ConnectionFactory
cf = (ConnectionFactory)
context.lookup("java:comp/env/eis/CCI_MOKA_EIS");
Un
componente J2EE per ottenere la connessione con l'EIS
deve invocare il metodo getConnection del ConnectionFactory.
Connection CONNECTION (javax.resource.cci.Connection)
Rappresenta la connessione con il sottosistema EIS.
La Connection si ottiene invocando il metodo getConnection
su un'istanza di ConnectionFactory.
Connection
con = cf.getConnection(spec);
Permette
inoltre di creare un oggetto Interaction per interagire
con la risorsa EIS.
Interaction
ix = con.createInteraction();
Il
metodo close permette di chiudere la connessione con
l'EIS.
try
{ con.close();}
catch (ResourceException ex) {. . .}
ConnectionMetadata
(javax.resource.cci.ConnectionMetaData)
Permette di specificare le informazioni sull'istanza
EIS puntata dal Connection reference. I metadata sono
ottenibili invocando il metodo getMetaData sull'oggetto
Connection.
MokaCciConnectionMetaData
conMetaData =
(MokaCciConnectionMetaData)con.getMetaData();
System.out.println("EISProductName="+
conMetaData.getEISProductName());
System.out.println("ProductVersion="+
conMetaData.getEISProductVersion());
System.out.println("UsertName ="+
conMetaData.getUserName());
ConnectionSpec
(javax.resource.cci.Connection)
L'implementazione di questa interfaccia permette al
client di comunicare al ConnectionFactory eventuali
proprietà specifiche (request-specific properties
) della risorsa EIS durante la richiesta di connessione.
Questa
classe è di fatto un Java bean con proprietà,
metodi di accesso (mutators methods-setter) e metodi
di lettura (accessors methods-getter).
ConnectionSpec
spec = new CciConnectionSpec(user, password);
Connection con = connectionFactory.getConnection(spec);
ResourceAdapterMetaData
(javax.resource.cci.ResourceAdapterMetadata)
E' l'interfaccia che fornisce informazioni sulle caratteristiche
del Resource Adapter. E' ottenibile invocando il metodo
getMetaData sull'oggetto ConnectionFactory.
Tale invocazione quindi non implica che sia attiva una
connessione con la risorsa EIS in quanto si limita a
fornire informazioni descrittive e di utilizzo del RA.
MokaCciResourceAdapterMetaData
raMetaData =
(MokaCciResourceAdapterMetaData)cf.getMetaData();
System.out.println(raMetaData.getAdapterName());
System.out.println(raMetaData.getAdapterShortDescription());
System.out.println(raMetaData.getAdapterVendorName());
System.out.println(raMetaData.getAdapterVersion());
System.out.println(raMetaData.getInteractionSpecsSupported());
System.out.println(raMetaData.getSpecVersion());
System.out.println(raMetaData.
supportsExecuteWithInputAndOutputRecord());
System.out.println(raMetaData.
supportsExecuteWithInputRecordOnly());
System.out.println(raMetaData.
supportsLocalTransactionDemarcation());
InteractionSpec (javax.resource.cci.InteractionSpec)
Contiene le eventuali proprietà necessarie per
interagire con la risorsa EIS. E' utilizzata dall'oggetto
Interaction per l'esecuzione della specifica funzione
della risorsa EIS.
Come
il ConnectionSpec, anche l'InteractionSpec è
di fatto un Java Bean.
CciInteractionSpec
iSpec = new CciInteractionSpec();
iSpec.setFunctionName("WRITE");
ecc
Interaction (javax.resource.cci.Interaction)
Permette di interagire con la risorsa EIS indicando
la modalità d'accesso(scrittura/lettura). L'oggetto
Interaction viene costruito a partire dall'oggetto Connection.
Interaction
ix = con.createInteraction();
Il
metodo close chiude l'interaction corrente e rilascia
tutte le risorse associate ma non la connessione con
l'EIS. E' buona pratica invocare in modo esplicito il
metodo close alla fine di ogni interazione.
ix.close();
L'interazione
con la risorsa EIS avviene mediante il metodo execute
fornito con le seguenti firme:
public
boolean execute(InteractionSpec ispec,Record input,
Record output) throws ResourceException
esegue
l'interazione con la risorsa EIS aggiornando il valore
dell'output Record restituendo true se l'operazione
è andata a buon fine. Se l'interazione fallisce
il metodo solleva una javax.resource.ResourceException.
public Record execute(InteractionSpec ispec, Record
input)
throws ResourceException
esegue
l'interazione con la risorsa EIS ricevendo in ingresso
un Record e restituendo come output un nuovo Record
nel caso l'operazione abbia successo.
Record (javax.resource.cci.Record
E' l'interfaccia madre delle varie tipologie di Record.
Rappresenta i dati di input e output necessari per eseguire
le interazioni con l'EIS.
Esempi di interfacce derivate sono:
- MappedRecord:
record di coppie di chiave-valore basati sull'interfaccia
java.util.Map
- IndexedRecord:
collezione ordinata ed accessibile mediante indice
- ResultSet:
estende sia l'interfaccia Record, sia l'interfaccia
java.sql.ResultSet per reperire dati in forma tabellare.
E'
inoltre possibile creare una propria tipologia di Record
in funzione delle esigenze specifiche dell'EIS (es:
un Record per rappresentare un ordine di acquisto presso
un sistema ERP).
RecordFactory (javax.resource.cci.RecordFactory)
E' l'interfaccia factory responsabile della creazione
d'istanze di Record. Così come il ConnectionFactory
permette di avere oggetti Connection, il RecordFactory
permette di ottenere oggetti Record.
Mette
a disposizione un metodo factory specifico per ogni
tipologia di record (createIndexedRecord, createMappedRecord,
createResultSet).
LocalTransaction
( javax.resource.cci.resourceAdapterMetaData)
E' l'interfaccia utilizzata per demarcare
(begin, commit e rollback) le transazioni locali ad
un RA. La gestione della local transaction è
interna al RA e non coinvolge nessun coordinamento esterno.
Un'istanza
valida di LocalTransaction è ottenibile, se l'implementazione
CCI lo supporta, invocando il metodo Connection.getLocalTransaction.
Come
utilizzare un connettore
Dopo la panoramica delle API CCI, vediamo come un client
J2EE può accedere ad un RA.
Le operazioni che devono essere effettuate sono:
Importare
il package javax.resource.CCI, la classe javax.resource.ResourceException
e le classi relative al connettore da utilizzare
import
javax.resource.cci.*;
import javax.resource.ResourceException;
import it.mokabyte.mokajca.ra.*;
Effettuare, mediante JNDI, la lookup dell'oggetto ConnectionFactory
del Resource Adapter
Context
ctx = new InitialContext();
Object obj = ctx.lookup("java:comp/env/eis/CCI_MOKA_EIS");
effettuando
l'opportuno downcast
ConnectionFactory
cf = (ConnectionFactory)obj;
Creare l'oggetto ConnectionSpec per indicare gli eventuali
parametri specifici necessari ad ottenere la conessione
all'EIS
ConnectionSpec
spec = new CciConnectionSpec(
<<param1>>,.
. .,<<paramN>>);
Invocare
sull'oggetto ConnectionFactory il metodo getConnection
per ottenere l'apertura della connessione con il Resource
Manager dell'EIS
Connection
con = cf.getConnection(spec);
L'oggetto Connection rappresenta la connessione con
l'EIS e permette di interagire con la risorsa stessa.
Invocare
sull'oggetto Connection il metodo createInteraction
per creare un'istanza Interaction. Mediante l'istanza
ottenuta sarà possibile interagire con la risorsa
EIS
Interaction
ix = con.createInteraction();
Per specificare eventuali parametri specifici per interagire
con la risorsa EIS (ad esempio per indicare il nome
di una tabella da accedere, il nome di un transazione,
i parametri dell'operazione ecc
) si utilizza l'oggetto
InteractionSpec
CciInteractionSpec
iSpec = new CciInteractionSpec();
iSpec.setFunctionName("WRITE_TO_MY_EIS");
Creare RecordFactory invocando il metodo getRecordFactory
sull'oggetto ConnectionFactory.
RecordFactory
rf = cf.getRecordFactory();
Utilizzare l'oggetto RecordFactory per costruire gli
appropriati record di lettura e/o scrittura. Tali record
possono essere di input, output o sia di input che di
output ( Record inout)
IndexedRecord
iRec = rf.createIndexedRecord("InputRecord");
iRec.add(new Integer(userid));
iRec.add(username);
Record
oRec = null; // Ouput Record
Eseguire le opportune operazioni sul Data Store invocando
il metodo execute sull'oggetto Interaction fornendo
gli opportuni Record di input, di output o di inout
Record
oRec = ix.execute(iSpec, iRec);
Iterator iterator = ((IndexedRecord)oRec).iterator();
while(iterator.hasNext()) {
Object obj = iterator.next();
. . .
}
oppure
if(ix.execute(iSpec,
iRec, oRec)) {
// success
}
else {
// failed
}
Conclusa
la comunicazione con la risorsa EIS è necessario
effettuare il codice di chiusura invocando sull'oggetto
Connection il metodo close
con.close();
L'immagine
seguente riporta il sequence diagram delle operazioni
descritte.
clicca per ingrandire
Se
il RA supporta la gestione delle transazioni, prima
di iniziare l'interazione con la risorsa EIS si deve
demarcare l'inizio della transazione
//
ottengo un reference al transaction context
LocalTransaction transaction = con.getLocalTransaction();
// avvio della transazione
transaction.begin();
Cocnclusa
l'operazione si deve gestire la commit se l'operazione
ha avuto successo o la rollback in caso si siano rilevati
errori
...
try {
ix.execute(iSpec, iRec);
transaction.commit();
} catch (ResourceException e) {
transaction.rollback();
}
// Close the connection
...
Conclusioni
In questo articolo abbiamo analizzato le API CCI. Nella
prossima puntata introdurremo un semplice connettore
implementato e pensato per scopi didattici: il MokaConnector.
Verrà presentata l'implementazione della classi
CCI del MokaConnector.
Bibliografia
e riferimenti
[JCA1] G.Morello - S.Rossini: "Java Connector Architecture",
Mokabyte N.66 - Settembre 2002
[JCA]
http://java.sun.com/j2ee/connector/
[SPEC]
J2EE Connector Architecture Specification, http://java.sun.com/j2ee/download.html#connectorspec
[CCI1]
Beth Stearns: Using the J2EETM Connector Architecture
Common Client Interface, http://java.sun.com,Aprile
2001
[BSTW]
David Marks: J2EE Connector Architecture Brings Business
Systems to the web,
http://developer.java.sun.com/developer/technicalArticles/J2EE/
connectorclient/resourceadapter.html
[JW2]
Dirk Reinshagen: Connect the enterprise with the JCA,
Part 2,JavaWorld Febbraio 2002
[JROD]
Jennifer Rodoni: The Java 2 Enterprise Edition Connector
Architecture's Resource Adapter, http://developer.java.sun.com/developer/technicalArticles/
J2EE/connectorclient/resourceadapter.html
[JTUT]
J2EE Tutorial, http://java.sun.com/j2ee/tutorial/download.html
: esample of black box resource adapter for J2EE reference
implementation.
[JBOSS]
http://www.jboss.org
|