ORACLE JAPAN Server Release 6.1

 

  |  

  WebLogic Server ホーム   |     FAQ   |   前へ   |   次へ   |   目次   |   PDF 版

FAQ: JMS

 

WebLogic JMS 6.1 製品BEA

コンフィグレーション

永続ストレージ

管理

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

JMS プログラミングの慣習

メッセージ駆動型 Bean


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

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


WLS 6.1 の新しい JMS 機能は何ですか。

WLS JMS 6.1 の新機能は以下のとおりです。


WLS 6.0 サービス パック 1 で修正された問題、およびまだ存在している既知の問題は何ですか。

このトピックに関する資料については、http://dev2dev.bea.com/docs/jmsjta.jsp を参照してください。


WLS 5.X JMS クライアントは WLS 6.X と対話できますか。また、その反対も可能ですか。

いいえ、これは現在サポートされていません。基本的に、RMI には相互運用性がありません。また、JMS は実質的に異なるプロトコルを使用します。


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

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


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

WebLogic Server でシン クライアント アプリケーションを作成するための現在のオプションについては、http://dev2dev.bea.com/resourcelibrary/whitepapers.jsp?highlight=whitepapers の「WebLogic Thin Client」ホワイト ペーパー (WebLogicThinClient.zip) を参照してください。

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


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

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

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

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

Sun Microsystems の JMS 仕様

BEA の dev2dev Web サイト

AskBEA

BEA Newsgroup サーバーで利用できる WebLogic JMS “weblogic.developer.interest.jms” ニュースグループ。


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

NT では、[スタート|プログラム|BEA Weblogic E-Business Platform|Weblogic Server 6.X|Start Default Server] を選択し、管理者パスワードを入力して WLS 6.X を起動します。

NT で JMS をコンフィグレーションするには、[スタート|プログラム|BEA Weblogic E-Business Platform|Weblogic Server 6.X|Start Default Console] を選択してコンソールを起動します。

  1. 左側のコンソール ツリー ビューで、[JMS] を選択します。

  2. 永続メッセージが必要な場合、最初にストアを作成します。そのためには、まず[ストア] を選択します。右側のウィンドウで、ファイル ストアの [新しい JMSFile Store のコンフィグレーション] を選択し、そのファイル ストアに名前を付け、ディレクトリを指定して [作成] を選択します。JDBCStore が必要な場合、最初に JDBC 接続プールを作成する必要があります。そのためには、ツリー ビューで JDBC を選択し、[接続プール]、[新しい JDBC Connection Pool のコンフィグレーション] を選択します。[対象] を選択し、対象サーバを選択し、右矢印を選択して、[適用] をクリックします。次に、[ストア]、[新しい JMSJDBCStore のコンフィグレーション] に戻ります。

  3. テンプレートが必要な場合、最初にテンプレートを作成します。そのためには、[テンプレート]を選択します。一時キューを作成するには、テンプレートが必要です。[新しい JMS Template のコンフィグレーション] を選択し、名前を指定して、[作成]を選択します。次に、[しきい値と割当] タブまたは [オーバライド] タブに移動します。変更が済んだら、[適用] を選択します。

  4. [サーバ] を選択します。[新しい JMSServer のコンフィグレーション] を選択し、その名前を指定し、ストアを選択し(作成済みの場合)、テンプレートを選択して(作成済みの場合)、最後に [作成] を選択します。次に、他のタブに移動し、変更を行って [適用] をクリックします。特に、[対象] を選択し、対象サーバを選択し、右矢印を選択して、[適用] をクリックします。これが、JMS が起動するサーバです。

  5. 送り先の作成 - 左パネルのツリー ビューから、[JMS] の左の + を選択し、[サーバ] の左の + を選択し、対象サーバの左の + を選択して、[送り先] を選択します。[新しい JMSQueue のコンフィグレーション] または [新しい JMSTopic のコンフィグレーション] を選択し、最初のページに値を入力して [作成] をクリックします。次に、他のタブで値を入力して [適用] をクリックします。

  6. 接続ファクトリの作成 - 左側のツリー ビューで、[JMS] を開きます。[接続ファクトリ] を選択します。右パネルで [新しい JMS Connection Factory のコンフィグレーション] を選択します。接続ファクトリ名と JNDI 名を入力します。右下隅にある [作成] を選択します。[対象] タブを選択します。接続ファクトリをデプロイするサーバを選択します。右矢印を選択すると、そのサーバが移動して選択されます。最後に、右下隅にある [適用] を選択します。


