[doc] [toc] [previous] [next]

管理リソースとしてのJMS

JBossでは、EJBのセッションやエンティティBeanからJMSメッセージを送信することは、JBossMQや別のJMSプロバイダにより従来から可能でした。これは通常のJMSプログラミングによっておこなわれます。 しかし、このような、JMSのプログラミングは、EJB契約以外の方法によってます。なぜなら、JMSは決してコンテナ管理のリソースとして扱われることはないからです。たとえば、これが意味するのは、あなたのJMSコードがトランザクション管理に決して登録(enlist)されないことと、あなたのJMSセッションをプールできないために、それらを使い切るかもしれないことです。

しかしながら、EJB v2.0とJ2EE v1.3を始めとして、JMSの接続とセッションがデータソースのように真のJ2EEリソースになることが要求としてあります。このことは、1.3仕様書に準拠したJ2EEサーバは、ひとつの管理されたリソースとして扱うことができなけれならないというを意味します。JBossバージョン2.4.0は、この点に関しては準拠していますが、JBossの以前のバージョンでは準拠していません

[2.4.0. これはあなたにとってどのような意味がありますか? それは、JBossバージョン2.4.0から、デプロイメント記述でJMSリソースを定義して、他のリソースと同様にルックアップして、リソースとしても利用する、ということを意味します。そして、コンテナはあなたのJMSリソースをプールして、データソースを使っているかのように、実行中または起動しようとするトランザクションにそれらを登録(enlist)します。

JMSの新しいリソース管理は、J2EEコネクタアーキテクチャ互換(その種の中では最初)のJMSリソースアダプタを基礎にしています。そのリソースアダプタは、JBossディストリビューションのdeploy/lib/jms-ra.rarファイルに含まれます。しかし、それは、分散トランザクションのために、jboss.jcmlで自動的にデプロイと設定がおこなわれますので、普通は気にする必要はありません。

セッション、エンティティ、そしてメッセージ駆動型というすべてのEJBのタイプで、リソースとしてJMSを管理できますが、Webコンテナからは(私が知っている限り)できません。この背後にある理由は、Webコンテナはトランザクションを扱う方法を知らないからです。

リソースをJMSを使うためには、二つの事をしなければなりません。 利用者はリソース互換のJMSコードを書かなければなりませんし、そのリソースはデプロイメント記述に追加されなければなりません。簡単なサンプルを使ってこのことを確認していきましょう。]

[2.4.0] JMSリソースのサンプル

このサンプルは単純なパターンにもとづいています。セッションBeanは、メッセージをパラメタとして持つ呼び出しを受信します。これらのメッセージを処理することは非常に時間がかかるかもしれません。したがって、これらを非同期に処理したいと考えます。セッションBeanにそれらを処理させる代わりとして、それは単にJMSの宛先へそれらを渡して、その結果すぐにリターンするかもしれません。別の理由として、メッセージが多くのサブスクライバに対して公開されたトピックへ送られるように、メッセージに対して複数のシステムが対応できるようにしたいということもあります。

リソースを処理する場合はいつでも、リソースをルックアップする名前が必要です。作成後は、コンテナはそのリソースを名前へバインドします。JMS(データソースとは対照的に)では、二つのリソースへのアクセスが必要です。接続ファクトリと宛先です。そこで二つの名前が必要になります。

図 8.77. [2.4.0] JMSリソースをルックアップするための名前

/**
 * TopicConnectionFactoryをルックアップするための名前
 */
private static final String CONNECTION_JNDI =
  "java:comp/env/jms/MyTopicConnection";

/**
 * トピックの宛先をルックアップするための名前
 */
private static final String TOPIC_JNDI = "java:comp/env/jms/TopicName";

これらのリソースのルックアップは、データソースと同様に、Beanの作成中におこなわれます。データソースとJMSが異なる点は、JMS接続(ファクトリではない)はデータソースに似ていて、JMSセッションはJDBC接続に似ているということです。したがって、そのBeanが作成されるときにJMS接続も作成します。そして、そのBeanが生きている間、それを使い続けます。

図 8.78. [2.4.0] JMSリソースのルックアップ(接続ファクトリと宛先)

