目次 前 次 PDF


Joltクラス・ライブラリの使用

Joltクラス・ライブラリの使用
Oracle Joltクラス・ライブラリは、Oracle Tuxedoサービスにアクセスするための、開発者向けのオブジェクト指向のJava言語クラス・セットです。クラス・ライブラリには、Jolt APIを実装するクラス・ファイルがあります。これらのクラスを使用すると、アプリケーションを拡張してインターネットやイントラネットでトランザクション処理ができるようになります。Joltクラス・ライブラリを使用して、JavaアプレットからOracle Tuxedoサービスへのアクセスをカスタマイズすることもできます。
このトピックには次の項が含まれます:
以降の項の情報を活用するには、Java言語によるプログラミングおよびオブジェクト指向プログラミングに関する全般的な知識が必要です。プログラミングの例はすべてJavaコードで記述されています。
注意:
プログラムの例では、Joltの機能を示す部分を抜粋して示しています。そのままコンパイルしたり、実行しないでください。これらのプログラム例を実際に実行するには、コードを追加する必要があります。
クラス・ライブラリの機能の概要
Joltクラス・ライブラリには、クライアント側のアプリケーションやアプレット(独立したJavaアプリケーションとして実行するか、またはJava対応のWebブラウザで実行)を開発するためのOracle Tuxedoアプリケーション開発者向けのツールが用意されています。bea.joltパッケージにはJoltクラス・ライブラリが用意されています。Joltクラス・ライブラリを使用するには、クライアント・プログラムやアプレットでこのパッケージをインポートする必要があります。bea.joltパッケージをインポートする方法については、「Joltの資金振替えの例(SimXfer.java)」を参照してください。
JavaアプリケーションとJavaアプレット
ブラウザで実行するJavaプログラムは「アプレット」と呼ばれます。アプレットとは、アプリケーションの一部として特定の機能を実行し、簡単にダウンロードできるサイズの小さいプログラムのことです。多くのブラウザでは、高度なセキュリティを実現するため、Javaアプレットの機能に制限が設けられています。以下は、アプレットに対するいくつかの制限です。
アプレットは通常、ホスト・システム上のファイルに対する読み取りや書込みを行うことができません。
アプレットは、アプレットを実行するホスト(クライアント)上のプログラムを起動できません。
アプレットは、ダウンロード元のホストに対してのみネットワーク接続を行うことができます。それ以外のホスト(クライアント・マシンを含む)に対してネットワーク接続を行うことはできません。
Javaアプレットのほとんどの制限には、プログラミングによる回避策があります。ブラウザでサポートされるアプレットの機能またはアプレットの制限については、お使いのブラウザのWebサイト(www.netscape.com、www.microsoft.comなど)や開発者用ドキュメントを参照してください。また、Joltリレーを使用すると、ネットワーク接続に関するいくつかの制限を回避することができます。
一方、Javaアプリケーションはブラウザ上では実行されず、上記のような制限を受けることはありません。たとえば、Javaアプリケーションは、実行中のホスト・マシン上で別のアプリケーションを起動できます。アプレットがユーザー・インタフェースとしてブラウザやappletviewerのウィンドウ環境に依存するのに対し、Javaアプリケーションでは独自のユーザー・インタフェースを作成する必要があります。アプレットは、コンパクトで移植性が高くなるように設計されています。一方、Javaアプリケーションは、他のJava以外のプログラムのように機能性を高くできます。JavaアプリケーションとJavaアプレットの最大の違いは、様々なブラウザによってアプレットにセキュリティ上の制限と、2つのプログラム・タイプのスコープです。
Joltクラス・ライブラリの特徴
Joltクラス・ライブラリには次の特徴があります。
完全にスレッド・セーフなクラスを備えています。
典型的なトランザクション処理(ログオン、同期型の呼び出し、トランザクションの開始、トランザクションのコミット、トランザクションのロールバック、ログオフなど)をJavaオブジェクトにカプセル化します。
連続的または断続的なクライアント・ネットワーク接続に対してアイドル・タイムアウト値を設定するメソッドが用意されています。
Joltクライアントがイベントに基づいた通知をサブスクライブし、受信することができるメソッドが用意されています。
エラーと例外処理
Joltクラス・ライブラリは、JoltインタープリタのエラーおよびOracle Tuxedoのエラーを例外として返します。「Jolt Class Library Reference」では、Joltクラスと、各クラスのエラーや例外を一覧表示します。『Oracle Jolt APIリファレンス』には、エラーと例外のクラス・リファレンスが含まれています。
Joltでのクライアント/サーバー関係
Oracle Joltは、分散型のクライアント/サーバー環境で動作し、JavaクライアントをOracle Tuxedoをベースとするアプリケーションに接続します。
図4-1は、JoltプログラムとJoltサーバーの間のクライアント/サーバー関係を示しています。
図4-1 Joltでのクライアント/サーバー関係
.
図に示すように、JoltサーバーはネイティブなOracle Tuxedoクライアントのプロキシとして動作し、ネイティブなOracle Tuxedoクライアントで利用できる機能を実装します。Oracle Joltサーバーは、Oracle Joltクライアントからのリクエストを受け取ると、Oracle Tuxedo ATMIインタフェースを介してこれらのリクエストをOracle Tuxedoサービス・リクエストにマッピングします。リクエストおよび関連付けられたパラメータは、メッセージ・バッファにパッケージされ、ネットワーク経由でOracle Joltサーバーに配信されます。Oracle JoltサーバーとOracle Joltアプレットの間のすべての通信は、Oracle Jolt接続マネージャにより、Oracle Joltトランザクション・プロトコルを使用して処理されます。Oracle Joltサーバーは、メッセージからデータを取り出し、必要に応じてデータ変換(数値形式や文字セットなど)を行ってから、メッセージで指定された適切なサービスをOracle Tuxedoにリクエストします。
Oracle Tuxedoシステムが受け取ったサービス・リクエストは、ほかのOracle Tuxedoのリクエストとまったく同じ方法で処理されます。結果はATMIインタフェースを通してOracle Joltサーバーに返され、そこで結果とエラー情報がメッセージにパッケージ化されると、Oracle Joltのクライアント・アプレットに送信されます。Oracle Joltクライアントはメッセージの中身を様々なOracle Joltクライアント・インタフェース・オブジェクトにマップして、リクエストを完了します。
クライアント側では、ユーザー・プログラムにクライアント・アプリケーション・コードが含まれています。Joltクラス・ライブラリが提供するJoltSessionとJoltTransactionがサービス・リクエストを処理します。
表4-1で、単純なプログラムの例におけるクライアント側のリクエストおよびJoltサーバー側のアクションについて説明します。
 
