BEA ホーム | 製品 | dev2dev | support | askBEA
 ドキュメントのダウンロード   サイト マップ   Glossary 
検索

WebLogic Server FAQ 集

 Previous Next Contents PDF で侮ヲ  

FAQ: JMS

BEA WebLogic JMS 製品

コンフィグレーション

永続ストレージ

管理

トランザクション サポート

JMS プログラミングの慣習

メッセージ駆動型 Bean

Q. WebLogic JMS がユニークである理由は何ですか。

A. WebLogic JMS をユニークにしている特長は以下のとおりです。

Q. WebLogic Server 7.0 の新しい JMS 機能は何ですか。

A. バージョン 7.0 の新機能は以下のとおりです。

Q. WebLogic JMS の詳細情報はどこで参照できますか。

以下のリンクを利用すれば、WebLogic JMS の詳細情報を参照できます。

『WebLogic JMS プログラマーズ ガイド』

『管理者ガイド』の「JMS の管理

Sun Microsystems の JMS 仕様

BEA の dev2dev Web サイト

BEA

BEA ニュース グループ サーバ上で利用可能な WebLogic JMS ニュースグループ「weblogic.developer.interest.jms」

Q. WebLogic JMS への C/C++ インタフェースは存在しますか。

A. いいえ、これはサポートされていません。

Q. クライアントをサポートするための weblogic.jar ファイルの小型軽量バージョンはありますか。

A. WebLogic Server でシン クライアント アプリケーションを構築するための現在のオプションについては、http://dev2dev.bea.com/technologies/jms/index.jsp にある「Small Footprint Client Options for BEA WebLogic Server」ホワイトペーパー (WebLogicThinClient.zip) で説明されています。

weblogic.jar の独自の軽量バージョンを作成する方法については、news://newsgroups.bea.com/3ad4ad17@newsgroups.bea.com も参照してください。

Q. WebLogic Server を起動して JMS をコンフィグレーションする方法を教えてください。

A. WebLogic Server の起動、Administration Console へのアクセス、および WebLogic JMS のコンフィグレーションに関する詳細な指示については、『管理者ガイド』の「JMS の管理」を参照してください。

Q. WebLogic JMS セキュリティはどのようにコンフィグレーションするのですか。

A. 以前のバージョンの WebLogic Server では、ACL を使って WebLogic リソースを保護していました。WebLogic Server バージョン 7.0 では、WebLogic リソースへの「アクセス権は誰が持つか」という問いに、セキュリティ ポリシーが答えます。セキュリティ ポリシーは、WebLogic リソースと、ユーザ、グループ、またはロールとの間に関連を定義したときに作成されます。WebLogic リソースは、セキュリティ ポリシーを割り当てられるまでは保護されません。

すべての WebLogic Server リソースに対してセキュリティを設定する方法に関する詳細については、Administration Console オンライン ヘルプの「WebLogic リソースの保護の設定」を参照してください。

Q. WebLogic JMS 5.1 でサポートされていたデフォルト接続ファクトリはまだ使用できますか。

A. はい。それ以降のバージョンの WebLogic JMS で、5.1 の接続ファクトリを使うことに関する詳細情報については、『WebLogic JMS プログラマーズ ガイド』の「WebLogic JMS アプリケーションの移植」を参照してください。

Q. JMSSession.createTopic または JMSSession.createQueue が WebLogic JMS 7.0 で送り先の作成に失敗するのはなぜですか (5.1 では正常に作成されます)。

A. この問題の詳細な説明については、バージョン 6.1 FAQ 集の「FAQ: JMS」を参照してください。

Q. キューまたはトピックのリストをプログラマティックに取得するにはどのようにすればよいですか。

A. 次のプログラムは MBean を使用します。

import weblogic.management.*;
import weblogic.management.configuration.*;

InitialContext ic = new InitialContext();
MBeanHome home = (MBeanHome)ic.lookup(MBeanHome.ADMIN_JNDI_NAME);

for(Iterator i = o.getMBeansByType("JMSTopic").iterator();
i.hasNext(); ){
WebLogicMBean wmb = (WebLogicMBean)i.next();
System.out.println("topic name found:" + wmb.getName());
}
for(Iterator i = o.getMBeansByType("JMSQueue").iterator(); i.hasNext(); ){
WebLogicMBean wmb = (WebLogicMBean)i.next();
System.out.println("queue name found:" + wmb.getName());
}

Q. 一時的な送り先はどのように使用するのですか。

A. 一時的な送り先を作成するすべての JMSServer にテンプレートを作成する必要があります。Temporary Template をサポートするために複数の JMSServer エントリを指定できます。これらの JMSServer の間でロード バランシングが行われ、一時的な送り先が設定されます。JMS のコンフィグレーション方法については、「WLS を起動して JMS をコンフィグレーションする方法を教えてください」を参照してください。作成されるテンプレート定義は、次のようになります。

<JMSTemplate  Name="MyTemplate"/>

JMSServer は次のように定義されます。

<JMSServer Name="MyJMSServer" TemporaryTemplate="MyTemplate" Targets="MyServer" >

テンプレート名の後に、テンプレートに任意のキュー/トピック属性を設定できます (JNDI 名とトピック マルチキャスト設定は含みません)。このテンプレートは最も外側のレベルに存在します。このため、<JMSServer> の中でネストすることはできません。

一時的な送り先は、作成する接続によってのみ消費されます。トピックを使用する場合、一時的なトピックを作成して、そのトピックにサブスクライブします。誰かにその一時的なトピックにパブリッシュしてもらうには、その人に自分のトピックを教える必要があります。その人にメッセージを送信して、一時的なトピックを JMSReplyTo フィールドに挿入できます。TemporaryTopic の作成者とサブスクライバは、同じでなければなりません。

import javax.jms.TopicSession;
TemporaryTopic myTopic = mySession.createTemporaryTopic();
TopicSubscriber = mySession.createSubscriber(myTopic);

一時的なトピックは、名前を取得せず、他の接続によってサブスクライブできません。一時的なトピックを作成すると、JMS プロバイダは javax.jms.Topic を返します。そのトピックは、他の当事者 (トピックにパブリッシュする人たち) に公開する必要があります。そのためには、JMSReplyTo フィールドにそのトピックを入れて、それらの当事者が応答できるようにします。一般に、そのトピックは他の誰もサブスクライブできません。トピックは、自分の好きなように公開できます。トピックは、シリアル化 (外部化) できます。このため、ファイルを介して RMI 呼び出しで受け渡し、JNDI 名にバインドできます。つまり、サブスクライバ サイドでトピックを作成し、他人がパブリッシュできるようにそれを公開できます。同じ接続で複数のサブスクライバを取得し、複数のセッションを使用して並行処理を取得できます。

Q. MBean を使用して実行時統計を出力する方法を教えてください。

A. ニュースグループの記事、news://newsgroups.bea.com/3B3B77A9.CDCE3954@not.my.address.com に、実行時 MBean に基づいて JMS 統計を出力するプログラムが掲載されています。

Q. 2 つの JMS サーバで同じ永続ストレージを共有できますか。

A. できません。各 JMS サーバは、それぞれ独自の永続ストレージを使用する必要があります。ファイルベースの 2 つの JMS 永続ストレージは同じディレクトリを共有できますが、それらのメッセージは別々のファイルに格納されます。この場合、ファイル名では別々のプレフィックスが使用されます。

JDBC ベースの 2 つの JMS 永続ストレージは同じデータベースを共有できますが、データベース テーブルのプレフィックス名に別々のものを使用するようにコンフィグレーションする必要があります。JDBC プレフィックス名のコンフィグレーションの詳細については、Administration Console オンライン ヘルプの「JMS JDBC ストア」を参照してください。同じプレフィックス名でコンフィグレーションすると、永続的メッセージは壊れるか、失われてしまいます。

Q. WebLogic JMS ではどのタイプの JDBC データベースがサポートされているのですか。

A. JMS データベースには、JDBC ドライバからアクセスできる任意のデータベースを指定できます。WebLogic JMS では、以下のデータベースに対応する一部のドライバが検出されます。

weblogic.jar ファイル内の weblogic/jms/ddl ディレクトリには、上記のデータベース用の JMS DLL ファイルがあります。これらは、JMS データベース テーブルを作成する SQL コマンドを含むテキスト ファイルです。

Q. WebLogic JMS でサードパーティの JDBC ドライバを使用する方法を教えてください。

使用する JDBC ドライバが、WebLogic JMS でサポートされる JDBC データベースに関する質問のドライバ リストに含まれていない場合は、JMS が必要とするテーブルを手動で作成する必要があります。

注意: WebLogic Server では、上のリストに含まれている JDBC ドライバだけがサポートされます。他の JDBC ドライバはサポートされません。

weblogic.jar ファイルの weblogic/ms/ddl ディレクトリに配置されている .ddl ファイルは、テンプレートとして使用できます。JDK で用意されている jar ユーティリティを使用すると、次のコマンドでそれらを weblogic/jm/ddl ディレクトリに抽出できます。

jar xf weblogic.jar weblogic¥jms¥ddl

注意: 2 番目のパラメータ (weblogic¥jms¥ddl) を省略すると、jar ファイル全体が抽出されます。

JDBC ストア用のデータベース テーブルを手動で作成するには、『WebLogic JMS プログラマーズ ガイド』の「JDBC データベース ユーティリティ」の手順に従ってください。

JDBC ストアの代わりにファイル ストアを使用する方法もあります。ファイル ストアはコンフィグレーションが簡単であり、パフォーマンスが大幅に向上することもあります。

Q. JDBC データベースで障害が発生した場合はどうなるのですか。

JDBC ストア テーブルの削除および再作成の手順、またはデータベース テーブルの手動作成の手順については、『WebLogic JMS プログラマーズ ガイド』の「JDBC データベース ユーティリティ」に説明してあります。

Q. 永続性はどのように使用するのですか。