public void ejbCreate() {

  try {

    Context context = new InitialContext();

    // トピックをルックアップします。
    topic = (Topic)context.lookup(TOPIC_JNDI);

    // 接続ファクトリをルックアップします。
    TopicConnectionFactory factory =
      (TopicConnectionFactory)context.lookup(CONNECTION_JNDI);

    topicConnection = factory.createTopicConnection();

    // 両方とも取っておきます。

  } catch (Exception ex) {

    // JMSExceptionやNamingExceptionがスローされるかもしれません。
    ex.printStackTrace();
    throw new EJBException(ex.toString());

  }

}

私たちのサンプルでは、hello()という、Stringオブジェクトの形式のテキストメッセージをパラメタに取るメソッドを持ちます。 これはリモートクライアントが呼び出すメソッドです。 Beanがメッセージをひとつ受信するたびに、それをJMSメッセージに詰め込み、宛先に向かってそれを送信します。 これは通常のJMSコードに本当によく似ています。

図 8.79. [2.4.0] JMSリソースを使ったメッセージのパブリッシュ

TopicPublisher topicPublisher = null;
TextMessage message = null;

// セッションを作成します。
topicSession = topicConnection.createTopicSession(true,
  Session.AUTO_ACKNOWLEDGE);

// パブリッシャを作成します。
topicPublisher = topicSession.createPublisher(topic);

// メッセージを作成します。
message = topicSession.createTextMessage();
message.setText(msg);

// パブリッシュします。
System.out.println("Publishing message " + msg);
topicPublisher.publish(message);

私たちは、現在、トランザクションに管理されたプールされた環境で仕事をしているので、注意してコードを書かなければなりません。コードの中でトランザクションをロールバックすることで、エラーを処理します。

図 8.80. [2.4.0] 例外が存在した場合のロールバックのためのマークの設定

try {

//... アプリケーション コード

} catch (JMSException ex) {

  ex.printStackTrace();
  ctx.setRollbackOnly();
  throw new EJBException(ex.toString());

}

例外が発生したら、finallyブロックで、セッションをクローズするのにも注意を払わなければなりません。

図 8.81. [2.4.0] JMSリソースを適切にクローズする

} finally {

  // セッションを常にクローズします。プールされるので心配しないでください。
  if (topicSession != null) {

    try {

      topicSession.close();

    } catch (Exception e) {

      e.printStackTrace();

    }

  }

}

これは完全なサンプルのBeanです。

図 8.82. [2.4.0] JMSとリソースとして利用したBeanのサンプル (org/jboss/docs/jms/ra/beanディレクトリのTopicHelloBean.javaより)

package org.jboss.docs.jms.ra.bean;

import java.rmi.RemoteException;

import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import javax.ejb.EJBException;

import javax.naming.InitialContext;
import javax.naming.Context;

import javax.jms.TopicConnectionFactory;
import javax.jms.TopicConnection;
import javax.jms.TopicSession;
import javax.jms.TopicPublisher;
import javax.jms.Topic;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.JMSException;

import org.jboss.docs.jms.ra.interfaces.*;

/**
 * 設定されたトピックへメッセージを送るHello Bean。
 * JMS関連のものは、デプロイメント記述で設定されます。
 *
 * TopicConnectionはJDBC DataSourceにたとえられます。
 * TopicSessionはJDBC Connectionにたとえられます。
 *
 * @author Peter Antman
 * @version $Revision: 1.1.1.1 $
 */
public class TopicHelloBean implements SessionBean {

  /**
   * TopicConnectionFactoryをルックアップするために使用される名前
   */
  private static final String CONNECTION_JNDI =
    "java:comp/env/jms/MyTopicConnection";

  /**
   * トピックの宛先をルックアップするために使用される名前
   */
  private static final String TOPIC_JNDI = "java:comp/env/jms/TopicName";

  private SessionContext ctx = null;

  private Topic topic = null;
  private TopicConnection topicConnection = null;

  public TopicHelloBean() {
  }

  public void setSessionContext(SessionContext ctx) {

    this.ctx = ctx;

  }

