MokaByte 89 - 8bre 2004 
Java Connector Architecture
VI parte: un Resource Adapter per accedere a CICS
di
Stefano Rossini

A più di un anno dalla pubblicazione dell'ultimo articolo di questa serie riprendiamo con una importante appendice, che immagino risulterà particolarmente interessante per tutti co-loro che lavorano abitualmente nel mondo enterprise transazionale e non. Parleremo questo mese di connessione tramite JCA a sistemi CICS.


Definizione del problema
Il primo problema che è necessario affrontare nell'ambito dell'integrazione è essenzialmente di comunicazione.
Sia che si operi in modalità punto-punto (vedi [MOKA_INT6]) sia che si adotti una visione centralizzata (vedi [MOKA_EAI_IM]), il problema principale è la normalizzazione del protocollo specifico della risorsa con un'interfaccia fruibile dal chiamante.
Tale problematica viene tipicamente affrontato attraverso componenti denominati genericamente Adapter. Nel caso specifico di Adapter destinati alla comunicazione con risorse Enterprise Information Systems (EIS), vengono più precisamente detti Resource Adapter (RA).
Nella serie di articoli di Mokabyte apparsi sui numeri di Mokabyte (vedere [MOKA_JCA1] e successivi) si è parlato di JCA sia da un punto di vista architetturale che da un punto di vista pratico presentando un esempio di Resource Adapter: il MokaConnector.
In questo articolo si metterà a frutto l'esperienza acquisita nei precedenti numeri per capire come utilizzare un connettore JCA per invocare un programma Cobol via CICS ECI.

 

Il Resource Adapter
Il RA è un componente che espone delle interfacce di accesso (client API) per permettere la comunicazione, sincrona o asincrona, con la corrispondente risorsa EIS come sistemi Legacy (CICS,IMS,3270,…), basi dati relazionali (Oracle, SQLServer, MySQL,...) e non (Lotus Notes), sistemi ERP (Enterprise Resource Planning),sistemi CRM (Customer Relationship Management).
Il RA ha quindi il duplice scopo di:

  • fornire un'interfaccia omogenea ai client per accedere all'EIS
  • mascherare la complessità dell'interazione con l'EIS al client


Figura 1
: Il Resource Adapter

 

Cos'è JCA?
JCA è l'acronimo di Java Connector Architecture. Definisce un'architettura standard (vedere [JCA_SPEC]) per uniformare l'accesso ad EIS eterogenei all'interno di applicazioni J2EE. Si focalizza sul design di Adapter software destinati a connettere applicazioni J2EE con applicazioni non-Java come risorse legacy e pacchetti applicativi.

L'architettura JCA è costituita da tre elementi : le API Common Client Interface (CCI), i Resource Adapter ed i System Contracts.


Figura 2
: L'architettura JCA


Vediamo una breve descrizione dei componenti dell'architettura JCA (per una maggiore trattazione si rimanda a [MOKABOOK2_JCA]).