A. 次のガイドラインを使用してください。

  1. 使用する JMSServer にストアがコンフィグレーションされていることを確認します。config.xml ファイルの JMSServer コンフィグレーション エントリには次の形式の行が含まれている必要があります。
    Store="<YOUR-STORE-NAME>" 

    ストアがコンフィグレーションされていない JMS が起動すると、ユーザがそのストアを必要としていないと見なされ、永続メッセージが自動的に非永続的メッセージにダウングレードされます (JMS 1.0.2 b に指定されているとおり)。

  2. 「Message.setJMSDeliveryMode」を使用しないようにします。こればベンダ専用のメソッドなので上書きされます。

  3. 以下のいずれかを呼び出す必要があります。
    QueueSender.send(msg, deliveryMode, ...)

    または

    QueueSender.setDeliveryMode(deliveryMode)

    または

    config.xml ファイルで接続ファクトリに対する DefaultDeliveryMode を永続的に設定します (QueueSender.setDeliver/send はこの値をオーバーライドします)。同様に、トピックの場合は TopicPublisher を介してこれを設定します。

  4. config.xml ファイルで送り先に対する「DeliveryModeOverride」が非永続的に設定されていないことを確認します。

  5. pub/sub を使用する場合、恒久サブスクリプションだけがメッセージを永続させます。非恒久サブスクリプションは、メッセージを永続させる必要がありません。これらは定義によってサーバの存続期間中にのみ存在するからです。

  6. JDBC を使用する場合、JMS サーバの起動時に JDBC テーブル、JMSSTATE、および JMSSTORE が自動的に作成されます。テーブルの作成に使用される DDL ファイルは、weblogic jms ddl の weblogic.jar に格納されます。以下のコンフィグレーション例は、Oracle 用の JDBC ストアを示したものです (最新の Oracle 動作確認情報については、「動作確認状況」ページを参照してください)。テーブルを手動で作成する (および既存のテーブルを削除する) には、前述の質問で説明したとおり、java utils.Schema を実行します。

JMS のコンフィグレーション方法については、「WLS を起動して JMS をコンフィグレーションする方法を教えてください」を参照してください。

以下に、JMS がコンフィグレーションされた config.xml ファイルのサンプルを示します。このサンプルは、実際に使用するファイルとほぼ同じであるはずです。JMS でデータベースの代わりにファイル ストアを使用する場合、JMSServer セクションの JDBCStoreFileStore に変更します。

<Server Name="myserver"
ListenPort="7001" DefaultProtocol="t3"
ThreadPoolSize="8" >
</Server>
<Security Realm="defaultRealm"
GuestDisabled="false" />
<Realm Name="defaultRealm"
FileRealm="defaultFileRealm" />
<FileRealm Name="defaultFileRealm"
/>
<JMSServer Name="TestJMSServer"
TemporaryTemplate="TestTemplate1"
Targets="myserver" Store="JDBCStore">
<JMSQueue Name="TestQueue1"
JNDIName="jms.queue.TestQueue1"
Template="TestTemplate1"
/>
</JMSServer>
<JMSTemplate Name="TestTemplate1"
/>
<JMSFileStore Name="FileStore"
Directory="myfilestore"
JMSServer="TestJMSServer"
/>
<JMSJDBCStore Name="JDBCStore"
ConnectionPool="testpool2"
JMSServer="TestJMSServer"
/>
<JDBCConnectionPool Name="testpool2"
Targets="myserver"
URL="jdbc:weblogic:oracle"
DriverName="weblogic.jdbc.oci.Driver"
InitialCapacity="0"
MaxCapacity="1"
CapacityIncrement="1"
Properties="user=SCOTT;password=tiger;server=bay816"
/>
</Domain>

次に、構築時にトピック メッセージを送信するサンプル クラスを示します。

import javax.naming.*;
import javax.jms.*;
import java.util.Hashtable;
public class t
{
public final static String DESTINATION="jms.topic.TestTopic1";
private TopicConnectionFactory connectionFactory;
private TopicConnection connection;
private TopicSession session;
private TopicPublisher producer;
private TextMessage message;
private Topic destination;
public t()
{
try {
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
env.put(Context.PROVIDER_URL, "t3://localhost:7001");
InitialContext ctx = new InitialContext(env);
destination = (Topic) ctx.lookup(DESTINATION);
connectionFactory = (TopicConnectionFactory)
ctx.lookup("javax.jms.TopicConnectionFactory");

connection = (TopicConnection)
connectionFactory.createTopicConnection();
session = (TopicSession) connection.createTopicSession(false,
Session.AUTO_ACKNOWLEDGE);

producer = (TopicPublisher) session.createPublisher(destination);
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
message = (TextMessage) session.createTextMessage();
message.setText("hello world");
producer.publish(message);
} catch (Exception e) {
}
}
}

Q. ファイル ストアと JDBC ストアの比較はどのように行えばよいですか。

A. 以下に、ファイル ストアと JDBC ストアの類似点と相違点を挙げます。

Q. JMS サーバ/送り先メッセージの最大値としきい値はどのように機能するのですか。

A. バイトとメッセージの最大値はフロー制御ではなく割り当てです。メッセージの割り当てにより、WebLogic JMS サーバがメッセージで一杯になり、メモリが不足して、予期しない結果になることが防止されます。割り当てに到達すると、JMS は (ブロッキングではなく) ResourceAllocationException によってそれ以上の送信を防ぎます。割り当ては、個々の送り先またはサーバ全体に設定できます。

同様に、しきい値もフロー制御ではありません。ただし、しきい値は割り当てよりもそのアプリケーションに適しています。しきい値は、超過した場合にメッセージをコンソールに記録するための設定値に過ぎません。これにより、ユーザは対処に遅れたことを知ることができます。

注意: WebLogic JMS 7.0 はフロー制御機能を備えています。この機能では、JMS サーバまたは送り先が、過負荷になりつつあるときにメッセージ プロデューサをスロー ダウンできます。特に、JMS サーバ/送り先は、指定されたバイトまたはメッセージしきい値を超えたときに、メッセージ フローを制限するようにプロデューサに指示します。詳細については、『管理者ガイド』の「JMS の管理」を参照してください。

接続ファクトリに対するメッセージの最大数の設定は割り当てではありません。これは、サーバから送信されてから非同期コンシューマが見るまでの間に存在する未処理メッセージの最大数を指定します。このデフォルト値は 10 です。

Q. JDBC をコンフィグレーションして JMS JDBC ストアが自動的に回復するようにする方法を教えてください。

A. JDBC ストアを使用しており、DBMS がダウンしてオンライン復帰した場合、JMS は WebLogic Server をシャットダウンして再起動するまで JDBC ストアにアクセスできないという問題があります。この問題を回避するには、JMSJDBCStore に関連付けられている JDBC 接続プールの次の属性をコンフィグレーションします。

TestConnectionsOnReserve="true"¥
TestTableName="[[[catalog.]schema.]prefix]JMSState"

Q. バージョン 7.0 での WebLogic JMS クラスタ化の価値は何ですか。

A. バージョン 6.x では、『WebLogic JMS プログラマーズ ガイド』の「WebLogic JMS の管理」で説明されているように、複数の接続ファクトリをコンフィグレーションし、対象を用いてそれらを複数の WebLogic Server へ割り当てることで、クラスタ内の任意のサーバから送り先まで、クラスタワイドで透過的なアクセスを確立できました。各接続ファクトリは、複数の WebLogic Server に対してデプロイされる可能性があります。管理者は、サーバがユニークに命名されている限り、クラスタ内のさまざまなノードに複数の JMS サーバをコンフィグレーションすることができます。また、さまざまな JMS サーバに対して送り先を割り当てることもできます。

WebLogic JMS 7.0 では、管理者は複数の送り先をクラスタ内部で単一の分散送り先セットの一部としてコンフィグレーションできます。プロデューサおよびコンシューマは、分散送り先との送受信ができます。クラスタ内部の単一サーバの障害時には、WebLogic JMS は、分散送り先内部で利用可能なすべての物理的送り先に渡って、その負荷を分散します。詳細については、『管理者ガイド』の「分散送り先のコンフィグレーション」を参照してください。

WebLogic JMS 7.0 はまた、クラスタ環境用の WebLogic Server コアで実装された移行フレームワークの利点も得られます。これにより、WebLogic JMS は、移行要求に適切に対応することができ、JMS サーバを通常の方法でオンラインやオフラインにすることができます。これには、WebLogic Server の障害時に対応した移行だけでなく、スケジュールされた移行も含まれます。詳細については、『WebLogic JMS プログラマーズ ガイド』の「WebLogic JMS の管理」を参照してください。

Q. アプリケーションがどの WebLogic Server で実行されるかを制御する方法を教えてください。

A. システム管理者は、接続ファクトリのコンフィグレーション時に対象を指定することで、アプリケーションをどの WebLogic Server で実行するのかを指定できます。各接続ファクトリは、複数の WebLogic サーバにデプロイできます。

注意: デフォルトの接続ファクトリを使用する場合は、接続ファクトリがデプロイされる WebLogic Server を指定できません。特定の WebLogic Server を対象にする場合は、新しい接続ファクトリを作成し、適切な JMS サーバの対象を指定してください。

Q. 手動のフェイルオーバはどのように実行するのですか。

A. WebLogic Server の障害からの回復手順、手動フェイルオーバの実行手順、およびプログラミングの考慮事項については、『管理者ガイド』の「JMS の管理」を参照してください。

Q. WebLogic JMS サーバは、クローズまたは失われた接続、クラッシュ、およびその他の問題を検出して、それらから回復できますか。

A. はい。クライアントがそのリソースをクローズした、ネットワーク接続に失敗した、およびその中に JVM が存在する場合、マルチキャスト pub/sub であっても、JMS サーバは「ピア」の損失を検出して回復します。

Q. WLS T3 プロトコルを使用する必要はありますか。

A. J2EE は、インタフェースを標準化しています。WebLogic の RMI 仕様の実装では、T3 という独自の通信プロトコルが使用されます。Sun の RMI の参照実装では、JRMP という独自のプロトコルが使用されます。WebLogic が T3 を開発した理由は、エンタープライズクラスの分散オブジェクト システムを Java で構築するためのスケーラブルで効率的なプロトコルが必要であったためです。

T3 は WebLogic 独自のプロトコルですが、ユーザのアプリケーション コードは T3 について何も知る必要はありません。このため、これについて心配する必要はありません。「WebLogic 固有の文字列」(PROVIDER_URL、INITIAL_CONTEXT_FACTORY、など) をプロパティ ファイル (またはどこか) に外部化します。これにより、コードを完全に移植可能にして、プロパティ ファイル内のそれらのみを変更するだけで、コードを取得して別の J2EE アプリケーション サーバで実行できるようになります。