  public void ejbCreate()  {

    try {

      Context context = new InitialContext();

      // トピックをルックアップします。
      topic = (Topic)context.lookup(TOPIC_JNDI);

      // 接続ファクトリをルックアップします。
      TopicConnectionFactory factory =
        (TopicConnectionFactory)context.lookup(CONNECTION_JNDI);

      topicConnection = factory.createTopicConnection();

      // 両方とも取っておきます。

    } catch (Exception ex) {

      // JMSExceptionやNamingExceptionはスローされるかもしれません。
      ex.printStackTrace();
      throw new EJBException(ex.toString());

    }
  }

  /**
   * 適切なMESSAGE_NRで、メッセージnrを持ったメッセージを送信します(訳注: 意味不明)。
   */
  public void hello(String msg) {

    sendMessage(msg);

  }

  public void ejbRemove() throws RemoteException {

    if (topicConnection != null) {

      try {

        // Beanが破壊されるとき接続をクローズすることを覚えておきます。
        topicConnection.close();

      } catch (Exception e) {

        e.printStackTrace();

      }

    }

  }

  public void ejbActivate() {}
  public void ejbPassivate() {}

  /**
   * JMSを使ってメッセージ送信をする補助メソッド
   */
  private void sendMessage(String msg) {

    TopicSession topicSession = null;

    try {

      TopicPublisher topicPublisher = null;
      TextMessage message = null;

      // セッションを作成します。
      topicSession = topicConnection.createTopicSession(true,
        Session.AUTO_ACKNOWLEDGE);

      // パブリッシャを作成します。
      topicPublisher = topicSession.createPublisher(topic);

      // メッセージを作成します。
      message = topicSession.createTextMessage();
      message.setText(msg);

      // それをパブリッシュします。
      System.out.println("Publishing message " + msg);
      topicPublisher.publish(message);

    } catch (JMSException ex) {

      ex.printStackTrace();
      ctx.setRollbackOnly();
      throw new EJBException(ex.toString());

    } finally {

      // 常にセッションをクローズします。プールされるので心配しないでください。

      if (topicSession != null) {

         try {

           topicSession.close();

         } catch (Exception e) {

           e.printStackTrace();

         }

       }

     }

  }

}

ここでは、リモートやホームのインタフェースも存在します。

図 8.83. [2.4.0] JMSリソースサンプルのためのリモートインタフェース (org/jboss/docs/jms/ra/interfacesディレクトリにあるHello.javaファイル)

package  org.jboss.docs.jms.ra.interfaces;

import javax.ejb.EJBObject;
import java.rmi.RemoteException;

/**
 * Hello Beanのリモート インタフェース
 *
 * @author Peter Antman
 * @version $Revision: 1.1.1.1 $
 */

public interface Hello extends EJBObject {

  /**
   * 設定されたトピックへメッセージを送信します。
   * (デプロイメント記述のjms/TopicName)
   */
  public void hello(String msg) throws RemoteException;

}

図 8.84. [2.4.0] JMSリソースサンプルのためのホームインタフェース (org/jboss/docs/jms/ra/interfacesディレクトリにあるHelloHome.javaより)

package  org.jboss.docs.jms.ra.interfaces;

import java.rmi.RemoteException;
import javax.ejb.EJBHome;
import javax.ejb.CreateException;

/**
 * Hello Beanのホーム インタフェース
 *
 * @author Peter Antman
 * @version $Revision: 1.1.1.1 $
 */
public interface HelloHome extends EJBHome {

  Hello create() throws RemoteException, CreateException;

}

セッションBeanにメッセージを送信するクライアントも必要です。それは、標準的なクライアントEJBプログラミングです。

図 8.85. [2.4.0] JMSリソースサンプルのためのクライアント (org/jboss/docs/jms/raディレクトリにあるHelloClient.javaより)

package org.jboss.docs.jms.ra;

import org.jboss.docs.jms.ra.interfaces.Hello;
import org.jboss.docs.jms.ra.interfaces.HelloHome;

import javax.naming.InitialContext;
import javax.naming.Context;