JMS のコンフィグレーションはどのように行うのですか。

JMS のセキュリティを設定するための適切な方法は、コンソールに移動し、ツリー ビューで ACL を選択して、アクセス制御リストを作成することです。

  1. ACL 名を選択します。これは、weblogic.jms.queue.QUEUENAME または weblogic.jms.topic.TOPICNAME です。

  2. [作成] を選択します。

  3. 送信または受信の新しいパーミッションを入力します。

  4. [作成] を選択します。

  5. ユーザまたはグループのカンマ区切りリストを入力します。

  6. [Grant Permission] を選択します。

  7. [saved to the realm implementation] を選択して、変更を保存します。

  8. [はい] を選択します。

これで、fileRealm.properties ファイルの行が次のように更新されます。

acl.send.weblogic.jms.queue.TestQueue1=user1
acl.receive.weblogic.jms.queue.TestQueue1=user1

キューまたはトピックの ACL が存在しない場合、セキュリティは開放状態です。

また、JNDI コンテキストにアクセスするための ACL も存在します。JNDI コンテキストは、最初に JMS にアクセスするために不可欠です。詳細については、JNDI のドキュメントを参照してください。


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

はい。ただし、以下の 2 つのデフォルト接続ファクトリに対する名前は非推奨となっています。

javax.jms.QueueConnectionFactory
javax.jms.TopicConnectionFactory.

ただし、これらの接続ファクトリは、下位互換性のためにこのリリースでも定義されており、使用することができます。

WebLogic JMS 6.1 では、デフォルトで次の 1 つの接続ファクトリが用意されています。

weblogic.jms.ConnectionFactory

JMS デフォルト接続ファクトリを有効にする必要があります。コンソールの [(サーバ名)|チューニング] を選択して、[デフォルト JMS 接続ファクトリを有効化] チェック ボックスをクリックします。

Administration Console を使用すれば、ユーザ定義の接続ファクトリも指定できます。


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

WLS 5.1 では、createTopic() または createQueue() はデータベースに永続的な送り先を(存在しない場合に)作成しますが、weblogic.properties ファイルは修正しません。

JavaSoft JMS 仕様バージョン 1.0.2 によれば、createQueue() および createTopic() は送り先を動的に作成するためのものではありません。これらは、JNDI ルックアップの代わりに文字列名を使用して参照される送り先を検索するために使用されます。送り先は、最初に config.xml ファイルに存在する必要があります。この変更は、WLS 6.0 のドキュメントに記載されています。この動作が前のリリースとは異なるからです。WLS JMS ヘルパー クラス(weblogic.jms.extensions.JMSHelper)またはコンソールを使用すると、実行時に送り先を作成できます(6.0 にはバグがあったため、サーバの再起動時に問題が発生しました。これはサービス パック 1 で修正されています)。これらのメカニズムにより送り先が作成され、コンフィグレーション ファイルも修正されます。

JMSHelper クラスの詳細については、『WebLogic JMS プログラマーズ ガイド』の「送り先の動的作成」を参照してください。

次のプログラムにより、トピックが作成されます。

import java.io.*;
import java.util.Hashtable;
import javax.jms.*;
import javax.naming.*;
import weblogic.jms.extensions.JMSHelper;


class t {
public final static String JNDI_FACTORY="weblogic.jndi.WLInitialContextFactory";
public final static String JMS_SERVER_NAME="TestJMSServer";
public final static String DEST_JNDI_PREFIX="javax.destination.";


static public void main(String [] args) throws Exception {
try {
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
env.put(Context.PROVIDER_URL, "t3://localhost:7001");
Context ctx = new InitialContext(env);


String topicName = "JMSHelperTestQueue01";
String topicJNDI = DEST_JNDI_PREFIX + topicName;
System.out.println("topic name=" + topicName + ", jndi=" + topicJNDI);
JMSHelper.createPermanentTopicAsync(ctx, JMS_SERVER_NAME, topicName,
topicJNDI);
} catch (JMSException e) {
e.printStackTrace();
}
}
}


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

次のプログラムは 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());
}


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