Q. HTTP トンネリングはどのようにして行いますか。

A. HTTP トンネリング (すべてのメッセージを HTTP に包み込んでファイアウォールを通過させること) を使用する場合、TunnelingEnabled="true"config.xml ファイルの <Server> 定義に追加するか、Administration Console 上の該当するボックスをオンにする必要があります。次に、InitialContext を取得するときに、Context.PROVIDER_URL 用に t3://localhost:7001 ではなく http://localhost:7001 というような URL を使用します。SSL を使用して HTTP トンネリングを行う場合、https://localhost:7002 を使用します (https は HTTP トンネリングと SSL を使用します。7002 はコンフィグレーションしたセキュアなポートです)。これを行うと、パフォーマンスが低下します。このため、必要な場合にのみ (ファイアウォールを通過する必要がある場合など) トンネリングを使用してください。

Q. WebLogic JMS は SSL をサポートしていますか。

A. はい、SSL は WebLogic JMS 実装でサポートされています。SSL2 は、初期 JNDI コンテキストをルックアップするときに、「t3:」の代わりに「t3s:」で始まる URL を使用することによって、自動的に使用されます。

Q. 非 WebLogic JMS プロバイダと WLS を統合する方法を教えてください。

A. MQ Series、IBus MessageServer、Fiorano、および SonicMQ との統合については、http://dev2dev.bea.com/technologies/jms/index.jsp のホワイト ペーパー「Using Foreign JMS Providers with WebLogic Server」(jmsproviders.pdf) を参照してください。

Q. 2 フェーズ トランザクションまたはグローバル トランザクションは、WebLogic JMS とどのように関連するのですか。

A. 2 フェーズ トランザクションまたはグローバル トランザクションを使用すると、複数のリソース マネージャ (EJB、データベース、JMS サーバなど) が 1 つのトランザクションに参加できます。

たとえばクライアントは、2 フェーズ トランザクションを使用して、1 つの JMS サーバ (サーバ A) のキューから別の JMS サーバ (サーバ B) のキューにメッセージを送信できます。各サーバには、固有の永続ストレージがあります。トランザクションがコミットされると、メッセージがサーバ B で表示可能になります。トランザクションがロールバックされた場合、メッセージはサーバ A のキューに戻されます。

注意: 両方のキューが同じ JMS サーバにある場合は、1 フェーズ トランザクションを使用します。

Q. WebLogic JMS 処理がユーザ トランザクションの一部にならない (トランザクション内で呼び出されるが、適切にロール バックされない) のはなぜでしょうか。トランザクションの問題を追跡するにはどのようにすればよいでしょうか。

A. 通常、この問題は、設計により外部のグローバルなトランザクションを無視するトランザクション セッションを明示的に使用することによって発生します (JMS 仕様の要件)。トランザクション JMS セッションは、常に独自の内部トランザクションを持ちます。これは、呼び出し側が持っているトランザクション コンテキストによって影響されません。

また、この問題は、「UserTransactionsEnabled」が false に設定されている接続ファクトリを使用することによっても発生します。

  1. 以下の 2 つのインポート行を追加して、現在のスレッドがトランザクションに存在するかどうかをチェックできます。
    import javax.transaction.*
    import weblogic.transaction.*;

    また、以下の行を追加します (各処理の直前および直後など)。

    Transaction tran = TxHelper.getTransaction();
    System.out.println(tran);
    System.out.println(TxHelper.status2String(tran.getStatus()));

    これにより、いつ新しいトランザクションが開始し、関連付けが発生するのかを明確に理解できます。

  2. JMS メッセージを送信するスレッドがトランザクションに関連付けられるようにします。createQueueSession または createTopicSession の最初のパラメータを false に設定することによって、コードがトランザクション セッションを使用していないことをチェックします。接続およびセッションの作成は、トランザクションと直交しています。トランザクションは、その前または後に開始できます。メッセージを送信または受信する前に、トランザクションを開始するだけで済みます。

  3. config.xml ファイルで接続ファクトリの UserTransactionsEnabled フラグが明示的に true に設定されていることを確認してください。この値のユーザ コンフィグレーション接続ファクトリのデフォルト値は false であるからです。コンフィグレーション済みの接続ファクトリの 1 つを使用する場合、次のように設定します。
    weblogic.jms.ConnectionFactory は、ユーザ トランザクションを無効化します。このため、ユーザ トランザクションが必要な場合には使用しないでください。

    javax.jms.QueueConnectionFactory および javax.jms.TopicConnectionFactory はユーザ トランザクションを有効化します。

  4. 次の追加プロパティを使用してサーバを起動することによって、JTA 処理を追跡できます。
    -Dweblogic.Debug.DebugJMSXA=true

    以下のようなトレース文がログに表示されます。

    XA ! XA(3163720,487900) <RM-isTransactional() ret=true>

    これを使用すると、JMS をトランザクションに関連付けることができます。

Q. アプリケーションがトランザクションの結果に関係なく JMS 処理を正常に実行する方法を教えてください。

A. 基本的に、JMS 処理がトランザクション セッションを使用して行われるか、またはトランザクションが次のようにサスペンド/無効化されなければなりません (以下の 1 つまたは複数を行います)。

  1. JMS 呼び出しを行う前に現在のトランザクションをサスペンドし、その完了後に再開します。コードは次のようになります。
    import javax.transaction.Transaction;
    import javax.transaction.TransactionManager;
    TransactionManager tranManager= TxHelper.getTransactionManager();
    Transaction saveTx = null;
    try {
    saveTx = tranManager.suspend();
    ... do JMS work, it will not participate in transaction
    } finally {
    // 中断されたトランザクションは常に再開する必要がある
    if (saveTx != null) tranManager.resume(saveTx);
    }

  2. createQueueSession または createTopicSession の最初のパラメータに true を指定することによって、トランザクション セッションを使用します。

  3. 接続ファクトリを使用し、ユーザ トランザクションを無効にします。つまり、config.xml ファイルで接続ファクトリの UserTransactionsEnabled フラグが明示的に false に設定されていることを確認するか、この値のユーザ コンフィグレーション接続ファクトリのデフォルト値の false を使用します。コンフィグレーション済みの接続ファクトリ weblogic.jms.ConnectionFactory はユーザ トランザクションを無効にします。

トランザクション JMS セッションは、常に独自の内部トランザクションを持ちます。これは、呼び出し側が持っているトランザクション コンテキストによって影響されません。非トランザクション JMS セッションはより複雑です。WLS 6.x 以降のデフォルト ファクトリ weblogic.jms.ConnectionFactory を使用する場合、セッションはユーザ トランザクションに参加しません。これは、UserTransactionsEnabled フラグが「False」に設定されているからです。しかし、非推奨の WebLogic 5.1 デフォルトの javax.jms.QueueConnectionFactory または javax.jms.TopicConnectionFactory ファクトリを使用する場合、または独自のファクトリを定義して UserTransactionsEnabled フラグを「True」に設定した場合、JMS セッションは外部のトランザクションに参加します (外部トランザクションが存在し、JMS セッションがトランザクション セッションではない場合)。

Q. トランザクション内で acknowledge() が呼び出された場合、何が起こりますか。

A. Sun Microsystems の JMS 仕様により、トランザクションの中では acknowledgeMode は無視されます。このため、トランザクションの中で acknowledge() メソッドが呼び出された場合、それは無視されます。

Q. トランザクションを必要とする EJB から非トランザクションの TopicSession を使用するときにエラーが発生するのはなぜですか。

A. あるトランザクションに 2 つのリソース (JMS やデータベースなど) が参加するときには、そのトランザクションは 2 フェーズとなります。使用しているデータベース ドライバが XA 互換ではないため、通常 2 フェーズ トランザクションには参加できません。これを解決するには、XA 互換ドライバを使用するか、または JDBCTxDataSource 値をコンフィグレーションして enableTwoPhaseCommit を true に設定します。後者の場合、ヒューリスティック エラーが発生する場合があるので注意してください。JMS を現在のトランザクションに参加させたくない場合、「アプリケーションがトランザクションの結果に関係なく JMS 処理を正常に実行する方法を教えてください」を参照してください。

Q. 他の作業に使用しているのと同じデータベース上に WebLogic JMS JDBC ストアがある場合、1 フェーズ コミットを使用できますか。

A. 使用できません。 WebLogic JMS は自身のリソース マネージャです。つまり、JMS 自体が XAResource を実装し、メッセージがデータベースに格納されている場合でも、データベースに依存せずにトランザクションを処理します。このため、JMS とデータベースを使用するときには、そのデータベースが JMS メッセージが格納されているデータベースと同じである場合でも、常に 2 フェーズ コミットになります。

JMS キューと同じサーバ上にデータベース作業に使用する接続プールが存在していれば、パフォーマンスが向上します。トランザクションは依然として 2 フェーズですが、より小さいオーバーヘッドで処理されるからです。また、JMS JDBC ストアではなく JMS ファイル ストアを使用することによっても、パフォーマンスが向上する場合があります。

Q. XAResource と WLS を統合して、別のリソース マネージャで JTA トランザクションを取得する方法を教えてください。

A. MQ Series の統合については、http://dev2dev.bea.com/products/wlserver61/resources.jsp のホワイト ペーパー「Using JTA Transactions to Envelope WLS JMS and IBM MQSeries」) (jmsjta.doc) を参照してください。

Q. XA ドライバまたは TX データ ソースを使用して WebLogic JMS を起動するときに例外が発生するのはなぜですか。

A. JMS で TX データ ソースを使用することはできません。JMS は、非 XA リソース ドライバを使用する JDBC 接続プールを使用する必要があります (XA ドライバまたは JTS ドライバは使用できません)。enableTwoPhaseCommit オプションは設定しないでください。JMS は JDBC ドライバの上で XA をサポートします。

Q. WL JMS は XAResource 互換ですか。

A. はい。WebLogic JMS 7.0 は XAResource インタフェースを JTA 仕様に定義されているとおりに完全実装しています。バージョン 7.0 では、XAConnectionXAConnectionFactoryXAQueueConnectionXAQueueConnectionFactoryXAQueueSessionXASessionXATopicConnectionXATopicConnectionFactory、および XATopicSession メソッドもサポートしています。これらのメソッドは、Sun Microsystems の JMS 仕様ではオプションとして定義されています。XAResource インタフェースの一部ではありません。