/**
 * セッションBeanへhelloメッセージを送信するクライアント
 * (リソースアダプタを介してJMSを使います).
 *
 * @author Peter Antman
 * @version $Revision: 1.1.1.1 $
 */

public class HelloClient
{

  /**
   * BeanのJNDI名
   */
  private String beanJNDI;

  /**
   * Hello Beanのリモート参照
   */
  private Hello hello;

  /**
   * @param beanJNDI メッセージを送信するBean
   */
  public HelloClient(String beanJNDI) throws Exception {

    this.beanJNDI = beanJNDI;
    setUp();

  }

  /**
   * Beanへのリモート参照の取得を補助するもの
   */
  protected void setUp() throws Exception {

    // Hello Beanを取得します。
    Context context = new InitialContext();
    HelloHome helloH = (HelloHome)context.lookup(beanJNDI);

    hello = helloH.create();

  }

  /**
   * Beanにハローと言います。
   */
  public void hello(String msg) throws Exception {

    System.out.println("Saying hello");
    hello.hello(msg);

  }

  public static void main(String[] args) {

    try {

      HelloClient c = new HelloClient("TopicHello");
      c.hello("Hello topic");

    } catch(Exception ex) {

      System.out.println("Error: " + ex);
      ex.printStackTrace();

    }

  }

} // HelloClient

次のステップは、Beanのためのデプロイメント記述を書くことです。標準ejb-jar.xmlでは、そのリソースのための一連の設定を追加しなければなりません。res-ref-name要素は、そのリソースをルックアップするためにBeanで使用される名前を含まなければなりません。

図 8.86. [2.4.0] JMSリソースサンプルのためのejb-jar.xmlにおけるresource-refの一連の設定

<resource-ref>
  <description>A Topic ConnectionFactory</description>
  <res-ref-name>jms/MyTopicConnection</res-ref-name>
  <res-type>javax.jms.TopicConnectionFactory</res-type>
  <res-auth>Container</res-auth>
</resource-ref>
<resource-ref>
  <description>A Topic </description>
  <res-ref-name>jms/TopicName</res-ref-name>
  <res-type>javax.jms.Topic</res-type>
  <res-auth>Container</res-auth>
</resource-ref>

jboss.xmlでは、実際にリソースを指し示すために、resource-managerの一連の設定を追加しなければなりません。

図 8.87. [2.4.0] JMSリソースサンプルのためのjboss.xmlにおけるresource-managersの一連の設定

<resource-managers>
  <resource-manager>
    <res-name>topicfactoryref</res-name>
    <res-jndi-name>java:/JmsXA</res-jndi-name>
  </resource-manager>
  <resource-manager>
    <res-name>topicref</res-name>
    <res-jndi-name>topic/testTopic</res-jndi-name>
  </resource-manager>
</resource-managers>

最も不思議な行は、res-jndi-name要素のjava:/JmsXAという内容です。それはJ2EEコネクタ準拠のJMSリソースアダプタを指します。同時にjboss.xmlでは、常にセッションEJBの定義を追加しなければなりません。

図 8.88. [2.4.0] JMSリソースサンプルのためのjboss.xmlにおけるBean設定

<session>
  <ejb-name>TopicHello</ejb-name>
  <jndi-name>TopicHello</jndi-name>
  <configuration-name>Standard Stateless SessionBean</configuration-name>
  <resource-ref>
    <res-ref-name>jms/MyTopicConnection</res-ref-name>
    <resource-name>topicfactoryref</resource-name>
  </resource-ref>
  <resource-ref>
    <res-ref-name>jms/TopicName</res-ref-name>
    <resource-name>topicref</resource-name>
  </resource-ref>
</session>

これは、デプロイメント記述のための完全なリストです。

図 8.89. [2.4.0] JMSリソースサンプルの ejb-jar.xml (org/jboss/docs/jms/resourcesディレクトリにあるTopicHello-ejb-jar.xmlより)

<?xml version="1.0" encoding="Cp1252"?>

