メッセージング
Nexaweb アプリケーションを実行する際に、Nexaweb クライアント (以下「クライアント」と表記) と Nexaweb サーバー (以下「サーバー」と表記) は Networking API のセットを使用して通信します。この API は HTTP プロトコルに基づいており、セキュリティで保護された接続用の SSL に対応しています。ここでは、次の通信インフラストラクチャについて説明します。
基本的なクライアント/サーバー間通信
一般的なメッセージング機能の使用:
クライアントサイド メッセージング
サーバーサイド メッセージング
詳細トピック
プッシュ接続
例外処理
高信頼性メッセージング
基本的なクライアント/サーバー間通信
クライアントは、 NetService インターフェイスを使用してサーバーと通信します。このインターフェイスでは、HTTP の GET/POST に相当する標準的な関数のほか、メッセージング、プッシュ接続、およびバックグラウンドポーリング機能に使用される高度な関数を使用できます。サーバー は、標準のリクエストに対するレスポンス、またはクライアントの PushConnection リクエストに対する PushConnection を通じて、クライアントにデータやメッセージを送信します。
NetService の取得
NetService インスタンスの数は、Nexaweb クライアントセッションの 1 つのインスタンスにつき 1 つのみです。次の呼び出しによって、MCO で NetService インスタンスを取得できます。
ClientSession session = McoContainer.getClientSessionFromMco(this);
NetService netService = _clientSession.getNetService();
HTTP の GET/POST に相当する関数
retrieve/retrieveAsynchronously
この関数セットを使用すると、サーバーからデータを取得できます。retrieve メソッドを文字列 URL または HttpRequest オブジェクトに渡すことができます。retrieve メソッドを呼び出した後で、HttpResponse を取得します。
HttpResponse response = netService.retrieve("data.jsp");または
HttpRequest request = netService.createHttpRequest();
request.setUri("data.jsp");
request.setContent("userid=1234&password=1234");
netService.retrieve(request);
アプリケーションで retrieve メソッドの呼び出しに時間がかかる場合は、retrieveAsychronously を使用して他の作業を行えるようにするか、UI を応答可能にします。応答可能な場合にはリスナに通知するように、NetServiceListenerインターフェイスを実装してリスナを非同期メソッドに追加できます。次にその例を示します。
NetServiceListener listener = new MyNetServiceListenerImpl();
netService.retrieveAsynchronously("data_from_a_long_task.jsp", listener);
retrieveAndProcess/retrieveAndProcessAsynchronously
UI 要素の更新やドキュメントデータの更新など、取得するデータが Nexaweb を認識する場合には、retrieveAndProcess API が多くの場合適しています。retrieveAndProcess API のパラメータに必要な条件は retrieve の場合とまったく同じです。ただし、retrieveAndProcess で は、データ取得後にもう 1 つ処理が行われ、レスポンスデータが DOM プロセッサによって自動的に処理されます。これは、メソッドの実行が終了したときに、UI の更新やドキュメントデータの更新が自動的に行われることを意味します。次に、コード例を使用して説明します。
クライアントサイドの MCO
netService.retrieveAndProcess("alertUser.jsp");
<% if (pwd==null) {%>
<messageDialog title="Warning" message="You have to input your password." type="warning"/>
<%}else{%>
// 通常のコードロジック
<%}%>
alertUser.jsp
retrieveAndProcessを呼び出すことができます。次に、サーバーサイドで、通常のロジックに進むか、ユーザーに警告メッセージを表示するかを決めることができます。
retrieveAndProcessAsynchronouslyは非同期で使用できるようにデザインされています。NetServiceListener のインスタンスを渡す必要があり、このインスタンスは、このレスポンスのプロセスが完了した後で呼び出されます。
PushConnection とポーリング
クライアントサイドの呼び出しでは、
openPushConnection/closePushConnection
PushConnection は、サーバーからクライアントへのデータストリームにライブ接続を提供します。クライアントとサーバーの両方で接続を維持するのは費用がかかりますが、ク ライアントでデータ更新を即座に行う必要がある場合には最大の効果を発揮します。クライアントは、サーバーに対してプッシュ接続を 1 つだけ確立できます。NetService では、次の呼び出しによってプッシュ接続を開くことができます。
netService.openPushConnection();
プッシュ接続を閉じるには、次の呼び出しを行います。
netService.closePushConnection();
プッ シュ接続は 1 つの Nexaweb クライアントセッションにつき 1 つしか使用できませんが、接続を閉じるまでこの接続は有効です。PushConnection を使用して、さまざまな種類のデータをサーバーからクライアントに送信することができます。次に、PushConnection がオンになっている場合に適用される 2 つの規則を示します。
すべての publish メッセージ、クライアント DOM の更新内容は、PushConnection によってクライアントに引き継がれます。
ただし、 retrieve、retrieveAndProcess、およびこれらの非同期メソッドを呼び出した場合、そのレスポンスは PushConnection を経由しません。これらのメソッドは、独自の http リクエストから HttpResponse オブジェクトを返す必要があるためです。
フラッシュやフラッシュポリシーなどに関連した PushConnection の機能については、後でさらに詳しく説明します。
startPolling()/stopPolling()
Web アプリケーションを構築する際、クライアントとサーバー間の状態の同期化について 2 つの問題があります。通常、開発者は次のような処理を行います。
Synchronize または RetrieveAndProcess を使用してリクエストをサーバーに手動で送信します。必要なリソースの量は最も少ないですが、更新が完了した時にのみデータが更新されます。
ポーリングによって自動更新を行います。最もバランス良くリソースが使用され、リアルタイムでデータが取得されます。
ライブのプッシュ接続を維持します。大量のリソースが使用され、サーバーからクライアントへの単方向のみに対応しています。即時に応答が得られるため、正真正銘のリアルタイム データが必要な場合に最適です。
ライブデータを更 新する間隔が数秒またはそれ以上でもかまわない場合は、ポーリングの使用によりこれらの問題が解決されます。定期的な同期化リクエストをサーバーに送信す るバックグラウンドスレッドでは、ポーリングによってクライアントサイドとサーバーサイドの両方でセッションデータを更新できます。次の呼び出しによっ て、クライアントサイドでポーリングを有効または無効にすることができます。
netService.startPolling();
または
netService.stopPolling();
PushConnection とポーリングの起動設定
クライアントセッションが既に開始している場合には、上の API を使用して PushConnection とポーリングを有効にできます。ただし、場合によっては、クライアントセッションの開始時にこれらを有効にする必要があります。この設定を行うには、WEB-INFフォルダ内の /session-configurations/default-session-configuration/configuration/ にある nexaweb-client.xml を使用します。
begin-polling-on-startup: これを true に設定すると、クライアント セッションの開始時にポーリングを有効にします。
polling-interval: ポーリングを実行する間隔をミリ秒単位で指定する長整数型 (long) の値です。これは、サーバーとの同期化でポーリング スレッドが待機する相対的な最大時間です。「相対的」というのは、最後に行われたクライアント/サーバー間通信を基準として、待機状態が新たに開始される ことを意味します。たとえば、ユーザーがボタンを押す操作によって
retrieveAndProcess の呼び出しが発生し、内部の待機プロセスが新たに開始されます。
establish-push-connection-on-startup: これを true に設定すると、クライアントがプッシュ接続を起動時に正しく確立します。
プッシュ 接続またはポーリングを開始する方法にかかわらず、openPushConnection と startPolling をさらに呼び出した場合には、返されるだけです。プッシュ接続またはポーリングを再開するには、それらを停止してから再び開始しなければなりません。
詳細については、com.nexaweb.client.netservice パッケージ内の API ドキュメントを参照してください。
一般的なメッセージングの使用
Nexaweb Platform は、クライアントからサーバー、クライアントからクライアント、サーバーからサーバー、サーバーからクライアントへの強力なメッセージングバスを提供しま す。クライアントサイドとサーバーサイドの両方に対称型の API があります。メッセージはメッセージバスを通じて送信されます。クライアントサイドまたはサーバーサイドのどちらからでもメッセージの発行、参加、および メッセージの受信が可能です。
クライアントサイドのメッセージングの使用
subscribe/unsubscribe/publish
Nexaweb サーバーのメッセージングバスのサポート機能により、クライアントでトピックへの参加やメッセージの発行が簡単に行えます。たとえば、ユーザーが特定のトピックに参加する必要がある場合、次のようにコードを記述できます。
netService.subscribe("fianical_topic", myTopicMessageListener);
次に、サーバーまたは他のクライアントのいずれかで、"finanical_topic" のメッセージが発行されるたびに、このメッセージはクライアントに送信されます。myTopicMessageListener は、MessageListenerインターフェイスのビジネス固有の実装です。このメッセージが到着すると、そのインスタンスが通知されます。このメッセージは、記述したコードによって希望の方法で処理されます。次の呼び出しを行うまで、リスナはこのトピックのメッセージを継続的に受信します。
// この呼び出しにより、このトピックへのすべてのリスナの参加を取り消します。
netService.unsubscribe("finanical_topic");
または
// この呼び出しにより、この特定のリスナの参加を取り消します。
netService.unsubscribe("finanical_topic", myTopicMessageListener);
メッセージを発行するのはさらに簡単で、多重定義されている 6 つの publish メソッドのいずれかを呼び出すだけです。次に、文字列メッセージを発行する例を示します。
netService.publish("financial_topic", "what is today's interest rate?");
このように指定すると、"fianical_topic" トピックに参加しているすべての人がこのメッセージを取得します。
MessageListener の実装
前のセクションでは、MessageListener について簡単に触れました。ここでは、MessageListener の実装方法について説明します。
abstract クラスの com.nexaweb.messaging.MessageListener を拡張することによって、独自のメッセージ リスナを実装します。この abstract クラスを拡張するには、対象となる onMessage メソッドをオーバーライドします。
多重定義された 6 つの onMessage 呼び出しは、次のメッセージのタイプにそれぞれ使用されます。
onMessage ( String topic, String message ) - 文字列メッセージ
onMessage ( String topic, byte[] bytes ) - バイト配列メッセージ
onMessage ( String topic, com.nexaweb.xml.Document document ) - Nexaweb XML ドキュメント メッセージ
onMessage ( String topic, com.nexaweb.xml.Element element ) - Nexaweb XML 要素メッセージ
onMessage ( String topic, Serializable serializable ) - Java の直列化可能オブジェクト。実行時にこのクラスの定義がクライアントで使用できることを確認する必要があります。
onMessage ( String topic, XmlSerializable xmlSerializable ) - Nexaweb の XML 直列化可能メッセージ。この方法は、ストリームをオブジェクトに直列化解除する場合にクラスの直列化 ID に依存しないため、XML オブジェクトの直列化により適しています。xmlSerializable インターフェイスから fromXml 呼び出しを使用して、ストリームを直列化解除します。
次の多重定義された 6 つの publish メソッドは、6 つの onMessage 多重定義関数にマップします。
publish ( String topic, String message )
publish ( String topic, byte[] bytes )
publish ( String topic, com.nexaweb.xml.Document document )
publish ( String topic, com.nexaweb.xml.Element element )
publish ( String topic, Serializable serializable )
publish ( String topic, XmlSerializable xmlSerializable )
また、クライアントサイドで、リスナ インスタンスの Nexaweb クライアント セッション オブジェクトにアクセスする必要がある場合は、MCO から取得する clientSession オブジェクトを拡張メッセージ リスナのコンストラクタに渡すだけです。
com.nexaweb.client.netservice パッケージ内の API ドキュメントには、さらに詳しい説明があります。
サーバーサイドのメッセージングの使用
サーバーサイドでは、メッセージングサービスを次のように取得します。
MessagingService messagingService = ServiceManager.getMessagingService();
トピックへの参加またはトピックへの参加取り消し
クライアントサイドでトピックに参加する場合と同じように、トピックへの参加または参加の取り消しができます。
messagingService.subscribe("fianical_topic", myTopicMessageListener);
messagingService.unsubscribe("fianical_topic", myTopicMessageListener);
すべてのリスナへのメッセージの発行
または
クライアントサイドでメッセージを発行する場合と同じように、次の呼び出しを行うだけで、すべてのリスナにメッセージを発行できます。
messagingService.publish("financial_topic", "what is today's interest rate?");
特定のクライアントセッションへの指定メッセージの送信
あるトピックのメッセージを特定のセッションに送信する必要がある場合は、次のように指定します。
// 対象となる特定のセッションを検出します。
SessionManager smgr = ServiceManager.getSessionManager();
ServerSession nxsession = smgr.findByRequest(request);
// このクライアントセッションがこのトピックに参加しているかどうか確認します。
// 参加していない場合は、クライアントがこのメッセージを受信することはありません。
if ( messagingService.isClientSubscribed( nxsession ) ){
// メッセージをキューに入れる場合は、sendAsynchronously を呼び出すことをお勧めします。
messagingService.sendAsynchronously(nxsession, "financial_topic", "this is today's rate");
// また、メッセージがクライアントのストリームに記述されるまでブロック化呼び出しを行うことができます。
// messagingService.send(nxsession, "financial_topic", "this is today's rate");
}
com.nexaweb.server.messaging パッケージ内の API ドキュメントには、さらに詳しい説明があります。
詳細トピック
プッシュ接続の効果的な使用
ネット ワークのセットアップ方法 (プロキシ サーバーの使用など) やクライアントの JVM 実装 (SSL を使用した接続など) によって、プッシュ接続の使用が制限される場合があります。このような問題を解決するために、Nexaweb Platform では、柔軟性と拡張性に優れたフラッシュ ポリシーのセットが用意されています。
次に、フラッシュポリシーが動作する仕組みについて説明します。
1 つの接続につき 1 つの FlushPolicy のインスタンスを使用して、プッシュ接続を設定できます。このポリシーをプログラム方式または設定方式に設定します。
ポリシーは、永続的な接続を通じて送受信されるコンテンツをイントロスペクトし、この設定に基づいてアクション (プッシュ接続でのflush() 呼び出し) を実行するタイミングを決定します。
各種ポリシーは、nexaweb-client.xml ファイルで指定した設定に基づいて、さまざまなインバウンド接続に適用される場合があります。
プロキシ バッファをフラッシュするか、ストリームを閉じるために、空白文字を接続に送信するようにポリシーを設定できます。
フラッシュポリシーは、次の3種類の方法で指定できます。
ポリシーは nexaweb-client.xml で指定されます。
default-session-configuration または session-configuration 要素の子
開発者は、FlushPolicy またはサーバー API で定義される ConfigurableFlushPolicy のいずれかを実装する独自のコードを記述できます。
次の例では、 Microsoft JVM 1.1 を使用して、100 ミリ秒ごとに 5K の容量をフラッシュするフラッシュポリシーを指定します。Microsoft JVM 1.1 はプッシュ接続を使用してコンテンツをバッファするため、Java API の呼び出しでデータを取得するように、このようなフラッシュを実行する必要があります。
<default-session-configuration>
<configuration>
<push-connection-flush-policies>
<policy>
<rules>
<match xpath="starts-with(/client-info/java-version, '1.1')" />
<match xpath="starts-with(/client-info/java-vendor, 'Microsoft')" />
</rules>
(未完成)