XAResource インタフェースは、トランザクション マネージャが JTA トランザクションを管理するために必要な開始、準備、コミットのようなメソッドを持ち、これらは WebLogic JMS によって提供されます。JMS の送信または受信を JTA トランザクション (開始/コミット) でラップした場合、JMS の処理はトランザクションの一部となります (トランザクション セッションを使用しない場合)。

このため、XAQueueConnectionFactory を使用して XAQueueConnection および XAQueueSession を取得して getXAResource() を呼び出すことはできません。ただし、WebLogic JMS は WebLogic JTA によって自動的に登録されるため、これを心配する必要はありません。また、WebLogic JMS はトランザクションを駆動する別のトランザクション マネージャ (少なくともドキュメント化されているインタフェース) では使用できません。

Q. コンテナ管理トランザクション内で送信したメッセージを受信できないのはなぜですか。

A. コンテナ管理トランザクションを使用している場合、EJB から送信された元のメッセージは送信されません。以下に、何が起こるかを示します。

  1. コンテナがトランザクションを起動します。

  2. メソッドを起動します。

  3. 新しいメッセージを生成します。

  4. メッセージを送信します (実際には送信されず、トランザクションのコミットまでバッファに格納されます)。

  5. キュー上でブロック受信を行います。

  6. メソッドを終了します。

  7. 元のメッセージが送信されなかったため、トランザクションのコミットは行われません。これは、過去のブロック受信を取得できないからです。

これを解決するには、Bean 管理のトランザクションを使用するか、または送信および受信を 2 つの独立したメソッドに分割します。

Q. ロールバックまたは回復されるメッセージはどのようになるのですか。

A. メッセージがロールバックまたは回復されると、そのメッセージが要求されます。キューおよびそのキューのその他のメッセージのソート順序に基づいてメッセージがキューに入れられます。

順序が設定されていないキュー (一般的) では、他のメッセージが同時に回復されない限り、通常メッセージはキューのヘッダに置かれます (キューが到着時間 (FIFO) でソートとされているため)。ただし、ソート順序は競合を解決します。メッセージは可能な限り最初に利用可能なコンシューマに再配信されます。要求時にコンシューマが存在しない場合、コンシューマが現れるまでそのままそこに置かれます。

メッセージの最大要求回数を設定できます。また、要求後にメッセージが使用できなくなるまでの遅延時間も指定できます。メッセージが最大要求回数に達した場合、エラー送り先に置かれるか (コンフィグレーションされている場合)、または通知することなく削除されます。

Q. メッセージを保留にしておいて、後で確認応答することは可能ですか?

A. これを行うためのプリミティブは存在しません。以下に、可能な解決策を 2 つ示します。

1 つは、次のように複数のセッションを使用することです。

while (true) {
Create a session, subscribe to one message on durable subscription
Close session
Save session reference in memory
To acknowledge the message, find the session reference and call
acknowledge() on it.
}

もう 1 つは、トランザクションを使用して、次のように作業をサスペンドすることです。

start transaction
while(true) {
message = receive();
if (message is one that I can handle)
process the message
commit
} else {
suspend transaction
put transaction aside with message
start transaction
}
}

メッセージを「確認応答」するには、次のようにします。

resume user transaction
commit

メッセージを「回復」するには、次のようにします。

resume user transaction
rollback

サスペンドするたびに、トランザクションをメッセージとともにスタックまたはリストに置いて、後で処理またはロールバックできるようにする必要があります。この解決策は、未処理トランザクションが大量に蓄積する可能性があるため、高いオーバーヘッドとなります。トランザクションはタイムアウトを持っており、自身でロールバックする場合があるため、メッセージを (異なるトランザクションで) 再び取得する可能性があることに注意してください。.また、未処理にしておくトランザクションの数には実際的な制限があることにも注意してください。デフォルトの制限は約 10000 です。最終的には、スタック/リストに戻ってトランザクションをコミット/ロールバックします。トランザクション参照 (javax.transaction.Transaction) はシリアル化できないことに注意してください。

Q. ソートされたキューはどのように使用するのですか。

A. 送り先キーは、特定の送り先に対してソート順を定義する場合に使用されます。送り先キーとしては、メッセージ ヘッダまたはプロパティ フィールドを使用できます。有効なメッセージ ヘッダおよびプロパティ フィールドのリストについては、『WebLogic JMS プログラマーズ ガイド』を参照してください。

キューは、送り先キーを基準に昇順または降順でソートできます。送り先は、送り先キーが JMSMessageID メッセージ ヘッダ フィールドの昇順として定義されている場合は先入れ先出しと判断され、降順として定義されている場合は後入れ先出しと判断されます。JMSMessageID ヘッダ フィールドに定義されるキーは、キー リストで定義されている最後のキーでなければなりません。

送り先をソートするために、複数の送り先キーを定義できます。

送り先キーを作成するには、Administration Console の [送り先キー] ノードを使用します。詳細については、Administration Console オンライン ヘルプを参照してください。

Q. メッセージ優先度に基づくソートはどのように機能するのですか。

A. 第 1 に、送り先にキーを追加する必要があります (デフォルトではそれらはソートされていません)。そのためには、JMSPriority をキーとして選択します。最も高い優先度を 0 にする場合は、キーを昇順にします。最も高い優先度を 9 にする場合は、キーを降順にします。

第 2 に、優先度は (メッセージではなく) プロデューサまたはセンダ側で設定される必要があります。

第 3 に、優先度のソートは、待ち状態のメッセージがキューに複数存在する場合に機能します。レシーバが常にセンダに追いついていれば、メッセージは到着した順序で処理されます。

Q. 送信されるメッセージに追いつかないリスナをどのように処理すればよいでしょうか。

A. 以下に、いくつかのガイドラインを挙げます。

Q. スレッド ダンプを取得して問題を追跡する方法を教えてください。

A. スレッド ダンプを取得する方法は次のとおりです。

Q. クライアント識別子はユニークにする必要がありますか。

A. 恒久サブスクライバを使用すると、2 つの異なるクライアントからサブスクライブし、同じ接続ファクトリを使用し、その接続ファクトリがコンフィグレーションされた clientID を持つ場合、TopicConnection を作成するたびにユニークな clientID を設定する必要があります。各接続は、ユニークな clientID を必要とします。clientID を使用して接続ファクトリをコンフィグレーションした場合、その接続ファクトリの TopicConnection は、その接続がクローズされるまで 1 つしか作成できません。

Q. メッセージはコピー/値か参照のどちらによって渡されますか。

A. メッセージは、アプリケーションから見た場合、値によって渡されます (コピーが作成されます)。内部的には、メッセージ渡しを最適化するためにあらゆる努力が払われます。

プロデューサが JMS サーバと同じ JVM 上に存在する場合、メッセージのコピーが作成されてから、そのメッセージが実際に送り先に置かれます。コンシューマが JMS サーバと同じ JVM 上に存在する場合、メッセージのコピーが作成されてから、そのメッセージがコンシューマに渡されます。これにより、実際に送り先に置かれるメッセージが保存されます。参照渡しは、Sun Microsystems の JMS 仕様違反です。特に、ある人間がメッセージを作成し、そのメッセージを自分の空間で修正した場合、それは既に送信されたメッセージに影響を与えてはなりません。したがって、送信されるメッセージはコピーでなければなりません。これは受信側にも当てはまります。誰かがメッセージを消費し、プロパティの削除、ヘッダ フィールドの設定、何らかの変更などを行った場合、その変更は他のコンシューマが受信するメッセージに影響を与えてはなりません。したがって、同じ JVM 上のレシーバに渡されるメッセージもコピーです (レシーバごとに 1 つ)。また、レシーバに参照を渡し、そのレシーバがメッセージを修正してロールバックまたは回復を行った場合、実際に受信する人間にとって、送り先にあるメッセージは変更されることになります。このため、送信されたメッセージと異なるメッセージを受信したように見えてしまいます。これは、このメッセージがそれを受信した誰かによって修正され、元の場所に戻されたからです。

Q. キューを管理して特定のメッセージを参照および削除する方法を教えてください。

A. QueueBrowser を使用するプログラムを記述します。次に、以下の例のとおり、セレクタとメッセージ識別子を使用して、特定のメッセージを削除します。

String selector = "JMSMessageID = '" + message.getMessageID() + "'";

キュー ブラウザは、キューの実際のビューではないことに注意してください。これはスナップショットです。

Q. キューをクローズして、サーバの次回の起動時にメッセージがリロードされないようにする方法を教えてください。

A. JMS は、キューの削除を定義しません。WebLogic JMS を使用すると、キューの作成と削除を管理できます。実行時にキューを動的に削除する方法は存在しません。

必要な場合、メッセージを確認応答するか、永続性を使用しないようにします。また、一時的なキューを使用することもできます。これらは、接続の存続期間中にのみ存在します。さらに、恒久サブスクリプションを使用することもできます。恒久サブスクライバのメッセージは、その恒久サブスクライバがサブスクライブしないにもかかわらず、トピックがそのまま存在する場合に削除されます。

Q. オブジェクト メッセージの受信後にそれが null として出力されるのはなぜですか。

A. オブジェクトは、ObjectMessage.getObject() が呼び出されるまでデシリアライズされません。toString() は、これが起こるまで NULL を出力します。WebLogic JMS 6.x 以降では、アプリケーションが setObject() を呼び出していなければ、メッセージを自動的にデシリアライズします。

Q. メッセージはどのような順序でコンシューマに配信されるのですか。

A. プロデューサとコンシューマ間の順序は、配信モードと同じようにソート順序で管理され、ロールバックまたは回復が存在しない場合はセレクタによって管理されます。複数のプロデューサが単独のコンシューマに送信するか、または複数のコンシューマが複数のプロデューサから受信する場合、順序の保証はまったくありません。

順序は、一般にプロデューサとコンシューマの間で管理されます。ただし、非永続メッセージは、ソート順序がより高い (優先度がより高い、など) 永続メッセージより優先し、他より前に移動できます。また、回復またはロールバックは受信済みのメッセージをキュー/トピックに戻します。これにより、順序が影響を受けます。