<ejb-jar>
  <description>Topic Hello</description>
  <display-name>TopicHelloBean</display-name>
  <enterprise-beans>
    <session>
      <display-name>TopicHello</display-name>
      <ejb-name>TopicHello</ejb-name>
      <home>org.jboss.docs.jms.ra.interfaces.HelloHome</home>
      <remote>org.jboss.docs.jms.ra.interfaces.Hello</remote>
      <ejb-class>org.jboss.docs.jms.ra.bean.TopicHelloBean</ejb-class>
      <session-type>Stateless</session-type>
      <transaction-type>Container</transaction-type>
      <resource-ref>
        <description>A Topic ConnectionFactory</description>
        <res-ref-name>jms/MyTopicConnection</res-ref-name>
        <res-type>javax.jms.TopicConnectionFactory</res-type>
        <res-auth>Container</res-auth>
      </resource-ref>
      <resource-ref>
        <description>A Topic </description>
        <res-ref-name>jms/TopicName</res-ref-name>
        <res-type>javax.jms.Topic</res-type>
        <res-auth>Container</res-auth>
      </resource-ref>
    </session>
  </enterprise-beans>
  <assembly-descriptor/>
</ejb-jar>

図 8.90. [2.4.0] JMSリソースサンプルのjboss.xml (org/jboss/docs/jms/resourcesディレクトリにあるTopicHello24-jboss.xml)

<?xml version="1.0" encoding="Cp1252"?>

<jboss>
  <secure>false</secure>
  <resource-managers>
    <resource-manager>
      <res-name>topicfactoryref</res-name>
      <res-jndi-name>java:/JmsXA</res-jndi-name>
    </resource-manager>
    <resource-manager>
      <res-name>topicref</res-name>
      <res-jndi-name>topic/testTopic</res-jndi-name>
    </resource-manager>
  </resource-managers>

  <enterprise-beans>
    <session>
      <ejb-name>TopicHello</ejb-name>
      <jndi-name>TopicHello</jndi-name>
      <configuration-name>Standard Stateless SessionBean</configuration-name>
      <resource-ref>
        <res-ref-name>jms/MyTopicConnection</res-ref-name>
        <resource-name>topicfactoryref</resource-name>
      </resource-ref>
      <resource-ref>
        <res-ref-name>jms/TopicName</res-ref-name>
        <resource-name>topicref</resource-name>
      </resource-ref>
    </session>
  </enterprise-beans>
</jboss>

Antターゲットとしてサンプルを実行することが可能です。

図 8.91. [2.4.0] JMSリソースサンプルの実行

ant jms-topic-hello24

[2.4.0] JMSリモートリソース

上のサンプルの別の方法は、リモートJBossサーバへメッセージを送信するためにそれを再設定する方法です。基本的に二つのことをやらなければなりません。

第一に、jboss.xmlに二つのことを追加することが必要です。 リモートJMSプロバイダを使うリモートJMSプロバイダとJMSリソースアダプタです。リモートJMSプロバイダを定義するとき、ProviderUrlプロパティを記入すべきです。JBossバージョン2.4.0とURLlinutv1.annons.dn.se:1099のためには、その内容はこのような感じになります。

図 8.92. [2.4.0] jboss.jcmlにおけるリモートJMSProviderLoaderの定義 (org/jboss/docs/jms/resourcesディレクトリにある、TopicHello24-Remote-snippet-jboss.jcml)

<mbean code="org.jboss.jms.jndi.JMSProviderLoader"
  name=":service=JMSProviderLoader,name=MyRemoteLoader">
  <attribute name="ProviderName">MyRemoteProvider</attribute>
  <attribute name="ProviderUrl">linutv1.annons.dn.se:1099</attribute>
  <attribute name="QueueFactoryRef">XAQueueConnectionFactory</attribute>
  <attribute name="TopicFactoryRef">XATopicConnectionFactory</attribute>
  <attribute name="ProviderAdapterClass">org.jboss.jms.jndi.JBossMQProvider</attribute>
</mbean>

[2.4.1. このバージョンでは、少し違った感じになります]

図 8.93. [2.4.1] jboss.jcmlにおけるリモートJMSProviderLoaderの定義

