| 関連付けの方法 | 説明 |
|---|---|
| 間接的なコンテキスト管理 | Currentオブジェクトや暗黙の伝播により、WebOTX Transactionサービスがトランザクションコンテキストをスレッドに関連付け、管理を行います(一般的にはこちらが利用されます)。 |
| 直接的なコンテキスト管理 | アプリケーションが Controlオブジェクトとスレッドとの関連付け、管理を行います。 |
| モデル | 説明 |
|---|---|
| 間接的なコンテキスト管理: クライアントトランザクション | クライアントプログラムが Currentオブジェクトの提供するインタフェースを使用してトランザクションの管理を行います。 したがって、クライアントプログラムはトランザクショナルクライアントとなります。 クライアントプログラムはトランザクショナルオブジェクトや、非トランザクショナルオブジェクトを呼び出してトランザクション処理を行います。 OTS1.2では、OTSPolicyにより振る舞いを決定します。 一般的には、サーバプログラムがデータベースを参照・更新するリカバラブルサーバとして動作します。 クライアントプログラム側にデータベースがあっても、サーバプログラム側にデータベースがなくてもかまいません。 |
| 間接的なコンテキスト管理: サーバトランザクション | サーバプログラムが、Currentオブジェクトの提供するインタフェースを使用してトランザクションの管理を行います。 クライアントプログラムはトランザクションとは無関係な非トランザクショナルクライアントとなります。 このモデルでは、サーバプログラムはトランザクショナルクライアントとなるか、トランザクションとして通信を行わない単独のオブジェクトになります。 したがって、CORBAトランザクションサービスの概念としてはクライアントトランザクションと差はありませんが、サーバオブジェクトはマルチスレッドで動作するため、WebOTX Transactionサービスの管理は変わります。 |
| 直接的なコンテキスト管理 | アプリケーションが Currentオブジェクトを利用しないで、直接 Controlオブジェクトを利用してトランザクションコンテキストの管理を行います。 この場合、WebOTX Transactionサービスはトランザクションコンテキストの伝播を支援しませんので、明示的な伝播が行われます。 そのため、クライアントプログラム・サーバプログラムの処理の分担はアプリケーションが自由に設定することができます。 |
| OTSPolicy | Transaction有りで呼び出し | Transaction無しで呼び出し |
|---|---|---|
| REQUIRES | トランザクション内で動作 | TRANSACTION_REQUIRED例外 |
| FORBIDS | INVALID_TRANSACTION例外 | トランザクション無しで動作 |
| ADAPTS | トランザクション内で動作 | トランザクション無しで動作 |
| 処理方針 | サポート | 説明 |
|---|---|---|
| スレッドを使用する | ○ | プログラマが作成した実装部分をマルチスレッドで実行します。 |
| スレッドを使用しない | △ | プログラマが作成した実装部分は必ずシングルスレッドで処理されます。トランザクションに参加させるリソースを実装するResourceオブジェクトやトランザクション完了時のコールバックを実装するSynchronizationオブジェクトはマルチスレッドで処理するようにしてください。 |
| 処理方針 | サポート | 説明 |
|---|---|---|
| スレッドを使用する | ○ | プログラマが作成した実装部分をマルチスレッドで実行します。 |
| スレッドを使用しない | △ | プログラマが作成した実装部分は必ずシングルスレッドで処理されます。トランザクションに参加させるリソースを実装するResourceオブジェクトやトランザクション完了時のコールバックを実装するSynchronizationオブジェクトはマルチスレッドで処理するようにしてください。 |
| 処理方針 | サポート | 説明 |
|---|---|---|
| スレッドを使用する | ○ | 指定されたオブジェクトをマルチスレッドで処理します。スレッド処理方針がスレッドを使用する場合のみ有効です。 |
| スレッドを使用しない | △ | 指定されたオブジェクトをシングルスレッドで処理します。スレッド処理方針がスレッドを使用する場合のみ有効です。トランザクションに参加させるリソースを実装するResourceオブジェクトやトランザクション完了時のコールバックを実装するSynchronizationオブジェクトはマルチスレッドで処理するようにしてください。 |
Memo
ResourceオブジェクトやSynchronizationオブジェクトで実装すべきメソッドについては[ リファレンス集 開発編(共通) > 4. CORBA > 4.6 Transactionサービス(C++)]を参照してください。
/* Test.idl */
module Test {
interface interop {
void write( in long a, in long b);
long read( in long a);
};
};
#include "orb.h"
#include "otxscur.h"
CORBA::ORB_ptr orb;
try{
orb = CORBA::ORB_init(argc, argv, "");
}catch(CORBA::Exception& exc){
exc._dump(stderr);
return -1;
}
トランザクションサービスの初期化
間接的なコンテキスト管理を行うには、はじめにTransactionServiceクラスのinitメソッドを呼び出すことによりトランザクションサービスを初期化します。トランザクションサービスの初期化は、ユーザプロセスで1回だけ行います。
try{
OTXSCur::TransactionService::init(orb,argc,argv);
}catch(CORBA::Exception& exc){
exc._dump(stderr);
return -1;
}
サーバプログラムのオブジェクトリファレンスの取得
サーバアプリケーションプログラム側で生成した実装オブジェクトのリファレンスを取得します。
Test::interop_var test;
// 名前コンテキストの取得
CosNaming::NamingContext_var namectx;
try {
CORBA::Object_var nmobj = orb->resolve_initial_references("NameService");
namectx = CosNaming::NamingContext::_narrow(nmobj);
if (CORBA::is_nil((CosNaming::NamingContext_ptr)namectx)) {
return -1;
}
} catch (CORBA::Exception &exc) {
exc._dump(stderr);
}
// オブジェクトリファレンスの取得
CosNaming::Name objname;
objname.length(1);
objname[0].id = (const char*)"test";
objname[0].kind = (const char*)"";
try {
obj = namectx->resolve(objname);
test = Test::interop::_narrow(obj);
} catch (CORBA::Exception &exc) {
exc._dump(stderr);
}
Currentの取得
Currentオブジェクトは、プロセスに1つだけ存在します。以降Currentオブジェクトが提供するインタフェースを利用することでトランザクションの動作が可能になります。Currentオブジェクトを入手するには、ORBクラスのresolve_initial_referencesメソッドを使用します。
CORBA::Object_var obj;
CosTransactions::Current_ptr current;
try{
obj = orb->resolve_initial_references("TransactionCurrent");
current = CosTransactions::Current::_narrow(obj);
}catch(CORBA::Exception& exc){
exc._dump(stderr);
return -1;
}
データベースの登録
トランザクション内で使用するデータベースを必要となる数だけ登録します。
OTXSCur::TransactionService trans;
try{
trans.__register("ORACLE");
}catch(CORBA::Exception& exc){
exc._dump(stderr);
return -1;
}
データベースの接続
トランザクション内で利用するデータベースと接続します。
try{
trans.__open();
}catch(CORBA::Exception& exc){
exc._dump(stderr);
return -1;
}
トランザクションの開始
トランザクションを開始します。Currentオブジェクトの
beginメソッドをコールすることで、新規トランザクションが生成されます。トランザクションが既に開始されている場合にトランザクションを開始すると、サブトランザクションが生成されます。
try{
current->begin();
}catch(CORBA::Exception& exc){
exc._dump(stderr);
return -1;
}
サーバプログラムの呼び出し
「サーバプログラムのオブジェクトリファレンスの取得」で取得したリファレンスを使用してサーバプログラムの呼び出しを実施します。メソッドは、IDLで定義されたインタフェースをもとにします。
try{
test->write(a, b);
}catch(CORBA::Exception& exc){
exc._dump(stderr);
return -1;
}
トランザクションの終了
トランザクション処理が終わったら、トランザクションを終了します。Currentオブジェクトの commitメソッドまたは
rollbackメソッドをコールすることでトランザクションは終了します。コミットまたはロールバックが完了すると、トランザクションは破棄されます。サブトランザクションが終了した場合、そのサブトランザクションを開始する前のトランザクション(親トランザクション)が再開されます。commitの引数には、2フェーズコミットの完了を待ち合わせるか、待ち合せないかを指定します。
try{
current->commit(CORBA_TRUE);
}catch(CORBA::Exception& exc){
exc._dump(stderr);
return -1;
}
または
try{
current->rollback();
}catch(CORBA::Exception& exc){
exc._dump(stderr);
return -1;
}
トランザクションサービスの停止
トランザクションサービスを停止するために、TransactionServiceクラスのtermメソッドをコールします。データベース処理を開始していた場合には、トランザクションサービスを終了させる前にデータベースの終了処理をコールします。以降トランザクションサービスを開始しない限り、トランザクション処理を行うことはできません。
try{
OTXSCur::TransactionService::term();
}catch(CORBA::Exception& exc){
exc._dump(stderr);
return -1;
}
try{
current->rollback_only();
}catch(CORBA::Exception& exc){
exc._dump(stderr);
}
get_status(トランザクション状態の取得)
トランザクションの状態を取得するには、Currentインタフェースの
get_statusメソッドをコールします。
CosTransactions::Status status;
try{
status = current->get_status();
}catch(CORBA::Exception& exc){
exc._dump(stderr);
}
get_transaction_name(トランザクション識別名の取得)
トランザクションを識別するための文字列を取得するには、Currentインタフェースの
get_transaction_nameメソッドをコールします。
char* txname;
try{
txname = current->get_transaction_name();
}catch(CORBA::exception& exc){
exc._dump(stderr);
}
set_timeout(トランザクションタイムアウト時間の設定)
トランザクションのタイムアウト時間を設定するには、Currentインタフェースの
set_timeoutメソッドをコールします。トランザクションの処理が無限ループに入ってしまった場合でも、このインタフェースを利用することで、指定秒数経過後にロールバック処理が自動的に実行されトランザクション処理が戻ります。
try{
current->set_timeout(30);
}catch(CORBA::Exception& exc){
exc._dump(stderr);
}
get_timeout(トランザクションタイムアウト時間の取得)
トランザクションのタイムアウト時間を取得するには、Currentインタフェースの
get_timeoutメソッドをコールします。
int timeout;
try{
timeout =current->get_timeout();
}catch(CORBA::Exception& exc){
exc._dump(stderr);
}
get_control(Controlオブジェクトの取得)
Controlオブジェクトを取得するには、Currentインタフェースの
get_controlメソッドをコールします。
Controlオブジェクトを使用して明示的なトランザクション処理を行う場合に使います。
CosTransactions::Control_ptr control;
try{
control = current->get_control();
}catch(CORBA::Exception& exc){
exc._dump(stderr);
}
suspend(トランザクションのサスペンド)
Currentオブジェクトは、トランザクションをアプリケーション内で動作しているスレッドと対応させて管理しています。そのスレッドからトランザクションコンテキストを切り離す場合には、Currentインタフェースの
suspendメソッドをコールします。
resumeまたはトランザクションを新たに開始するまで、スレッドはトランザクションと関連を持ちません。
CosTransactions::Control_ptr control;
try{
control = current->suspend();
}catch(CORBA::Exception& exc){
exc._dump(stderr);
}
resume(トランザクションのレジューム)
指定された
Controlオブジェクトが示すトランザクションをスレッドに関連付けるには、Currentインタフェースの
resumeメソッドをコールします。suspendしたトランザクションを再開する場合や、直接的なコンテキスト管理で入手したトランザクションを間接的なコンテキスト管理で利用する場合に使います。
try{
current->resume(control);
}catch(CORBA::Exception& exc){
exc._dump(stderr);
}
CORBA::ORB_ptr orb;
CORBA::Object_var obj;
CosTransactions::Current_ptr current;
try{
TPSGetORB(orb);
obj = orb->resolve_initial_references("TransactionCurrent");
current = CosTransactions::Current::_narrow(obj);
}catch(CORBA::Exception& exc){
exc._dump(stderr);
return -1;
}
import org.omg.CORBA.*;
public static void main(String args[]) {
try {
// Initialize ORB.
ORB orb = ORB.init(args, null);
} catch (Exception e) {
e.printStackTrace();
}
……
}
import org.omg.CORBA.*;
……
try {
// Initialize ORB.
ORB orb = ORB.init(Applet, null);
} catch (Exception e) {
e.printStackTrace();
}
……
}
Test.interop sv;
try {
// 名前コンテキストの取得
org.omg.CORBA.Object o =
orb.resolve_initial_references("NameService");
NamingContext ns = NamingContextHelper.narrow(o);
// オブジェクトリファレンスの取得
NameComponent nc = new NameComponent("test", "");
NameComponent ncseq[] = {nc};
sv = Test.interopHelper.narrow(ns.resolve(ncseq));
} catch (Exception e) {
e.printStackTrace();
}
Currentオブジェクトの取得
Currentオブジェクトは、プロセスに1つだけ存在します。これによりトランザクションサービスが初期化され、以降Currentオブジェクトが提供するインタフェースを利用することでトランザクションの動作が可能になります。
org.omg.CosTransactions.Current cur;
try {
cur = (Current)orb.resolve_initial_references("TransactionCurrent");
} catch (Exception e) {
e.printStackTrace();
}
トランザクションの開始
トランザクションを開始します。Currentオブジェクトの
beginメソッドをコールすることで、新規トランザクションが生成されます。トランザクションが既に開始されている場合にトランザクションを開始すると、サブトランザクションが生成されます。
try {
cur.begin();
} catch (Exception e) {
e.printStackTrace();
}
サーバプログラムの呼び出し
「サーバプログラムのオブジェクトリファレンスの取得」で取得したリファレンスを使用してサーバプログラムの呼び出しを実施します。メソッドは、IDLで定義されたインタフェースをもとにします。
try {
sv.write(a, b);
} catch (Exception e) {
e.printStackTrace();
}
トランザクションの終了
トランザクション処理が終わったら、トランザクションを終了します。Currentオブジェクトの commitメソッドまたは
rollbackメソッドをコールすることでトランザクションは終了します。コミットまたはロールバックが完了すると、トランザクションは破棄されます。サブトランザクションが終了した場合、そのサブトランザクションを開始する前のトランザクション(親トランザクション)が再開されます。commitの引数には、2フェーズコミットの完了を待ち合わせるか、待ち合せないかを指定します。
try {
cur.commit(true);
} catch (Exception e) {
e.printStackTrace();
}
または
try {
cur.rollback();
} catch (Exception e) {
e.printStackTrace();
}
try {
cur.rollback_only();
} catch (Exception e) {
e.printStackTrace();
}
get_status(トランザクション状態の取得)
トランザクションの状態を取得するには、Currentインタフェースの
get_statusメソッドをコールします。
CosTransactions.Status status;
try {
status = cur.get_status();
} catch (Exception e) {
e.printStackTrace();
}
get_transaction_name(トランザクション識別名の取得)
トランザクションを識別するための文字列を取得するには、Currentインタフェースの
get_transaction_nameメソッドをコールします。
String txname;
try {
txname = cur.get_transaction_name();
} catch (Exception e) {
e.printStackTrace();
}
set_timeout(トランザクションタイムアウト時間の設定)
トランザクションのタイムアウト時間を設定するには、Currentインタフェースの
set_timeoutメソッドをコールします。トランザクションの処理が無限ループに入ってしまった場合でも、このインタフェースを利用することで、指定秒数経過後にロールバック処理が自動的に実行されトランザクション処理が戻ります。
try {
cur.set_timeout(30);
} catch (Exception e) {
e.printStackTrace();
}
get_timeout(トランザクションタイムアウト時間の取得)
トランザクションのタイムアウト時間を取得するには、Currentインタフェースの
get_timeoutメソッドをコールします。
int timeout;
try {
timeout = cur.get_timeout();
} catch (Exception e) {
e.printStackTrace();
}
get_control(Controlオブジェクトの取得)
Controlオブジェクトを取得するには、Currentインタフェースの
get_controlメソッドをコールします。
Controlオブジェクトを使用して明示的なトランザクション処理を行う場合に使います。
org.omg.CosTransactions.Control control;
try {
control = cur.get_control();
} catch (Exception e) {
e.printStackTrace();
}
suspend(トランザクションのサスペンド)
Currentオブジェクトは、トランザクションをアプリケーション内で動作しているスレッドと対応させて管理しています。そのスレッドからトランザクションコンテキストを切り離す場合には、Currentインタフェースの
suspendメソッドをコールします。
resumeまたはトランザクションを新たに開始するまで、スレッドはトランザクションと関連を持ちません。
org.omg.CosTransactions.Control control;
try {
cur.suspend();
} catch (Exception e) {
e.printStackTrace();
}
resume(トランザクションのレジューム)
指定された
Controlオブジェクトが示すトランザクションをスレッドに関連付けるには、Currentインタフェースの
resumeメソッドをコールします。suspendしたトランザクションを再開する場合や、直接的なコンテキスト管理で入手したトランザクションを間接的なコンテキスト管理で利用する場合に使います。
try {
cur.resume(control);
} catch (Exception e) {
e.printStackTrace();
}
org.omg.CORBA.ORB orb;
org.omg.CosTransactions.Current cur;
try {
orb = jp.co.nec.WebOTX.orbsvwpr.WoServerWrapper.TPSGetORB();
cur = (Current)orb.resolve_initial_references("TransactionCurrent");
} catch (Exception e) {
e.printStackTrace();
}
| 動作 | 疎結合での動作 | 密結合での動作 |
|---|---|---|
| SQL命令実行時のデータ共有可否 | トランザクションブランチ間では、SQL命令の実行時に表ロックや行ロックによる排他が行われます。このため、同じテーブルなどの資源を共有することはできません。 | トランザクションブランチ間では、SQL命令の実行時に表ロックや行ロックによる排他が行われません。このため、同じテーブルなどの資源を共有することができます。更新結果は、トランザクションブランチ間で引き継がれます。 |
| SQL命令実行時にデッドロックが発生する可能性の有無 | あります。 | ありません。 |
| 動作 | 開始・終了方法 | 説明 |
|---|---|---|
| 開始 | 新規作成 | トランザクションブランチを新規に作成します。 |
| 連結 | 以前終了したトランザクションブランチに参加します。 | |
| 再開 | 以前中断されたトランザクションブランチに参加します。 | |
| 終了 | 正常終了 | トランザクションブランチを正常終了します。 |
| 中断 | トランザクションブランチを一時的に中断します。 | |
| 結合移行 | トランザクションブランチを他のスレッドに移行するために、一時的に中断します。 |
| 契機 | 開始・終了方法 | |
|---|---|---|
| 開始契機 |
トランザクションの開始
Current:: begin()
|
新規作成
|
|
サーバメソッドの呼び出し開始直前
|
新規作成: 1回目の呼び出し
連結: 2回目以降の呼び出し
再開: 結合移行指定時
|
|
|
メソッド呼び出しの応答受信直後
|
再開
|
|
|
トランザクションの再開
Current::resume()
|
再開
|
|
| 終了契機 |
トランザクションの終了
Current::commit()またはrollback()
|
正常終了
|
|
サーバメソッド終了直後
|
正常終了: 通常動作
中断: 中断指定時
結合移行: 結合移行指定時
|
|
|
サーバメソッド呼び出しの要求送信直前
|
中断: 通常動作
結合移行: 結合移行指定時
|
|
|
トランザクションの中断
Current::suspend()
|
中断: 通常動作
結合移行: 結合移行指定時
|
CosTransactions::Current_ptr current; current->begin(); // トランザクションの開始 current->suspend(); // トランザクションの中断 // ここではグローバルトランザクションに参加していない current->resume(); // トランザクションの再開 // ここでSQLカーソルが引き継がれるかはデータベース依存 サーバのメソッド呼び出し // トランザクションを中断後、再開 // ここでSQLカーソルが引き継がれるかはデータベース依存 current->commit(CORBA_TRUE); // トランザクションのコミットサーバアプリケーションは、クライアントから呼び出されたメソッドが終了する度にトランザクションから切り離された状態になります。このため、通常は、サーバアプリケーションのメソッド間でSQLカーソルなどの資源を引き継ぐことはできません。一般に、各メソッドの先頭でSQLカーソルなどの資源を再設定する必要があります。
| 関数名 | 説明 |
|---|---|
| is_new_sqlsession() | 同一トランザクション内で既にハンドルがエンリストされているかどうかを問い合わせます。 |
| get_sqlsession() | is_new_sqlsession()の結果、エンリスト実施済みの場合に、既にトランザクションに登録済みのハンドルを取得します。 エンリスト実施未の場合は、コネクションプールに登録されているハンドルを取得します。 |
| register_sqlsession() | 新規にデータベース接続ハンドルをトランザクションに登録します。引数で、コネクションをプールするか、自動切断するかを指定します。 |
Memo
RmSqlインタフェースの詳細は、[ リファレンス集 開発編(共通) > 4. CORBA > 4.6 Transactionサービス(C++)] を参照してください。
EXEC SQL BEGIN DECLARE SECTION;
// ホスト変数の宣言
DB_NAME CHARACTER(16);
long accountno;
long balance;
EXEC SQL END DECLARE SECTION;
int actno, bal;
CosTransactions::Current_ptr current;
SET DB_NAME = ‘ORCL’;
try { //グローバルトランザクションを開始
current->begin();
} catch( CORBA::Exception& exc ){
return -1;
}
accountno = actno;
balance = bal;
//SQL命令の実行
EXEC SQL AT :DB_NAME UPDATE a_account
SET BALANCE = :balance WHERE ACCOUNTNO = :accountno;
try { //グローバルトランザクションをコミット
current->commit(CORBA_TRUE);
} catch( CORBA::Exception& exc ){
return -1;
}
Memo
この例では、"ORCL"というデータベース名を使用しています。デフォルトデータベースを使用する場合は、データベースの宣言とAT句の記述は必要ありません。
LOGINREC *login; dbinit(); login = dblogin(); DBSETLUSER( login, "SCOTT" ); DBSETLPWD( login, "TIGER" );Oracle OCIでのグローバルトランザクションの実行例 グローバルトランザクションを実行するためには、次のように記述します。
text *sqlstmt = (text *) "update a_account set
BALANCE=:bal where ACCOUNTNO=:actno";
int actno,
bal;
text *dbname = "ORCL";
OCIStmt *stmthp;
OCIEnv *envhp;
OCIError *errhp;
OCISvcCtx *svchp;
OCIStmt *stmthp;
OCIBind *bnd1p = (OCIBind *) 0;
OCIBind *bnd2p = (OCIBind *) 0;
CosTransactions::Current_ptr current;
try { //グローバルトランザクションを開始
current->begin();
} catch( CORBA::Exception& exc ){
return -1;
}
//環境ハンドルとサービスコンテキストの取得
envhp = xaoEnv( dbname );
svchp = xaoSvcCtx( dbname );
//エラーハンドルの初期化
(void) OCIHandleAlloc( (dvoid *)envhp, (dvoid **)&errhp,
OCI_HTYPE_ERROR, (size_t) 0, (dvoid **) 0);
//ステートメントハンドルの初期化
OCIHandleAlloc( (dvoid *)envhp, (dvoid **)&stmthp,
OCI_HTYPE_STMT, (size_t)0, (dvoid **)0) );
//SQL命令の実行準備
OCIStmtPrepare( stmthp, errhp, selectp, (ub4)strlen((char *)selectp),
(ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT) );
//変数の割り当て
OCIBindByName( stmthp1, &bnd1p, errhp, (text *)":bal", -1,
(dvoid *)&bal, (sword)sizeof(bal),
SQLT_INT, (dvoid *)0, (ub2 *)0, (ub2 *)0,
(ub4)0, (ub4)0, OCI_DEFAULT );
OCIBindByName( stmthp1, &bnd2p, errhp, (text *)":actno", -1,
(dvoid *)&actno, (sword)sizeof(actno),
SQLT_INT, (dvoid *)0, (ub2 *)0, (ub2 *)0,
(ub4)0, (ub4 *)0, OCI_DEFAULT );
// SQL命令の実行
OCIStmtExecute( svchp, stmthp, errhp, (ub4)1, (ub4)0,
(CONST OCISnapshot *)NULL, (OCISnapshot *)NULL, OCI_DEFAULT );
try { //グローバルトランザクションをコミット
current->commit(CORBA_TRUE);
} catch( CORBA::Exception& exc ){
return -1;
}
Memo
この例では、"ORCL"というデータベース名を使用しています。デフォルトデータベースを使用する場合は、データベース名として空文字””を指定してください。
LOGINREC *login;
dbinit();
login = dblogin();
DBSETLUSER( login, "SCOTT" );
DBSETLPWD( login, "TIGER" );
DB Libraryでのグローバルトランザクションの実行例
グローバルトランザクションを実行するためには、次のように記述します。
static char *sqlstmt = "update a_account set balance = %d where accountno = %d", bal, actno";
int err_handler( DBPROCESS*, int, int, int, char*, char* );
int msg_handler( DBPROCESS*, DBINT, int, int, char* );
int actno, bal;
DBPROCESS *dbproc;
CosTransactions::Current_ptr current;
//データベースとの接続
dbproc = dbopen( login, NULL );
//ハンドラの登録
dbprocmsghandle( dbproc, (DBMSGHANDLE_PROC)msg_handler );
dbprocerrhandle( dbproc, (DBERRHANDLE_PROC)err_handler );
//データベースの指定
dbuse( dbproc, "pubs" );
try { //グローバルトランザクションを開始
current->begin();
} catch( CORBA::Exception& exc ){
return -1;
}
//エンリストの実施
dbenlistxatrans ( dbproc, TRUE );
//SQL命令のフォーマット
dbfcmd( dbproc, sqlstmt, bal, actno );
//SQL命令の実行
dbsqlexec( dbproc );
dbresults( dbproc );
try { //グローバルトランザクションをコミット
current->commit(CORBA_TRUE);
} catch( CORBA::Exception& exc ){
return -1;
}
//コネクションの切断
dbclose();
int err_handler( DBPROCESS*, int, int, int, char*, char* );
int msg_handler( DBPROCESS*, DBINT, int, int, char* );
LOGINREC *login;
DBPROCESS *dbproc;
long sessid = 0;
// トランザクションに登録済みのハンドル有無を確認
if (::is_new_sqlsession(sessid) == false) {
// プールからハンドルを取得
handle = ::get_sqlsession(sessid, WEBOTXS_SQL_SESSPOOL);
if (handle == NULL) {
// 新規ハンドルの取得
dbproc = dbopen( login, NULL );
dbprocmsghandle( dbproc, (DBMSGHANDLE_PROC)msg_handler );
dbprocerrhandle( dbproc, (DBERRHANDLE_PROC)err_handler );
dbuse( dbproc, "pubs" );
}
// エンリストの実施
dbenlistxatrans ( dbproc, TRUE );
// トランザクションに新規ハンドルを登録
::register_sqlsession(sessid, handle, WEBOTXS_SQL_DBLIB, WEBOTXS_SQL_SESSPOOL);
} else {
// トランザクションに登録済みのハンドルを取得
handle = ::get_sqlsession(sessid, WEBOTXS_SQL_NONE);
}
// SQL命令の実行
Memo
RmSqlインタフェースの詳細は、[ リファレンス集 開発編(共通) > 4. CORBA > 4.6 Transactionサービス(C++)]を参照してください。
Caution
loginは、::dblogin()を呼び出して予め初期化しておく必要があります。
int err_handler( DBPROCESS*, int, int, int, char*, char* );
int msg_handler( DBPROCESS*, DBINT, int, int, char* );
LOGINREC *login;
DBPROCESS *dbproc;
long sessid = 0;
// トランザクションに登録済みのハンドル有無を確認
if (::is_new_sqlsession(sessid) == false) {
// 新規ハンドルの取得
dbproc = dbopen( login, NULL );
dbprocmsghandle( dbproc, (DBMSGHANDLE_PROC)msg_handler );
dbprocerrhandle( dbproc, (DBERRHANDLE_PROC)err_handler );
dbuse( dbproc, "pubs" );
// エンリストの実施
dbenlistxatrans ( dbproc, TRUE );
// トランザクションに新規ハンドルを登録
::register_sqlsession(sessid, (void *)dbproc, WEBOTXS_SQL_DBLIB, WEBOTXS_SQL_SESSDELETE);
} else {
// トランザクションに登録済みのハンドルを取得
handle = ::get_sqlsession(sessid, WEBOTXS_SQL_NONE);
}
// SQL命令の実行
Memo
RmSqlインタフェースの詳細は、[ リファレンス集 開発編(共通) > 4. CORBA > 4.6 Transactionサービス(C++)]を参照してください。
Caution
loginは::dblogin()を呼び出して予め初期化しておく必要があります。
ENV henv; SQLAllocEnv( &henv );Microsoft SQL Server ODBCでのグローバルトランザクションの実行例 グローバルトランザクションを実行するためには、次のように記述します。
static char *sqlstmt = (text *)"update a_account set balance = ? where accountno = ?";
HENV henv;
HDBC hdbc;
SDWORD cbact;
SDWORD cbbal;
SDWORD sdact;
SDWORD sdbal;
int bal, actno;
CosTransactions::Current_ptr current;
//hdbcの初期化
SQLAllocConnect( henv, &hdbc );
//データベースとの接続
SQLConnect( hdbc, "ACCOUNT", SQL_NTS,
"SCOTT", SQL_NTS, "TIGER", SQL_NTS );
try { //グローバルトランザクションを開始
current->begin();
} catch( CORBA::Exception& exc ){
return -1;
}
//エンリストの実施
SQLSetConnectOption( hdbc, SQL_COPT_SS_ENLIST_IN_XA, TRUE );
//ステートメントの初期化
SQLAllocStmt( hdbc, &hstmt );
//SQL命令の実行準備
SQLPrepare( hstmt, sqlstmt, SQL_NTS );
//変数の割り当て
SQLBindParameter( hstmt, 1, SQL_PARAM_INPUT,
SQL_C_LONG, SQL_INTEGER,0, 0, &sdbal,0,&cbbal );
SQLBindParameter( hstmt, 2, SQL_PARAM_INPUT,
SQL_C_LONG, SQL_INTEGER,0, 0, &sdact,0,&cbact );
sdbal = bal;
sdact = actno;
//SQL命令の実行
SQLExecute( hstmt );
//ステートメントの解放
SQLFreeStmt( hstmt, SQL_DROP );
try { //グローバルトランザクションをコミット
current->commit(CORBA_TRUE);
} catch( CORBA::Exception& exc ){
return -1;
}
//コネクションの切断
SQLDisconnect( hdbc );
SQLFreeConnect( hdbc );
HENV henv;
long sessid = 0;
void *handle;
// トランザクションに登録済みのハンドル有無を確認
if (::is_new_sqlsession(sessid) == false) {
// プールからハンドルを取得
handle = ::get_sqlsession(sessid, WEBOTXS_SQL_SESSPOOL);
if (handle == NULL) {
// 新規ハンドルの取得
::SQLAllocConnect(henv, &handle);
::SQLConnect(handle, "ODBCSourceName", SQL_NTS,
"username", SQL_NTS, "password", SQL_NTS);
}
// エンリストの実施
::SQLSetConnectOption(handle, SQL_COPT_SS_ENLIST_IN_XA, TRUE);
// トランザクションに新規ハンドルを登録
::register_sqlsession(sessid, handle, WEBOTXS_SQL_ODBC, WEBOTXS_SQL_SESSPOOL);
} else {
// トランザクションに登録済みのハンドルを取得
handle = ::get_sqlsession(sessid, WEBOTXS_SQL_NONE);
}
// SQL命令の実行
Memo
RmSqlインタフェースの詳細は、[ リファレンス集 開発編(共通) > 4. CORBA > 4.6 Transactionサービス(C++)]を参照してください。
Caution
henvは::SQLAllocEnv()を呼び出して予め初期化しておく必要があります。
HENV henv;
long sessid = 0;
void *handle;
// トランザクションに登録済みのハンドル有無を確認
if (::is_new_sqlsession(sessid) == false) {
// 新規ハンドルの取得
::SQLAllocConnect( henv, &handle );
::SQLConnect(handle, "ODBCSourceName", SQL_NTS,
"username", SQL_NTS, "password", SQL_NTS);
// エンリストの実施
::SQLSetConnectOption(handle, SQL_COPT_SS_ENLIST_IN_XA, TRUE);
// トランザクションに新規ハンドルを登録
::register_sqlsession(sessid, handle, WEBOTXS_SQL_ODBC, WEBOTXS_SQL_SESSDELETE);
} else {
// トランザクションに登録済みのハンドルを取得
handle = ::get_sqlsession(sessid, WEBOTXS_SQL_NONE);
}
// SQL命令の実行
Memo
RmSqlインタフェースの詳細は、[ リファレンス集 開発編(共通) > 4. CORBA > 4.6 Transactionサービス(C++)]を参照してください。
Caution
henvは::SQLAllocEnv()を呼び出して予め初期化しておく必要があります。
#define MYQMGR "MQM"
MQOD od = {MQOD_DEFAULT};
MQPMO pmo = {MQPMO_DEFAULT};
MQHCONN Hcon;
MQHOBJ Hobj;
MQLONG CompCode, Reason, CReason;
MQMD PMsgDescriptor= { MQMD_DEFAULT };
char QMName[50];
char MyMsg[16];
int mode;
CosTransactions::Current_ptr current;
// コネクションハンドルの取得
strcpy(QMName, MYQMGR);
MQCONN( QMName, &Hcon, &CompCode, &CReason );
// キューのオープン
strcpy(od.ObjectName, "SYSTEM.DEFAULT.LOCAL.QUEUE");
mode = MQOO_OUTPUT+MQOO_FAIL_IF_QUIESCING;
MQOPEN( Hcon, &od, mode, &Hobj, &CompCode, &Reason );
try { //グローバルトランザクションを開始
current->begin();
} catch( CORBA::Exception& exc ){
return -1;
}
// SYNCPOINTオプションの設定
pmo.Options |= MQPMO_SYNCPOINT;
// メッセージの送信
strcpy( MyMsg, "TESTMessage!" );
MQPUT( Hcon, Hobj, &PMsgDescriptor, &pmo,
(long int)strlen(MyMsg)+1, MyMsg, &CompCode, &Reason );
try { //グローバルトランザクションをコミット
current->commit(CORBA_TRUE);
} catch( CORBA::Exception& exc ){
return -1;
}
// キューのクローズ
// コネクションハンドルの解放
MQDISC(&Hcon, &CompCode, &Reason);
Memo
この例では、"MQM"というキュー管理プログラム名を使用しています。デフォルトのキュー管理プログラムを使用する場合は、名前に空文字””を指定してください。
Caution
グローバルトランザクションの実行時には、メッセージ送信の場合はMQPMO構造体のOptionsメンバにMQPMO_SYNCPOINTを、また、メッセージ受信の場合はMQGMO構造体のOptionsメンバにMQGMO_SYNCPOINTを必ず指定してください。
本節では画面テンプレートのサーバAP部分のプログラミングについて説明します。
WebOTX画面テンプレートでは、サーバAPのソースやバッチファイルのテンプレートを提供しており、これらを利用することにより効率的に開発作業を行うことができます。