大部分のメッセージング システム (WebLogic JMS を含む) は、プロデューサと送り先間、および送り先とコンシューマ間の順序を管理します。このため、いったんメッセージが送り先に到着したら、順序は変更されません。

最後に、WebLogic JMS でサポートされる非同期パイプラインも順序に影響を与えます。デフォルトでは、サーバから非同期クライアントに送信される未処理メッセージが最大 10 通も存在する可能性があります。非同期コンシューマが「捕まえられた」場合、これらのメッセージはソートされません。パイプラインでは送り先のソートは行われません。送り先が優先度でソートされ、到着する新しいメッセージの優先度がパイプラインに既に存在するメッセージより高い場合、新規メッセージはパイプライン内を飛び越えることはなく、送り先の最初に置かれます。パイプラインのサイズはコンフィグレーション可能です。使用する接続ファクトリの MessagesMaximum 設定を参照してください。真の優先度ソートを行いたい場合、接続ファクトリの最大メッセージ数を 1 に変更してください。

Q. 接続ファクトリを見つけようとしているときに例外が送出されるのはなぜですか。

A. 例外は、一般に java.io.InvalidClassException または java.lang.NoClassDefFoundError のようなものです。

クライアントの CLASSPATHweblogic.jar が存在することを確認してください。また、適切な Java 実行時 jar ファイルが含まれていることを確認してください (たとえば rt.jar が必要な場合もあります)。

Q. メッセージ セレクタの使用を避ける必要があるのはなぜですか。

A. BEA は、セレクタを頻繁に使用するアーキテクチャを避けることをお勧めしています。セレクタを使用する必要がある場合、トピック セレクタを使用するようにしてください。これらは、1 サブスクライバ、1 メッセージ当たり 1 度の負担しか負いません。メッセージがサブスクライバの選択条件に一致しない場合、そのメッセージは無視され、サブスクライバの「サブスクリプション」には置かれません。

キューの場合、セレクタはより重くなります。各受信要求では、レシーバの選択条件に一致するメッセージの検索でキュー全体のスキャンが必要となる場合があります。選択条件が厳しく、キューの深さが大きい場合、これは非常に重い負担になる可能性があります。

トピックの動作は、一般にキューより優れています。ただし、これはメッセージの混在とキューの深さに依存します。キューを使用する場合、検索しているメッセージに一致しないメッセージが数多く存在する場合、自分のメッセージの 1 つを検索するたびに、多数のメッセージとセレクタを何度も繰り返し比較しなければなりません。トピックを使用する場合は、各メッセージとすべてのコンシューマが 1 度だけ比較されます。このため、重複する作業は存在しません。

また、非同期キュー (受信呼び出しのポスト) を使用する場合、アクセスするたびにメッセージを検索する必要があります。つまり、サーバが比較を行っている間は待機する必要があります。トピックを使用する場合、メッセージはあらかじめ比較され、本質的に専用のキューに置かれます。そのポイントを参照する必要はありません。それは独自の専用キューからの FIFO となります。サーバは、順序を処理する間に比較を行うことができます。これに対し、アプリケーションはサーバがメッセージを検索している間はブロックされます。

Q. メッセージ セレクタ (通常は相関 ID に基づくフィルタ処理) を使用して実際にメッセージを受信するリスナを決定することによって、複数のキュー レシーバが同じキューをリスンすることは可能ですか。

A. Sun Microsystems の JMS 仕様では、こうした動作は定義されていません。WebLogic JMS 6.x 以降では、これをサポートしています。メッセージがキューに置かれると、JMS は、そのキューのすべてのコンシューマを、それらが受信を行った順番に検索します。その結果、そのメッセージに一致する最初のコンシューマがそのメッセージを受信します。非同期キュー コンシューマの場合、リスナを最初に設定しておくことで、コンシューマ リストの先頭に置かれます。ただし、非同期キュー コンシューマがメッセージを受信するたびに、コンシューマはリストの最後に移動します。トピックとは異なり、メッセージがセレクタに一致しない場合、誰かがセレクタを持たないか、または一致するセレクタを持つまでそのメッセージはキューに残されます。

Q. 1 つのアプリケーションがあるキューにリスナとして 1 つのオブジェクトを持っており、他のアプリケーションがそのキューのメッセージをリスンできるようにキューを作成する方法はありますか。

A. いいえ。その代わりとして、1 つの恒久サブスクリプションを持つトピックを作成できます。恒久サブスクリプションには、1 つのコンシューマだけを関連付けることができるからです。この欠点は、セレクタがキューのときのようには機能しなくなることです。Sun Microsystems の JMS 仕様によると、恒久サブスクリプションに対するセレクタを変更すると、サブスクリプションが「リセット」されます。この結果、そのサブスクリプションに現在存在するすべてのメッセージが削除されます。

Q. javax.jms.Message.setJMSPriority、DeliveryMode、Destination、TimeStamp、または Expiration を使用するときに設定値が機能しないのはなぜですか。

A. これらのメソッドは、ベンダ専用です。メッセージの値は、各 send/publish メソッドにオーバーライドされます。これらの値を設定するには、MessageProducerQueueSender、または TopicPublisher の対応メソッド (setJMSPrioritysetDeliveryModesetTimeToLive など) を使用する必要があります。これらの値がオプションのテンプレート コンフィグレーションのオーバーライド値によってオーバーライドされていないかどうかをチェックしてください。

Q. WebLogic JMS クライアントをマルチスレッド化する場合は、どのような注意が必要ですか。

A. マルチスレッドのルールについては、JMS 仕様の 2.8 節に記載されています。セッションの使い方に関しては 4.4.6 節、複数のセッションに関しては 4.4.9 節、そして並行メッセージ配信に関しては 4.4.17 節で追加の言語と共に説明されています。nutshell では、JMS セッションがシングル スレッドであることが示されています。したがって、複数のスレッドがセッションあるいはコンシューマまたはプロデューサのどれかに同時にアクセスする場合、動作は保証されません。さらに、複数の非同期コンシューマがセッションに存在する場合、メッセージは並列的ではなく連続的にそれらに配信されます。

JMS で複数のスレッドを利用するには、複数のセッションを使用します。たとえば、並列な同期受信要求を可能にするには、セッションごとに 1 つのコンシューマだけがアクティブになるようにアプリケーションを設計し、複数のセッションを使用します。

Q. 複数のトピックをサブスクライブするにはアプリケーションをどのように設定すればよいですか。

A. N 個のトピックをリスンする場合、N 個のサブスクライバと N 個のセッションを使用すると N 個の同時実行スレッドまで同時実行性が提供されます (それだけ多くのスレッドを使用する場合)。N 個のサブスクライバと 1 個のセッションでは、そのセッションを介してすべてのサブスクリプションがシリアライズされます。負荷が重い場合、追加のスレッドがなければ追いつくことができません。また、CLIENT_ACKNOWLEDGE を使用する場合、N 個のセッションによって、個々に回復可能な N 個の独立したメッセージ ストリームが与えられます。1 個のセッションだけがそれらのストリームを横切ると、制御が低下します。

バージョン 6.x 以降では、サーバサイドの WebLogic JMS は、存在するクライアント セッションの数に関係なく、小さい固定数のスレッドを有効に使用します。

Q. receive() 呼び出しのブロックおよび非同期の receive() 呼び出しはどのように利用するのですか。

A. 同期 receive() メソッドは、メッセージが生成されるまで、タイムアウト値に達するまで (指定されている場合)、またはアプリケーションが閉じるまでブロックされます。サーバサイドでの receive() 呼び出しのブロックはできる限り行わないでください。同期 receive() 呼び出しは、その呼び出しがブロックされている全期間にわたってリソースを消費するからです。

『WebLogic JMS プログラマーズ ガイド』の「クライアント サーブレットを使用したメッセージの受信」で説明されているように、クライアント サーブレットを使用してメッセージを受信する場合はサーバのデッドロックが発生する可能性があります。

メソッドが非同期で受信される場合、メッセージが生成されたときにのみメッセージ リスナを使用してアプリケーションに通知されます。そのため、メッセージを待つことでリソースが消費されることがありません。

Q. receive() 呼び出しをブロックするときに注意することは何ですか。

A. アプリケーションの設計上、メッセージを同期的に受信する必要がある場合、以下のメソッドのいずれかを使用することをお勧めします (望ましい順に挙げてあります)。

注意: ビジー状態のサーバでデッドロックを引き起こすことがあるため、このオプションの使用は最小限にします。

Q. NO_ACKNOWLEDGE 確認応答モードの目的は何ですか。

A. NO_ACKNOWLEDGE 確認応答モードは、受信したメッセージで確認応答の必要がないことを示します。これでパフォーマンスは向上しますが、メッセージが失われる恐れがあります。このモードは、セッションの確認応答で提供されるサービスの質を必要とせず、それに関連するオーバーヘッドを避ける必要があるアプリケーションで使用します。

NO_ACKNOWLEDGE セッションに送信されたメッセージは、サーバから即座に削除されます。このモードで受信されたメッセージは回復されないので、メッセージを配信する最初の試行が失敗した場合はメッセージが失われたり、重複メッセージが配信されたりします。

注意: アプリケーションで、失われたメッセージや重複メッセージを処理できない場合は、このモードは使用しないでください。重複メッセージは、メッセージを配信する最初の試行が失敗した場合に送信されます。

また、この確認応答モードは永続的なメッセージングでは使用しないでください。永続的なメッセージングにとっては、サービスの質が低すぎる可能性があります。

Q. マルチキャスト サブスクライバを使用するのはどのような場合ですか。

A. マルチキャストを使用することによって、後でメッセージをマルチキャスト サブスクライバに転送する、指定したホストのグループにメッセージを配信できます。マルチキャストには、次のような利点があります。

注意: マルチキャストは、Pub/sub メッセージング モデルのみでサポートされています。

マルチキャストを使用すると便利な例としては、株価表示があります。最新の株価を入手する場合に重要になるのは、信頼性よりもタイムリーな配信です。全部または一部の内容が配信されなくても、リアルタイムの株価情報にアクセスするときに、クライアントは簡単に情報の再送信を要求できます。クライアントでは情報の回復は必要とされません。回復された情報が再配信される頃には、その情報は古くて価値のないものになっているからです。