<!-- リモートバージョンを動作させるためには、-->
<!-- これはjboss.jcmlに入れなければなりません -->
<mbean code="org.jboss.jms.jndi.JMSProviderLoader"
  name=":service=JMSProviderLoader,name=MyRemoteLoader">
  <attribute name="ProviderName">MyRemoteProvider</attribute>
  <attribute name="ProviderUrl">linutv1.annons.dn.se:1099</attribute>
  <attribute name="QueueFactoryRef">XAConnectionFactory</attribute>
  <attribute name="TopicFactoryRef">XAConnectionFactory</attribute>
  <attribute name="ProviderAdapterClass">org.jboss.jms.jndi.JBossMQProvider</attribute>
</mbean>

次に、リモートプロバイダを使用しているJMSリソースアダプタを追加する必要があります。名前を付け(この場合はRemoteJmsXA)、新しく定義したリモートプロバイダjava:MyRemoteProviderを指し示すように、アダプタのプロパティJmsProviderAdapterJNDIを設定します。

図 8.94. [2.4.0] jboss.jcmlにおけるリモートJMSリソースアダプタの定義 (org/jboss/docs/jms/resourcesディレクトリにあるTopicHello24-Remote-snippet-jboss.jcmlより)

<!-- JMS XA リソースアダプタ -->
<!-- Bean内でトランザクション管理のJMSを取得するのにこれを使います。-->
<mbean code="org.jboss.resource.ConnectionFactoryLoader"
  name="JCA:service=ConnectionFactoryLoader,name=RemoteJmsXA">
  <attribute name="FactoryName">RemoteJmsXA</attribute>
  <attribute name="RARDeployerName">JCA:service=RARDeployer</attribute>
  <attribute name="ResourceAdapterName">JMS Adapter</attribute>
  <attribute name="ConnectionManagerFactoryName">MinervaXACMFactory</attribute>
  <!-- 使用可能なプロパティについてはお使いの接続マネージャ実装のドキュメントを
       ご覧ください。-->
  <attribute name="ConnectionManagerProperties">
  <attribute name="Properties">
    JmsProviderAdapterJNDI=java:MyRemoteProvider
    # Pool type - uncomment to force, otherwise it is the default
    #PoolConfiguration=per-factory

    # Connection pooling properties - see
    # org.opentools.minerva.pool.PoolParameters
    MinSize=0
    MaxSize=10
    Blocking=true
    GCEnabled=false
    IdleTimeoutEnabled=false
    InvalidateOnError=false
    TrackLastUsed=false
    GCIntervalMillis=120000
    GCMinIdleMillis=1200000
    IdleTimeoutMillis=1800000
    MaxIdleTimeoutPercent=1.0
  </attribute>

  <!-- プリンシパル マッピングの設定 -->
  <attribute name="PrincipalMappingClass">org.jboss.resource.security.ManyToOnePrincipalMapping</attribute>
  <attribute name="PrincipalMappingProperties">
  </attribute>
</mbean>

二番目にすることは、jboss.xmlデプロイメント記述を書き換えることです。こうして、topicfactoryrefリソースのためのres-jndi-nameプロパティが、私たちが定義したリソースアダプタjava:/RemoteJmsXAを指し示すようにします。そして、宛先のリソースを私たちのリモートサーバのJNDI名前空間であるjnp://linutv1.annons.dn.se:1099/topic/testTopicを指すようにします。これは完全なディスクリプタファイルです。

図 8.95. [2.4.0] JMSリソースサンプルのリモートバージョンのためのjboss.xml (org/jboss/docs/jms/resourcesディレクトリにあるTopicHello24-Remote-jboss.xml)

<?xml version="1.0" encoding="Cp1252"?>

<jboss>
  <secure>false</secure>
  <resource-managers>
    <resource-manager>
      <res-name>topicfactoryref</res-name>
      <res-jndi-name>java:/RemoteJmsXA</res-jndi-name>
    </resource-manager>
    <resource-manager>
      <res-name>topicref</res-name>
      <res-jndi-name>jnp://linutv1.annons.dn.se:1099/topic/testTopic</res-jndi-name>
    </resource-manager>
  </resource-managers>

  <enterprise-beans>
    <session>
      <ejb-name>TopicHello</ejb-name>
      <jndi-name>TxTopicHello</jndi-name>
      <configuration-name>Standard Stateless SessionBean</configuration-name>
      <resource-ref>
        <res-ref-name>jms/MyTopicConnection</res-ref-name>
        <resource-name>topicfactoryref</resource-name>
      </resource-ref>
      <resource-ref>
        <res-ref-name>jms/TopicName</res-ref-name>
        <resource-name>topicref</resource-name>
      </resource-ref>
    </session>
  </enterprise-beans>