一時的な送り先を作成するすべての JMSServer にテンプレートを作成する必要があります。TemporaryTemplate をサポートするために複数の 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 名にバインドできます。つまり、サブスクライバ サイドでトピックを作成し、他人がパブリッシュできるようにそれを公開できます。同じ接続で複数のサブスクライバを取得し、複数のセッションを使用して並行処理を取得できます。


MBean を使用して実行時統計を印刷する方法を教えてください。

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


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

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

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


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

JMS データベースには、JDBC ドライバからアクセスできる任意のデータベースを指定できます。WebLogic では、以下のデータベースがサポートされており、それぞれに対応する JDBC ドライバが用意されています。


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

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

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

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

jar xf weblogic.jar weblogic\jms\ddl

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

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

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


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

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


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

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

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

    Store="<YOUR-STORE-NAME>"

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

  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\ddlweblogic.jar に格納されます。以下のコンフィグレーション例は、Oracle 用の JDBC ストアを示したものです(JDK 1.3 で WLS 6.1 を実行するにはクライアント バージョン 8.1.7 以上が必要です)。テーブルを手動で作成する(および既存のテーブルを削除する)には、前述の質問で説明したとおり、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) {
}
}
}


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

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


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

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

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

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


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

複数の顧客からの報告によると、JDBC ストアを使用しており、DBMS がダウンして復帰した場合、JMS は WLS をシャットダウンして再起動するまで JDBC ストアを使用しないという問題があります。この問題を回避するには、JMSJDBCStore に関連付けられている JDBC 接続プールの次の属性をコンフィグレーションします。

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

これらが設定されていないと、JDBC リソースがダウンして復帰した場合、JMS は WLS をシャットダウンしてから再起動するまで接続プールを使用できません。これは、WLS 6.0 SP02 と WLS 6.1 でテスト済みです。


WebLogic JMS はクラスタ化をサポートしていますか。

WebLogic JMS では、クラスタ内のあらゆるサーバから送り先へのクラスタワイドで透過的なアクセスがサポートされています。システム管理者は、複数の接続ファクトリをコンフィグレーションし、対象を使用してそれらを WebLogic サーバに割り当てることで、クラスタ内のあらゆるサーバから送り先へのクラスタワイドで透過的なアクセスを確立できます。各接続ファクトリは、複数の WebLogic サーバにデプロイできます。

アプリケーションでは、Java Naming and Directory Interface(JNDI)を使用して接続ファクトリをルックアップし、JMS サーバとの通信を確立するための接続を作成します。各 JMS サーバでは、複数の送り先に対する要求が処理されます。JMS サーバで処理されない送り先への要求は、適切なサーバに転送されます。

クラスタ内のさまざまなノード上の複数の JMS サーバに異なる名前が付けられている場合、それらのサーバをコンフィグレーションできます。また、さまざまな JMS サーバに送り先を割り当てることができます。

ただし、JNDI でエントリをレプリケートする際に伝播遅延が発生するという問題を認識しておく必要があります。あるノードにデプロイされる MDB が別のノード上の送り先を参照する場合、デプロイメントは失敗し、javax.naming.NamingException 例外が送出されます。この問題が発生するのは、サーバがまだリモート サーバ(JMS サーバ)からの JNDI と同期化されておらず、このため MDB のデプロイメントの一部としての送り先の JNDI ルックアップが失敗するためです。この解決策のひとつは、各 MDB がローカルの送り先を参照するようにすることです。、また、サーバの起動(プラス JNDI 伝播の遅延)後に MDB をデプロイするという方法もあります。MDB のデプロイ前にメッセージを失うことを回避するには、恒久サブスクリプションを使用します。この問題は、WLS 6.1 では修正されています。WLS 6.1 では、MDB はデプロイされ、送り先が使用可能になるまで再接続が試行されます。ただし、これはローカル以外の JMS 送り先を参照する EJB については依然として問題であることに注意してください。

接続ファクトリの詳細については、『WebLogic JMS プログラマーズ ガイド』の「WebLogic JMS の基礎」を参照してください。WebLogic クラスタの詳細については、『WebLogic Server Clusters ユーザーズガイド』を参照してください。


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

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

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


WLS 6.1 での JMS クラスタ化の価値はなんですか。

コンシューマとプロデューサは、送り先が実際にどこに存在するかに関係なく、クラスタ内の任意のサーバからその送り先にアクセスできます。これにより、場所の透過性が実現されます。ただし、場所の透過性(レプリケートされた JNDI を使用する)を実現するには、クラスタのメンバのいずれか(管理サーバ以外)の JMSServer をコンフィグレーションする必要があります。