マルチキャストでは、ホスト グループの全メンバーに対するメッセージの配信は保証されません。確実な配信と回復が必要なメッセージについては、マルチキャストを使用しないでください。

Q. サーバ セッション プールと接続コンシューマは、どのような場合に使用するのですか。

A. WebLogic JMS には、サーバ セッションのサーバ管理プールを定義するためのオプションの JMS 機能が実装されています。この機能を使用すると、アプリケーションで複数のメッセージを並行して処理できます。ConnectionConsumer オブジェクトでは、サーバ セッションを使用して受信メッセージを処理します。メッセージ トラフィックが大きい場合は、スレッド コンテキストの切り替えを最小限に抑えるために、接続コンシューマでは複数のメッセージで各サーバ セッションをロードすることができます。複数の接続コンシューマで、サーバ セッション プールのサーバ セッションを共有できます。

アプリケーションで接続コンシューマを使用する方法については、『WebLogic JMS プログラマーズ ガイド』の「メッセージの並行処理」、または javax.jms.ConnectionConsumer javadoc を参照してください。

注意: サーバ セッション プールはメッセージ駆動型 Bean を使用して実装することもできます。サーバ セッション プールを使用する場合、MDB を使用することをお勧めします。この問題については「サーバ セッション プールとメッセージ駆動型 Bean を比較したいのですが。」を参照してください。メッセージ駆動型 Bean によるサーバ セッション プールの実装については、『WebLogic エンタープライズ JavaBeans プログラマーズ ガイド』を参照してください。

Q. onMessage() メソッド呼び出し内で close() メソッドを発行するにはどのようにすればよいですか、また、close() メソッドのセマンティクスは何ですか。

A. onMessage() メソッド呼び出し内で close() メソッドを発行する場合、システム管理者は接続ファクトリをコンフィグレーションするときに [メッセージの短縮を許可] チェックボックスを選択しなければなりません。詳細については、Administration Console オンライン ヘルプの「[JMS 接続ファクトリ]」を参照してください。このチェックボックスが選択されていない状態で、onMessage() メソッド呼び出し内で close() メソッドを発行すると、その呼び出しはハングします。

close() メソッドは、次の手順を実行して系統的にシャットダウンを行います。

接続をクローズすると、関連付けられているすべてのオブジェクトがクローズされます。受信メッセージの acknowledge() メソッドを除いて、接続で作成または受信されたメッセージ オブジェクトは引き続き使用できます。閉じた接続をクローズしても影響ははありません。

注意: クローズされた接続のセッションから受信したメッセージを確認応答しようとすると、IllegalStateException が送出されます。

セッションをクローズすると、関連付けられているすべてのプロデューサとコンシューマもクローズされます。

各オブジェクトについての close() メソッドの影響については、適切な javax.jms javadoc を参照してください。

Q. XML メッセージをパブリッシュするにはどのようにすればよいですか。

A. 以下の手順を実行します。

  1. DOM ドキュメント ツリーから XML を生成します。

  2. 生成された DOM ドキュメントを StringWriter にシリアライズします。

  3. StringWritertoString を呼び出し、それを message.setText に渡します。

  4. メッセージをパブリッシュします。

Q. WebLogic JMS をアプレットで使用するにはどのようにすればよいですか。

A. このトピックについては、news://newsgroups.bea.com/3ad321d5@newsgroups.bea.com を参照してください。

Q. 起動クラスを使用して WebLogic JMS オブジェクトを初期化し、後でそれを参照するにはどのようにすればよいですか。

A. このトピックについては、news://newsgroups.bea.com/3ad0d7f3@newsgroups.bea.com を参照してください。サンプル コードでは、シャットダウン時に正しくクリーンアップが実行されません。以下のような処理を行う停止クラスを使用できます。

JMSobject WLSobject = null;
try {
WLSobject = JMSStartUp.getJMSobject();
WLSobject.JMSCleanup();
} catch(Exception e) {}

サーブレットは、初期化とクリーンアップの両方を行うための優れたソリューションを提供します。「アプリケーション サーバ内でスレッドの作成や初期化の実行などを行うための標準的な方法を教えてください」を参照してください。

Q. メッセージ リスナ内からのメッセージの送受信は可能ですか。

A. はい。メッセージ リスナ内から任意のキューまたはトピックに対して送受信を行うことができます。

MDB ではない場合、onMessage() を含む同じ Connection または Session を使用してこれを行うことができます。メッセージ リスナを作成する場合、コンストラクタにセッションを渡します。次に、onMessage メソッドにアクセスし、onMessage メソッド内から非同期ではなく同期呼び出しを行うことができます。別の onMessage() にサービスを提供する Session を使用しないでください。Session および Sessions はマルチスレッドをサポートしないからです。

トランザクション非対応の処理を行った場合、メッセージの重複または紛失が起こる場合があります (onMessage() コードがメッセージを転送しようとした場合)。

  1. publish() の後に確認応答を呼び出し、確認応答が何らかの理由 (ネットワーク/サーバの障害) で失敗した場合、メッセージが再び表示され、パブリッシュが 2 度行われます (セマンティクスが重複する可能性があります)。連続番号を追跡して重複を削除することもできますが、簡単ではありません。

  2. publish() の前に確認応答を呼び出した場合、セマンティクスを 1 度だけ取得します。publish() が失敗すると、メッセージがサーバに到着する前か後のどちらで障害が発生したのかが分かりません。

onMessage を使用してトランザクション セマンティクスが 1 度だけ必要な場合は、トランザクション MDB を使用する必要があります。トランザクション MDB の onMessage() は、トランザクションを起動し、そのトランザクション内で受信した WebLogic Server JMS メッセージを組み込みます。publish() も同じトランザクションに入ります。次のコードは、受信した各メッセージへの応答を送信します。このコードは、ejbCreate メソッドで接続などを作成し、onMessage が呼び出されるたびに接続を作成する必要がないようにします。QueueSender は匿名 (ヌル Queue) です。これは、誰に返信する必要があるのか分からないからです。ejbRemove メソッドは、接続をクローズすることによってクリーンアップされます。これと同じアプローチを使用して、レシーバ、サブスクライバ、またはパブリッシャを作成できます。

import javax.ejb.CreateException;
import javax.ejb.EJBContext;
import javax.naming.*;
import javax.naming.directory.*;
import java.util.Hashtable;
import javax.ejb.MessageDrivenBean;
import javax.ejb.MessageDrivenContext;
import javax.jms.*;
public class MDB
implements MessageDrivenBean, MessageListener {
public static final String WLSqcf =
"javax.jms.QueueConnectionFactory";
public static final String WLSqname =
"jms.queue.TestQueue1";
public static final String WLSurl =
"t3://localhost:7001";
public static final String WLSJNDIfactory =
"weblogic.jndi.WLInitialContextFactory";
private MessageDrivenContext context;
private QueueSession session;
private QueueConnection connection = null;
private QueueConnectionFactory factory;
private InitialContext ctx;
private QueueSender QueueSender;
// 必須 - 引数のないパブリック コンストラクタ
public MDB() {}
// 必須 - ejbActivate
public void ejbActivate() {}
// 必須 - ejbRemove
public void ejbRemove() {
context = null;
if (connection != null) {
try {
connection.close();
} catch(Exception e) {}
connection = null;
}
}
// 必須 - ejbPassivate
public void ejbPassivate() {}
public void setMessageDrivenContext(
MessageDrivenContext mycontext) {
context = mycontext;
}
// 必須 - 引数のない ejbCreate()
public void ejbCreate () throws CreateException {
try {
// 初期コンテキストを取得
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, WLSJNDIfactory);
env.put(Context.PROVIDER_URL, WLSurl);
env.put(Context.REFERRAL, "throw");
ctx = new InitialContext(env);
    factory = (QueueConnectionFactory)ctx.lookup(WLSqcf);
  // QueueConnection、QueueSession、QueueSender を作成
connection = factory.createQueueConnection();
session = connection.createQueueSession(false,
Session.AUTO_ACKNOWLEDGE);
queueSender = session.createSender(null);
connection.start();
} catch (Exception e) {
throw(new CreateException(e.toString()));
}
}
// MessageListener の実装
// 例外の送出なし
public void onMessage(Message msg) {
try {
System.out.println("MDB: " +
((TextMessage)msg).getText());
msg.clearBody();
((TextMessage)msg).setText("reply message");
queueSender.send((Queue)msg.getJMSReplyTo(), msg);
}
catch(Exception e) { // すべての例外を取得
e.printStackTrace();
}
}
}

このアプローチにより、EJB/MDB インスタンスごとに接続が作成されます。このため、EJB インスタンスによって共有されるプロデューサ プールを作成できます。これを行うには、静的プールにプロデューサを挿入するクラスを記述します (サンプル プロデューサ プールについては次の質問を参照)。onMessage 呼び出しは、必要なときにプロデューサを取得します。Sessions は単一スレッドである必要があるので、プロデューサ プール内のセッションごとに 1 つのプロデューサしか存在しません。

Q. プロデューサ プールはどのように作成するのですか。

A. 次に、プロデューサ クラスの疑似コードを示します。

class ProducerPool {
static Hashmap pSets = new Hashtable();
static Hashmap inUse = new Hashtable();
QueueSender get(String contextURL,
String connectionFactoryName,
String destinationName) {
String lookup = contextURL+";"+connectionFactName+";"+destName;
synchronized(pSets) {
producer set = pSets.get(lookup);
if (set != null && set not empty)
qs = set.removeFirst();
}
if (producer == null) {
create ctx
get connect factory
create connection
create session
look up destination
qs = create queue sender
}
synchronized(inUse) {
inUse.put(qs, lookup);
}
return qs;
}
void put(QueueSender qs) {
String lookup;
synchronized(inUse) {
lookup = inUse.remove(p);
}
synchronzied(pSets) {
producer set = pSets.get(lookup);
if (set == null) {
producer set = new producer set
pSets.put(lookup, producer set);
}
producer set.add(qs);
}
}
}

注意: 静的クラスへの参照が存在しない場合、それらはガベージ コレクションによって削除されます。このため、アプリケーション サーバが何らかの方法でそれらのクラスへの永続的なポインタを持っていることを確認してください。その方法の 1 つは、起動時に初期化されるときにサーブレットまたは EJB 内から永続的にそのクラスを参照することです。