</jboss>

JBossがエミュレートするリソース

それでは、JBoss 2.2.xではリソースとしてJMSを使う方法はないのですか? それは、やり方次第です。おそらく、JBossバージョン2.2.xではJMSのためにリソースアダプタをデプロイすることは可能です。しかし、それは高度で、未確認のテーマです。是非テストして動作するかどうか報告してください。しかし、JBossリリース2.2.xから新しいものへ移行するのを簡単にするためには、少なくとももう一つできることがあります。あなたのBeanがあたかもJMSをリソースとして使っているかのように実際にコーディングするができるのです。

たとえこれを実行したとしても、トランザクションが登録(enlist)されるという正しい振る舞いを見ることはないということを理解することはとても重要です。唯一の利点は、少なくともバージョン2.4.0へアップグレードするときに、多くのコードやディスクリプタを書きかえることなく正常に機能するということです。

では、どうすればよいのでしょう? 最初におこなうべきことは、バージョン2.4.0と互換性のあるサンプルと比較して、JMSセッションが作成されるコードにおいて小さな修正をおこなうことです。あなたはそのセッションをトランザクションによる管理をおこなわないようにマークする必要があります。

図 8.96. JMSリソースのエミュレーションのためのセッションの作成 (org/jboss/docs/jms/ra/beanディレクトリにあるTopicHelloBean22.javaより)

topicSession = topicConnection.createTopicSession(
  // トランザクションなし
  false,
  Session.AUTO_ACKNOWLEDGE);

包み隠さずに言うと、バージョン2.4.0でもJMSリソースアダプタを使ってこのコードを使うことが実際に可能です。なぜなら、トピック接続は、XAトランザクションで実行中に、あなたがJMSセッションにトランザクション管理としてマークを付けたか否かは問題にしません。このようにコードを書くことで、2.2.x以後のバージョンで動作します。

しかし、デプロイメント記述ファイルは変更することは強制されます。バージョン2.4.0では、接続ファクトリのリソースがJMSリソースアダプタを指すようにしました。2.2.xでは、それが直接ConnectionFactoryのインスタンスを指すようにしなければなりません。res-jndi-name要素を使うことは不可能です。代わりにres-url要素を使ってください。このように感じになるでしょう。

図 8.97. jboss.xmlにおけるJMSリソースエミュレーション

<?xml version="1.0" encoding="Cp1252"?>

<jboss>
  <secure>false</secure>
  <resource-managers>
    <resource-manager>
      <res-name>topicfactoryref</res-name>
      <res-url>TopicConnectionFactory</res-url>
    </resource-manager>
    <resource-manager>
      <res-name>topicref</res-name>
      <res-url>topic/testTopic</res-url>
    </resource-manager>
  </resource-managers>

  <enterprise-beans>
    <session>
      <ejb-name>TopicHello</ejb-name>
      <jndi-name>TopicHello</jndi-name>
      <configuration-name>Standard Stateless SessionBean</configuration-name>
      <resource-ref>
        <res-ref-name>jms/MyTopicConnection</res-ref-name>
        <resource-name>topicfactoryref</resource-name>
      </resource-ref>
      <resource-ref>
        <res-ref-name>jms/TopicName</res-ref-name>
        <resource-name>topicref</resource-name>
      </resource-ref>
    </session>
  </enterprise-beans>
</jboss>

Antを使ってサンプルをテストできます。

図 8.98. エミュレートされたJMSリソースサンプルの実行

ant jms-topic-hello22

[doc] [toc] [previous] [next]

Copyright © 2000 2001 JBoss Organization
Copyright © 2001 2002 日本語訳: Neverbird Project