図1.2.4-1
| 作業 | 説明 |
|---|---|
|
CORBAインタフェースクラス
|
WebOTX画面テンプレートが提供するCORBAインタフェースクラスを継承して作成します。コンストラクタを実装するだけでWebサーバ上で動作するWebOTX画面テンプレートとの連携が可能になります。 |
|
APロジッククラス
|
WebOTX画面テンプレートが提供するAPロジッククラスを継承して作成します。doMethod メソッドをオーバライドして、ビジネスロジックを実装する各メソッドを呼び出すためのディスパッチ処理を実装します。 |
| 作業 | 説明 |
|---|---|
|
サーバAPの雛形を作成
|
テンプレートをコピーして作成します。 |
|
ビジネスロジッククラスの作成
|
ビジネスロジックを追加します。 |
|
コンパイル
|
サーバAPのインターフェース名に合わせて、テンプレートのバッチファイルを修正した後実行すると、WebOTXに登録するサーバAP(二つのjarファイルから構成)ができます。 |
|
WebOTXへの配備
|
コンパイルして作成されたjarファイルとifファイルを、WebOTXへ配備します。 |
| テンプレートファイル | 説明 |
|---|---|
|
make.BAT
|
コンパイル用のバッチファイル(Windows 2003/2008/XP/Vista用) |
|
makefile
|
コンパイル用のmakeファイル(HP-UX、Linux用) |
|
makejar
|
jarファイル作成用のmakeファイル(HP-UX、Linux用) |
|
Template.idl
|
IDLファイル |
|
AppLogic1.java
|
ビジネスロジッククラス |
|
WebGWObj.java
|
CORBAインタフェースクラス |
| サーバAPのインタフェースを変更する場合の変更個所 |
|---|
|
IDLファイルのファイル名と、interface宣言
|
|
CORBAインタフェースクラスのファイル名
|
|
CORBAインタフェースクラスのクラス名
|
|
WebGWOperationsの名称コンストラクタの名称
|
set CLASSPATH=%CLASSPATH%;..\package\WebGWpackage.jar;..\BASE62\WebGWBASE62.jarWebGWBASE62.idlのパスを環境に合わせて変更してください。
call woi2j.bat -tie -rp jp.co.nec.WebOTX.WebGWBS -R ..\BASE62\WebGWBASE62.idl TemplateIDLファイル名を変更した場合は、「call woi2j.bat ・・・ WebGW」のWebGWの部分を新しいファイル名に合わせて変更します。
jar cvf TemplateApp.jarjp\co\nec\WebOTX\ObjectCreator Logic %REDIRECT% jar cvf Template.jar jp template Logic %REDIRECT%
> makecpk Template.cpk module=classes\Template.jar if=Template.if > makecpk TemplateApp.spk module=classes\TemplateApp.jar
SHELL = /usr/bin/sh RM = /usr/bin/rm IDLBASEDIR = ../BASE62WebGWpackage.jarとWebGWBASE62.jarのパスを環境に合わせて変更してください。
CLASSPATH = .:/opt/WebOTX/dev/javalib/svsimj.jar:/opt/WebOTX/dev/javalib/WOTXBS90.jar:/opt/WebOTX/dev/javalib/WOTXTRM.jar:../BASE62/WebGWBASE62.jar:../package/WebGWpackage.jarIDLファイル名を変更した場合は、「call woi2j.bat ・・・ WebGW」のWebGWの部分を新しいファイル名に合わせて変更します。
jSVOBJ = Template.jar APPOBJ = TemplateApp.jarmakeを実行します。
> makecpk Template.cpk module=classes/Template.jar if=Template.if > makecpk TemplateApp.spk module=classes/TemplateApp.jar
> cd <BASE62ディレクトリ> > makecpk WebGWBASE62.spk module= WebGWBASE62.jar if= WebGWBASE62.if > cd <packageディレクトリ> > makecpk WebGWpackage.spk module= WebGWpackage.jar > makecpk classes12.spk module=<JDBCライブラリファイル>HP-UX, Solaris, Linuxの場合 以下のコマンドを実行して共有コンポーネントを作成します。
> cd <BASE62ディレクトリ> > /opt/WebOTX/bin/makecpk WebGWBASE62.spk module= WebGWBASE62.jar if= WebGWBASE62.if > cd <packageディレクトリ> > /opt/WebOTX/bin/makecpk WebGWpackage.spk module= WebGWpackage.jar > makecpk classes12.spk module=<JDBCライブラリファイル>
| ファイル名 | 説明 |
|---|---|
|
WebGWBASE62.spk
|
画面テンプレートのフレームワーククラスをspkアーカイブしたファイルです。 |
|
WebGWpackage.spk
|
画面テンプレートの使用するクラスをspkアーカイブしたファイルです。 |
|
TemplateApp.spk
|
ビジネスロジッククラスをspkアーカイブしたファイルです。 |
|
classes12.spk
|
データベースベンダの提供するJDBCライブラリをspkアーカイブしたファイルです。 |
| ファイル名 | 説明 |
|---|---|
|
Template.cpk
|
サーバAPクラスをcpkアーカイブしたファイルです。 |