以下は、onMessage メソッド内でプロデューサ プールを使用する例です。

onMessage() {
QueueSender qs = ProducerPool.get(...);
qs.send(...);
ProducerPool.put(qs);
}

起動クラスまたは起動時にロードされるサーブレット クラスから呼び出すことによって、このプールにあらかじめプロデューサを入れておくことができます。

Q. コンソール内の保留中のメッセージとは何ですか。

A. 保留中とは、メッセージが以下の状態にあることです。

ロール バックされたメッセージは、トランザクションが実際にロール バックするまで保留状態に置かれます。ロール バックを何度も行っても、重複カウントは発生せず、例外も発生しません。トランザクションが rollbackOnly として設定され、続いて実際のロールバックが発生します。

Current は、保留中でないメッセージを表します。

Total は、サーバが最後に起動したときからの合計を表します。バイト数は、メッセージのペイロードのみを考慮します。これには、プロパティと本文が含まれますが、ヘッダは含まれません。

Q. ejb-jar.xml のメッセージ選択で「より小さい」または「より大きい」を使用する方法を教えてください。

A. セレクタを CDATA セクションで囲みます。これにより、XML パーサは「より小さい」または「より大きい」をタグとして認識しなくなります。

<jms-message-selector>
<![CDATA[ JMSXAppID <> 'user' ]]>
</jms-message-selector>

Q. 一定数のサブスクライバに対するセッションを増やした方がよいですか、減らした方がよいですか。

A. N 個のサブスクライバに対して N 個のセッションを使用すると N 個の同時実行スレッドまで同時実行性が提供されます (それだけ多くのスレッドを使用する場合)。各 Session は、十分なスレッドを使用できる限り独自のスレッドを取得します。それ以外の場合、セッションは使用可能なスレッドを逐次的に再利用します。

N 個のサブスクライバに対する 1 個のセッションでは、その 1 個のセッションを介してすべてのサブスクリプションがシリアライズされます。負荷が重い場合、追加のスレッドがなければ追いつくことができません。

CLIENT_ACKNOWLEDGE を使用する場合、N 個のセッションによって、個々に回復可能な N 個の独立したメッセージ ストリームが与えられます。1 個のセッションだけがそれらのストリームを横切ると、制御が低下します。

Q. 外部 JMS メッセージで外部送り先は処理されますか。

A. WebLogic Server JMS は、外部の送り先を処理する方法を知りません。この問題については Sun と協議してきましたが、Sun 仕様での送り先の定義は、ベンダがそのレベルで相互運用できるほど明確ではありません。JavaSoft 側は、受信/送信が正常に機能するように外部送り先を処理するには、この仕様は十分でないことを認めています。WebLogic JMS の場合、外部送り先を使用して setJMSdestination を実行した場合 (これを設定するのはプロバイダだけなので、実際には行わないでください)、それは無視されます (NULL に設定される)。同様に、外部送り先用に setJMSReplyTo を実行した場合、WebLogic JMS はそれを無視します (NULL に設定する)。

Q. アプリケーション サーバ内でスレッドの作成や初期化の実行などを行うための標準的な方法を教えてください。

A. 通常、スレッドを直接作成しないでください。正常に機能しない場合があります。ユーザが作成したスレッドは、WebLogic Server が独自の実行スレッド、関連付けられるトランザクション コンテキスト、または環境 (適切なクラス ローダなど) の作成時にあらかじめ設定するスレッドローカル変数の一部を備えていません。WebLogic 独自の方法でこれを行うには、起動クラスまたは WebLogic Time サービスを使用します。これを行うための移植可能な方法は、起動時にロードされるサーブレットを定義し、init() メソッドで初期化を行い、destroy() メソッドでクリーンアップを行うことです。サーブレット自体は何も行いません。このアプローチを使用すると、サーバを再起動せずにアンデプロイ/再デプロイを行うことができます (毎回の適切なクリーンアップ/初期化を含む)。また、サーバを起動せずに依存クラスをより動的に管理できるようになります。

Q. トピック A.B と 2 番目のトピック A.B.C に名前を付けたときに JNDI の問題が発生するのはなぜですか。

A. これは JNDI の実装の問題です。JNDI はドット (.) を使用してディレクトリに似た構造を構築します。ある要素がノードとツリー内のリーフを兼ねることはできません。この例では、B は A のリーフとして使用されますが、次にリーフ C のノードとして使用されます。

Q. トピック メッセージを処理するためにネットワーク間で送信されるメッセージの数はどのくらいですか。

A. たとえば、あるメッセージのサブスクライバが 3 つ存在し、そのうちの 1 つが一致しないセレクタを持っている場合、どのくらいのメッセージが送信されるでしょうか。

WebLogic JMS 6.x 以降では、 3 つのコンシューマがすべて同じセッションに参加している場合、フロー制御されないすべてのサブスクライバに対してメッセージの 1 つのコピーがネットワーク間で送信されます。多数のメッセージを確認応答しないようコンシューマがフロー制御されると、そのフロー制御が緩和されるまでメッセージは送信されません。したがって、答えは通常は 1 ですが、2 の場合もあります。この選択はサーバ サイドで行われるので、一致しないサブスクライバは何も破棄する必要がありません。

Q. XPATH セレクタとはどのようなものですか。

A. 次に、XPATH セレクタの例を示します。二重引用符と単一引用符の使い方に注意してください。

String selector = 
"JMS_BEA_SELECT('xpath', '/recipient/transport/text()') = 'email'";
tsubscriber = tsession.createSubscriber(topic, selector, false);

JMS_BEA_SELECT は、WebLogic JMS SQL 構文の組み込み関数です。この関数は、コンシューマの作成時にセレクタ文字列に組み込みます。xpath、XML タブ、および文字列値が単一引用符で囲まれていることに注意してください。

Q. WebLogic JMS を使用して要求/応答を処理する方法を教えてください。

A. JMS で要求/応答を処理する方法はいくつかあります。

Q. メッセージをキューに戻して処理するにはどうすればよいですか。

A. 以下のように、いくつかの方法があります。

Q. キューまたはトピック接続が開始されてから新しいセッションとサブスクライバをそれらに追加することはできますか。

A. はい。ただし、1 つ注意が必要です。セッションがアクティブな非同期コンシューマを持つ場合、そのセッションに新しいサブスクライバ/コンシューマを追加できません。Sun Microsystems の JMS 仕様により、セッションは単一スレッドでのみアクセスされる必要があります。これを行う必要がある場合、新しい Session を作成し、そのセッションにそれを追加します。

開始された接続にレシーバを追加できます。レシーバ自体は非同期ではありません。非同期にするには、リスナが必要となります。最初のレシーバの作成は、常に安全です。その最初のレシーバに対してリスナを追加する場合、同じセッションに参加する将来のレシーバについて心配する必要があります。新しいセッション、およびそのセッションの最初のレシーバは、何の心配もなく作成できます。

セッションに 2 番目のレシーバを作成する場合、最初のレシーバが MessageListener を持っているときには、そのセッションに他の実行スレッドが存在しないことを確認する必要があります。そのためには、接続を停止するか、または最初のレシーバの onMessage ルーチンから 2 番目のレシーバを実際に作成します。

Q. プロデューサがコンシューマより高速であるため java.lang.OutOfMemoryError を受け取った場合、何を行えばよいですか。

A. 割り当てを使用すると、この状況を解決できます。センダは ResourceAllocationExceptions を受け取り、サーバは引き続き正常に動作します。

WLS 6.1 SP02 以降では、メッセージ ページング機能を使えます。この機能を使うと、メッセージが所定のしきい値に達した場合にメッセージを仮想メモリから永続ストレージへスワップアウトすることで、メッセージ負荷のピーク時に貴重な仮想メモリを開放できます。詳細については、『管理者ガイド』の「JMS の管理」を参照してください。

Q. さまざまな接続ファクトリがあるのはなぜですか。

A. 複数の異なる接続属性セットを取得するためです。異なる動作が必要なクライアントは、異なるファクトリを使用する必要があります。すべてのクライアントが同じ動作を必要とする場合、1 つのファクトリで十分です。

Q. 接続とセッションはどのように割り当てればよいですか。

A. 接続は、単一の物理的な接続 (TCP/IP リンク) であると考えることができます。セッションは、順序付けられた一連のメッセージを作成および消費するための手段です。接続の作成は、一般に高くつきます。セッションの作成は、それほど高くありません。一般に、1 つの接続を使用し、すべてのスレッドを共有します。各スレッドは、独自のセッションを持ちます。複数のスレッド グループがあり、特定のスレッド グループのリソースを起動/停止/クローズする必要がある場合は、グループごとに 1 つの接続を使用するのが適切です。グループは、1 つのスレッドを持つことができます。

Q. アプリケーションは、アプリケーション サーバがダウンしているかどうかをどのように知るのですか。

A. 登録できるリスナが 2 種類存在します。Sun Microsystems の JMS 仕様では、接続に問題があるかどうかを通知する Connection.setExceptionListener が定義されています。接続に問題がある場合、その接続を使用するすべてのコンシューマにも問題が発生します。接続例外を取得する理由は、接続する相手側の WebLogic サーバがダウンしているか、無応答であるか、または誰かが Mbean インタフェースを介して接続を切断したためです。

しかし、WebLogic Server JMS の場合、1 つの接続に複数のセッションが存在し、それらが複数のバックエンド サーバにアクセスする場合があります。このため WebLogic Server には、セッションに問題があるかどうかを通知する WLSession.setExceptionListener という拡張が用意されています。詳細については、http://e-docs.bea.com/wls/docs70/javadocs/weblogic/jms/extensions/WLSession.html を参照してください。

Q. setMessageSelect(String s) を使用して、TopicConsumer の既存のセレクタを動的に変更する方法はありますか。

A. いいえ。いったんコンシューマをインスタンス化したら、セレクタはコンシューマが作成される時点で固定されます。セレクタを変更することは、現在のコンシューマを削除し、関連付けられているすべてのメッセージを削除して新しいコンシューマを作成することとほぼ同じです。

Q. 非同期メッセージのデッドロックを回避するにはどうすればよいですか。

