|
Introduzione
Per semplicità didattica, il MokaConnector gestisce
come risorsa EIS un file testuale, senza addentrarsi
nelle problematiche complesse legate a risorse EIS più
evolute (HOST, ERP,
).
Come si è visto in [JCA2] e [JCA3], le API CCI
sono il contratto tra il client J2EE ed il Resource
Adapter mentre i System Contracts sono i contratti che
si stipulano tra il Resource Adapter ed i servizi dell'Application
Server J2EE ospitante [JCA4].
In questo articolo descriveremo le classi che compongono
il Resource Adapter (RA) MokaConnector.
Le classi del Resource Adapter MokaConnector

Dalla
tabella si vede come le classi si riferiscano al Connection
Management ad eccezione della classe MokaConnectorSecurity
che partecipa al Security Management. Il Transaction
Contract non è gestito per l'intrinseca non-transazionalità
della risorsa file.

Figura 1 - Le classi del ResourceAdapter MokaConnector
Ogni
RA deve obbligatoriamente fornire l'implementazione
delle tre interfacce SPI: ManagedConnectionFactory,ManagedConnection
e ManagedConnectionMetaData.
La
classe MokaManagedConnectionFactory
E'
la classe del MokaConnector che implementa l'interfaccia
javax.resource.spi.ManagedConnectionFactory
public
class MokaManagedConnectionFactory implements
javax.resource.spi.ManagedConnectionFactory, java.io.Serializable
{
Agisce
da entry-point per la comunicazione tra l'AS ed il RA
permettendo la creazione di connessioni con l'EIS.
Questa classe contiene i due importantissimi metodi
createConnectionFactory() e createManagedConnection().
L'AS invoca il metodo createConnectionFactory() per
richiedere un'istanza della classe ConnectionFactory
del RA. Nel caso del MokaConnector il metodo ManagedConnectionFactory.createConnectionFactory()
restituisce all'AS un oggetto di classe MokaCciConnectionFactory
permettendo l'opportuno bind presso il JNDI Server.
public
Object createConnectionFactory(ConnectionManager cm)
throws ResourceException{
// return new MyContextFactoryImpl(
.);
// Nel caso di RA NON CCI compliant !
this.file = new File(this.fileName);
return new MokaCciConnectionFactory(this, cm);
}
Quando
l'AS neccessita della risorsa fisica EIS invoca il metodo
ManagedConnectionFactory. CreateManagedConnection().
public
ManagedConnection createManagedConnection(Subject subject,
ConnectionRequestInfo
info)
throws
ResourceException {
this.file = new File(this.fileName);
return new MokaManagedConnection(subject, this.file);
}
Nella
realizzazione di un RA per DBMS, sarebbe stato ad esempio
necessario creare una connessione JDBC (DataSource.getConnection()),
passandola all'oggetto ManagedConnection.
La
classe MokaManagedConnectionFactory contiene quindi
al suo interno il factory della risorsa EIS che viene
passata sia al MokaCciConnectionFactory che alla MokaManagedConnection.
Nel
caso di un RA per DBMS la proprietà incapsulata
sarebbe un oggetto di classe javax.sql.DataSource.
La classe MokaMagedConnectionFactory ha anche la responsabilità
di gestire le proprietà del connettore dichiarate
nel deployment descriptor XML.
Ogni proprietà definita nel file XML (mediante
i tag <config-property-name> ,<config-property-type>,<config-property-value>)
deve essere mappata in notazione JavaBean nella classe
MokaCciManagedConnectionFactory.
Nel caso del MokaConnector nel file ra.xml si dichiara
una sola proprietà relativa al nome del file
EIS:
<config-property>
<config-property-name>FileName</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>/moka_jca/eis/prova.txt</config-property-value>
</config-property>
che
viene mappata nella classe MokaManagedConnectionFactory
nel seguente modo:
public
class MokaManagedConnectionFactory
implements
ManagedConnectionFactory, Serializable {
private String fileName;
. . .
public void setFileName(String filename){
this.fileName = filename;
}
public String getFileName(){
return this.fileName;
}

Figura 2 - Sequence
diagram delle interazioni tra AS e RA durante la fase
di deploy
(clicca sull'immagine per ingrandire)
ManagedConnection
E'
la classe del MokaConnector che implementa l'interfaccia
javax.resource.spi.ManagedConnection
public
class MokaManagedConnection implements javax.resource.spi.ManagedConnection
{
Incapsula
la risorse EIS e fornisce i metodi necessari per stabilire
la connessione fisica con l'EIS. Nel caso del MokaConnector
questo si traduce nell'avere una proprietà di
classe java.io.File.
private
java.io.File file = null;
public java.io.File getFile() throws ResourceException
{
if(this.file == null){
throw new ResourceException(" ### ERROR !
###");
}
else {
return this.file;
}
}
Nel
caso di un RA per DBMS, la proprietà incapsulata
sarebbe un oggetto java.sql.Connection.
La
classe MokaManagedConnection mette a dispozione il metodo
getConncetion() che permette di ottenere un riferimento
alla connessione fisica della risorsa EIS
public
java.lang.Object getConnection(javax.security.auth.Subject
subject,
ConnectionRequestInfo cxRequestInfo) throws ResourceException
Tale
metodo riceve in ingresso il contesto di sicurezza (javax.security.auth.Subject)
e le informazioni riguardanti la richiesta della connessione
(javax.resource.spi.ConnectionRequestInfo) e restituisce
un'istanza MokaCciConnection.
public Object getConnection(javax.security.auth.Subject
subject,
javax.resource.spi.ConnectionRequestInfo info)throws
ResourceException {
if(MokaConnectorSecurity.isCredentialValid(subject,
info)){
if(this.conn == null ){
conn = new MokaCciConnection(this);
}
}
. . .
return conn;
}
Dalla
figura 3 si vede la relazione che intercorre tra le
classi ConnectionFactory e ConnectionCCI e le corrispondenti
SPI.

Figura 3 - Class diagram MokaConnector: relazione
tra le classi
ConnectionFactory e Connection
(clicca sull'immagine per ingrandire)
Sempre
mediante l'implementazione dell'interfaccia ManagedConnection
è possible accedere alle interfacce javax.resource.spi.LocalTransaction
e javax.transaction.xa.XAResource per la gestione delle
transazioni del RA.
Inoltre il MokaManagedConnection permette inoltre di
ottenere le informazioni descrittive d'interfaccia javax.resource.spi.ManagedConnectionMetaData
mediante il metodo getMetaData()
public
ManagedConnectionMetaData getMetaData() throws ResourceException{
return new MokaManagedConnectionMetaData(this);
}
ManagedConnectionMetaData
Invocando
il metodo MokaManagedConnection.getMetaData() è
possibile ottenere le informazioni descrittive incapuslate
in un oggetto d'interfaccia ManagedConnectionMetaData
public
class MokaManagedConnectionMetaData implements javax.resource.spi.ManagedConnectionMetaData
{
Tale
classe agisce di fatto da Wrapper per gli specifici
Meta Data della risorsa EIS. Nel caso del MokaConnector
l'implementazione è poco significativa visto
che la risorsa EIS è un semplice file.
Nel caso di un Resource Adapter per DBMS verrebbero
forniti i dati ricavati mediante l'interfaccia java.sql
Interface DatabaseMetaData
public
class MetaDataImpl implements ManagedConnectionMetaData
{
private java.sql.Connection con;
public MetaDataImpl(Connection c) { this. con= c; }
public String getEISProductName() throws ResourceException
{
try{ return con.getMetaData().getDatabaseProductName();
}
catch(
.){ throw
}
}
public int getMaxConnections() throws ResourceException
{
try { return con.getMetaData().getMaxConnections();
}
catch(
.){ throw
}
}
<< etc
>>
}
ConnectionRequestInfo
Fornisce
le informazioni che descrivono i dati necessari alla
richiesta di connessione all'EIS.
Nel caso del MokaConnector viene specificata (per puro
scopo dimostrativo) la userid di accesso al file.
Nel caso non si dovessero passare dati specifici per
la connessione richiesta, è possibile utilizzare
null come secondo parametro del metodo allocateConnection().
Nel caso invece si voglia implementare tale interfaccia,
la classe concreta deve obbligatoriamente fornire i
metodi equals e hashcode per "aiutare" l'AS
nella gestione del pooling di connessioni.
public
class MokaConnectionRequestInfo
implements ConnectionRequestInfo{
private String eisAccount; // utenza per accedere al
file
public MokaConnectionRequestInfo(String usr){ this.eisAccount=usr;}
public String getEisAccount() {return this.eisAccount;}
public boolean equals(Object obj) { . . . }
public int hashCode() {. . . }
private boolean isEqual(Object o1, Object o2) { . .
. }
}
Il Transaction Management del MokaConnector
Mediante
l'implementazione dell'interfaccia ManagedConnection
è possible accedere alle interfacce javax.resource.spi.LocalTransaction
per la gestione delle transazioni locali al RA e javax.transaction.xa.XAResource
per la gestione delle transazioni distribuite.
Nel semplice caso del MokaConnector l'implementazione
dei metodi si limita a lanciare una ResourceException,
essendo il file una risorsa di natura non transazionale
public
LocalTransaction getLocalTransaction() throws ResourceException{
throw new ResourceException("Local transaction
are NOT SUPPORTED by MokaConnector #");
}
public
XAResource getXAResource() throws ResourceException
{
throw new ResourceException("XA transaction are
NOT SUPPORTED by MokaConnector #");
}
Il
Security Management nel MokaConnector
Il
metodo ManageConnection.getConnection() riceve come
parametri di input un oggetto Subject con i dati di
sicurezza dell'AS ed un oggetto d'interfaccia ConnectionRequestInfo.
public
Object getConnection(Subject subject,
ConnectionRequestInfo
info)
throws ResourceException {
Alla
classe MokaConnectorSecurity viene chiesta l'autenticazione
del Subject e la validazione dei dati ConnectionRequestInfo.
La classe MokaConnectorSecurity offre dei controlli
di sicurezza elementari, ma rappresenta un ottimo punto
per concentrare le eventuali estensioni del sistema
di sicurezza del RA (es. JAAS).
L'oggetto Subject è valorizzato dall'AS con modalità
proprietarie. Nel caso di JBoss, i valori vengono inseriti
nei tag Principal all'interno della dichiarazione del
bean JMX relativo al RA:
<!--
The Moka example filesystem resource adapter -->
<mbean code="org.jboss.resource.ConnectionFactoryLoader"
name="JCA:service=ConnectionFactoryLoader,
name=NoTransMokaConnectorFS">
. . . . .
<!--
Principal mapping configuration -->
<attribute name="PrincipalMappingClass">
org.jboss.resource.security.ManyToOnePrincipalMapping
</attribute>
<attribute name="PrincipalMappingProperties">
userName=mokauser
password=abc123
</attribute>
</mbean>
Il
Tester EJB client crea l'EJB di test specificando nel
metodo create la userid inserita dall'utente da tastiera
Tester
remoteReference = home.create(userid);
Nel
metodo ejbCreate del TesterBean viene costruito un oggetto
di classe MokaCciConnectionSpec
MokaCciConnectionSpec
spec = new MokaCciConnectionSpec(userid);
L'oggetto
MokaCciConnectionSpec viene passato come parametro al
metodo ConnectionFactory.getConnection()
Connection
con = cf.getConnection(spec);
All'interno
del metodo ConnectionFactory.getConnection() viene creato
un oggetto ConnectionRequestInfo con i dati contenuti
nell'oggetto MokaCciConnectionSpec
public
javax.resource.cci.Connection getConnection(ConnectionSpec
properties) throws ResourceException {
ConnectionRequestInfo info =
new MokaConnectionRequestInfo(
((MokaCciConnectionSpec)properties).getUser(),
((MokaCciConnectionSpec)properties).getPassword());
per
poi essere passato come parametro del metodo ConnectionManager.allocateConnection()
con
= (Connection)this.connectionManager.allocateConnection(
this.managedConnectionFactory,info);
L'AS
a questo punto invoca il metodo MokaManaged.getConnection()
che al suo interno demanda la gestione della sicurezza
alla classe MokaConnectorSecurity.
Se i check di sicurezza (MokaConnectorSecurity.isCredentialValid())
hanno esito positivo, viene creata (finalmente!) una
connessione alla risorsa EIS
public
Object getConnection(Subject subject,
ConnectionRequestInfo
info)
throws
ResourceException {
if(MokaConnectorSecurity.isCredentialValid(subject,
info)){
if(this.conn == null ){
conn = new MokaCciConnection(this);
}
}
else{
throw new ResourceException("# SecurityException
#
Subject or Credentials NON VALIDE!");
}
return conn;
}
Il MokaConnector in azione: deploy
ed esecuzione
Conclusa
la panoramica del codice delle classi Resource Adapter
del MokaConnector, vediamo ora come effettuare deploy
ed esecuzione in un ambiente JBoss [JBOSS].
Il file ra.xml
Ogni RA è "accompagnato" da un file
deployment descriptor di nome ra.xml posizionato sotto
la directory METAINF (METAINF/ra.xml).
Il deployment descriptor contiene le seguenti informazioni:
- informazioni
generiche e descrittive del RA
<display-name>File
System Resource Adapter</display-name>
<vendor-name>MokaByte S.R.L</vendor-name>
<spec-version>1.0</spec-version>
<version>1.0</version>
<eis-type>FileSystem</eis-type>
<license>
<description>Mokabyte simple example</description>
<license-required>false</license-required>
</license>
-
interfacce e relative classi concrete per accedere
al connettore
<managedconnectionfactory-class>
it.mokabyte.mokajca.ra.MokaManagedConnectionFactory
</managedconnectionfactory-class>
<connectionfactory-interface>
javax.resource.cci.ConnectionFactory</connectionfactory-interface>
<connectionfactory-impl-class>
it.mokabyte.mokajca.ra.cci.MokaCciConnectionFactory
</connectionfactory-impl-class>
<connection-interface>
javax.resource.cci.Connection
</connection-interface>
<connection-impl-class>
it.mokabyte.mokajca.ra.cci.MokaCciConnection
</connection-impl-class>
-
supporto Transazionale
<transaction-support>NoTransaction</transaction-support>
-
informazioni di autenticazione (<authentication-mechanism>)
- permessi
di sicurezza (<security-permission>)
- proprietà
di configurazione
<config-property>
<config-property-name>FileName</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>
/moka_jca/eis/prova.txt
</config-property-value>
</config-property>
Contiene
quindi le informazioni necessarie per effettuare sia
il deploy che la configurazione del RA per un AS JCA-enabled.
Deploy
del Resource Adapter
Per effettuare il deploy del RA è necessario
archiviare tutti i file in un jar di estensione .rar.
Il RA risulta quindi costituito da classi Java che implementano
sia le API CCI, le classi del RA, gli eventuali driver
nativi e l' XML deployment descriptor. Questi file sono
tutti archiviati nel medesimo file jar che prende il
nome di Resource ARchive file (RAR); un file RAR è
l'unità di distribuzione del RA.
Una volta creato il file RAR è possibile effettuare
l'operazione di deploy del RA in un server J2EE, analogamente
a quanto accade per gli EJB jar, i file war o gli stessi
file ear.
La procedura di deploy è vendor-dependent, cioè
varia a secondo dell'AS che si utilizza.
Ad esempio con JBoss è sufficiente posizionare
il file RAR nella directory <JBossHome>\deploy\lib.
Il deploy è automatico e a carico dell'AS.
Deploy dell'EJB di test del MokaConnector
L'EJB di test utilizza il MokaConnector esplicitando
come resource-reference il nome logico ra/CCI_MOKA_EIS
nel file ejb-jar.xml
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>MokaEjbTestRA</ejb-name>
<home>it.mokabyte.mokajca.ejb.TesterHome</home>
<remote>it.mokabyte.mokajca.ejb.Tester</remote>
<ejb-class>it.mokabyte.mokajca.ejb.TesterBean</ejb-class>
<session-type>Stateful</session-type>
<transaction-type>Container</transaction-type>
<resource-ref>
<res-ref-name>ra/CCI_MOKA_EIS</res-ref-name>
<res-type>it.mokabyte.mokajca.ra.cci.MokaCciRecordFactory</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</session>
</enterprise-beans>
</ejb-jar>
All'interno
del file vendor-dependent (jboss.xml) si ha il mapping
tra il riferimento del connettore ed il nome logico
JNDI a cui corrisponde la risorsa fisica del MokaConnector
<jboss>
<enterprise-beans>
<session>
<ejb-name>MokaEjbTestRA</ejb-name>
<resource-ref>
<res-ref-name>ra/CCI_MOKA_EIS</res-ref-name>
<jndi-name>java:NoTransMokaConnectorFS </jndi-name>
</resource-ref>
<jndi-name>MokaConnectorEjbTester</jndi-name>
</session>
</enterprise-beans>
</jboss>
La
configurazione dell'Mbean del ConnectionManager è
definita nel file <JBOSS_HOME>\conf\default\jboss.jcml>
<mbean
code="org.jboss.resource.ConnectionFactoryLoader"
name="JCA:service=ConnectionFactoryLoader,name=NoTransMokaConnectorFS">
<attribute name="FactoryName">NoTransMokaConnectorFS</attribute>
<attribute name="RARDeployerName">JCA:service=RARDeployer</attribute>
<attribute name="ResourceAdapterName">File
System Adapter</attribute>
<attribute name="ConnectionManagerFactoryName">MinervaNoTransCMFactory</attribute>
<!-- See the documentation for the specific connection
manager
implementation you are using for the properties you
can set -->
<attribute name="ConnectionManagerProperties"
/>
<!--
Principal mapping configuration -->
<attribute name="PrincipalMappingClass">
org.jboss.resource.security.ManyToOnePrincipalMapping
</attribute>
<attribute name="PrincipalMappingProperties">
userName=mokauser
password=abc123
</attribute>
</mbean>
Esecuzione dell'esempio
L'esecuzione del Tester EJB Client produrrà la
lettura/scrittura del file "/moka_jca/eis/prova.txt".

Figura 4 - Esecuzione del test del MokaConnector
Conclusioni
In questo articolo abbiamo esaminato l'implementazione
del MokaConnector, concludendo la serie dedicata a JCA.
L'esempio pratico presentato riassume e concretizza
quanto presentato su JCA nei precedenti numeri di MokaByte.
Allegati
Risorse
L'esempio
completo del MokaConnector è scaricabile qui
Bibliografia
e riferimenti
[JCA1] S.Rossini-G.Morello: "JCA: I parte: la teoria",
Mokabyte N.66 - Settembre 2002
[JCA2] S.Rossini-G.Morello: "JCA: II parte: CCI
la teoria", Mokabyte N.67 - Ottobre 2002
[JCA3] S.Rossini-G.Morello: "JCA: III parte: CCI
la pratica", Mokabyte N.68 - Novembre 2002
[JCA4] S.Rossini-G.Morello:"JCA: IV parte: il Resource
Adapter e i System Contracts", Mokabyte N.69 -
Dicembre 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
[JB_DOC] Scott Stark, Mark Fleury : JBoss Administration
and Development
|