CCI definisce un insieme di API per uniformare l'accesso a EIS da parte di applicazioni J2EE. Grazie a CCI non è necessario affrontare un'integrazione ad hoc per ogni diversa tipologia di EIS, analogamente a quanto avviene con JDBC, JNDI e JMS.
Il Resource Adapter è il connettore vero e proprio, cioè è il driver software che permette al client (sia esso un componente J2EE come un EJB o l'Application Server stesso) di connettersi fisicamente alla risorsa EIS.


Figura 3
: Esempi di connettori JCA

 

Un Resource Adapter JCA interagisce con le infrastrutture del server J2EE tramite i cosiddetti System Contracts (Connection, Transaction e Security ).
Il Connection Management determina le politiche per stabilire/chiudere le connessioni con le risorse di Backend ottimizzando la gestione degli accessi mediante un Connection Pool gestito dall'Application Server.
Il Transaction Management permette di gestire l'accesso transazionale verso le risorse EIS, definendo le interazioni tra la risorsa ed il transaction manager.
Le transazioni possono richiedere la presenza di un Transaction Manager esterno oppure possono essere gestite internamente dal Resource Manager della risorsa stessa.
Il Security contract definisce un contratto che permette di gestire la Sicurezza per accedere all'EIS. Consente allo sviluppatore del RA di implementare/fornire i meccanismi per la gestione dell'autenticazione e dell'autorizzazione, ed eventualmente consente la gestione di un security environment custom per la comunicazione sicura tra il server J2EE e l'EIS.
Il RA è contenuto in un file archivio (jar) di estensione RAR (Resource Adapter Archive) composto dai file Java e dalle eventuali librerie native necessarie per accedere alla risorsa EIS. Un file .rar rappresenta a tutti gli effetti una risorsa J2EE e può essere installato singolarmente o all'interno di un file .ear. Ogni RA è "accompagnato" da un file deployment descriptor di nome ra.xml posizionato sotto la directory META­INF (META­INF/ra.xml).
Il deployment descriptor contiene le informazionidel RA quali il nome, le interfacce e relative classi concrete per accedere al connettore, il tipo di supporto Transazionale, le informazioni di autenticazione, le proprietà di configurazione, … cioè tutte le informazioni necessarie per effettuare sia il deploy che la configurazione del RA per un Application Server JCA-enabled.
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.

 

Come connettersi a CICS con un Resource Adapter JCA
E veniamo al nocciolo dell'articolo. Negli articoli [MOKA_JCA_3] e [MOKA_JCA_5] si era presentato il MokaConnnector, un resource adapter CCI-compliant che si connette ad una risorsa EIS rappresentata da un file testuale. Il MokaConnector permette a componenti J2EE un accesso standard mediante le API CCI descritte in [MOKA_JCA_2]. Per motivi didattici, il MokaConnector non si concentra sulle problematiche specifiche dell'accesso a risorse EIS complesse, ma gestisce un semplice file testuale

La SUN nel J2EE Tutorial (vedere [JTUT]) presenta un esempio di connettore JCA (anch'esso CCI compliant) che permette di invocare Stored Procedure per Cloudscape denominato "CCI black box".

Per usare un connettore JCA (CCI-compliant) bisogna effettuare una serie di operazioni in modo pragmatico (vedere [MOKA_JCA2]) come schematizzato nella figura che segue:


Figura 4 : utilizzo delle API CCI

Supponiamo di doverci collegare ad un programma Cobol via CICS-ECI utilizzando un connettore JCA.
Il CICS (Customer Information Control System ) è un TP monitor che permette di eseguire transazioni a HOST. L'interfaccia CICS ECI (External Call Interface) permette di eseguire, da un'applicazione esterna nonCICS, un progamma CICS su un server CICS come se il chiamante fosse un programma Cobol all'interno del suo stesso ambiente ed eseguisse un comando EXEC CICS LINK.
Per fare questo useremo il connettore JCA per IBM CICS della ditta Comporsys Hansa GmbH (vedere [COMPORSYS]), liberamente scaricabile da Internet (vedere [COMPORSYS_DWLD]).
Il connettore Comporsys supporta JCA 1.0, mette a disposizione un'interfaccia CCI e permette di invocare programmi CICS via ECI.


Figura 5 : Scenario CICS

Avendo letto l'articolo di come utilizzare il Moka Connector (vedere [MOKA_JCA3]) e/o il connettori del Tutorial SUN, cosa ci dobbiamo aspettare?
Ci dobbiamo aspettare di riutilizzare gran parte del codice client già usato con gli altri due connettori JCA (essendo CCI-Compliant!) e modificare le parti di codice che utilizzano le classi dipendenti dalla specfica risorsa EIS.
Quindi dovremmo avere che le seguenti operazioni siano le medesime indipendentemente dal RA (sia esso un RA per DBMS, Host, file,…)

  • Lookup dell'oggetto ConnectionFactory del Resource Adapter mediante API JNDI
    Context ctx = new InitialContext();
    Object obj = ctx.lookup("java:comp/env/eis/CCI_MOKA_EIS");
    ConnectionFactory cf = (ConnectionFactory)obj;


  • invocazione del metodo ConnectionFactory.getConnection() per ottenere l'apertura della connessione con il Resource Manager dell'EIS passando come parametro un oggetto ConnectionSpec:
    Connection con = cf.getConnection(connSpec);

  • invocazione sull'oggetto Connection (la connessione con l'EIS ) del metodo createInteraction() per creare un'istanza
    Interaction. Mediante l'istanza ottenuta sarà possibile interagire con la risorsa EIS
    Interaction ix = con.createInteraction();


  • creazione del RecordFactory invocando il metodo ConnectionFactory getRecordFactory()
    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");

  • Invocazione del metodo execute sull'oggetto Interaction.execute() fornendo gli opportuni Record di input, di output (o di inout) e un'istanza InteractionSpec
    if(ix.execute(interSpec, iRec, oRec)) {
      // Recupero del risultato ...
      risultato=oRec.getXXX()
      // ... o eventuale iterazione nel caso di liste di risultati
      Iterator iterator = ((IndexedRecord)oRec).iterator();
      while(iterator.hasNext()) {
        Object obj = iterator.next();
          ...
      }
    }
    else {
      // failed
    }

  • Chiusura della connessione con l'EIS
    con.close();

Quello che cambierà nell'interazione della specifica risorsa EIS sono le classi ConnectionSpec e InteractionSpec che sono classi specifiche per la risorse EIS.


Figura 6 : API CCI


L'oggetto ConnectionSpec (che implementa l'interfaccia javax.resource.cci.ConnectionSpec) permette di indicare gli eventuali parametri specifici necessari ad ottenere la conessione all'EIS)
Ad esempio per il MokaConnector si specificare un'utenza