A. Sun Microsystems の JMS 仕様の制限により、セッションの close() メソッドがユーザ同期ブロックの内部に存在する場合、非同期メッセージがデッドロックされる場合があります。これを解決するには、close() メソッドをユーザ同期ブロックの外部に移動する必要があります。次に例を示します。

public class CloseTest() {
private void xxx() {
synchronized (this) {
create connection/session/consumer
initialize and set a listener for this consumer;
wait();
connection.close();
}
}
 private void onMessage(Message message) {
synchronized (this) {
notify();
}
}
}

connection.close() メソッドがクローズされる前に、JMSProvider によって別のメッセージが onMessage ルーチンに配信される場合があります。main() メソッド スレッドは、CloseTest メソッドのモニタ ロックを保有します。CloseTest クラスの onMessage() メソッドが実行される前に、JMS は INLISTENERJMSSession のセッションのステートとして設定します (JMS 仕様では、close() メソッドは onMessage ルーチンを待つ必要があります)。このため、main() メソッド スレッドは onMessage ルーチンが完了するのを待つことができます。

onMessage ルーチンがモニタ ロックを取得しようとすると、このルーチンはブロックして main() メソッド スレッドがあきらめるのを待ち、main() メソッド スレッドは onMessage が完了するのを待ちます。

また、コンシューマの close() メソッドが onMessage ルーチンから実行され、config.xml ファイルの allowCloseInOnMessage 属性が false に設定されると、JMS もブロックします。

Q. メッセージ駆動型 Bean の利点は何ですか。

A. メッセージ駆動型 Bean は、JMS のキューやトピックからメッセージを受信した結果として EJB コンテナによって呼び出されるステートレスなコンポーネントです。呼び出されたメッセージ駆動型 Bean は、メッセージの内容に基づいてビジネス ロジックを実行します。 これにより、JMS コンフィグレーションや再接続といった作業から開放されます。

メッセージ駆動型 Bean モデルを使用すると、EJB 開発者は慣れ親しんだフレームワークやツールを利用できると同時に、コンテナの提供する追加サポートへのアクセスを提供することもできます。メッセージ駆動型 Bean モデルの目的は、JMS メッセージを処理するために非同期で呼び出される EJB の開発を、他の JMS MessageListener で同じ機能を開発することと同じくらい容易にすることです。

標準の JMS MessageListener の代わりにメッセージ駆動型 Bean を使用する主な利点の 1 つは、JTA トランザクションを自動的に開始することができ、受信メッセージがそのトランザクションの一部になることです。この場合、他の処理が同じ JTA トランザクション (データベース処理など) に参加できます。これは、非同期コンシューマからのメッセージと別の JTA 処理を同じトランザクションに参加させる唯一の方法です。

メッセージ駆動型 Bean の詳細については、『WebLogic エンタープライズ JavaBeans プログラマーズ ガイド』の「メッセージ駆動型 Bean の設計」を参照してください。

Q. メッセージ駆動型 Bean の同時実行性はどのように機能するのですか。

A. Queue の同時実行性は、プール内の MDB インスタンスごとに 1 つの JMSSession を生成することによって実現されます。JMSSessions は JMS によって並列に処理されるので、同時実行性が自然に取得され、JMS はメッセージを 1 つのリスナに配信します。MDB がクラスタ内の複数のサーバにデプロイされる場合、JMSSessions は各サーバの MDB インスタンスごとに作成され、それらの間でロード バランシングが行われます。

単独のサーバでは、各メッセージのコピーを 1 つだけ作成し、1 つのトピック コンシューマを使用してメッセージを複数のスレッドに渡すことによって同時実行性を取得します。複数の MDB をコンフィグレーションして同じトピックでリスンでき、各 MDB はすべての各メッセージのコピーを受信します。複数のサーバを使用する場合、各サーバは独自のコンシューマを取得し、したがって各メッセージの 1 つのコピーを取得します。複数のサーバ間でコンシューマを共有することは現時点ではできません。メッセージを 1 つの MDB によって処理するには、キューを使用してください。

ある顧客の例では、同じトピックでリスンしている MDB の複数の実装でトピック MDB が必要になりました。この場合、異なる実装を持つ複数の MDB が同じトピックをサブスクライブする場合があります。クライアントは、同じトピックでリスンしている MDB の種類がいくつあるのかを調べる効率的な方法を持っていません。しかし、キューではなく複数のリスナ、したがってトピックが存在することは可能です。トピックでリスンしている各 MDB に対して、メッセージは正確に 1 度だけ配信されます (たとえば、メッセージはトピックをリスンしている名前付きの MDP プール内のインスタンスに 1 度だけ配信される)。

Q. MDB はメッセージ プロデューサ、またはプロデューサとコンシューマの両方になれますか。

A. はい。MDB の内部に JMS コンテキストは存在しないので、接続、セッション、およびプロデューサを自分で確立する必要があります。そのための 1 つ目のオプションは、MDB の onMessage ルーチンに入るたびにこれを行うことです。メッセージ レートが相対的に低い場合、これで十分です。2 つ目のオプションは、ejbActivate() に必要なオブジェクトを確立することです。これらのオブジェクトはシリアライズ可能ではないので、ステートフル セッション Bean またはエンティティ Bean に対してパッシベーションを行うことができません。EJB が非アクティブ化した場合、関連付けられているオブジェクトをクローズする必要があります。3 番目のオプションは、起動クラスに JMS 接続/センダ セッション プールを構築し、独自の同期化とブロッキングを使用して完成させ、接続を取得することです。この質問の回答例については、「メッセージ リスナ内からのメッセージの送受信は可能ですか」を参照してください。

Q. MDB が恒久サブスクリプションを使用する場合、MDB がデプロイされないときにメッセージは蓄積されますか。

A. その時点では蓄積されません。MDB が最初にデプロイされる前は、MDB のデプロイ時にメッセージは蓄積されません。これはパッシベーションとは異なります。MDB が現在アクティブ化されていないということは、それがデプロイされないということを意味しないからです。コンテナは依然としてサブスクリプションを管理し、メッセージを MDB に送信します。

Q. 非 WebLogic JMS プロバイダの送り先を使用して MDB を駆動する方法を教えてください。

A. このトピックに関する資料については、http://dev2dev.bea.com/technologies/jms/index.jsp の「Using Foreign JMS Providers with WebLogic Server」ホワイト ペーパー (jmsproviders.pdf) を参照してください。

Q. 外部 JMS プロバイダを使用してトランザクション対応 MDB を駆動できますか。

A. はい。WebLogic Server 7.0 では、外部 JMS プロバイダに対してコンテナ管理によるトランザクションをサポートする MDB をデプロイできます。MDB が、「transaction-type」属性が「Container」で、「trans-attribute」属性が「Required」でコンフィグレーションされている場合、WLS は XA を使って外部 JMS プロバイダをトランザクションの中に自動的に取得します (コンテナ管理によるトランザクションを使用する MDB の例についての次の質問を参照してください)。

外部 JMS プロバイダが XA をサポートしていない場合、そのプロバイダではコンテナ管理によるトランザクションをサポートする MDB をデプロイすることはできません。また、JMS プロバイダが XA をサポートしている場合は、weblogic-ejb-jar.xml ファイル内で指定する JMS 接続ファクトリが XA をサポートするということを保証する必要があります。この指定方法は、各 JMS プロバイダでさまざまです。

外部プロバイダを使用するための MDB のコンフィグレーションの方法の例については、http://dev2dev.bea.com/technologies/jms/index.jsp にあるホワイト ペーパー「Using Foreign JMS Providers with WebLogic Server」(jmsproviders.pdf) を参照してください。

Q. JTA トランザクションを MDB で使用するにはどのようにすればよいですか。

A. 次の例のとおり、ejb-jar.xml ファイルで、トランザクション タイプを Container として、trans-attribute を Required として定義します。

<ejb-jar>
<enterprise-beans>
<message-driven>
<ejb-name>MDB</ejb-name>
<ejb-class>MDB</ejb-class>
<transaction-type>Container</transaction-type>
<message-driven-destination>
<destination-type>javax.jms.Queue</destination-type>
</message-driven-destination>
</message-driven>
</enterprise-beans>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>MDB</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>
Required
</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>

トランザクションをロールバックするには、次のコード例のとおり、Web Logic 拡張の TXHelper か、または MDB コンテキストを使用します。

UserTransaction ut =
weblogic.transaction.TXHelper.getUserTransaction();
ut.setRollbackOnly();

または

private MessageDrivenContext context;
public void setMessageDrivenContext(
MessageDrivenContext mycontext) {
context = mycontext;
}
public void onMessage(Message msg) {
try { // 何らかのロジック
}
catch(Exception e) {
System.out.println("MDB doing rollback");
context.setRollbackOnly();
}

Q. サーバ セッション プールとメッセージ駆動型 Bean を比較したいのですが。

A. MDB は、1 つの送り先だけでリスンします。コンシューマは、1 つの送り先だけでリスンします。ConnectionConsumers は、1 つの送り先だけでリスンします。

ServerSessionPool は、複数の ConnectionConsumers を持つことができます。このため、1 つの MessageListener を複数のコンシューマによって供給できます。

ServerSessionPools は、MessageListener にトランザクションを関連付けません。このため、リスナを実行したメッセージの受信は、トランザクションの一部ではありません。MDB の場合、トランザクションを REQUIRED として指定でき、メッセージの起動はトランザクションの一部です。

ServerSessionPools には、接続コンシューマがリスンしている送り先が同じ JVM によってホストされなければならないという制限があります。つまり、リモート キューまたはトピックをリスンするサーバ セッション プールを持つことができず、外部 (非 WebLogic Server JMS) 送り先はサポートされません。MDB は配布することができ、外部送り先を持つことができます。

MDB は、現時点では 1 回のデプロイメントにつき 1 つのメッセージのみを受信します (サービス パック 1 の場合)。トピックをリスンする単一のサーバ上の複数のインスタンスを持つ MDB が存在する場合、その MDB は、インスタンスの数に関係なく、パブリッシュされたメッセージのコピーを 1 つだけ受信します。トピックをリスンする複数のマシンに MDB がデプロイされている場合、各デプロイメントはそのトピックのパブリッシュされたメッセージのコピーを受信します。すべての MDB デプロイメントに均等に配布されるメッセージの複数のコピーを取得します。

 

Back to Top Previous Next