|
この章では、Oracle シンプル イベント API と C++ プログラミング言語を使用してノーティフィケーション サービス アプリケーションを作成するための開発手順を説明します。
注意 : | Oracle Tuxedo CORBA Java クライアントと Oracle Tuxedo CORBA Java クライアント ORB は Tuxedo 8.1 で非推奨になり、サポートされなくなりました。Oracle Tuxedo CORBA Java クライアントおよび Oracle Tuxedo CORBA Java クライアント ORB のテキスト参照、関連するコード サンプルはすべてサードパーティの Java ORB ライブラリの実装/実行の簡易化とプログラマによる参照だけに使用する必要があります。 |
注意 : | サード パーティの CORBA Java ORB のテクニカル サポートは、各ベンダによって提供されます。Oracle Tuxedo では、サード パーティの CORBA Java ORB に関する技術的なサポートやマニュアルは提供していません。 |
表 3-1 は、ノーティフィケーション サービス アプリケーションの開発プロセスの概略です。
イベントの設計は、あらゆるノーティフィケーション サービスの基本です。イベントの設計は、一致するサブスクリプションに配信される情報の量だけでなく、ノーティフィケーション サービスの効率と性能にも影響します。したがって、計画を慎重に行って、ノーティフィケーション サービスが現在のニーズだけでなく将来の規模拡大にも対応できるようにする必要があります。イベント設計の説明については、「イベントの設計」を参照してください。
次のタイプの CORBA アプリケーションは、イベントをポストできます。
イベントをポストするために、アプリケーションでは最低でも次の機能を実装する必要があります。
最初にイベント チャネルを取得しないと、クライアント アプリケーションではイベントをポストできません。
この開発ステップは、コード リスト 3-1 で示されています。コード リスト 3-1 は、Oracle シンプル イベント API を使用する Notification Service サンプル アプリケーションに基づいています。
イベント チャネル ファクトリのオブジェクト参照を取得するために、"Tobj_SimpleEventsService"
環境オブジェクトを使用して Bootstrap オブジェクトの resolve_initial_references
メソッドが呼び出されます。取得したオブジェクト参照は、チャネル ファクトリを取得するために使用します。チャネル ファクトリは、イベント チャネルを取得するために使用します。コード リスト 3-1 は、C++ のサンプル コードを示しています。
// シンプル イベント チャネル ファクトリのオブジェクト参照を取得
CORBA::Object_var channel_factory_oref =
bootstrap.resolve_initial_references(
"Tobj_SimpleEventsService");
Tobj_SimpleEvents::ChannelFactory_var channel_factory =
Tobj_SimpleEvents::ChannelFactory::_narrow(
channel_factory_oref.in());
// チャネル ファクトリを使用してデフォルト チャネルを取得
Tobj_SimpleEvents::Channel_var channel =
channel_factory->find_channel(
Tobj_SimpleEvents::DEFAULT_CHANNEL);
イベントをポストするには、まずイベントを作成しなければなりません。以下のリストは、Notification Service サンプル アプリケーションに基づいています。
コード リスト 3-2 は、C++ での実装を示しています。イベント チャネルにニュースを報告するために、このアプリケーションでは次の手順が実行されます。
push_structured_event
オペレーションを使用して、イベントをノーティフィケーション サービスにポストします。// イベントを作成
CosNotification::StructuredEvent notification;
// ドメインを「News」に設定
notification.header.fixed_header.event_type.domain_name =
CORBA::string_dup("News");
// 型をニュース カテゴリに設定
notification.header.fixed_header.event_type.type_name =
CORBA::string_dup(“Sports”);
// 記事を格納するフィールドを 1 つイベントのフィルタ
// 処理可能データに追加。フィールドの名前は「Story」、
// 値は記事の文字列に設定
notification.filterable_data.length(1);
notification.filterable_data[0].name =
CORBA::string_dup("Story");
notification.filterable_data[0].value <<= “John Smith wins again”;
// イベントをポスト
// ドメインが「News」で、型がニュース カテゴリと一致する
// イベントをサブスクライブしたサブスクライバがこのイベント
// を受信する
channel->push_structured_event(notification);
次のタイプの CORBA アプリケーションは、イベントをサブスクライブできます。
イベントをサブスクライブするために、アプリケーションでは最低でも次の機能を実装する必要があります。
コールバック オブジェクトでイベントを受信するためには、push_structured_event
オペレーションをサポートする CosNotifyComm::StructuredPushConsumer インタフェースを実装する必要があります。一致するサブスクリプションがあるイベントが発生すると、ノーティフィケーション サービスではコールバック オブジェクトのこのオペレーションを呼び出してイベントをサブスクライバ アプリケーションにプッシュします。
CosNotifyComm::StructuredPushConsumer インタフェースでは、offer_change
および disconnect_structured_push_consumer
というオペレーションも定義されます。これらのオペレーションはノーティフィケーション サービスで呼び出されないので、CORBA::NO_IMPLEMENT
を送出するスタブ アウト バージョンを実装する必要があります。
コード リスト 3-3 とコード リスト 3-4 は、このインタフェースが C++ でどのように実装されるのかを示しています。
#ifndef _news_consumer_i_h
#define _news_consumer_i_h
#include "CosNotifyComm_s.h"
// サーバント クラスでニュース イベントを受信するためには、
// CosNotifyComm::StructuredPushConsumer idl インタフェース
// を実装する必要がある
class NewsConsumer_i : public POA_CosNotifyComm::StructuredPushConsumer
{
public:
// このメソッドはニュース イベントの発生時に呼び出される
virtual void push_structured_event(
const CosNotification::StructuredEvent& notification
);
// OMG の CosNotifyComm::StructuredPushConsumer idl インタフェース
// では、offer_change メソッドと disconnect_structured_push_consumer
// メソッドが定義される。ノーティフィケーション サービスからそれらの
// メソッドが呼び出されることはないので、ただ単に CORBA::NO_IMPLEMENT
// 例外を送出させる
virtual void offer_change(
const CosNotification::EventTypeSeq& added,
const CosNotification::EventTypeSeq& removed )
{
throw CORBA::NO_IMPLEMENT();
}
virtual void disconnect_structured_push_consumer()
{
throw CORBA::NO_IMPLEMENT();
}
};
#endif
#include "NewsConsumer_i.h"
#include <iostream.h>
//-----------------------------------------------------------
// Subscriber.cpp は「News」イベントのシンプル イベント
// サブスクリプションを作成し、イベントが NewsConsumer_i オブジェクト
// に配信されるようにする。ニュース イベントが発生すると (ユーザが
// Reporter アプリケーションを実行してニュース記事を報告すると発生する)、
// 次のメソッドが呼び出される
void NewsConsumer_i::push_structured_event(
const CosNotification::StructuredEvent& notification )
{
// イベントのフィルタ処理可能データの最初のフィールドから
// 記事を抽出する
char* story;
notification.filterable_data[0].value >>= story;
// コードを単純化するために、「story」は「null」ではないと想定
// イベントを出力
cout
<< "-----------------------------------------------------"
<< endl
<< "Category : "
<< notification.header.fixed_header.
event_type.type_name.in()
<< endl
<< "Story : "
<< story
<< endl;
...
}
このステップは、イベント ポスト元とイベント サブスクライバの両方で同じです。このステップの説明については、「CosNotifyComm::StructuredPushConsumer インタフェースの実装」を参照してください。
イベントを受信するためには、アプリケーションはサーバであることも必要です。つまり、アプリケーションでは、サブスクライバのサブスクリプションと一致するイベントが発生したときに呼び出すことができるコールバック オブジェクトを実装しなければなりません。
注意 : | この手順は、Oracle Tuxedo CORBA 共同クライアント/サーバでの手順です。Oracle Tuxedo CORBA サーバでもイベントをサブスクライブできます。 |
BEAWrapper コールバック オブジェクトとそのメソッドの詳細については、『Tuxedo CORBA プログラミング リファレンス』の「共同クライアント/サーバ」を参照してください。
注意 : | BEAWrapper コールバック オブジェクトを使用してコールバック オブジェクトを作成する方法は、以下に説明します。POA を使用してコールバック オブジェクトを実装する方法については、『Oracle Tuxedo CORBA サーバ間通信』を参照してください。 |
コード リスト 3-5 は、C++ で、BEAWrapper コールバック オブジェクトを使用してコールバック オブジェクトを作成する方法を示しています。サンプル コードでは、NewsConsumber_i servant
が作成され、start_transient
メソッドを使用して一時的なオブジェクト参照が作成されます。
// このクライアントではコールバックをサポートする必要があるので
// コールバック ラッパー オブジェクトを作成する
BEAWrapper::Callbacks wrapper(orb.in());
NewsConsumer_i* news_consumer_impl = new NewsConsumer_i;
CORBA::Object_var news_consumer_oref =
wrapper.start_transient(
news_consumer_impl,
CosNotifyComm::_tc_StructuredPushConsumer->id()
);
CosNotifyComm::StructuredPushConsumer_var
news_consumer =
CosNotifyComm::StructuredPushConsumer::_narrow(
news_consumer_oref.in()
);
サブスクライバでイベントを受信するためには、ノーティフィケーション サービスをサブスクライブする必要があります。一時的なサブスクリプションまたは永続的なサブスクリプションのいずれかを作成できます。
Introductory サンプル アプリケーションのコードであるコード リスト 3-6 は、C++ で一時的なサブスクリプションを作成する方法を示しています。
subscription_name
(省略可能)、domain_name
、type_name
、および data_filter
(省略可能) を指定します。domain_name
、type_name
、data_filter
(省略可能)、およびサービスの品質 (QoS) を設定し、サブスクライバのコールバック オブジェクトのオブジェクト参照をノーティフィケーション サービスに提供します。// サービスの品質を TRANSIENT に設定
CosNotification::QoSProperties qos;
qos.length(1);
qos[0].name =
CORBA::string_dup(Tobj_SimpleEvents::SUBSCRIPTION_TYPE);
qos[0].value <<=
Tobj_SimpleEvents::TRANSIENT_SUBSCRIPTION;
// 型をニュース カテゴリに設定
const char* type = “Sports”;
// サブスクリプションを作成する。ドメインを「News」に設定し、
// データ フィルタを 30 を超える年齢に設定する
Tobj_SimpleEvents::SubscriptionID subscription_id =
channel->subscribe(
subscription_name,
"News", // ドメイン
“Sports”, // 型
"Age > 30", // データ フィルタ
qos,
news_consumer.in()
);
注意 : | データのフィルタ処理を利用する場合は、コンフィグレーション タスクも行う必要があります。データ フィルタ処理のコンフィグレーション要件については、「データ フィルタのコンフィグレーション」を参照してください。 |
C++ の Advanced サンプル アプリケーションのコードであるコード リスト 3-7 は、ノーティフィケーション サービスの永続的なサブスクリプションを作成するコード記述手順を示しています。永続的なサブスクリプションを作成する手順は、前述の一時的なサブスクリプションを作成する手順と同じです。
注意 : | サンプル コードでは news_consumer コールバック オブジェクトのオブジェクト参照が永続的であると想定されていますが、一時的なコールバック オブジェクト参照で永続的なサブスクリプションを作成することもできます。一時的と永続的を対比させたコールバック オブジェクト参照の説明については、表 2-3 を参照してください。 |
CosNotification::QoSProperties qos;
qos.length(1);
qos[0].name =
CORBA::string_dup(Tobj_SimpleEvents::SUBSCRIPTION_TYPE);
qos[0].value <<= Tobj_SimpleEvents::PERSISTENT_SUBSCRIPTION;
CosNotifyComm::StructuredPushConsumer_var
news_consumer =
CosNotifyComm::StructuredPushConsumer::_narrow(
news_consumer_oref.in()
);
Tobj_SimpleEvents::SubscriptionID sub_id =
channel->subscribe(
subscription_info.subscription_name(),
"News", // ドメイン
“Sports”, // 型
“”, // データ フィルタなし
qos,
news_consumer.in()
)
);
共同クライアント/サーバ アプリケーションは、まずクライアント アプリケーションとして機能し、その後にサーバ アプリケーションにスイッチすることができます。そのために、共同クライアント/サーバ アプリケーションでは次の呼び出しを行って、スレッドの制御を完全にオブジェクト リクエスト ブローカ (ORB) に移します。
共同クライアント/サーバ アプリケーションのサーバ部分のメソッドが ORB::shutdown()
を呼び出すと、サーバのアクティビティはすべて停止し、共同クライアント/サーバ アプリケーションのサーバ部分で ORB::run()
が呼び出されると、制御はステートメントに返されます。制御が共同クライアント/サーバ アプリケーションのクライアント機能に返されるのは、この条件においてのみです。
クライアント アプリケーションにはスレッドが 1 つしかないため、共同クライアント/サーバ アプリケーションのクライアント機能とサーバ機能で、中央演算処理装置 (CPU) を共有する必要があります。この共有は、ORB をときどき確認して、共同クライアント/サーバ アプリケーションに、実行すべきサーバ アプリケーション作業があるかどうかを調べることによって行われます。ORB の確認を実行するには、次のコードを使用します。
if ( orb->work_pending() ) orb->perform_work();
ORB はサーバ アプリケーションの作業を完了すると、共同クライアント/サーバ アプリケーションに戻ります。共同クライアント/サーバ アプリケーションはその後、クライアント アプリケーション機能を実行します。共同クライアント/サーバ アプリケーションでは、 ORB の不定期な確認を、確実に行う必要があります。行われない場合、共同クライアント/サーバ アプリケーションは呼び出しをまったく処理しません。
共同クライアント/サーバ アプリケーションが要求でブロックされている間は、ORB でコールバックを提供できないことに注意してください。共同クライアント/サーバ アプリケーションが別の Oracle Tuxedo CORBA サーバ アプリケーションのオブジェクトを呼び出した場合、その応答を待つ間 ORB はブロックされます。ブロック中の ORB はコールバックを扱うことができないため、要求が完了するまでコールバックはキュー入れられます。
ノーティフィケーション サービス アプリケーション開発の最後のステップでは、アプリケーションをコンパイル、ビルド、および実行します。そのためには、次の手順を実行する必要があります。
クライアント スタブ ファイルとスケルトン ファイルを生成するには、アプリケーションで使用されるノーティフィケーション IDL ファイルごとに idl
コマンドを実行する必要があります。表 3-2 は、各タイプのサブスクライバで使用する idl
コマンドを示しています。
>idl -IC:\tuxdir\include C:\tuxdir\include\CosEventComm.idl
表 3-3 は、Oracle シンプル イベント インタフェースを使用する各タイプのノーティフィケーション サービス アプリケーションで必要な IDL ファイルを示しています。
ビルドの手続きは、ノーティフィケーション サービス アプリケーションのタイプによって異なります。表 3-4 は、各タイプのノーティフィケーション サービス アプリケーションをビルドするために使用するファイルのコマンドと種類を示しています。
コード リスト 3-8 は、Microsoft Windows システム上の C++ ポスト元アプリケーション (Reporter.cpp
) で使用するコマンドを示しています。C++ の実行可能ファイルを作成するために、idl
コマンドが必要な IDL ファイルで実行され、buildobjclient
コマンドによって C++ クライアント アプリケーション ファイルと IDL スタブがコンパイルされます。
# idl コマンドを実行
idl -IC:\tuxdir\include C:\tuxdir\include\CosEventComm.idl \
C:\tuxdir\include\CosNotification.idl \
C:\tuxdir\include\CosNotifyComm.idl \
C:\tuxdir\include\Tobj_Events.idl \
C:\tuxdir\include\Tobj_SimpleEvents.idl
# buildobjclient コマンドを実行
buildobjclient -v -o subscriber.exe -f " \
-DWIN32 \
Reporter.cpp \
CosEventComm_c.cpp \
CosNotification_c.cpp \
CosNotifyComm_c.cpp \
Tobj_Events_c.cpp \
Tobj_SimpleEvents_c.cpp \
"
# アプリケーションを実行
is_reporter
コード リスト 3-9 とコード リスト 3-10 は、それぞれ Microsoft Windows および UNIX 上の C++ サブスクライバ アプリケーション (Subscriber.cpp
) で使用するコマンドを示しています。C++ の実行可能ファイルを作成するために、-P
オプションを設定した buildobjclient
コマンドによって、共同クライアント/サーバ アプリケーション ファイル (Subscriber.cpp
と NewsConsumer_i.cpp
)、IDL スタブ、および IDL スケルトン (CosNotifyComm_s.cpp
) がコンパイルされます。
# idl コマンドを実行
idl -P -IC:\tuxdir\include C:\tuxdir\include\CosEventComm.idl \
C:\tuxdir\include\CosNotification.idl \
C:\tuxdir\include\CosNotifyComm.idl \
C:\tuxdir\include\Tobj_Events.idl \
C:\tuxdir\include\Tobj_SimpleEvents.idl
# buildobjclient コマンドを実行
buildobjclient -v -P -o subscriber.exe -f " \
-DWIN32 \
Subscriber.cpp \
NewsConsumer_i.cpp \
CosEventComm_c.cpp \
CosNotification_c.cpp \
CosNotifyComm_c.cpp \
CosNotifyComm_s.cpp \
Tobj_Events_c.cpp \
Tobj_SimpleEvents_c.cpp \ c:\tuxdir\lib\libbeawrapper.lib \
"
# アプリケーションを実行
is_subscriber
# idl コマンドを実行
idl -P -I/usr/local/tuxdir/include /usr/local/tuxdir/include/CosEventComm.idl \
/usr/local/tuxdir/include/CosNotification.idl \
/usr/local/tuxdir/include/CosNotifyComm.idl \
/usr/local/tuxdir/include/Tobj_Events.idl \
/usr/local/tuxdir/include/Tobj_SimpleEvents.idl
# buildobjclient コマンドを実行
buildobjclient -v -P -o subscriber -f " \
Subscriber.cpp \
NewsConsumer_i.cpp \
CosEventComm_c.cpp \
CosNotification_c.cpp \
CosNotifyComm_c.cpp \
CosNotifyComm_s.cpp \
Tobj_Events_c.cpp \
Tobj_SimpleEvents_c.cpp \
-lbeawrapper \
"
# アプリケーションを実行
is_subscriber