特定のプロデューサまたはコンシューマが存在するサーバがダウンした場合でも、他のサーバは送り先にアクセスできます。しかし、送り先がダウンした場合、すべてのプロデューサおよびコンシューマは役に立たなくなります。JMS サーバがダウンした場合、そのサーバが関与しているすべてのトランザクションがロール バックされます。JMS は、クラスタ内のダウンしたサーバ以外のサーバで引き続き正常に動作します。そのサーバが復帰すると、そのサーバが再び JMS サービスを提供します。サーバが復帰すると、メッセージがコンシューマに送信されるか、またはコンシューマによって取得されます。サーバを再起動すれば、正常に動作するはずです。

たとえば、トピックがサーバ B にデプロイされ、サブスクライバがサーバ A を介し、パブリッシャがサーバ B を介してそのトピックにアクセスするとします。この場合、サーバ A がダウンすると、パブリッシャはメッセージをパブリッシュできますが、サブスクライバはメッセージを受信できません(サーバ B に接続していない場合)。

将来のリリースでは、WLS JMS は、送り先が存在するサーバがダウンしたときに自動移行およびフェイルオーバを処理するようになります。


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

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


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

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


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

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

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


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

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


WLS JMS は SSL2 をサポートしていますか。

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


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

MQ Series、IBus MessageServer、Fiorano、および SonicMQ との統合については、ftp://edownload:BUY_ME@ftpna2.bea.com/pub/downloads/jmsproviders.doc を参照してください。


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

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

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

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


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 をトランザクションに関連付けることができます。


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

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

  1. JMS 呼び出しを行う前に現在のトランザクションをサスペンドし、その完了後に再開します。コードは次のようになります。

    import javax.transaction.Transaction;
    import javax.transaction.TransactionManager;

    TransactionManager tranManager= TxHelper.getTransactionManager();
    Transaction saveTx = null;
    try {
    saveTx = tranManager.suspend();
    ... JMS 処理を行う。トランザクションには参加しない
    } finally {
    // 中断されたトランザクションは常に再開する必要がある
    if (saveTx != null) tranManager.resume(saveTx);
    }

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

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

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


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

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


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

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


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

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

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


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

MQ Series の統合については、http://dev2dev.bea.com/docs/jmsjta.jsp を参照してください。


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

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


WLS JMS は XAResource 互換ですか。

はい。バージョン 6.0 では、WLS JMS は JTA 仕様に定義されているとおりに XAResource インタフェースを実装していました。バージョン 6.1 では、XAConnectionXAConnectionFactoryXAQueueConnection、XAQueueConnectionFactory、XAQueueSession、XASession、XATopicConnection、XATopicConnectionFactory、および XATopicSession の各メソッドも実装されています。これらは、JMS 仕様ではオプションとして定義されています。これらのメソッドは、XAResource インタフェースの一部ではありません。XAResource インタフェースは、トランザクション マネージャが JTA トランザクションを管理するために必要な開始、準備、コミットのようなメソッドを持ち、これらは WLS JMS によって提供されます。JMS の送信または受信を JTA トランザクション(開始/コミット)でラップした場合、JMS の処理はトランザクションの一部となります(トランザクション セッションを使用しない場合)。

このため、XAQueueConnectionFactory を使用して XAQueueConnection および XAQueueSession を取得して getXAResource() を呼び出すことはできません。ただし、WLS JMS は WLS JTA によって自動的に登録されるため、これを心配する必要はありません。

また、WLS JMS はトランザクションを駆動する別のトランザクション マネージャ(少なくともドキュメント化されているインタフェース)では使用できません。


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

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

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

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

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

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

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

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

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

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


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

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

順序が設定されていないキュー(一般的)では、他のメッセージが同時に回復されない限り、通常メッセージはキューのヘッダに置かれます(キューが到着時間(FIFO)でソートとされているため)。ただし、ソート順序は競合を解決します。

メッセージは可能な限り最初に利用可能なコンシューマに再配信されます。要求時にコンシューマが存在しない場合、コンシューマが現れるまでそのままそこに置かれます。

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


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

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

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