MokaCciConnectionSpec connSpec = new MokaCciConnectionSpec("mokabyte");

mentre nel caso del RA Sun si deve indicare username e password per accedere a DB

ConnectionSpec connSpec = new CciConnectionSpec(user, password);

Per indicare eventuali parametri specifici per interagire con la risorsa EIS si deve utilizzare l'oggetto InteractionSpec (che implementa l'interfaccia javax.resource.cci.InteractionSpec)
Ad esempio per il MokaConnector si indicava l'operazione (lettura/scrittura del file) e il numero di linee del file coinvolte:

CciInteractionSpec interSpec = new CciInteractionSpec();
iSpec.setFunctionName(MokaCciInteractionSpec.READ);
iSpec.setNumOfLines(num);

mentre nel caso del RA Sun si deve specificare il nome della Stored procedure da invocare ed il relativo Schema e Catalog:

CciInteractionSpec interSpec = new CciInteractionSpec();
iSpec.setFunctionName("INSERTCOFFEE");
iSpec.setSchema(user);
iSpec.setCatalog(null);

Ci si deve quindi concentrare sul capire quali sono le classi del Connecttore Comporsys specifiche per accedere a Host via CICS-ECI.
Da notare come a seconda della specifica esigenza di I/O con la risorsa EIS è possibile implementare una propria classe Record che deve implementare l'interfaccia javax.resource.cci.Record. Tale classe può mettere quindi a disposizione gli opportuni metodi puntuali per il set dei dati di input ed il get dei dati di output. Ma procediamo per gradi…
Il programma Cobol che si vuole invocare esegue un semplice calcolo computazionale che prevede di restituire la lunghezza (WS-COUNTER) della stringa (WS-STRINGA) fornitagli in ingresso.
Analizzando la COMMAREA del programma Cobol si vede che è prevista una stringa di 30 caratteri (PICX(30)) come dato in ingresso e un numero di 10 cifre (s9(10)) come dato in uscita:

01 COMMAREA
03 WS-STRINGA PIC X(30).
03 WS-COUNTER PIC 9(10).

Figura 7: Scenario Host: Programma Cobol & COMMAREA