表4-1 Joltクライアント/サーバーの相互作用
Joltクライアント
Joltサーバー
1
attr=new JoltSessionAttributes();
attr.setString(attr.APPADDRESS, "//myhost:8000");
クライアントをOracle Tuxedo環境にバインドします。
2
session=new JoltSession(attr, username, userRole, userPassword, appPassword);
クライアントをOracle Tuxedoにログオンさせます。
3
withdrawal=new JoltRemoteService( servname, session );
リポジトリ内のサービス属性を検索します。
4
withdrawal.addString("accountnumber", "123");
withdrawal.addFloat("amount", (float) 100.00);
クライアントに変数を設定します(Joltサーバー側の動作なし)
5
trans=new JoltTransaction( time-out, session);
新しいTuxedoトランザクションを開始します。
6
withdrawal.call(trans);
Oracle Tuxedoサービスを実行します。
7
trans.commit() or trans.rollback();
トランザクションを完了またはロールバックします。
8
balance=withdrawal.getFloatDef(“balance," (float) 0.0);
結果を取り出します(Joltサーバー側の動作なし)。
9
session.endSession();
クライアントをOracle Tuxedoからログオフさせます。
「Joltクライアント/サーバーの相互作用」をまとめると、次のようになります。
1.
JoltSessionAttributesクラスを使用してクライアントをOracle Tuxedo環境にバインドします。
2.
セッションを確立します。
3.
変数を設定します。
4.
必要なトランザクション処理を行います。
5.
クライアントをOracle Tuxedoからログオフさせます。
上記のアクティビティは、Joltクラス・ライブラリのクラスによって処理されます。これらのクラスには、データの設定や消去を行ったり、リモート・サービスのアクションを処理するメソッドが用意されています。Joltクラス・ライブラリの詳細は、「Joltオブジェクト間の関係」を参照してください。
Joltオブジェクト間の関係
図4-2は、Joltクラス・ライブラリのクラスをインスタンス化したオブジェクト間の関係を示しています。
図4-2 Joltオブジェクト間の関係
Joltクラスは、オブジェクトとして様々な関係で相互作用します。上の図は、3種類の基本的なカテゴリを示しています。
contains-a関係 - クラス・レベルでは、1つのオブジェクトに別のオブジェクトを含めることができます。たとえば、JoltTransactionはJoltSessionオブジェクトを格納します(または含みます)。
is-a関係 - is-a関係は通常、クラス・インスタンス・レベルまたはサブオブジェクト・レベルで成立し、オブジェクトが特定のオブジェクトのインスタンスであることを示します。
uses-a関係 - オブジェクトが別のオブジェクトを格納することなく使用できることを示します。たとえばJoltSessionはJoltSessionAttributesオブジェクトを使用して、ホストとポート情報を入手できます。
Joltクラス・ライブラリのウォークスルー
Joltクラスを使用すると、ログオン/ログオフ、同期型のサービス呼び出し、トランザクションの開始、トランザクションのコミット、トランザクションのロールバックなどの基本的なトランザクション処理を実行できます。次の項では、これらの機能を実行するためのJoltクラスの使い方を説明します。
Joltクラス・ライブラリを使用して、マルチスレッド化されたアプリケーションを開発したり、Tuxedo固有のバッファ・タイプを定義したり、イベントや非請求メッセージのサブスクライブを実行することもできます。これらの機能については、後の項で説明します。
ログオン/ログオフ
クライアント・アプリケーションには、トランザクション処理を行う前にOracle Tuxedo環境にログオンしておく必要があります。Joltクラス・ライブラリには、Oracle Tuxedoシステムとの接続を確立するためのJoltSessionAttributesクラスとJoltSessionクラスが用意されています。
JoltSessionAttributesクラスには、様々なプロパティのほか、JoltおよびOracle Tuxedoシステムへの接続プロパティが格納されます。接続を確立するには、クライアント・アプリケーション側でJoltSessionクラスのインスタンスを作成する必要があります。このインスタンスがJoltSessionオブジェクトです。開発者がJoltセッションおよびOracle Tuxedoオブジェクトをインスタンス化すると、JoltおよびOracle Tuxedoのログオン機能が有効になります。endSessionメソッドを呼び出すと、セッションは終了し、ユーザーのログオフが可能になります。
同期型のサービス呼出し
リクエストや応答などのトランザクションは、JoltRemoteServiceオブジェクト(JoltRemoteServiceクラスのインスタンス)を使用して処理されます。各JoltRemoteServiceオブジェクトは、エクスポートされたOracle Tuxedoのリクエスト/応答サービスを参照します。JoltRemoteServiceオブジェクトを使用する前には、サービス名とJoltSessionオブジェクトを指定して、JoltRemoteServiceオブジェクトをインスタンス化しておく必要があります。
JoltRemoteServiceオブジェクトを使用するには、次の手順に従います。
1.
入力パラメータを設定します。
2.
サービスを呼び出します。
3.
出力パラメータを検証します。
効率を高めるため、Joltでは入力パラメータ・オブジェクトはコピーされません。オブジェクトへの参照(文字列とバイト配列)だけが保存されます。JoltRemoteServiceオブジェクトは、ステートフル・オブジェクトです。そのため、このオブジェクトの入力パラメータとリクエスト属性は、オブジェクトの寿命がある限り維持されます。JoltRemoteServiceオブジェクトを再利用する前に、clear()メソッドを使用して、属性や入力パラメータをリセットできます。
Joltはマルチスレッド環境用に設計されているので、Javaのマルチスレッド機能を使用して複数のJoltRemoteServiceオブジェクトを同時に呼び出すことができます。詳細は、「マルチスレッド・アプリケーション」を参照してください。
トランザクションの開始、コミット、およびロールバック
Joltでは、トランザクションはJoltTransactionクラスのオブジェクトとして表されます。トランザクションは、トランザクション・オブジェクトがインスタンス化されると開始されます。次に示すように、トランザクション・オブジェクトの作成時には、タイムアウト値とJoltSessionオブジェクトのパラメータが設定されます。
trans = new JoltTransaction(timeout, session)
Joltでは、トランザクションに関与するすべてのサービスに対して明示的なトランザクション・モデルを使用します。トランザクション・サービスを呼び出すには、JoltTransactionオブジェクトがパラメータとして必要です。また、サービスとトランザクションが同じセッションに属していることも必要です。Joltでは、同じセッションにバインドされていないサービスとトランザクションを使用することはできません
「Joltの資金振替えの例(SimXfer.java)」のサンプル・コードは、Joltクラス・ライブラリの使い方を示しています。ここでは、JoltSessionAttributes、JoltSession、JoltRemoteServiceおよびJoltTransactionクラスを使用しています。
例では、ユーザー定義された2つのOracle Tuxedoサービス(WITHDRAWALとDEPOSIT)をバインドして、TRANSFERトランザクションを擬似的に実行します。WITHDRAWAL操作が失敗した場合は、ロールバックが実行されます。それ以外の場合はDEPOSITが実行され、commitによりトランザクションが完了します。
「Joltの資金振替えの例(SimXfer.java)」のサンプル・コードに示すトランザクション・プロセスのプログラミング手順は、次のとおりです。
1.
hostnameportnumberなどの接続属性をJoltSessionAttributeオブジェクトに設定します。
コード・リストで次の行を参照してください。
sattr = new JoltSessionAttributes();
2.
sattr.checkAuthenticationLevel()を使用すると、サーバーへのログオンに必要なセキュリティ・レベルをアプリケーション側で決定できます。
コード・リストで次の行を参照してください。
switch (sattr.checkAuthenticationLevel())
3.
JoltSessionオブジェクトをインスタンス化してログオンします。
コード・リストで次の行を参照してください。
session = new JoltSession (sattr, userName, userRole,
userPassword, appPassword);
この例では、SessionExceptionエラーを明示的に取得しません。
4.
すべてのJoltRemoteService呼出しでは、サービスの指定とJoltSession()から返されたセッション・キーが必要です。
コード・リストで次の行を参照してください。
withdrawal = new JoltRemoteService("WITHDRAWAL", session);
deposit = new JoltRemoteService("DEPOSIT", session);
これらの呼出しは、Oracle Tuxedoサービス・メタデータ・リポジトリに格納されているWITHDRAWALおよびDEPOSITのサービス定義を、withdrawalオブジェクトおよびdepositオブジェクトにそれぞれバインドします。WITHDRAWALおよびDEPOSITサービスがメタデータ・リポジトリで定義されていないと、ServiceExceptionがスローされます。この例では、ServiceExceptionエラーを明示的に取得しません。
5.
サービス定義が返されると、アプリケーション固有のフィールド(アカウント番号を示すACCOUNT_IDや引出し額を示すSAMOUNTなど)に自動的に値が設定されます。
コード・リストで次の行を参照してください。
withdrawal.addInt("ACCOUNT_ID", 100000);
withdrawal.addString("SAMOUNT", "100.00");
add*()メソッドでは、IllegalAccessErrorまたはNoSuchFieldError例外がスローされる場合があります。
6.
JoltTransaction呼出しでは、指定した時間内にトランザクションが完了しない場合のタイムアウト値を指定できます。
コード・リストで次の行を参照してください。
trans = new JoltTransaction(5,session);
7.
withdrawalサービスの定義が自動的に設定された後でwithdrawal.call(trans)メソッドを呼び出すと、withdrawalサービスが呼び出されます。
コード・リストで次の行を参照してください。
withdrawal.call(trans);
8.
失敗したWITHDRAWALはロールバックできます。
コード・リストで次の行を参照してください。
trans.rollback();
9.
または、いったんDEPOSITが実行されると、すべてのトランザクションがコミットされます。コード・リストで次の行を参照してください。
deposit.call(trans);
trans.commit();
リスト4-1に、Joltクラスを使用して資金の振替えを行うための単純なアプリケーションの例を示します。
リスト4-1 Joltの資金振替えの例(SimXfer.java)
/* Copyright 1999 Oracle Systems, Inc. All Rights Reserved */
import bea.jolt.*;
public class SimXfer
{
public static void main (String[] args)
{
JoltSession session;
JoltSessionAttributes sattr;
JoltRemoteService withdrawal;
JoltRemoteService deposit;
JoltTransaction trans;
String userName=null;
String userPassword=null;
String appPassword=null;
String userRole=���myapp���;
sattr = new JoltSessionAttributes();
sattr.setString(sattr.APPADDRESS, ���//bluefish:8501���);
switch (sattr.checkAuthenticationLevel())
{
case JoltSessionAttributes.NOAUTH:
System.out.println(���NOAUTH\n���);
break;
case JoltSessionAttributes.APPASSWORD:
appPassword = ���appPassword���;
break;
case JoltSessionAttributes.USRPASSWORD:
userName = ���myname���;
userPassword = ���mysecret���;
appPassword = ���appPassword���;
break;
}
sattr.setInt(sattr.IDLETIMEOUT, 300);
session = new JoltSession(sattr, userName, userRole,
userPassword, appPassword);
// Simulate a transfer
withdrawal = new JoltRemoteService(���WITHDRAWAL���, session);
deposit = new JoltRemoteService(���DEPOSIT���, session);
withdrawal.addInt(���ACCOUNT_ID���, 100000);
withdrawal.addString(���SAMOUNT���, ���100.00���);
// Begin the transaction w/ a 5 sec timeout
trans = new JoltTransaction(5, session);
try
{
withdrawal.call(trans);
}
catch (ApplicationException e)
{
e.printStackTrace();
// This service uses the STATLIN field to report errors
// back to the client application.
System.err.println(withdrawal.getStringDef(���STATLIN���,���NO
STATLIN���));
System.exit(1);
}
String wbal = withdrawal.getStringDef(���SBALANCE���, ���$-1.0���);
// remove leading ���$��� before converting string to float
float w = Float.valueOf(wbal.substring(1)).floatValue();
if (w < 0.0)
{
System.err.println(���Insufficient funds���);
trans.rollback();
System.exit(1);
}
else // now attempt to deposit/transfer the funds
{
deposit.addInt(���ACCOUNT_ID���, 100001);
deposit.addString(���SAMOUNT���, ���100.00���);
deposit.call(trans);
String dbal = deposit.getStringDef(���SBALANCE���, ���-1.0���);
trans.commit();
System.out.println(���Successful withdrawal���);
System.out.println(���New balance is: ��� + wbal);
System.out.println(���Successful deposit���);
System.out.println(���New balance is: ��� + dbal);
}
session.endSession();
System.exit(0);
} // end main
} // end SimXfer
 
Oracle Tuxedoのバッファ・タイプをJoltで使用する
Joltでは、次のOracle Tuxedo組込みのバッファ・タイプがサポートされています。
FML、FML32
VIEW、VIEW32
X_COMMON
X_C_TYPE
CARRAY
X_OCTET
STRING
XML
MBSTRING
注意:
X_OCTETの使用方法はCARRAYと同じです。
X_COMMONおよびX_C_TYPEの使用方法はVIEWと同じです。
Joltアプリケーションのプログラマは、Oracle Tuxedoに組み込まれているバッファ・タイプのうち、特にCARRAY (文字配列)およびSTRINGの扱い方を知っておく必要があります。
CARRAY型はデータを非透過的に処理するために使用されます(つまり、CARRAYデータ型の文字はどんな形式にも解釈されません)。JoltクライアントとOracle Tuxedoサービス間でのデータ変換は行われません。
STRINGのデータ型は文字であり、CARRAYとは違って、null文字にまでの文字数を指定して転送長を設定できます。そのため、異なる文字セットを使用するマシン間でデータを交換する場合は、データが自動的に変換されます。
Oracle Tuxedoの型付きバッファ、データ型、バッファ・タイプに関するすべての情報については、以下のドキュメントを参照してください。
『C言語を使用したOracle Tuxedo ATMIアプリケーションのプログラミング』
『Oracle Tuxedo ATMI C言語関数リファレンス』
『Oracle Tuxedo ATMI FML関数リファレンス』
『ファイル形式、データ記述、MIBおよびシステム・プロセス・リファレンス』
STRINGバッファ・タイプを使用する
STRINGバッファ・タイプは、null以外の文字配列で構成され、最後がnull文字で終了します。CARRAYとは違って、null文字までの文字数を指定して転送長を設定できます。STRINGバッファは、自己記述型です。そのため、異なる文字セットを使用するマシン間でデータを交換する場合は、Oracle Tuxedoシステムによってデータが自動的に変換されます。
注意:
JoltからSTRINGへのデータ変換時には、STRINGバッファの終端にnull終結文字が自動的に追加されます。Java文字列はnullで終結しないためです。
STRINGバッファ・タイプを使用するには、次の2つの操作が必要です。
1.
バッファ・タイプで使用するTuxedoサービスを定義します。
2.
STRINGバッファ・タイプを使用するコードを記述します。
次の2つの項では、これらの手順について例を挙げて説明します。
「STRINGバッファ・タイプの使い方(ToUpper.java)」に示すコードToUpperは、STRINGバッファ・タイプが設定されたサービスがJoltでどのように動作するかを示しています。Oracle TuxedoサービスToUpperは、Oracle Tuxedoのサンプルsimpappで利用できます。
リポジトリ・エディタでTOUPPERサービスを定義する
ToUpper.javaを実行する前に、メタデータ・リポジトリ・エディタを使用してTOUPPERサービスを定義する必要があります。
ToUpper.javaクライアント・コード
リスト4-2内のJavaコードToUpper.javaは、STRINGバッファ・タイプが設定されたサービスがJoltでどのように動作するかを示しています。この例では、STRINGバッファ・タイプを使用するJoltクライアントがサーバーにデータを渡す様子を示しています。Oracle Tuxedoサーバーはバッファを受け取り、文字列をすべて大文字に変換し、変換後の文字列をクライアントに返します。次の例では、セッション・オブジェクトがすでにインスタンス化されていることが前提となっています。
リスト4-2 STRINGバッファ・タイプの使い方(ToUpper.java)
/* Copyright 1996 Oracle Systems, Inc. All Rights Reserved */
import bea.jolt.*;
public class ToUpper
{
public static void main (String[] args)
{
JoltSession session;
JoltSessionAttributes sattr;
JoltRemoteService toupper;
JoltTransaction trans;
String userName=null;
String userPassword=null;
String appPassword=null;
String userRole=���myapp���;
String outstr;
sattr = new JoltSessionAttributes();
sattr.setString(sattr.APPADDRESS, ���//myhost:8501���);
switch (sattr.checkAuthenticationLevel())
{
case JoltSessionAttributes.NOAUTH:
break;
case JoltSessionAttributes.APPASSWORD:
appPassword = ���appPassword���;
break;
case JoltSessionAttributes.USRPASSWORD:
userName = ���myname���;
userPassword = ���mysecret���;
appPassword = ���appPassword���;
break;
}
sattr.setInt(sattr.IDLETIMEOUT, 300);
session = new JoltSession(sattr, userName, userRole,
userPassword, appPassword);
toupper = new JoltRemoteService (���TOUPPER���, session);
toupper.setString(���STRING���, ���hello world���);
toupper.call(null);
outstr = toupper.getStringDef(���STRING���, null);
if (outstr != null)
System.out.println(outstr);
session.endSession();
System.exit(0);
} // end main
} // end ToUpper
 
CARRAYバッファ・タイプを使用する
CARRAYバッファ・タイプは、Oracle Tuxedoシステムに組み込まれている文字配列による単純なバッファ・タイプです。CARRAYバッファ・タイプのデータはシステム側で解釈されないため、データ型が明らかであってもJoltクライアント・アプリケーションでデータの長さを指定する必要があります。このバッファ・タイプを処理するときは、常にJoltクライアントでデータの長さを指定してください。
たとえば、Oracle TuxedoサービスがCARRAYバッファ・タイプを使用する場合、ユーザーが32ビットのintegerを設定すると(Javaではintegerはビッグ・エンディアン・バイト順)、そのデータは変換されずにOracle Tuxedoサービスに送信されます。
CARRAYバッファ・タイプを使用するには、まずバッファ・タイプで使用するTuxedoサービスを定義します。次に、そのバッファ・タイプを使用するコードを記述します。次の2つの項では、これらの手順について説明します。
注意:
X_OCTETの使用方法はCARRAYと同じです。
リポジトリ・エディタでTuxedoサービスを定義する
例を実行する前に、TuxedoのECHOサービスを作成し、起動する必要があります。ECHOサービスは、バッファを取得し、Joltクライアントに返します。メタデータ・リポジトリ・エディタでECHOサービスを定義する必要があります(例については、「リポジトリ・エディタでTOUPPERサービスを定義する」を参照)。
tryOnCARRAY.javaクライアント・コード
次のリスト内のコードは、CARRAYバッファ・タイプが設定されたサービスがJoltでどのように動作するかを示しています。JoltはCARRAYデータ・ストリームの内部のデータを調べないので、JoltクライアントとCARRAYサービスのデータ形式を一致させるのはプログラマ側の役割になります。リスト4-3の例では、セッション・オブジェクトがすでにインスタンス化されていることが前提となっています。
リスト4-3 CARRAYバッファ・タイプの例
/* Copyright 1996 Oracle Systems, Inc. All Rights Reserved */
/* This code fragment illustrates how Jolt works with a service
* whose buffer type is CARRAY.
*/
import java.io.*;
import bea.jolt.*;
class ...
{
...
public void tryOnCARRAY()
{
byte data[];
JoltRemoteService csvc;
DataInputStream din;
DataOutputStream dout;
ByteArrayInputStream bin;
ByteArrayOutputStream bout;
/*
* Use java.io.DataOutputStream to put data into a byte array
*/
bout = new ByteArrayOutputStream(512);
dout = new DataOutputStream(bout);
dout.writeInt(100);
dout.writeFloat((float) 300.00);
dout.writeUTF("Hello World");
dout.writeShort((short) 88);
/*
* Copy the byte array into a new byte array "data". Then
* issue the Jolt remote service call.
*/
data = bout.toByteArray();
csvc = new JoltRemoteService("ECHO", session);
csvc.setBytes("CARRAY", data, data.length);
csvc.call(null);
/*
* Get the result from JoltRemoteService object and use
* java.io.DataInputStream to extract each individual value
* from the byte array.
*/
data = csvc.getBytesDef("CARRAY", null);
if (data != null)
{
bin = new ByteArrayInputStream(data);
din = new DataInputStream(bin);
System.out.println(din.readInt());
System.out.println(din.readFloat());
System.out.println(din.readUTF());
System.out.println(din.readShort());
}
}
}
 
FMLバッファ・タイプを使用する
FML (フィールド操作言語)は、型付きバッファとして使用できる柔軟性のあるデータ構造です。FMLは、タグ付きの値を格納するデータ構造です。このタグ付きの値には型が付いており、長さを変更することができ、複数のオカレンスを持つ場合があります。FMLでは、型付きバッファを抽象的なデータ型として扱います。
FML操作を用いると、データ構造やデータの格納方法を知らなくても、データに対してアクセスしたり、更新を行うことができます。アプリケーション・プログラムでは、単に識別子を使ってフィールド化されたバッファのフィールドにアクセスしたり更新するだけで済みます。操作の実行時には、FMLのランタイム・システムによってフィールドの場所と操作を行うデータ型が決定されます。
FMLは、クライアントとサーバーがそれぞれ別のコード(Java言語とC言語など)で記述されている場合、プラットフォームで扱われるデータ型の仕様が異なる場合、またはクライアント/サーバー間のインタフェースが頻繁に変わる場合のJoltクライアントでの使用に特に適しています。
次のtryOnFmlは、FMLバッファ・タイプの使用方法を示しています。この例では、FMLバッファを使用するJoltクライアントがサーバーにデータを渡す様子を示しています。サーバーはバッファを取得し、データを格納するための新しいFMLバッファを作成し、バッファをJoltクライアントに返します。以下は、サンプル・コードの説明です。
「tryOnFml.javaのサンプル・コード」は、PASSFMLサービスを持つJoltクライアントの例。
「tryOnFml.f16のフィールド定義」は、PASSFMLサービスで使用されるOracle TuxedoのFMLフィールドの定義表の例。
「tryOnFml.cのサンプル・コード」は、Joltクライアントから送信されたデータを処理するサーバー側のCコードを含むサーバー・コードの一部。
tryOnFml.javaクライアント・コード
リスト4-4内のJavaコードtryOnFml.javaは、FMLバッファ・タイプが設定されたサービスがJoltでどのように動作するかを示しています。この例では、セッション・オブジェクトがすでにインスタンス化されていることが前提となっています。
リスト4-4 tryOnFml.javaのサンプル・コード
/* Copyright 1997 Oracle Systems, Inc. All Rights Reserved */

import bea.jolt.*;
class ...
{
...
public void tryOnFml ()
{
JoltRemoteService passFml;
String outputString;
int outputInt;
float outputFloat;
...
passFml = new JoltRemoteService("PASSFML",session);
passFml.setString("INPUTSTRING", "John");
passFml.setInt("INPUTINT", 67);
passFml.setFloat("INPUTFLOAT", (float)12.0);
passFml.call(null);
outputString = passFml.getStringDef("OUTPUTSTRING", null);
outputInt = passFml.getIntDef("OUTPUTINT", -1);
outputFloat = passFml.getFloatDef("OUTPUTFLOAT", (float)-1.0);
System.out.print("String =" + outputString);
System.out.print(" Int =" + outputInt);
System.out.println(" Float =" + outputFloat);
}
}
 
FMLフィールド定義
次の「tryOnFml.f16のフィールド定義」は、「tryOnFml.javaのサンプル・コード」のFMLフィールド定義を示しています。
リスト4-5 tryOnFml.f16のフィールド定義
#
# FML field definition table
#
*base 4100
INPUTSTRING 1 string
INPUTINT 2 long
INPUTFLOAT 3 float
OUTPUTSTRING 4 string
OUTPUTINT 5 long
OUTPUTFLOAT 6 float
 
リポジトリ・エディタでPASSFMLを定義する
BULKPKGパッケージには、PASSFMLサービスが含まれており、tryOnFml.javaおよびtryOnFml.cのコードで使用されます。tryOnFml.javaの例を実行する前に、メタデータ・リポジトリ・エディタでPASSFMLサービスを変更する必要があります(例については、「リポジトリ・エディタでTOUPPERサービスを定義する」を参照)。
tryOnFml.cサーバー・コード
リスト4-6に、FMLバッファ・タイプを使用するためのサーバー側のコードを示します。PASSFMLサービスは入力FMLバッファを読み取り、FMLバッファを出力します。
リスト4-6 tryOnFml.cのサンプル・コード
/*
* tryOnFml.c
*
* Copyright (c) 1997 Oracle Systems, Inc. All rights reserved
*
* Contains the PASSFML Oracle Tuxedo server.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <malloc.h>
#include <math.h>
#include <string.h>
#include <fml.h>
#include <fml32.h>
#include <Usysflds.h>
#include <atmi.h>
#include <userlog.h>
#include "tryOnFml.f16.h"
/*
* PASSFML service reads in a input fml buffer and outputs a fml buffer.
*/
void
PASSFML( TPSVCINFO *rqst )
{
FLDLEN len;
FBFR *svcinfo = (FBFR *) rqst->data;
char inputString[256];
long inputInt;
float inputFloat;
FBFR *fml_ptr;
int rt;
if (Fget(svcinfo, INPUTSTRING, 0, inputString, &len) < 0) {
(void)userlog("Fget of INPUTSTRING failed %s",
Fstrerror(Ferror));
tpreturn(TPFAIL, 0, rqst->data, 0L, 0);
}
if (Fget(svcinfo, INPUTINT, 0, (char *) &inputInt, &len) < 0) {
(void)userlog("Fget of INPUTINT failed %s",Fstrerror(Ferror));
tpreturn(TPFAIL, 0, rqst->data, 0L, 0);
}
if (Fget(svcinfo, INPUTFLOAT, 0, (char *) &inputFloat, &len) < 0) {
(void)userlog("Fget of INPUTFLOAT failed %s",
Fstrerror(Ferror));
tpreturn(TPFAIL, 0, rqst->data, 0L, 0);
}
/* We could just pass the FML buffer back as is, put lets */
/* store it into another FML buffer and pass it back. */
if ((fml_ptr = (FBFR *)tpalloc("FML",NULL,rqst->len))==(FBFR *)NULL) {
(void)userlog("tpalloc failed in PASSFML %s",
tpstrerror(tperrno));
tpreturn(TPFAIL, 0, rqst->data, 0L, 0);
}
if(Fadd(fml_ptr, OUTPUTSTRING, inputString, (FLDLEN)0) == -1) {
userlog("Fadd failed with error: %s", Fstrerror(Ferror));
tpfree((char *)fml_ptr);
tpreturn(TPFAIL, 0, NULL, 0L, 0);
}
if(Fadd(fml_ptr, OUTPUTINT, (char *)&inputInt, (FLDLEN)0) == -1) {
userlog("Fadd failed with error: %s", Fstrerror(Ferror));
tpfree((char *)fml_ptr);
tpreturn(TPFAIL, 0, NULL, 0L, 0);
}
if(Fadd(fml_ptr, OUTPUTFLOAT, (char *)&inputFloat, (FLDLEN)0) == -1) {
userlog("Fadd failed with error: %d\n", Fstrerror(Ferror));
tpfree((char *)fml_ptr);
tpreturn(TPFAIL, 0, NULL, 0L, 0);
}
tpreturn(TPSUCCESS, 0, (char *)fml_ptr, 0L, 0);
}
 
VIEWバッファ・タイプを使用する
VIEWはOracle Tuxedo組込みのバッファ型です。VIEWは、Oracle TuxedoシステムでC構造体およびCOBOLレコードを使用するために提供されています。この型付きバッファにより、Oracle Tuxedoのランタイム・システムは、実行時に読み込まれるview記述に基づいてCの構造体やCOBOLのレコードのフォーマットを認識します。
VIEWを割り当てると、アプリケーションはバッファ・タイプとしてVIEWを指定し、viewの名前(view記述ファイル内の名前)を示すサブタイプを指定します。また、パラメータ名とview内のフィールド名は一致していなければなりません。Oracle Tuxedoのランタイム・システムは構造体のサイズに応じて必要な空間を割り当てるため、アプリケーション側でバッファ長を指定する必要はありません。また、ランタイム・システムは、リクエストまたはレスポンスの際に送信されるデータ量の計算や、異なるマシン間で送受信されるメッセージのエンコードやデコードを自動的に行います。
次は、Joltクライアントとサーバー側アプリケーションがある環境でのVIEWバッファ・タイプの使い方の例です。
「simpview.javaのサンプル・コード」は、Oracle Tuxedoに接続するためのコードが記述されたJoltクライアント・コード。バッファ・タイプとしてVIEWが指定されています。
「simpview.v16のフィールド定義」には、Oracle TuxedoのVIEWフィールド定義が記述されています。
「simpview.cのサンプル・コード」には、Joltクライアントからの入力情報を処理するサーバー側のCコードが記述されています。
Joltクライアントでは、VIEWバッファの文字列に含まれるnull文字は行末文字として扱われ、null文字の後の文字列は切り捨てられます。
リポジトリ・エディタでVIEWを定義する
simpview.javaおよびsimpview.cの例を実行する前に、メタデータ・リポジトリ・エディタでSIMPVIEWサービスを定義する必要があります(例については、「リポジトリ・エディタでTOUPPERサービスを定義する」を参照)。
simpview.javaクライアント・コード
「simpview.javaのサンプル・コード」は、VIEWバッファ・タイプが指定されたサービスがJoltでどのように動作するかを示しています。クライアント・コードは、FMLサービスにアクセスするときに使用されるコードと同じです。
注意:
次のリスト内のコードでは、例外は取得されません。Jolt例外はすべてjava.lang.RunTimeExceptionに由来するため、アプリケーションが例外を取得しない場合はJava仮想マシン(JVM)によって捕捉されます。(よいアプリケーションは、これらの例外を捕捉して適切な処理を行います。)
次のリストに示す例を実行する前に、メタデータ・リポジトリ・エディタを使用してSIMPAPPパッケージにVIEWサービスを追加し、Oracle Tuxedoアプリケーションsimpview.cを記述する必要があります。このサービスは、クライアントのVIEWバッファからデータを取り出し、新しいバッファを作成して、新しいVIEWバッファとしてクライアントに返します。次の例では、セッション・オブジェクトがすでにインスタンス化されていることを想定しています。
リスト4-7 simpview.javaのサンプル・コード
/* Copyright 1997 Oracle Systems, Inc. All Rights Reserved */
/*
* This code fragment illustrates how Jolt works with a service whose buffer
* type is VIEW.
*/
import bea.jolt.*;
class ...
{
...
public void simpview ()
{
JoltRemoteService ViewSvc;
String outString;
int outInt;
float outFloat;
// Create a Jolt Service for the Oracle Tuxedo service "SIMPVIEW"
ViewSvc = new JoltRemoteService("SIMPVIEW",session);
// Set the input parameters required for SIMPVIEW
ViewSvc.setString("inString", "John");
ViewSvc.setInt("inInt", 10);
ViewSvc.setFloat("inFloat", (float)10.0);
// Call the service. No transaction required, so pass
// a "null" parameter
ViewSvc.call(null);
// Process the results
outString = ViewSvc.getStringDef("outString", null);
outInt = ViewSvc.getIntDef("outInt", -1);
outFloat = ViewSvc.getFloatDef("outFloat", (float)-1.0);
// And display them...
System.out.print("outString=" + outString + ",");
System.out.print("outInt=" + outInt + ",");
System.out.println("outFloat=" + outFloat);
}
}
 
VIEWフィールド定義
「simpview.v16のフィールド定義」は、前記のリストsimpview.javaのOracle Tuxedo VIEWフィールド定義を示しています。
リスト4-8 simpview.v16のフィールド定義
#
# VIEW for SIMPVIEW. This view is used for both input and output. The
# service could also have used separate input and output views.
# The first 3 params are input params, the second 3 are outputs.
#
VIEW SimpView
$
#type cname fbname count flag size null
string inString - 1 - 32 -
long inInt - 1 - - -
float inFloat - 1 - - -
string outString - 1 - 32 -
long outInt - 1 - - -
float outFloat - 1 - - -
END
 
simpview.cサーバー・コード
リスト4-9では、入力バッファ・タイプと出力バッファ・タイプはVIEWです。このコードは、VIEWバッファ・タイプの入力データを受け入れ、同じVIEWバッファ・タイプのデータを出力します。
リスト4-9 simpview.cのサンプル・コード
/*
* SIMPVIEW.c
*
* Copyright (c) 1997 Oracle Systems, Inc. All rights reserved
*
* Contains the SIMPVIEW Oracle Tuxedo server.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <malloc.h>
#include <math.h>
#include <string.h>
#include <fml.h>
#include <fml32.h>
#include <Usysflds.h>
#include <atmi.h>
#include <userlog.h>
#include "simpview.h"
/*
* Contents of simpview.h.
*
*struct SimpView {
*
* char inString[32];
* long inInt;
* float inFloat;
* char outString[32];
* long outInt;
* float outFloat;
*};
*/
/*
* service reads in a input view buffer and outputs a view buffer.
*/
void
SIMPVIEW( TPSVCINFO *rqst )
{
/*
* get the structure (VIEWSVC) from the TPSVCINFO structure
*/
struct SimpView *svcinfo = (struct SimpView *) rqst->data;
/*
* print the input params to the UserLog. Note there is
* no error checking here. Normally a SERVER would perform
* some validation of input and return TPFAIL if the input
* is not correct.
*/
(void)userlog("SIMPVIEW: InString=%s,InInt=%d,InFloat=%f",
svcinfo->inString, svcinfo->inInt, svcinfo->inFloat);
/*
* Populate the output fields and send them back to the caller
*/

strcpy (svcinfo->outString, "Return from SIMPVIEW");
svcinfo->outInt = 100;
svcinfo->outFloat = (float) 100.00;
/*
* If there was an error, return TPFAIL
* tpreturn(TPFAIL, ErrorCode, (char *)svcinfo, sizeof (*svcinfo), 0);
*/
tpreturn(TPSUCCESS, 0, (char *)svcinfo, sizeof (*svcinfo), 0);
}
XMLバッファ・タイプを使用する
XMLバッファ・タイプを使用すると、Oracle TuxedoアプリケーションでXMLドキュメントを使用して、アプリケーション内やアプリケーション間でデータを交換できるようになります。Oracle Tuxedoアプリケーションでは、XML型バッファをお送受信したり、それらのバッファを適切なサーバーにルーティングできます。解析など、XMLドキュメントのすべての処理ロジックはアプリケーション側にあります。
整形式のXMLドキュメントは、次の要素から構成されます。
表題、タグなどを含む、エンコードされた文字の並びで構成されるテキスト
ドキュメントの論理構造の記述と、その構造に関する情報
XMLバッファ・タイプを使用するには、まずバッファ・タイプで使用するTuxedoサービスを定義します。次に、そのバッファ・タイプを使用するコードを記述します。次の2つの項では、これらの手順について説明します。
注意:
CARRAY同様に、XMLバッファ・タイプはSTRINGではなくバイト配列として扱われます。JoltクライアントとOracle Tuxedoサービス間でのデータ変換は行われません。
リポジトリ・エディタでTuxedoサービスを定義する
例を実行する前に、TuxedoのXMLサービスを作成し、起動する必要があります。XMLサービスは、バッファを取得し、Joltクライアントに返します。メタデータ・リポジトリ・エディタでXMLサービスを定義する必要があります(例については、「リポジトリ・エディタでTOUPPERサービスを定義する」を参照)。
simpxml.javaクライアント・コード
次のリスト内のコードは、XMLバッファ・タイプが設定されたサービスがJoltでどのように動作するかを示しています。JoltはXMLデータ・ストリームの内部のデータを調べないので、JoltクライアントとXMLサービスのデータ形式を一致させるのはプログラマ側の役割になります。リスト4-10の例では、セッション・オブジェクトがすでにインスタンス化されていることが前提となっています。
リスト4-10 XMLバッファ・タイプの例
/* Copyright 2001 Oracle Systems, Inc. All Rights Reserved */
/*
* This code fragment illustrates how Jolt works with a service whose buffer
* type is XML.
*/
import java.io.*;
import java.lang.*;
import bea.jolt.*;
public class xmldoc {
public static void main (String[] args) {
JoltSessionAttributes sattr;
JoltSession session;
JoltRemoteService echo_xml;
String inString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><ORDER><HEADER DATE=\"05/13/1999\" ORDERNO=\"22345\"/><COMPANY>ACME</COMPANY><LINE><ITEM MODEL=\"Pabc\" QUANTITY=\"5\">LAPTOP</ITEM></LINE><LINE><ITEM MODEL=\"P500\" QUANTITY=\"15\">LAPTOP</ITEM></LINE></ORDER>";
byte data[];
DataInputStream din;
DataOutputStream dout;
ByteArrayInputStream bin;
ByteArrayOutputStream bout;
byte odata[];
String outString = null;
String appAddress = null;
//...Create Jolt Session
try {
/*
* Use java.io.DataOutputStream to put data
* into a byte array
*/
bout = new ByteArrayOutputStream(inString.length());
dout = new DataOutputStream(bout);
dout.writeBytes(inString);
/*
* Copy the byte array into a new byte array "data".
* Then issue the Jolt remote service call.
*/
data = bout.toByteArray();
} catch (Exception e) {
System.out.println("toByteArray error");
return;
}
try {
echo_xml = new JoltRemoteService("ECHO_XML", session);
System.out.println("JoltRemoteService Created");
echo_xml.setBytes("XML", data, data.length);
} catch (Exception e) {
System.out.println("RemoteService call error" + e);
return;
}
echo_xml.call(null);
System.out.println("Service Call Returned");
odata = echo_xml.getBytesDef("XML", null);
try {
System.out.println("Return String is:" + new String(odata));
} catch (Exception e) {
System.err.println("getByteDef Error");
}
}
}
// end of class
 
MBSTRINGバッファ・タイプを使用する
Tuxedo 9.0以降、JoltではMBSTRINGバッファ・タイプがサポートされています(Tuxedo ATMIではTuxedo 8.1以降ですでにサポートされています)。
Javaではマルチ・バイト文字のエンコーディングの標準としてUnicodeが使用され、Unicodeの文字列データ用にStringクラスが提供されているので、Jolt MBSTRINGのサポートではJavaクライアント側のMBSTRINGコンテナとしてStringクラスが使用されます。Joltでは、JoltクライアントとTuxedoサーバーの間でデータが転送されるときに、Stringオブジェクト内のUnicode MBSTRINGデータがバイト配列MBSTRINGデータ(ATMIのMBSTRING表現)に、またはその逆に自動的に変換されます。
次の各メソッドが、bea.jolt.Messageインタフェース、bea.jolt.JoltMessageクラスおよびbea.jolt.JoltRemoteServiceクラスに追加されています。
addMBString
setMBString
setMBStringItem
getMBStringDef
getMBStringItemDef
MBSTRINGバッファ・タイプの使用方法はSTRINGバッファ・タイプとほとんど同じですが、メタデータ・リポジトリ・エディタで指定されるバッファ・タイプはMBSTRINGで、MBSTRINGデータを取得および設定するためのJavaメソッドは前述のメソッドです。
さらに、次のJavaシステム・プロパティは、Tuxedoサーバーに送信されるMBSTRINGデータの文字エンコーディング名を指定するために使用されます。
bea.jolt.mbencoding
MBSTRINGデータをTuxedoサーバーに送信するときに、Unicode MBSTRINGデータを対応するバイト配列MBSTRINGデータに変換するために使用されるTuxedoエンコーディング名。このプロパティが指定されていない場合、Javaのデフォルトの文字エンコーディング名が使用され、対応するTuxedoエンコーディング名にマップされます。たとえば、デフォルトの日本語版Windowsのエンコーディング名MS932は、対応するTuxedoエンコーディング名CP932にマップされ、このプロパティ内に指定されます。
bea.jolt.mbencodingmap
JoltクライアントとTuxedoサーバー間の文字エンコーディング名のマッピングを指定するファイルのフル・パス名。このマッピングが必要なのは、同じ文字エンコーディングの文字エンコーディング名がJavaとTuxedoで異なる場合があるためです。たとえば、デフォルトの日本語版Windowsのエンコーディング名は、JavaではMS932ですが、TuxedoではCP932です。このプロパティを指定しない場合、マッピングは行われません。
つまり、Java文字エンコーディング名が、Tuxedoサーバーに送信されるMBSTRINGデータに直接設定され、Tuxedoサーバーから受信したMBSTRINGデータ内に設定されているエンコーディング名がJavaエンコーディング名として使用されます。そのエンコーディング名がJavaまたはTuxedoでサポートされていない場合、変換エラーが発生する場合があります。
bea.jolt.mbencodingまたはbea.jolt.mbencodingmapを指定するには、jolti18n.jarCLASSPATHに追加する必要があります。jolti18n.jarCLASSPATHに存在しない場合、エンコーディング名はISO-8859-1に設定され、Javaコマンド行でこれらのプロパティを指定しても、JavaとTuxedoの間でエンコーディング名のマッピングは行われません。
マルチスレッド・アプリケーション
Javaベースのクラス・セットであるJoltでは、マルチスレッド・アプリケーションをサポートしていますが、Java言語の様々な実装は特定の言語および環境の機能によって異なります。Joltのプログラマは、次のことを知っておく必要があります。
Joltクラス・ライブラリを使用してアプリケーションやアプレットを作成するときのプリエンプティブなスレッドとノンプリエンプティブなスレッドの使用方法。
非同期的な動作を取得するためのスレッドの使用方法(Oracle Tuxedoのtpacall()機能に類似)。
「スレッドの状態の種類」では、様々なJava実装でスレッドを使用する際に発生する問題について説明し、Joltプログラムでのスレッドの使用例を示します。
注意:
ほとんどのJava実装では、ノンプリエンティブなスレッドではなくプリエンプティブなスレッドが使用されます。プリエンティブなスレッドとノンプリエンティブなスレッドでは、パフォーマンスやプログラミングの要件が大きく異なります。
スレッドの状態の種類
Java仮想マシンで同時に実行される個々のタスクは、スレッドです。スレッドの主要な状態には、RUNNING、RUNNABLEおよびBLOCKEDがあります。
RUNNINGスレッドは、現在実行中のスレッドです。
RUNNABLEスレッドは、現在のスレッドがCPUの制御を放棄すると実行可能になります。RUNNABLE状態のスレッドは多数存在できますが、RUNNING状態のスレッドは1つしか存在できません。スレッドを実行するということは、スレッドの状態をRUNNABLEからRUNNINGに変更し、そのスレッドがJava仮想マシン(VM)を制御するようになることを意味します。
BLOCKEDスレッドは、イベントまたはリソースが使用可能になるのを待機しているスレッドです。
注意:
Java仮想マシン(VM)は、優先度が同じスレッドがラウンドロビン・モードで実行されるようスケジュールします。
プリエンプティブなスレッド
2つのスレッド・モデルの主要なパフォーマンス上の違いは、実行中のスレッドにJava仮想マシン(VM)の制御を放棄するよう指示するかどうかにあります。プリエンプティブなスレッド環境では通常、ハードウェアのタイマーが定期的にオフになるように設定します。タイマーがオフになると現在のスレッドの状態がRUNNINGからRUNNABLEになり、かわって別のスレッドが選択されて実行されます。
ノンプリエンプティブなスレッド
ノンプリエンプティブなスレッド環境においては、スレッドは自発的にCPUの制御を放棄し、RUNNABLEな状態に移行します。Java言語クラス内の多くのメソッドには、制御を自発的に放棄するコードが含まれており、通常は長い処理時間のかかる操作に関連付けられています。たとえば、ネットワークからデータを読み取ると、スレッドは通常パケットの到着を待機します。イベントやリソースが使用可能になるまで待機するスレッドは、BLOCKED状態になります。イベントが発生するか、リソースが使用可能になると、そのスレッドはRUNNABLEになります。
Joltをノンプリエンプティブなスレッドで使用する
ノンプリエンプティブなスレッドを使用する仮想マシン(Sun Solarisなど)でJoltベースのJavaプログラムを実行する場合、プログラムで次のいずれかが行われる必要があります。
スレッドをブロックするメソッドをときどきコールします。
Thread.yield()メソッドを使用して、CPUの制御を明示的に放棄します。
通常は、実行するコードが長い部分または時間がかかりそうなループすべてで次のコールを行います。
Thread.currentThread.yield();
このメッセージを送信しないと、Joltライブラリで使用されるスレッドはスケジューリングされず、Jolt操作に不具合が生じます。
ノンプリエンプティブなスレッドを使用する仮想マシンとして知られている唯一のマシンは、Sunプラットフォーム用のJava Developer's Kit (JDK)です。アプレットをJDK 1.3で実行するには、yieldメッセージを必ず送信してください。すでに述べたように、メソッドの中にはyieldを含むものがあります。例外はSystem.in.readメソッドです。このメッセージはスレッドの切替えを行いません。これらのメッセージを使用するかわりに、yieldを明示的に使用することをお薦めします。
非同期的な処理を行うためにスレッドを使用する
スレッドを使用して、Oracle Tuxedoのtpacall()に似た非同期的な処理をJoltで行うことができます。この機能があれば、非同期的にサービスをリクエストする機能は必要ありません。この機能が使えるのはJoltがスレッド・セーフであるためです。たとえば、Joltクライアント・アプリケーションは、Oracle Tuxedoサービスにリクエストを送信するスレッドを開始した後で直ちにOracle Tuxedoサービスに別のリクエストを送信する別のスレッドを開始することができます。したがって、Joltによるtpacall()の呼出しが同期的であっても、2つのスレッドが同時に実行されているため、アプリケーションは非同期的です。
Joltでスレッドを使用する
Joltクライアント側のプログラムまたはアプレットは完全にスレッド・セーフです。Joltがサポートするマルチスレッド・アプリケーションでは、クライアント側に次の特徴があります。
1つのクライアントに対して複数のセッションがある
1つのセッションがマルチスレッドである
クライアント・アプリケーションは、非同期呼出しのかわりにスレッドを管理する
同期呼出しを実行する
リスト4-11に、Joltアプリケーションで2つのスレッドを使用する方法を示します。
リスト4-11 Joltでマルチスレッドを使用する(ThreadBank.java)
/* Copyright 1996 Oracle Systems, Inc. All Rights Reserved */
import bea.jolt.*;
public class ThreadBank
{
public static void main (String [] args)
{
JoltSession session;
try
{
JoltSessionAttributes dattr;
String userName = null;
String userPasswd = null;
String appPasswd = null;
String userRole = null;
// fill in attributes required
dattr = new JoltSessionAttributes();
dattr.setString(dattr.APPADDRESS,���//bluefish:8501���);
// instantiate domain
// check authentication level
switch (dattr.checkAuthenticationLevel())
{
case JoltSessionAttributes.NOAUTH:
System.out.println(���NOAUTH\n���);
break;
case JoltSessionAttributes.APPASSWORD:
appPasswd = ���myAppPasswd���;
break;
case JoltSessionAttributes.USRPASSWORD:
userName = ���myName���;
userPasswd = ���mySecret���;
appPasswd = ���myAppPasswd���;
break;
}
dattr.setInt(dattr.IDLETIMEOUT, 60);
session = new JoltSession (dattr, userName, userRole,
userPasswd, appPasswd);
T1 t1 = new T1 (session);
T2 t2 = new T2 (session);
t1.start();
t2.start();
Thread.currentThread().yield();
try
{
while (t1.isAlive() && t2.isAlive())
{
Thread.currentThread().sleep(1000);

}
}
catch (InterruptedException e)
{
System.err.println(e);
if (t2.isAlive())
{
System.out.println(���job 2 is still alive���);
try
{
Thread.currentThread().sleep(1000);
}
catch (InterruptedException e1)
{
System.err.println(e1);
}
}
else if (t1.isAlive())
{ System.out.println(���job1 is still alive���);
try
{
Thread.currentThread().sleep(1000);
}
catch (InterruptedException e1)
{
System.err.println(e1);
}
}
}
session.endSession();
}
catch (SessionException e)
{
System.err.println(e);
}
finally
{
System.out.println(���normal ThreadBank term���);
}
}
}

class T1 extends Thread
{
JoltSession j_session;
JoltRemoteService j_withdrawal;
public T1 (JoltSession session)
{
j_session=session;
j_withdrawal= new JoltRemoteService(���WITHDRAWAL���,j_session);
}
public void run()
{
j_withdrawal.addInt(���ACCOUNT_ID���,10001);
j_withdrawal.addString(���SAMOUNT���,���100.00���);
try
{
System.out.println(���Initiating Withdrawal from account 10001���);
j_withdrawal.call(null);
String W = j_withdrawal.getStringDef(���SBALANCE���,���-1.0���);
System.out.println(���-->Withdrawal Balance: ��� + W);
}
catch (ApplicationException e)
{
e.printStackTrace();
System.err.println(e);
}
}
}
class T2 extends Thread
{
JoltSession j_session;
JoltRemoteService j_deposit;
public T2 (JoltSession session)
{
j_session=session;
j_deposit= new JoltRemoteService(���DEPOSIT���,j_session);
}
public void run()
{
j_deposit.addInt(���ACCOUNT_ID���,10000);
j_deposit.addString(���SAMOUNT���,���100.00���);
try
{
System.out.println(���Initiating Deposit from account 10000���);
j_deposit.call(null);
String D = j_deposit.getStringDef(���SBALANCE���,���-1.0���);
System.out.println(���-->Deposit Balance: ��� + D);
}
catch (ApplicationException e)
{
e.printStackTrace();
System.err.println(e);
}
}
}
 
イベント・サブスクリプションおよびイベント通知
Joltを使用してクライアント・アプリケーションを開発するプログラマは、Oracle TuxedoサービスまたはほかのOracle Tuxedoクライアントからイベント通知を受信することができます。Joltクラス・ライブラリには、イベントに基づく通信を処理するため、次のOracle Tuxedo通知をサポートするクラスが用意されています。
非請求イベント通知 - これは、Oracle Tuxedoのクライアントかサービスが、tpbroadcast()を呼び出してブロードキャストを発行するか、またはATMI呼出しのtpnotify()を使用してJoltクライアント宛てに直接ターゲット指定されたメッセージを送信した結果、Joltクライアントが受信する通知です。
ブローカ経由のイベント通知 - JoltクライアントがOracle Tuxedoイベント・ブローカ経由で受信する通知です。これらの通知は、Joltクライアントがイベントをサブスクライブしており、かつ、任意のOracle Tuxedoクライアントかサーバーがシステム通知イベントを発行するか、またはtppost()呼出しを発行する場合にのみ受信されます。
イベント・サブスクリプション用のクラス
Joltクラス・ライブラリには、Joltクライアント・アプリケーション用の非同期通知メカニズムを実装するための4つのクラスが用意されています。
JoltSession - JoltSessionクラスには、通知およびメッセージを受信するonReply()メソッドが用意されています。
JoltReply - JoltReplyクラスを使用すると、クライアント・アプリケーションからイベントや通知とともに受信したメッセージにアクセスできます。
JoltMessage - JoltMessageクラスには、通知またはイベントに関する情報を取得するためのget()メソッドが用意されています。
JoltUserEvent - JoltUserEventクラスは、非請求メッセージとイベント通知の両方のサブスクリプションをサポートします。
これらのクラスについては、Oracle Jolt APIリファレンスを参照してください。
通知イベント・ハンドラ
Joltクライアント・アプリケーションでは、非請求メッセージとブローカ経由のイベント通知の両方に対してイベント・ハンドラ・ルーチン(通知の受信時に呼び出される)が必要になります。Joltでは、1セッションでサポートされるハンドラは1つです。Oracle Tuxedoでは、通知の生成元であるイベントを特定することはできません。したがって、特定のイベントが発生したときに、そのイベント特有のハンドラを呼び出すことはできません。
クライアント・アプリケーション側では、セッションごとに1つのハンドラを用意(onReply()メソッドをオーバーライド)し、そのセッションでクライアントが受信するすべての通知に対して呼び出されるようにしなければなりません。単一ハンドラによるコールバック関数は、非請求とイベント通知型の両方で使用されます。ハンドラ呼出しの原因となったイベントを特定し、適切な措置を取ることは(ユーザー定義の)ハンドラ・ルーチンの役割です。ユーザーがセッション・ハンドラをオーバーライドしないと、通知メッセージはデフォルトのハンドラによって暗黙のうちに廃棄されます。
Joltクライアントは、JoltSessionクラスのサブクラスを作成し、onReply()メソッドをユーザー定義されたonReply()メソッドでオーバーライドすることによって、コールバック関数を提供します。
Oracle Tuxedo/ATMIクライアントでは、ハンドラ・コールバック関数内では、ATMI呼出しのサブセットしか使用することができません。この制約は、Joltクライアントには適用されません。別々のスレッドを使用して、通知をモニターし、イベント・ハンドラ・メソッドを実行します。Joltがサポートするすべての機能をハンドラ内から実行することが可能です。Joltクライアント・プログラムに適用される通常の規則(1セッションにつき1トランザクションなど)は、すべてハンドラにも適用されます。
ハンドラ・メソッドの呼出しは、独立したスレッド内で行われます。別々のスレッドがonReply()メソッドを同時に実行しないようにするため、アプリケーション開発者は必ずそのメソッドにsynchronizedキーワードを付けるか、またはそのメソッドがスレッド・セーフになるように記述します。
Joltでは、ハンドラ・ルーチンを有効にする暗黙的なモデルが使用されます。クライアントがイベントをサブスクライブすると、Joltはそのクライアントのハンドラを内部で有効にしますが、その結果、非請求メッセージの受信も有効になります。Joltクライアントがイベント通知をサブスクライブする場合は、同時に必ず非請求メッセージも受信します。さらに、これらの2種類の通知に対して、単一のonReply()メソッドが呼び出されます。
接続モード
Joltは、コネクション保持モードまたはコネクションレス・モードで稼動しているクライアントの通知の受信をサポートします。コネクション保持モード(RETAINED)のクライアントは、すべての通知を受信します。コネクションレス・モードで動作するJoltクライアントは、Joltセッション・ハンドラ(JSH)へのネットワーク接続がアクティブな間は通知を受信します。ネットワーク接続が切断されている場合、JSHはクライアント宛ての通知のログを記録し、その通知を廃棄します。コネクションレス・モードで稼動しているJoltクライアントは、ネットワーク接続がアクティブでない間は非請求メッセージまたはイベント通知を受信しません。この間に受信されたメッセージは、JSHによって記録され、廃棄されます。
接続モードでの通知処理には、Oracle Tuxedo環境でのJoltクライアントへの確認付きメッセージ通知の処理も含まれます。JSHがクライアントへの確認付きメッセージ通知を受信し、そのクライアントに対してアクティブなネットワーク接続が確立されていない場合、JSHはエラーのログを記録し、通知メッセージに対して失敗を示す確認を返します。
通知データ・バッファ
クライアントが通知を受信する場合、通知にはデータ・バッファが付随しています。データ・バッファはどのOracle Tuxedoデータ・バッファ・タイプでもかまいません。Joltクライアント(ハンドラ)はこれらのバッファをJoltMessageオブジェクトとして受信し、適切なJoltMessageクラスのget*()メソッドを使用してこのオブジェクトからデータを取り出します。
Oracle Tuxedoサービス・メタデータ・リポジトリには、通知に使用されるバッファの定義は必要ありません。ただし、Joltクライアント・アプリケーションのプログラマは、フィールド名を知っておく必要があります。
Joltシステムには、Oracle Tuxedoのtptypes()と同様の機能はありません。FMLおよびVIEWのバッファ型の場合は、適切なフィールド名を指定してget*()メソッドを使用してデータにアクセスします。たとえば、次のように入力します。
getIntDef ("ACCOUNT_ID", -1);
STRINGおよびCARRAYのバッファ・タイプの場合は、バッファ・タイプと同じ名前でデータにアクセスします。たとえば、次のように入力します。
getStringDef ("STRING", null);
getBytesDef ("CARRAY", null);
STRINGとCARRAYのバッファ型には、単一のデータ要素しか含まれていません。この要素全体は、get*()メソッドで返されます。
Oracle Tuxedoのイベント・サブスクリプション
Oracle Tuxedoのブローカ経由のイベント通知により、Oracle Tuxedoプログラムは、どのプログラムがイベントの発生通知を受信するかを気にしないで、イベントをポストすることができます。また、Joltのイベント通知機能により、Joltクライアント・アプリケーションは、Oracle Tuxedoのtpnotify()またはtpbroadcast()を呼び出してブロードキャストまたはポストされるOracle Tuxedoイベントをサブスクライブすることができます。
Joltクライアントがサブスクライブできるのは、Oracle Tuxedoの他のコンポーネントによって生成されたイベントまたはメッセージ通知(Oracle Tuxedoのサービスまたはクライアントなど)のみです。Joltクライアントは、イベントまたはメッセージ通知を送信することはできません。
サポートされているサブスクリプションの種類
Joltでは、メッセージ通知型のサブスクリプションしかサポートされません。サブスクリプションが実行されるとonReply()メソッドが呼び出されます。JoltのAPIでは、メッセージ通知の受信時にサービス・ルーチンをディスパッチしたり、アプリケーション・キューにメッセージを入れる機能はサポートされていません。
通知をサブスクライブする
Joltクライアントが単一のイベント通知をサブスクライブする場合、クライアントは、非請求メッセージとイベント通知を両方とも受信します。イベントをサブスクライブすることにより、暗黙的に非請求メッセージも利用できるようになります。つまり、たとえばアプリケーションがイベントXに対してJoltUserEventオブジェクトを作成した場合にtpnotify()またはtpbroadcast()を呼び出すと、クライアントは自分宛てのメッセージを自動的に受信します。
注意:
単一のイベント通知をサブスクライブするために非請求メッセージを用いることはお薦めしません。非請求メッセージを受信したい場合は、アプリケーション側で明示的に指定してください(JoltUserEventクラスで説明)。次の項では、通知のサブスクライブ解除について説明します。
通知をサブスクライブ解除する
イベント通知または非請求メッセージのいずれか、または両方のサブスクライブを停止するには、JoltUserEventのunsubscribeメソッドを使用する必要があります。Joltでは、unsubscribeメソッドを使用して非請求メッセージの受信を停止しても、すべてのサブスクリプション通知が停止されるわけではありません。この点がOracle Tuxedoと異なります。Oracle Tuxedoでは、NULLハンドラを指定してtpsetunsol()を呼び出すと、すべてのサブスクリプション通知が停止します。
イベントの通知をサブスクライブ解除する場合、次の点に注意してください。
クライアントが単一のイベントをサブスクライブする場合に通知をサブスクライブ解除すると、イベント通知と非請求メッセージが両方共受信されなくなります。
クライアントが複数のイベントをサブスクライブしている場合は、サブスクライブ解除対象のサブスクリプションだけが利用できなくなります。非請求メッセージは、引き続き受信されます。最後のサブスクリプションが停止されると、非請求メッセージの受信も停止されます。
クライアントが非請求メッセージとイベント通知の両方をサブスクライブしている場合は、非請求メッセージだけをサブスクライブ解除しても、どちらの通知も停止されません。さらに、このサブスクライブ解除では、例外がスローされません。ただし、Jolt API側では非請求メッセージのサブスクライブ解除を記憶しているため、残りのイベント通知をサブスクライブ解除すると、イベント通知と非請求メッセージの両方が利用できなくなります。
クライアント・アプリケーションで非請求メッセージの受信を停止したい場合は、すべてのイベントをサブスクライブ解除する必要があります。
Jolt APIを使用してOracle Tuxedoからの通知を受信する
「非同期型通知」のリストは、Joltクラス・ライブラリを使用して通知を受信する方法を示しています。ここでは、JoltSessionJoltReplyJoltMessageおよびJoltUserEventクラスが使用されています。
リスト4-12 非同期型通知
class EventSession extends JoltSession
{
public EventSession( JoltSessionAttributes attr, String user,
String role, String upass, String apass )
{
super(attr, user, role, upass, apass);
}
/**
* Override the default unsolicited message handler.
* @param reply a place holder for the unsolicited message
* @see bea.jolt.JoltReply
*/
public void onReply( JoltReply reply )
{
// Print out the STRING buffer type message which contains
// only one field; the field name must be "STRING". If the
// message uses CARRAY buffer type, the field name must be
// "CARRAY". Otherwise, the field names must conform to the
// elements in FML or VIEW.
JoltMessage msg = (JoltMessage) reply.getMessage();
System.out.println(msg.getStringDef("STRING", "No Msg"));
}
public static void main( Strings args[] )
{
JoltUserEvent  unsolEvent;
JoltUserEvent   helloEvent;
EventSession    session;
...
// Instantiate my session object which can print out the
// unsolicited messages. Then subscribe to HELLO event
// and Unsolicited Notification which both use STRING
// buffer type for the unsolicited messages.
session = new EventSession(...);

helloEvent = new JoltUserEvent("HELLO", null, session);
unsolEvent = new JoltUserEvent(JoltUserEvent.UNSOLMSG, null,
session);
...
// Unsubscribe the HELLO event and unsolicited notification.
helloEvent.unsubscribe();
unsolEvent.unsubscribe();
}
}
 
パラメータ値をクリアする
Joltクラス・ライブラリには、オブジェクトの既存の属性値を消去し、事実上オブジェクトの再利用ができるようにするclear()メソッドが用意されています。「Joltオブジェクトの再利用(reuseSample.java)」は、clear()メソッドを使用してパラメータ値をクリアする方法とJoltRemoteServiceのパラメータ値を再利用する方法を示しています。この例では、再利用するためにサービスを破棄する必要がないことを示しています。代わりに、svc.clear();文を使用して既存の入力パラメータ値を廃棄してからaddString()メソッドを再度使用しています。
リスト4-13 Joltオブジェクトの再利用(reuseSample.java)
/* Copyright 1999 Oracle Systems, Inc. All Rights Reserved */
import java.net.*;
import java.io.*;
import bea.jolt.*;
/*
* This is a Jolt sample program that illustrates how to reuse the
* JoltRemoteService after each invocation.
*/
class reuseSample
{
private static JoltSession s_session;
static void init( String host, short port )
{
/* Prepare to connect to the Tuxedo domain. */
JoltSessionAttributes attr = new JoltSessionAttributes();
attr.setString(attr.APPADDRESS,���//���+ host+���:��� + port);
String username = null;
String userrole = ���sw-developer���;
String applpasswd = null;
String userpasswd = null;
/* Check what authentication level has been set. */
switch (attr.checkAuthenticationLevel())
{
case JoltSessionAttributes.NOAUTH:
break;
case JoltSessionAttributes.APPASSWORD:
applpasswd = ���secret8���;
break;
case JoltSessionAttributes.USRPASSWORD:
username = ���myName���;
userpasswd = ���BEA#1���;
applpasswd = ���secret8���;
break;
}
/* Logon now without any idle timeout (0). */
/* The network connection is retained until logoff. */
attr.setInt(attr.IDLETIMEOUT, 0);
s_session = new JoltSession(attr, username, userrole,
userpasswd, applpasswd);
}
public static void main( String args[] )
{
String host;
short port;
JoltRemoteService svc;
if (args.length != 2)
{
System.err.println(���Usage: reuseSample host port���);
System.exit(1);
}
/* Get the host name and port number for initialization. */
host = args[0];
port = (short)Integer.parseInt(args[1]);
init(host, port);
/* Get the object reference to the DELREC service. This
* service has no output parameters, but has only one input
* parameter.
*/
svc = new JoltRemoteService(���DELREC���, s_session);
try
{
/* Set input parameter REPNAME. */
svc.addString(���REPNAME���, ���Record1���);
svc.call(null);
/* Change the input parameter before reusing it */
svc.setString(���REPNAME���, ���Record2���);
svc.call(null);
/* Simply discard all input parameters */
svc.clear();
svc.addString(���REPNAME���, ���Record3���);
svc.call(null);
}
catch (ApplicationException e)
{
System.err.println(���Service DELREC failed: ���+
e.getMessage()+��� ���+ svc.getStringDef(���MESSAGE���, null));
}
/* Logoff now and get rid of the object. */
s_session.endSession();
}
}
 
オブジェクトを再利用する
次の「Joltリモート・サービスを拡張する(extendSample.java)」は、JoltRemoteServiceクラスをサブクラス化する1つの方法を示しています。この例では、JoltRemoteServiceクラスをサブクラス化してTransferServiceクラスを作成します。TransferServiceクラスはJoltRemoteServiceクラスを拡張し、Oracle TuxedoのBANKAPPのTRANSFERサービスを利用するTransfer機能を追加しています。
リスト4-14では、Java言語のextendsキーワードが使用されています。extendsキーワードは、Javaでベース(親)クラスをサブクラス化するために使用されています。次のコードは、JoltRemoteServiceを拡張する方法の1つを示しています。
リスト4-14 Joltリモート・サービスを拡張する(extendSample.java)
/* Copyright 1999 Oracle Systems, Inc. All Rights Reserved */
import java.net.*;
import java.io.*;
import bea.jolt.*;
/*
* This Jolt sample code fragment illustrates how to customize
* JoltRemoteService. It uses the Java language ���extends��� mechanism
*/
class TransferService extends JoltRemoteService
{
public String fromBal;
public String toBal;
public TransferService( JoltSession session )
{
super(���TRANSFER���, session);
}
public String doxfer( int fromAcctNum, int toAcctNum, String amount )
{
/* Clear any previous input parameters */
this.clear();
/* Set the input parameters */
this.setIntItem(���ACCOUNT_ID���, 0, fromAcctNum);
this.setIntItem(���ACCOUNT_ID���, 1, toAcctNum);
this.setString(���SAMOUNT���, amount );
try
{
/* Invoke the transfer service. */
this.call(null);
/* Get the output parameters */
fromBal = this.getStringItemDef(���SBALANCE���, 0, null);
if (fromBal == null)
return ���No balance from Account ��� +
fromAcctNum;
toBal = this.getStringItemDef(���SBALANCE���, 1, null);
if (toBal == null)
return ���No balance from Account ��� + toAcctNum;
return null;
}
catch (ApplicationException e)
{
/* The transaction failed, return the reason */
return this.getStringDef(���STATLIN���, ���Unknown reason���);
}
}
}
class extendSample
{
public static void main( String args[] )
{
JoltSession s_session;
String host;
short port;
TransferService xfer;
String failure;
if (args.length != 2)
{
System.err.println(���Usage: reuseSample host port���);
System.exit(1);
}
/* Get the host name and port number for initialization. */
host = args[0];
port = (short)Integer.parseInt(args[1]);
/* Prepare to connect to the Tuxedo domain. */
JoltSessionAttributes attr = new JoltSessionAttributes();
attr.setString(attr.APPADDRESS,���//���+ host+���:��� + port);
String username = null;
String userrole = ���sw-developer���;
String applpasswd = null;
String userpasswd = null;
/* Check what authentication level has been set. */
switch (attr.checkAuthenticationLevel())
{
case JoltSessionAttributes.NOAUTH:
break;
case JoltSessionAttributes.APPASSWORD:
applpasswd = ���secret8���;
break;
case JoltSessionAttributes.USRPASSWORD:
username = ���myName���;
userpasswd = ���BEA#1���;
applpasswd = ���secret8���;
break;
}
/* Logon now without any idle timeout (0). */
/* The network connection is retained until logoff. */
attr.setInt(attr.IDLETIMEOUT, 0);
s_session = new JoltSession(attr, username, userrole,
userpasswd, applpasswd);
/*
* TransferService extends from JoltRemoteService and uses the
* standard Oracle Tuxedo BankApp TRANSFER service. We invoke this
* service twice with different parameters. Note, we assume
* that ���s_session��� is initialized somewhere before.
*/
xfer = new TransferService(s_session);
if ((failure = xfer.doxfer(10000, 10001, ���500.00���)) != null)
System.err.println(���Tranasaction failed: ��� + failure);
else
{
System.out.println(���Transaction is done.���);
System.out.println(���From Acct Balance: ���+xfer.fromBal);
System.out.println(��� To Acct Balance: ���+xfer.toBal);
}
if ((failure = xfer.doxfer(51334, 40343, ���$123.25���)) != null)
System.err.println(���Tranasaction failed: ��� + failure);
else
{
System.out.println(���Transaction is done.���);
System.out.println(���From Acct Balance: ���+xfer.fromBal);
System.out.println(��� To Acct Balance: ���+xfer.toBal);
}
}
}
 
Joltアプレットのデプロイとローカライズ
Joltクラス・ライブラリを使用すると、クライアントのWebブラウザから実行するJavaアプリケーションを作成することができます。この種のアプリケーションを作成するには、次のアプリケーション開発作業を行います。
JoltアプレットをHTMLページ内にデプロイする
Joltアプレットを適切な言語と文字セットにローカライズする
次の項では、アプリケーションを開発する際のこれらの注意点について説明します。
Joltアプレットのデプロイ
Joltアプレットをデプロイするときは、次の要件を検討してください。
Oracle TuxedoサーバーおよびJoltサーバーのインストールおよび構成の要件
クライアント側でのアプレットの実行
JavaアプレットをダウンロードするWebサーバーの要件
JoltアプリケーションでOracle TuxedoサーバーとJoltサーバーを使用するための構成については、Oracle Tuxedoシステムのインストールを参照してください。次の項では、Joltアプレットをデプロイする際に一般的にクライアントやWebサーバーで考慮すべき点について説明します。
クライアント側の注意事項
Joltクラスを使用してJavaアプレットを記述すると、HTMLページで動作するJavaアプレットと同じように機能します。JoltアプレットはHTMLアプレットのタグを使用してHTMLページに埋め込むことができます。
<applet code=���applet_name.class���> </applet>
JoltアプレットをHTMLページに埋め込むと、HTMLページのロード時にアプレットがダウンロードされます。アプレットは、ダウンロード直後に実行されるように記述することができます。また、ユーザーによる操作の実行時、タイムアウト値の到達時、または指定した間隔で実行されるようにコードを記述することもできます。さらに、アプレットのダウンロード時に別のウィンドウが開かれるように設定したり、指定した間隔で周期的に音楽を鳴らすこともできます。プログラマは、アプレットを最初にコーディングする際に、さまざまな設定を行うことができます。
注意:
新しいHTMLページをブラウザにロードすると、アプレットの実行が停止します。
Webサーバーに関する注意事項
JavaアプレットでJoltクラスを使用する場合、WebサーバーにJoltリレーがインストールされていない限り、JoltサーバーとWebサーバー(Javaアプレットのダウンロード元のWebサーバー)は同じマシンで実行する必要があります。
Web管理者がWebサーバーをセットアップすると、すべてのHTMLファイルの格納先ディレクトリが指定されます。指定されたディレクトリに「classes」という名前のサブディレクトリを作成し、Javaクラスのすべてのファイルとパッケージを格納してください。例:
<html-dir>/classes/bea/jolt
または、すべてのJoltクラスを含むjolt.jarファイルを指すようにCLASSPATHを設定することもできます。
注意:
Joltクラスのサブディレクトリは、任意の場所に置くことができます。アクセスしやすいようにHTMLファイルと同じディレクトリに置くと便利です。Joltクラスのサブディレクトリに関する唯一の条件は、Webサーバーで利用できることです。
JoltアプレットのHTMLファイルは、jolt.jarファイルまたはclassesディレクトリを参照している必要があります。例:
/export/html/
|___ classes/
| |_____ bea/
| | |______ jolt/
| | |_____ JoltSessionAttributes.class
| | |_____ JoltRemoteServices.class
| | |_____ ...
| |_____ mycompany/
| |________ app.class
|___ ex1.html
|___ ex2.html
Web管理者は、次のようにex1.htmlに「app」アプレットを指定することができます。
<applet codebase=���classes��� code=mycompany.app.class width=400 height=200>
Joltアプレットをローカライズする
Joltアプリケーションを多言後で使用する場合は、ローカライズに関わる問題を考慮する必要があります。クライアント側のWebブラウザで実行するアプリケーション、およびWebブラウザ環境以外で実行するよう設計されたアプリケーションの両方でこの問題を考慮する必要があります。ローカライズのタスクは2種類に分けることができます:
アプリケーションを元の言語からターゲットの言語に変更します。
文字列を希望する言語に翻訳します。このとき、元の言語とは異なるアルファベットや文字セットを指定する必要がある場合があります。
ローカライズの際、Joltクラス・ライブラリのパッケージは、Java言語およびOracle Tuxedoシステムの仕様に従います。JoltはJavaの16ビットUnicode文字をJSHに転送します。JSHには、Unicodeをローカルな文字セットに変換するメカニズムが組み込まれています。
UnicodeのJava実装および文字エスケープの詳細は、Java Development Kit (JDK)のドキュメントを参照してください。
SSLを使用する
Joltでは、デフォルトのリンク・レベルの暗号化のかわりに、安全な優先トランスポート・メカニズムとしてSSLを使用できます。JoltでSSLを使用できるようにするには、JSLに対してTUXEDO UBBCONFIGファイルで「-s secure_port」を構成する必要があります。
JSL接続ポートがSSLポートである場合、Joltクライアント・ライブラリは自動的にSSLを選択します。SSLの場合、Joltクライアントは、X.509証明書の場所、秘密鍵、パスフレーズの暗号化に使用されるパスフレーズなどの情報を提示する必要があります。
これらの要件に対応するために、JoltSessionAttributesクラスに5つの属性が追加されています。
KEYSTORE - クライアントの秘密鍵とX.509証明書のファイル・パス
KSPASSPHRASE - キーストアのパスフレーズ
TRUSTSTORE - 信頼性のあるX.509証明書の信頼ストアのファイル・パス
TSPASSPHRASE - 信頼ストアのパスフレーズ
KEYPASSPHRASE - 秘密鍵のパスフレーズ
Joltクライアント・ライブラリでは、SSL通信に対応するサード・パーティのJava Secure Socket Extension (JSSE)実装を使用します。以下のJSSE実装がテスト済です。
Sun JRE 8.0にバンドルされているJSSE実装
HP JRE 8.0にバンドルされているSun JSSE実装
IBM JRE 8.0にバンドルされているIBM JSSE実装
注意:
JDKリリース8u31以降、SSLv3プロトコルは無効になっており、デフォルトでは使用できません。SSLv3が必要な場合は、"SSLv3"を<JRE_HOME>/lib/security/java.securityファイルのjdk.tls.disabledAlgorithmsプロパティから削除するか、JSSEが初期化される前にこのセキュリティ・プロパティを動的に"true"に設定することでプロトコルを再度アクティブにできます。
リスト4-15は、JSL/JSHとの通信時にSSLを使用できるようにするJoltクライアント・コードのサンプルを示します。
リスト4-15 Joltクライアント・コードでのSSLの使用
import java.util.*;
import bea.jolt.*;
public class simpcl extends Object {
private String userName = null;
private String userRole = null;
private String appPassword = null;
private String userPassword = null;
private JoltSessionAttributes attr = null;
private JoltSession session = null;
private JoltRemoteService toupper = null;
private JoltTransaction trans = null;
 
// JSL is configured with '-s 5555'
// the communication between jolt client and JSH will use SSL
private String address = new String('//cerebrum:5555');
 
public static void main(String args[]) {
simpcl c = new simpcl();
c.doTest();
}
 
public void doTest() {
attr = new JoltSessionAttributes();
 
// adding these session attribute
attr.setString(attr.APPADDRESS, address);
attr.setString(attr.TRUSTSTORE,'c:\\samples\\samplecacerts');
attr.setString(attr.KEYSTORE, 'c:\\samples\\client\\testkeys');
 
// Only key store and key will be protected by passphrase in this sample.
// But optionly the trust store can also be protected by a passphrase
// although it is not in this sample.
attr.setString(attr.KSPASSPHRASE, 'passphrase');
attr.setString(attr.KEYPASSPHRASE, 'passphrase');
attr.setInt(attr.IDLETIMEOUT, 300);
 
userName = 'juser';
userRole = 'JUSER';
userPassword = 'abcd';
appPassword = 'abcd';
 
session = new JoltSession(attr, userName, userRole, userPassword,
appPassword);
 
// access a Tuxedo TOUPPER service
toupper = new JoltRemoteService('TOUPPER', session);
toupper.addString('STRING', 'string');
trans = new JoltTransaction(60, session);
try {
toupper.call(trans);
} catch (ApplicationException ae) {
ae.printStackTrace();
System.exit(1);
}
 
String retString = toupper.getStringDef('STRING', null);
trans.commit();
System.out.println(' returned: ' + retString);
session.endSession();
return;
}
}
 
 

Copyright ©1994, 2017,Oracle and/or its affiliates. All rights reserved