while (true) {
セッションを作成し、恒久サブスクリプションの 1 つのメッセージにサブスクライブ
セッションを閉じる
セッション参照をメモリ内に保存
メッセージを確認応答するため、セッション参照を見つけ、
acknowledge() を呼び出す
}

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

トランザクションを開始
while(true) {
message = receive();
if (message が処理可能)
メッセージを処理
コミット
} else {
トランザクションをサスペンド
トランザクションをメッセージとともに保留にしておく
トランザクションを開始
}
}

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

ユーザ トランザクションを再開
コミット

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

ユーザ トランザクションを再開
ロールバック

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


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

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

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

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

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


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

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

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

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


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

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


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

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


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

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


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

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

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


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

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

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

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


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

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

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


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

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


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

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

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

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

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


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

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

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


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

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

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

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

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


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

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


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

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


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

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


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

JavaSoft JMS 仕様バージョン 1.0.2 では、JMS セッションがシングル スレッドであることが示されています。したがって、複数のスレッドがセッションあるいはコンシューマまたはプロデューサのどれかに同時にアクセスする場合、動作は保証されません。さらに、複数の非同期コンシューマがセッションに存在する場合、メッセージは並列的ではなく連続的にそれらに配信されます。

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


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

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


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

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

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

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


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

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

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


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

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

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

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

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


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

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

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

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

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


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

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

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

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


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

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

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

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

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

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

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


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

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

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

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

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

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


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

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


スタートアップ クラスを使用して JMS オブジェクトを初期化し、後でそれを参照するにはどのようにすればよいですか。

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

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

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


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

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

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 つのプロデューサしか存在しません。


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

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

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);
}

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


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

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

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

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

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


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

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

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


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

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

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

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


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

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


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

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


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

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


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

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

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


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

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

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

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


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

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


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

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


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

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

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

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


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

割り当てを使用すると、この状況を解決できます。送信者はセンダは ResourceAllocationExceptions を受け取り、サーバは引き続き正常に動作します。WLS 6.X は、メッセージのメモリからのページングをサポートしていません。

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


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

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


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

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


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

登録できるリスナが 2 種類存在します。JMS 仕様では、接続に問題があるかどうかを通知する Connection.setExceptionListener が定義されています。接続に問題がある場合、その接続を使用するすべてのコンシューマにも問題が発生します。接続例外を取得する理由は、接続する相手側の WebLogic サーバがダウンしているか、無応答であるか、または誰かが Mbean インタフェースを介して接続を切断したためです。しかし、WebLogic Server JMS の場合、1 つの接続に複数のセッションが存在し、それらが複数のバックエンド サーバにアクセスする場合があります。このため WebLogic Server には、セッションに問題があるかどうかを通知する WLSession.setExceptionListener という拡張が用意されています。詳細については、http://e-docs.bea.com/wls/docs61/javadocs/weblogic/jms/extensions/WLSession.html を参照してください。


Visual Cafe 4.1 を使用して WebLogic Server をデバッグする方法を教えてください。

VisualCafe Enterprise Edition 4.1 をインストールして、サーバに接続します。3.X と同じように機能します。

次に、VC 4.1 を使用してデバッグを行う手順を示します。必要に応じてディレクトリ名を変更してください。

  1. d:\VisualCafeEE にインストールします。特別なオプションは必要ありません。

  2. c:\Program Files\Common Files\WebGain Shared にライセンスをインストールします。

  3. [スタート|プログラム|WebGain Studio Professional|Visual Cafe Enterprise Edition 4.1|Distributed Debugging Services|Start DD Services (Java2 - 1.3)] を選択して、ddservices を起動します。

  4. java.exe の代わりに debugvm.exe を使用して WebLogic Server を起動します。
    cd D:\bea\wlserver6.1\config\mydomain
    setEnv
    startWebLogic.cmd
    change "%JAVA_HOME%\bin\java" -hotspot -ms64m -mx64m to \visualcafeEE\jdk13\bin\debugvm.exe

  5. startWebLogic を実行します。デバッグ情報が出力されます。

  6. [スタート|プログラム|WebGain Studio Professional|Visual Cafe Enterprise Edition 4.1|Visual Cafe Enterprise Edition 4.1] を選択して、VisualCafe を実行します。

  7. [ファイル] メニューで、[プロセスへのアタッチ] を選択します。すべてが正常に機能する場合、マシン名が表示されます。

  8. + 記号をクリックしてツリーを展開し、実行中の WebLogic Server を選択します。


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

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


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

