この章では、Java インターフェースの COBOL プログラムへのマッピングと、Micro Focus リソースアダプタの使用について説明します。
手続き型 COBOL で作成したプログラムは、Interface Mapping Toolkit を使用してインターフェースを COBOL プログラムにマップすることで EJB または Java bean として公開できます。Interface Mapping Toolkit は、COBOL サービス、EJB、Java bean を生成し、オプションで EJB のクライアントを生成します。
つまり、Interface Mapping Toolkit を使用すると、COBOL の入口点またはプログラム ID、および新しいインターフェースに使用するパラメタが選択できます。Interface Mapping Toolkit によってマッピング情報がすべて保存されるため、EJB や Java bean は COBOL サービスを呼び出すことができます。Interface Mapping Toolkit を使用して、EJB、Java bean、および COBOL サービスを生成します。詳細は、『 Interface Mapping Toolkit 』の章を参照してください。
次のどれかの方法で Java をディプロイまたは実行します。
実行時には、Java クライアントアプリケーションから Java 要求を送信し、生成された EJB または Java bean を呼び出します。EJB は受信した要求をリソースアダプタを介してエンタープライズサーバーに渡し、公開されている COBOL プログラムがエンタープライズサーバーによって実行されます。Java bean は要求をエンタープライズサーバーに直接渡します。
マッピング情報は実行時に、公開されている COBOL プログラムとの情報のやり取りに使用されます。エンタープライズサーバーは、応答をリソースアダプタを介して EJB に返すか、Java bean に直接返します。EJB または Java は応答をクライアントに渡します。
サポートされている J2EE バージョン、J2EE アプリケーションサーバー、および J2SE ランタイム環境の詳細は、Readme を参照してください。
ディプロイツールInterface Mapping Toolkitを使用して、クライアントを生成すると、自動的にEJBが生成されます。
生成されたEJBとオプショナルのクライアントはアーカイブファイル内(.jar、.warおよび.ear)に、マニュアルファイルと記述子とともにパッケージ化されます。 これらのファイルはmyProject/repos/myService.deploy下のディレクトリ内にあり、 以下のアーカイブファイルが生成されます。
.jarコマンドまたはWinzipなどのZIPユーティリティーを使用して、アーカイブファイルの内容を見ることができます。
EJBを生成すると、以下のファイルとともにJavaアーカイブファイル(myService.jar)内にパッケージ化されます。
ejb-jar.xml | EJBを定義する一般ディプロイメント記述子 |
myServiceBean.class | EJB のBeanクラス |
myServiceHome.class | EJBのホームインターフェース |
myService.class | EJBのリモートインターフェース |
myRecord.class | EJBが必要とする可能性があるカスタムレコード |
manifest.mf | .jarファイルを記述するマニフェスト |
*.xml, such as weblogic-ejb-jar.xml | 複数のJ2EEアプリケーションサーバー(WebLogicなど)でアプリケーションサーバーにEJBをディプロイするためのディプロイメント記述子 |
EJBクラスのソースコードは、com/mypackage/myServiceディレクトリ内に生成されます。
EJBのクライアントを生成すると、以下のファイルとともにアーカイブファイル(myService.war)内にパッケージ化されます。
*.jsp | JPSファイル。 これらのパスデータは、エンドユーザーとservlet間を行き来します |
myServiceJspBean.class | このファイルは、servletとJSP間を行き来するターゲットとセッターのメソッドを含んでいます |
myServiceServlet.class | このファイルはservlet。JSPからの着信要求を処理し、EJBのインスタンスを起動し、JSPから返されるレスポンスを転送します |
myServiceSessionMonitor.class | これはヘルパークラスであり、処理状態が確認できるセッションビーンのEJBインスタンスを保存します |
manifest.mf | .warファイルを記述するマニフェスト |
mfejlib.jar | カスタムレコード |
web.xml | servletとEJCリファレンスを定義する一般ディプロイメント記述子 |
*.xml, such as weblogic.xml | 複数のJ2EEアプリケーションサーバー(WebLogicなど)で、アプリケーションサーバーに.warファイルをディプロイするためのディプロイメント記述子 |
EJBのクライアントを生成すると、EJBとクライアントは以下のファイルとともにエンタープライズアーカイブファイル(myService.ear)内にパッケージ化されます。
application.xml | .jarファイルとクライアント.warファイルを定義する一般ディプロイメント記述子 |
myService.jar | EJBアーカイブファイル |
myService.war | クライアントアーカイブファイル |
manifest.mf | .jarファイルを記述するマニフェスト |
mfejlib.jar | カスタムレコード |
ディプロイメントディスクリプタは COBOL で作成したプログラムは、Interface Mapping Toolkit を使用してインターフェースを (.jar、.war、および .ear) のディプロイメントディスクプリタが必要です。実行時に、J2EE アプリケーションサーバーはディスクプリタを処理し、それに従って動作します。ディプロイメントディスクリプタは、生成された Java bean には必要ありません。
EJB またはクライアントの生成時に、次の汎用的なディプロイディスクプリタが作成され、関連するアーカイブファイルにパッケージ化されます。
一部の J2EE アプリケーションサーバーでは、別のディプロイメントディスクリプタがアーカイブファイルに必要になります。これらのディプロイメントディスクリプタは、サポートされているアプリケーションサーバーに対して自動的に生成されます。サポートされている J2EE アプリケーションサーバーの詳細は、Readmeを参照してください。
アプリケーションサーバーで別のディプロイメントディスクリプタが必要であるが、必要なディプロイメントディスクリプタが生成されない場合には、手動で作成してアーカイブファイルに追加する必要があります。ほとんどの場合には、この作業はアプリケーションサーバーの管理コンソールを使用して行うことができます。関連するディプロイメントディスクリプタに、次の情報を指定する必要があります。
EJB を生成するときは、生成されるそれぞれのアーカイブファイルにマニフェストファイル manifest.mf がインクルードされます。マニフェストファイルは、アーカイブのファイルに必要な情報を指定します。次に例を示します。
マニフェストファイルでは、次のようにクラスパスを指定することにより、mfejblib.jar がディプロイされたアーカイブファイルのルートにあることを指示します。
Class-path: mfejblib.jar
mfejblib.jar をその位置に置く必要があります。または、mfejblib.jar を別の位置に置く必要がある場合は、それに従ってクラスパスを変更できます。J2EE RI (reference implementation) を使用する場合は、これを行う必要があります。詳細は、後述する『CustomRecord および他の Java のサポート』の節を参照してください。
EJB または Java bean がカスタムレコードを使用する場合は、それらがサポートされているか確認する必要があります。COBOL 集団項目を Java データ型にマップするとカスタムレコードが作成されます。集団項目の再利用可能なマッピングを設定すると、Interface Mapper でその集団項目をマップでき、複雑なインターフェースフィールドに対応付けることができます。
Java bean の場合には、CustomRecord インターフェースと RuntimeProperties インターフェースのサポートは $COBDIR/lib にある mfj2se.jar で提供されます。このサポートは実行時に使用可能でなければならないため、mfj2se.jar をクラスパスに置く必要があります。たとえば、次のコマンドでアプリケーションを実行できます。
java -classpath class-directory/mfj2se.jar myProgram.class
EJB の場合には、CustomRecord インターフェースと RuntimeProperties インターフェースのサポートは、mfejblib.jar で提供されます。インターフェースのサポートは、EJB 用のクライアント生成時にアプリケーションの .ear ファイルに自動的にインクルードされます。ディプロイツールが EJB を作成する際に、マニフェストファイル manifest.mf を .jar ファイルに追加します。このマニフェストファイルでは、クラスパスが mfejblib.jar に設定されます。
手動でクライアントを作成する場合は、.ear ファイルに mfejblib.jar を手動で追加します。 ファイルには J2EE 1.3 用と J2EE 1.4 用の2つのバージョンがあり、それぞれ $COBDIR/lib/j2ee13 ディレクトリと $COBDIR/lib/j2ee14 ディレクトリに格納されています。mfejblib.jar へのクラスパスが EJB の .jar ファイルの manifest.mf ファイルにあるルートに設定されるため、デフォルトでは mfejblib.jar ファイルは .ear ファイルのルートに属します。
このマニフェストファイルは、EJB のアーカイブファイル myservice.jar 内で確認することができます。このアーカイブファイルは、myproject/Repos/myservice.deploy にあります。クラスパスは次のように設定されます。
Class-path: mfejblib.jar
mfejblib.jar を別の位置に置く必要がある場合は、それに従って EJB の jar ファイルにある manifest.mf のクラスパスを変更する必要があります。
クライアントを生成する、しないにかかわらずに J2EE RI にディプロイする場合には、.ear ファイルがあるディレクトリの library サブディレクトリに mfejblib.jar を置き、library/mfejblib.jar へのクラスパスをマニフェストファイルに設定する必要があります。
COBOL 開発システムには複数のリソースアダプタ (J2EE コネクタ) が付属しており、これらのリソースアダプタによって、J2EE アプリケーションサーバー上の EJB とエンタープライズサーバー上の COBOL プログラム間の通信が可能になります。リソースアダプタは生成された Java bean では使用されません。
EJB にエンタープライズサーバー上の COBOL プログラムとの通信を開始させるには、J2EE アプリケーションサーバー上にリソースアダプタをディプロイする必要があります。
Micro Focus のリソースアダプタは JCA (java connector architecture) に準拠しており、個々のアダプタが API として CCI (common client interface) を実装しています。JCA と CCI はどちらも Sun が策定した規格であり、EJB や他の J2EE コンポーネントは準拠が義務付けられています。
要求がリソースアダプタを経由して送信される基本的な過程は次のとおりです。
Micro Focus のリソースアダプタは API として CCI を使用するため、生成された EJB を使用しないで、リソースアダプタを直接呼び出すことも可能です。後述する『J2SE の管理非対象コネクションの使用方法』の節を参照してください。
生成された EJB または Java bean を呼び出して、COBOL サービスに必要なパラメータを渡すには、Java クライアントソフトウェアを作成する必要があります。このクライアントは JSP やサーブレット、または他のモジュールとして実装できます。
EJB または Java bean インターフェースは Interface Mapping Toolkit で定義されます。通常は Java 開発ツールに EJB または Java bean をインポートして、そこでインターフェースを調べます。その際には特に、出力パラメタに注意してください。マップされたインターフェースで (集団項目や対応するカスタムレコードではなく) 複数の出力パラメタが渡される場合には、これらの出力パラメタは EJB または Java bean インターフェース内のコンテナオブジェクトを介して返されます。Java 開発ツールでは、そのような出力パラメタの有無も確認できます。
実行時には、Java クライアントソフトウェアは EJB または Java bean を呼び出します。EJB は要求をリソースアダプタに渡します。リソースアダプタは、エンタープライズサーバーと通信して COBOL サービスを実行します。Java bean はエンタープライズサーバーと直接通信します。
COBOL エンタープライズサーバーに直接アクセスする Java bean を生成することで、J2EE アプリケーションサーバーとリソースアダプタを使用しないですみます。この方法では J2EE アプリケーションサーバーを管理するためのオーバーヘッドを回避することができますが、トランザクションサポートなどの利点を得ることができません。
生成された Java bean はステートレスです。bean 用に1つのクラスが、マップされたレコードを表すデータクラス用に別のクラスが生成されます。
Java bean は、J2SE の環境下で J2EE サーバーのライブラリで実行されます。Java bean は、アウトオブプロセスの方法で COBOL エンタープライズサーバーに直接アクセスします。 J2SE とエンタープライズサーバーはそれぞれ個別のプロセスとして実行され、ソケットを使用して互いに通信します。
Java bean を呼び出すクライアントソフトウェアを作成する必要があります。
Java bean のサポートは、$COBDIR/lib ディレクトリにある mfj2se.jar で提供されます。
Java bean の動作をトレースする場合は、-Dmfdebug=true を使用します。たとえば、プログラム myBean を次のように実行します。
java -Dmfdebug=true myBean
リソースアダプタを呼び出してエンタープライズサーバーに要求を送信するコードを独自に作成すると、J2EE アプリケーションサーバーを使用しないで、COBOL プログラムにメッセージを送信できます。その場合には、接続は管理されない状態になります。プログラムコードは、J2SE の環境下で J2EE サーバーのライブラリで実行されます。この方法では J2EE アプリケーションサーバーを管理するためのオーバーヘッドを回避することができますが、トランザクションサポートなどの利点を得ることができません。
管理非対象コネクションをディプロイするには、Micro Focus のリソースアダプタへのサポートを提供するクラスを含むようにクラスパスを更新するのみです。クラスは、mfcobolpure.jar と mfconnector.jar にパッケージ化されています。ファイルには J2EE 1.3 用と J2EE 1.4 用の 2 つのバージョンがあり、それぞれ $COBDIR/lib/j2ee13 ディレクトリと $COBDIR/lib/j2ee14 ディレクトリに格納されています。
Java で作成するクライアントは、CCI に準拠する必要があります。CCI では、リソースアダプタから Enterprise Server などの EIS (enterprise information server) に接続するために必要な API が定義されています。また、Micro Focus のリソースアダプタ専用の拡張クラスも使用可能です。
クライアントによる処理の大まかな流れは次のとおりです。
CCI で定義されている各クラスと、それらのメソッドの一部を次に示します。
com.microfocus.cobol.connector.cci package で提供される Micro Focus 拡張は、 J2EE Connector Class Library Reference を参照してください。com.microfocus.cobol.connector.cci package には、次のようなクラスとメソッドがあります。
以降では、COBOL サービスを要求する Java プログラムのコード例を示します。この Java プログラムは、CCI のインターフェースを使用してリソースアダプタとの間で情報をやり取りし、リソースアダプタによって COBOL サービスに要求を渡します。また、COBOL 集団項目を表す CCI カスタムレコードの使用方法も示しています。この例では、Calculate という名前の COBOL プログラムから入口点 ADD を介し、再利用可能レコード Calculator を使用して、add サービスがマップされます。
COBOL の Calculate プログラムは、インターフェースマッパーで Java インターフェースにマップする必要があります。Calculator パラメタを「再利用マッピング」ペインにドラッグし、続いて add オペレーションの「インターフェースフィールド」ペインにドラッグします。subtract、divide、multiply の各オペレーションでも、同じ操作を行います。このようにインターフェースをマップするのは、アプリケーションサーバーで管理されないクラスによって、CCI カスタムレコードの使用方法を示しているためです。
このプログラム例では、次の各 Java パッケージに含まれるクラスを使用します。
javax.resource.cci | J2EE のコネクタアーキテクチャ仕様で定義されている CCI インターフェース群 |
com.microfocus.cobol.connector.spi | SPI (service provider interface) インターフェースを実装する Micro Focus リソースアダプタ専用のクラス群 |
com.microfocus.cobol.connector.cci | CCI インターフェースを実装する Micro Focus リソースアダプタ専用のクラス群 |
これらのパッケージは、コードにインポートすることが推奨されます。次のような文をコード内に記述してください。
import com.microfocus.cobol.connector.spi.*; import com.microfocus.cobol.connector.cci.*; import javax.resource.cci.*;
次にサービスのコード例を示します。コードに続いて、主な行を詳しく説明しています。
1 try { 2 // 接続ファクトリのインスタンスを取得します。 3 mcf = new CobolNoTxManagedConnectionFactory(); 4 // 必要なフィールドを設定します。 5 mcf.setServerHost("localhost"); 6 mcf.setServerPort("9003"); 7 // 接続ファクトリのインスタンスを取得します (JNDI は使用しません)。 8 cxf = (javax.resource.cci.ConnectionFactory) mcf.createConnectionFactory(); 9 // Cobol 接続ハンドルを取得します。 10 connection = cxf.getConnection(); 11 initialize(connection, cxf, true); 12 // 対話通信を設定します。 13 interaction = connection.createInteraction(); 14 // 新しい対話設定を作成します。 15 CobolInteractionSpec iSpec = new CobolInteractionSpec(); 16 iSpec.setFunctionName("myservice.add"); 17 javax.resource.cci.RecordFactory rf = cxf.getRecordFactory(); 18 Calculator calc = new Calculator(); 19 calc.setArg1(new java.math.BigDecimal(10)); 20 calc.setArg2(new java.math.BigDecimal(20)); 21 iSpec.setArgument(0, com.microfocus.cobol. RuntimeProperties.BY_REFERENCE); 22 interaction.execute(iSpec, calc, calc); 23 System.out.println( "Input - Arg 1 was" + calc.getArg1()); 24 System.out.println( "Input - Arg 2 was" + calc.getArg2()); 25 System.out.println( "Result was" + calc.getResult()); 26 System.out.println( "Memory was" + calc.getStorage()); 28 interaction.close(); 29 connection.close(); 30 } catch( javax.resource.ResourceException re) { 31 re.printStackTrace(); 32 Exception le = re.getLinkedException(); 33 }
3~6 行目
mcf = new CobolNoTxManagedConnectionFactory();
前述した ManagedConnectionFactory クラスのインスタンスを生成しています。続いて、Java プログラムとリソースアダプタ間の管理されない接続を対象に、このオブジェクトを使用して次の属性を設定します。
mcf.setServerHost("localhost");
リソースアダプタが位置しているマシンの名前。
mcf.setServerPort("9003");
エンタープライズサーバーがリソースアダプタからのメッセージ着信を監視するポート。
8 行目
cxf = (javax.resource.cci.ConnectionFactory) mcf.createConnectionFactory();
3 行目で生成した CobolNoTxManagedConnectionFactory を使用して javax.resource.cci.ConnectionFactory クラスをインスタンス化しています。
10 行目
connection = cxf.getConnection();
javax.resource.cci.Connection クラスをインスタンス化しています。接続ファクトリオブジェクトの getConnection メソッドを呼び出すと、CobolNoTxManagedConnectionFactory の設定が反映された Connection インスタンスのハンドルが取得されます。この接続ハンドルは常に1つの ManagedConnection にマップされます。
11 行目
initialize(connection, cxf, true);
接続を初期化しています。この処理は省略できません。引数 true はエンタープライズサーバー上の COBOL プログラムの状態を指定しています。呼び出すたびにプログラムを初期状態で実行する場合は true、サービス呼出しの間、同じ状態を保持させるには false に設定します。
13 行目
interaction = connection.createInteraction();
Connection オブジェクトの createInteraction() メソッドを呼び出し、javax.resource.cci.Interaction をインスタンス化しています。Interaction オブジェクトの生成には Connection オブジェクトを使用します。生成した Interaction オブジェクトでエンタープライズサーバーとの通信を行います。
15 行目
CobolInteractionSpec iSpec = new CobolInteractionSpec();
必要な対話通信の種類に応じて、専用のクラスをインスタンス化し、設定します。この例では、com.microfocus.cobol.connector.cci.CobolInteractionSpec クラスを使用しています。このクラスで、パラメタを渡す要求と方法を作成します。このクラスのインスタンスに、関数の名前と、索引レコード内の各引数 (入力、出力、入出力) またはカスタムレコードの引数の方向が保持されます。
16 行目
iSpec.setFunctionName("myservice.add");
エンタープライズサーバーで実行するプログラムの名前を、setFunctionName メソッドで指定しています。
18~21 行目
Calculator calc = new Calculator(); calc.setArg1(new java.math.BigDecimal(10)); calc.setArg2(new java.math.BigDecimal(20)); iSpec.setArgument(0, com.microfocus.cobol. RuntimeProperties.BY_REFERENCE);
カスタムレコードクラスのオブジェクトを生成します。単独のカスタムレコードを引数として渡す場合は、このコードで十分です。カスタムレコードは EJB の生成時に自動的に生成されます。カスタムレコード用に生成されたソースファイルが myproject/repos/myService.deploy/packageName に格納されています。
複数のカスタムレコード、またはカスタムレコードと Java の基本データ型を1つの引数として渡す場合には、索引レコードを使用する必要があります。 たとえば、整数型の値とカスタムレコードをパラメタとして渡す場合には、次のコードを使用します。
javax.resource.cci.RecordFactory rf = cxf.getRecordFactory(); javax.resource.cci.IndexedRecord iRec = rf.createIndexedRecord("IndexedIn"); javax.resource.cci.IndexedRecord oRec = rf.createIndexedRecord("IndexedOut"); iRec.add(new Integer(5)); iRec.add(calc); iSpec.setArgument(0, com.microfocus.cobol. RuntimeProperties.BY_REFERENCE);
このコードによって引数の方向が設定されます。各引数には 0 を基数とする連番が付けられ、この番号が最初の引数として setArgument に渡されます。方向の有効値は次のとおりです。
com.microfocus.cobol.RuntimeProperties.BY_REFERENCE com.microfocus.cobol.RuntimeProperties.BY_VALUE com.microfocus.cobol.RuntimeProperties.OUTPUT_ONLY
22 行目
interaction.execute(iSpec, calc, calc);
対話通信を実行します。Interaction オブジェクトの execute() メソッドを呼び出すと、要求がエンタープライズサーバーに送信されます。
28~29 行目
interaction.close();
最後に Interaction と Connection をクローズします。Connection オブジェクトの close() は接続を終了するメソッドです。このメソッドを実行すると、リソースアダプタとの接続が解除されます。このメソッドを実行する前に、必ず Interaction オブジェクトの close() メソッドを実行してください。
initialize メソッドのコードの例を次に示します。
private void initialize( javax.resource.cci.Connection con, javax.resource.cci.ConnectionFactory cf, boolean isInitial) { try { javax.resource.cci.Interaction ix = con.createInteraction(); com.microfocus.cobol.connector.cci.CobolInteractionSpec iSpec = new com.microfocus.cobol.connector.cci.CobolInteractionSpec(); iSpec.setFunctionName("initialize"); javax.resource.cci.RecordFactory rf = cf.getRecordFactory(); javax.resource.cci.IndexedRecord irec = rf.createIndexedRecord("beanArgs"); irec.add(new Boolean(isInitial)); javax.resource.cci.Record orec = ix.execute(iSpec, irec); ix.close(); } catch(javax.resource.ResourceException ex) { throw new javax.ejb.EJBException( "initialize threw ResourceException: ", ex); } }
上記のサンプルでは、COBOL サービス (myservice.add) でグループレコード Calculator を使用しています。リソースアダプタの CCI では、このグループレコードはカスタムレコードとして表されます。このグループレコードに対応するカスタムレコードクラス、Calculator.java のコード例を次に示します。
/******************************************************* この例題は、Micro Focus Net Express 4.0 で生成されたファイルです。 このファイルは、Calculator のカスタムクラスを表します。 *******************************************************/ public class Calculator extends com.microfocus.cobol.connector.cci.CustomRecord { private java.math.BigDecimal arg1 = java.math.BigDecimal.valueOf(0); private java.math.BigDecimal arg2 = java.math.BigDecimal.valueOf(0); private java.math.BigDecimal result = java.math.BigDecimal.valueOf(0); private java.math.BigDecimal storage = java.math.BigDecimal.valueOf(0); public Calculator() { } public java.math.BigDecimal getArg1() { return arg1; } public void setArg1(java.math.BigDecimal ___p) { arg1 = ___p ; } public java.math.BigDecimal getArg2() { return arg2; } public void setArg2(java.math.BigDecimal ___p) { arg2 = ___p ; } public java.math.BigDecimal getResult() { return result; } public void setResult(java.math.BigDecimal ___p) { result = ___p ; } public java.math.BigDecimal getStorage() { return storage; } public void setStorage(java.math.BigDecimal ___p) { storage = ___p ; } public Object[] getParameters() { Object[] objs = new Object[4]; objs[0] = arg1; objs[1] = arg2; objs[2] = result; objs[3] = storage; return objs; } public void setParameters(Object[] objs) { arg1 = (java.math.BigDecimal)objs[0]; arg2 = (java.math.BigDecimal)objs[1]; result = (java.math.BigDecimal)objs[2]; storage = (java.math.BigDecimal)objs[3]; } }
サービスのサンプルで使用される COBOL プログラム、CALCULATOR のコードを次に示します。
$set intlevel(4) identification division. program-id. calculate. environment division. data division. working-storage section. 01 calmemory pic s9(9) comp-5 value 0. linkage section. 01 calculator. 05 arg1 pic s9(19)v9(19) comp-3. 05 arg2 pic s9(19)v9(19) comp-3. 05 result pic s9(19)v9(19) comp-3. 05 storage pic s9(19)v9(19) comp-3. procedure division. exit program. entry "add" using calculator. move arg1 to result add arg2 to result add result to calmemory move calmemory to storage exit program. entry "subtract" using calculator. move arg1 to result subtract arg2 from result add result to calmemory move calmemory to storage exit program. entry "multiply" using calculator. move arg1 to result multiply arg2 by result add result to calmemory move calmemory to storage exit program. entry "divide" using calculator. move arg1 to result divide arg2 into result add result to calmemory move calmemory to storage exit program.