Una transazione CICS è strutturata in modo da condividere un'area di memoria per il passaggio dei dati (input e output) esterni al programma.
Questa area comune di memoria (di dimensione fissa di 32K) è denominata COMMAREA e serve per il transito dei dati verso/da CICS e quindi nella sua definizione si trovano sia i campi di input che di output.
Il sistema CICS riceve i dall'esterno e passa i dati di input della COMMAREA al programma Cobol associato alla transazione. Finita l'elaborazione del programma Cobol, i dati di output verranno scritti dall'applicazione COBOL nella COMMAREA ed il CICS provvederà a veicolarli verso il programma esterno chiamante.
Con il RA Comporsys si ha a disposizione un utility chiamata CodeGen che permette, a partire da una CopyCobol descritta in un file di estensione .cob, di creare classi Java che mappano la COMMAREA del programma Cobol convertendo i tipi da Cobol a Java.
Queste classi saranno i Record contenente i dati da scambiarsi (input e output) con CICS.
Bisogna quindi mandare in esecuzione la classe de.comporsys.codegen.ImportCobol specificando il file Cobol in ingresso (mokarecord.cob), la directory di ouput, il nome del package (it.mokabyte.jca.cicseci) ed il codepage.

java de.comporsys.codegen.ImportCobol mokarecord.cob classes it.mokabyte.jca.cicseci cp273

Quello che si ottiene è la classe MOKARECORD. Mediante il metodo setWS-STRINGA(), sarà possibile specificare il dato di input e ottenere la relativa lunghezza tramite il metodo getWS-COUNTER():

public class MOKARECORD extends Record implements java.io.Serializable{

  static final MOKARECORDDescription description = new MOKARECORDDescription() ;
  public static class MOKARECORDDescription extends
  de.comporsys.connector.datatype.Description implements java.io.Serializable{
  final de.comporsys.connector.datatype.cobol.X ws_stringa ;
  final de.comporsys.connector.datatype.cobol.Nine ws_counter ;

  public MOKARECORDDescription( ){
    super() ;
    ws_stringa = new X( new PicClause( "X(30)" )) ;
    ws_counter = new Nine( new PicClause( "9(10)" )) ;
    ...
  }

  public MOKARECORD(){
    super(description ) ;
    description.setName( "MOKARECORD" ) ;
  }

  public String getWS_STRINGA() {
    return description.ws_stringa.getValue( this ).toString() ;
  }
  
  
public void setWS_STRINGA( String value ){
    description.ws_stringa.setValue( value, this ) ;
  }

  public long getWS_COUNTER(){
    return description.ws_counter.longValue( this ) ;
  }

  public void setWS_COUNTER( long value ){
    description.ws_counter.setValue( value, this ) ;
  }

  ...

}


Figura 8
: Generazione del Record I/O per COMMAREA CICS

Nel file ra.xml, il file deployment descriptor del RA (vedere [MOKA_JCA4]) bisogna inserire, mediante il tag <config-property>, i valori delle proprietà del RA necessari per collegarsi al CICS Server. Le principali informazioni del RA Comporsys CICS sono:

  • ServerName: nome del server CICS
  • ConnectionURL: indirizzo del server CTG (es: tcp://localhost:2007)
  • CCISupport: supporto API CCI (nostro caso è true)
  • TimeoutSecs: timeout di connessione
  • UserName, Password: utenza di accesso a Host

Si vede come per accedere a Host si deve specificare un indirizzo tcp. A cosa si riferisce tale indirizzo? L'indirizzo si riferisce al CICS Transaction Gateway (CTG) grazie al quale sarà possibile accedere al CICS Server.
Il connettore COMPORSYS di fatto espone, mediante API CCI, l'utilizzo delle classi Java IBM client del CTG.
Il CTG rappresenta il connettore strategico fornito da IBM per abilitare il dialogo con le applicazioni CICS. Il prodotto supporta la tecnologia J2EE, implementa lo standard JCA 1.0 e fornisce un'interfaccia Java programmabile (vedere [IMB_CTG]).
Il CTG contiene un Java Gateway Application che permette di comunicare con programmi in esecuzione su un server CICS, fornisce un'interfaccia ECI (External Call Interface) per chiamate di programmi CICS da applicazioni NON-Cics "COMMAREA-based"(transazioni), un'interfaccia EPI (External Presentation Interface) per l'utilizzo di applicazioni CICS come terminali 3270 cioè "terminal based" (mappe) e un'interfaccia ESI (External Security Interface).


Figura 9: CICS Transaction Gateway (CTG)


Nel file XML del RA ra.xml vengono indicate inoltre le classi factory CCI e Managed del connettore che servono per la stipula dei System Contracts tra l'Application Server ed il RA.
Nel caso del connettore Comporsys la classe Managed Factory (che implementa javax.resource.spi.ManagedConnectionFactory) indicata dal tag la classe <managedconnectionfactory-class> è la classe de.comporsys.connector.cics.ManagedConnectionFactoryImpl mentre quella CCI (che implementa javax.resource.cci.ConnectionFactory ed è indicata dal tag <connectionfactory-impl-class>) è la

de.comporsys.connector.cics.cci.ConnectionFactoryImpl.

Di fatto la classe del connettore Comporsys che implementa l'interfaccia SPI ManagedConnection wrappa al suo interno un'oggetto di classe com.ibm.ctg.client.JavaGateway jgaConnection così come un oggetto ManagedConnection del MokaConnector wrappava un oggetto java.io.File mentre quella di sample della SUN una java.sql.Connection
E arriviamo a parlare (finalmente) del client del RA: l'EJB MokaCicsEci.
L'EJB ha la seguente Remote interface che dichiara un metodo di business che riceve in ingresso una stringa e restituisce un long (il valore della lunghezza della stringa text ricevuta in ingresso):

public interface MokaCicsEci extends EJBObject {
  public long getLength(String text) throws RemoteException;
}

L'EJB è di fatto il client del RA e si occupa di interagire con il RA:

public long getLength(String text) {
  Connection connection = null;
  Interaction interaction=null;
  try {
    InitialContext ic = new InitialContext();
    Object obj = ic.lookup("java:comp/env/eis/cics");
    ConnectionFactory cciCf=(ConnectionFactory)obj;
    ConnectionSpecImpl connSpec = new ConnectionSpecImpl("ale", "maio");
    connection = cciCf.getConnection(connSpec);
    interaction = connection.createInteraction() ;
    InteractionSpecImpl spec = new de.comporsys.connector.cics.cci.InteractionSpecImpl();
    spec.setFunctionName("MY_PGM_COB");
    MOKARECORD input = new MOKARECORD();
    MOKARECORD output = new MOKARECORD();
    input.setWS_STRINGA(text);
    interaction.execute(spec, input, output);
    return output.getWS_COUNTER();
  }
  catch( javax.naming.NamingException e ){
  }
  
catch( javax.resource.ResourceException e ){
  }
}

A livello di deployment descriptor dell'EJB bisogna indicare il riferimento alla risorsa JCA mediante il tag <resource-ref> nel file ejb-jar.xml e indicare la risorsa "fisica" nel file proprietario dell'Application Server (vedere [MOKA_JCA_5]).

Il client dell'EJB si occupa di invocare il metodo getLength() dell'EJB verificando che il risultato sia corretto:

public class MokaCicsEciClient {
  public static void main(String[] args) {
    try {
    Context initial = new InitialContext(properties);
    Object objref = initial.lookup("MokaCicsEciEJB");
    MokaCicsEciHome home = (MokaCicsEciHome)
                           PortableRemoteObject.narrow(objref,MokaCicsEciHome.class);
    MokaCicsEci eci = home.create();
    long res=eci.getLength("ciao");
    if(res==4){
      System.out.println("SUCCESS !" + res);
    }
    else{
      System.out.println("Risultato Atteso DIVERSO da quello ottenuto: " + res);
    }
    System.out.println("MokaCicsEciClient: TEST OVER!");
    }
    catch(Exception e){
      ...       
    }
}

Per provare l'esempio bisogna effettuare il deploy del RAR e del Jar dell'EJB di prova e mandare in esecuzione il programma client MokaCicsEciClient.
Il client di test invierà all'EJB, mediante protocollo RMI, la stringa "ciao". L'EJB demanderà al RA l'accesso al programma CICS ritornando al client il risultato 4 (la lunghezza della parola "ciao").


Figura 10
: Architettura dello scenario proposto

 

Conclusioni
Rispetto al complesso scenario dell'integrazione (vedere [MOKABOOK2_JCA]), lo scopo di JCA ad oggi è sostanzialmente limitato al mondo degli Adapter e copre quindi una parte relativamente piccola dell'intera piattaforma d'integrazione.
La specifica Java Connector Architecture (JCA), seppur orientata al solo ambito J2EE, assume nello scenario dei Resource Adapter una grande rilevanza in quanto è uno dei primi tentativi di stabilire uno standard nel campo dell'integrazione di EIS.
L'importanza di JCA è innegabile. Basta vedere come, ad oggi, sul mercato molti vendor già supportano le specifiche JCA rendendo disponibili molti Resource Adapter per differenti EIS, tra questi SAP, CICS, IMS, Oracle, PeopleSoft, …(per una lista completa vedere [JCAIS]).

 

Bibliografia e riferimenti
[MOKA_INT6] S.Rossini: Integrazione di applicazioni Enterprise VI parte: il panorama d'insieme,Mokabyte N.83 -Marzo 2004
[MOKA_EAI_IM] S.Rossini-G.Morello: Integrazione di applicazioni Enterprise (parte VII): l'Integration Middleware Mokabyte N.88 - Settembre 2004
[MOKABOOK2_JCA] S.Rossini-G.Morello:: "Manuale pratico di Java: La piattafroma J2EE" (Capitolo 12: JCA), HOPS-2004 [http://www.mokabyte.it/manualejava2/download.htm]
[MOKA_JCA1] S.Rossini-G.Morello:: "JCA: I parte: la teoria", Mokabyte N.66 - Settembre 2002
[MOKA_JCA2] S.Rossini: "JCA: II parte: CCI la teoria", Mokabyte N.67 - Ottobre 2002
[MOKA_JCA3] S.Rossini: "JCA: III parte: CCI la pratica", Mokabyte N.68 - Novembre 2002
[MOKA_JCA4] S.Rossin :"JCA: IV parte: il Resource Adapter e i System Contracts", Mokabyte N.69 - Dicembre 2002
[MOKA_JCA5] S.Rossini: "JCA: "V parte: il Resource Adapter MokaConnector", Mokabyte N.70 - Gennaio 2003
[JCA] http://java.sun.com/j2ee/connector/
[JCA_SPEC] J2EE Connector Architecture Specification, http://java.sun.com/j2ee/download.html#connectorspec
[JRCA] 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.
[PROD] JCA Industry Support, http://java.sun.com/j2ee/connector/industry.html
[JTUT] J2EE Tutorial, http://java.sun.com/j2ee/tutorial/download.html: Dale Green and Beth Stearns: example of black box resource adapter for J2EE reference implementation (examples/src/connector/cci dal j2ee-1_3-doc-tutorial-draft5.zip
[COMPORSYS] http://www.comporsys.de
[COMPORSYS_DWLD] http://www.comporsys.de/de/download/
[COMPORSYS_IARG] Connector for IBM CICS/TXSeries Version 1.5: Installation And Reference Guide
[IBM_CTG] IBM CICS Transaction Gateway V5.1: http://www-306.ibm.com/software/htp/cics/ctg/overview.html
[RB_CTG] IBM RedBook sg246133: CICS Transaction Gateway V5 The WebSphere Connector for CICS
[RB_JCA_CICS] IBM RedBook sg246401: Java Connectors for CICS: Featuring the J2EE Connector Architecture
[IWAS_J2C] RedBook sg246133: Integrating WebSphere Application Server and CICS using the
JCA- http://www-306.ibm.com/software/os/zseries/pdf/G224-7218-00_CICS_JCA_WP.pdf
[JCAIS] J2EE Connector Architecture Industry Support: http://java.sun.com/j2ee/connector/industry.html


MokaByte® è un marchio registrato da MokaByte s.r.l. 
Java®, Jini® e tutti i nomi derivati sono marchi registrati da Sun Microsystems.
Tutti i diritti riservati. E' vietata la riproduzione anche parziale.
Per comunicazioni inviare una mail a info@mokabyte.it