JMS 1.0.2 仕様の制限により、セッションの 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 は INLISTENER を JMSSession のセッションのステートとして設定します(JMS 仕様では、close() メソッドは onMessage ルーチンを待つ必要があります)。このため、main() メソッド スレッドは onMessage ルーチンが完了するのを待つことができます。

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

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


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

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

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

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

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


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

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

WebLogic JMS 6.1 の Topics の場合、プール内の Bean インスタンスごとに 1 つの JMSSession が存在します。Topics の機能により、セッション、そしてすべての Bean インスタンスはその Topic でパブリッシュされた各メッセージのコピーを受信します。(並行処理の異常を引き起こす問題もありましたが、WLS 6.0 サービス パック 1 で修正されました。)単独のサーバでは、各メッセージのコピーを 1 つだけ作成し、1 つのトピック コンシューマを使用してメッセージを複数のスレッドに渡すことによって同時実行性を取得します。複数の MDB をコンフィグレーションして同じトピックでリスンでき、各 MDB はすべての各メッセージのコピーを受信します。複数のサーバを使用する場合、各サーバは独自のコンシューマを取得し、したがって各メッセージの 1 つのコピーを取得します。複数のサーバ間でコンシューマを共有することは現時点ではできません。メッセージを 1 つの MDB によって処理するには、キューを使用してください。

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


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

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


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

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


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

このトピックに関する資料については、http://dev2dev.bea.com/docs/jmsmdb.jsp を参照してください。


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

いいえ。メッセージはトランザクションの外部で非同期に受信され、メッセージをトランザクションに関連付けるための J2EE API は存在しません。

WebLogic Server JMS でこれが機能する唯一の理由は、メッセージをトランザクションに関連付けるためのメソッドを備えた WebLogic Server 拡張インタフェースが定義されているためです。このインタフェース、MDBTransaction は、news://newsgroups.bea.com/3b3a009b$1@newsgroups.bea.com に定義されています。これは associateTransaction() というメソッドを持ち、このメソッドは javax.jms.Message というパラメータを取ります。このメッセージはトランザクションに関連付ける必要があります。BEA は、WebLogic Server との統合に関心のある他のベンダがこのインタフェースを実装することを期待しています。

もう 1 つのアプローチは、ソース管理トランザクションと呼ばれているものです。このアプローチでは、メッセージを非同期コンシューマに配信する前にユーザに代わってトランザクションを開始するよう JMS プロバイダに通知するための API が存在するはずでした。この API は、J2EE にも存在しません。このような規定が存在したにもかかわらず、このようなトランザクションを独自に開始および駆動できる非 WLS JMS プロバイダはほとんど存在しません。

現在のソリューションは、すべてのメッセージを外部送り先から WebLogic Server JMS 送り先(外部 JMS プロバイダがこれをサポートする場合はトランザクション内の)に移動し、その WebLogic Server JMS 送り先にトランザクション対応 MDB を駆動させることです(WLS JMS 特別インタフェースを使用する)。現在のところ、http://dev2dev.bea.com/docs/jmsproviders.jsp で説明されているのとほぼ同じコードを使用して、メッセージをプロバイダ間で移動できます。このコードは、スレッドを開始し、以下のことを行うスタートアップ クラスに含めることができます。

while (true) {
トランザクションを開始
タイムアウトに同期してメッセージを受信
if timed_out { ロールバックして継続 }
処理を実行
トランザクションをコミット }

同期受信を行うと、問題が発生して、メッセージの受信前にトランザクションがタイム アウトになる場合があります。指定されたタイムアウトを使用して受信を行うことができます。これにより、トランザクションが処理を完了するための時間を十分に確保できます。受信が失敗した場合、トランザクションをロール バックして再試行します。また、これは MDB ほど効率的ではありません。非同期受信ではなく同期受信を行う(スレッドを拘束する)からです。また、タイムアウトが増加すると、CPU の負担が増加します。

実際のところ、WLS JMS はこのメッセージ渡しを処理するブリッジを提供します。

これらのアプローチのどれを使用する場合でも、XAResource を Transaction Manager に登録する必要があります(これは WebLogic Server JMS では自動的に行われる)。


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

次の例のとおり、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>

トランザクションをロールバックするには、次のコード例のとおり、WebLogic 拡張の 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();
}


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

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 page next page