管理設定ガイド

JBoss Enterprise Application Platform 5

JBoss Enterprise Application Platform 5 向け

エディッション 5.1.2

Community JBoss

編集者

Documentation Group Red Hat

概要

本書は JBoss Enterprise Application Platform 5 およびその修正リリースに対する管理設定ガイドです。

本書の範囲

本書の第一の目的は、 設定とアーキテクチャーの両方の観点より標準の JBoss Enterprise Application Platform 5.0 のアーキテクチャーコンポーネントについて説明することです。 標準の JBoss ディストリビューションユーザーは、 標準コンポーネントの設定方法を理解できるようになるでしょう。 本書は JavaEE の紹介やアプリケーションで JavaEE を使用する方法について書かれたものではなく、JBoss サーバーアーキテクチャー内部の詳細や、 JavaEE コンテナー実装の設定方法や拡張方法に焦点が置かれています。
JBoss の開発者として、標準コンポーネントの統合やアーキテクチャーを十分理解でき、ご利用のインフラストラクチャーで必要な標準コンポーネントを拡張、又は入れ替えることができるようになるでしょう。また、このマニュアルでは、JBoss サーバーの 構築とデバッグの方法と共に JBoss ソースコードの取得の方法も案内しています。

第1章 はじめに

JBoss Enterprise Application Platform 5 は新しい JBoss Microcontainer 上に構築されています。JBoss Microcontainer は、POJO (Plain Old Java Object) の直接デプロイや設定、ライフサイクルをサポートする軽量コンテナーです。 このスタンドアローンの JBoss Microcontainer プロジェクトは、JBoss Enterprise Application Platform 4.x で使用された JBoss JMX Microkernel を置き換えるものとなっています。
JBoss Microcontainer は JBoss Aspect Oriented Programming フレームワーク (JBoss AOP) とスムーズに統合することができます。 JBoss AOP については 10章JBoss AOP に説明されています。 JBoss Enterprise Application Platform 5 でも JMX に対するサポートは継続されるため、 従来の Microkernel 向けに書かれた MBean サービスも動作するはずです。
JBoss Enterprise Application Platform 5.0.0.GA 以降のバージョン上で実行可能で、興味深い技術を多数保持するサンプル Java EE 5 アプリケーションが本ディストリビューションで提供される Seam Booking Application となっています。このサンプルアプリケーションは、JBoss Enterprise Application Platform 5 上で稼働する以下の技術を利用しています。
  • EJB3
  • ステートフルセッション Bean
  • ステートレスセッション Bean
  • JPA (Hibernate 検証あり)
  • JSF
  • Facelets
  • Ajax4JSF
  • Seam
JBoss Enterprise Application Platform 5 にある主要機能の多くは、次のようなスタンドアロン JBoss プロジェクトを統合して提供されます。
  • JBoss Enterprise Application Platform 5 に含まれる JBoss EJB3 は、Enterprise Java Beans (EJB) 仕様の最新バージョンを実装します。EJB 3.0 は EJB 仕様が大幅に改良、簡素化されています。EJB 3.0 の目標は、開発の簡素化やテスト駆動型アプローチの推進を図るとともに、複雑な EJB API に対するコード化ではなくPOJO (Plain Old Java Object) の書き込みに焦点を置いています。
  • JBoss Messaging は、 JBoss Enterprise Application Platform 5 のデフォルトのメッセージプロバイダーとして提供される高パフォーマンス JMS プロバイダーです。JBoss ESB インフラストラクチャーのバックボーンでもあります。 JBoss Messaging は、 JBoss Enterprise Application Platform 4.2 のデフォルトの JMS プロバイダーである JBossMQ を完全に書き直したものです。
  • JBoss Cache は、従来のツリー構造のノードベースキャッシュと、 PojoCache の 2 種類のキャッシュを提供します。PojoCache はインメモリでレプリケーション型のトランザクションキャッシュシステムで、レプリケーションや永続性アスペクトのユーザー管理をアクティブに行わなくてもユーザーが簡単な POJO を透過的に操作できるようにします。
  • JBossWS 3.x は、 Java EE 互換 Web サービス JAXWS-2.x を提供する JBoss Enterprise Application Platform 5 の Web サービススタックです。
  • JBoss Transactions は、 JBoss Enterprise Application Platform 5 のデフォルトのトランザクションマネージャーです。JBoss Transactions は業界で定評のある技術を基盤とし、分散トランザクションのリーダーとして 18 年の実績を持っています。JBoss Transactions は最も相互操作性に優れた実装の 1 つです。
  • JBoss Web は JBoss Enterprise Application Platform 5 の Web コンテナーで、APR (Apache Portable Runtime) と Tomcat ネイティブ技術を含む Apache Tomcat を基盤とした実装となっており、Apache Http サーバー以上のパフォーマンス特性やスケーラビリティを実現します。

1.1. JBoss Enterprise Application Platform ユースケース

  • 99% の Web アプリケーションがデータベースを活用している場合
  • クラスター化される可能性の高いミッションクリティカルな Web アプリケーション
  • JSP/サーブレットを持つ簡単な Web アプリケーションがTomcat 組み込みの JBoss Enterprise Application Platform にアップグレードされる場合
  • JSP/ サーブレットを持ち、 Struts、 Java Server Faces、 Cocoon、 Tapestry、 Spring、 Expresso、 Avalon、 Turbine などの Web フレームワークを使用する中級ウェブアプリケーション。
  • JSP/サーブレット、 SEAM、 EJB (Enterprise Java Bean)、 JMS (Java Messaging)、 キャッシングなどを持つ複雑な Web アプリケーション
  • アプリケーション間共通のミドルウェア (JMS、Corba、JMX など)

パート I. JBoss Enterprise Application Platform インフラストラクチャー

第2章 JBoss Enterprise Application Platform 5 アーキテクチャー

次の図は、 JBoss Enterprise Application Server とそのコンポーネントの概略を表しています。
JBoss Enterprise Application Platform 5 のディレクトリ構造は 4.x シリーズと似ていますが、明らかな違いがいくつかあります。
-jboss-as - the path to your JBoss Enterprise Application Server.
  |-- bin - contains start scripts and run.jar
  |-- client - client jars 
  |-- common/lib - static jars shared across server profile
  |-- docs - schemas/dtds, examples
  |-- lib - core bootstrap jars
  |   lib/endorsed - added to the server JVM java.endorsed.dirs path
  `-- server - server profile directories. See Section 3.2 
                     for details of the server profiles included in this release.
-seam - the path to JBoss SEAM application framework 
  |-- bootstrap
  |-- build
  |-- examples - examples demonstrating uses of SEAM's features
  |-- extras
  |-- lib - library directory
  |-- seam-gen - command-line utility used to generate simple skeletal SEAM code to get your project started
  |-- ui -
-resteasy - RESTEasy - a portable implementation of JSR-311 JAX-RS Specification
  |-- embedded-lib
  |-- lib
  |-- resteasy-jaxrs.war

2.1. JBoss Enterprise Application Platform のブートストラップ

JBoss Enterprise Application Platform 5 のブートストラップは org.jboss の JBoss Enterprise Application Platform 4.x バージョンと似ています。 メインエントリポイントが org.jboss.system.server.Server 実装をロードします。 JBoss Enterprise Application Platform 4.x では JMX ベースのマイクロカーネルでしたが、 JBoss Enterprise Application Platform 5 では JBoss マイクロコンテナーになりました。
JBoss Enterprise Application Platform 5 のデフォルトの org.jboss.system.server.Server implementationorg.jboss.bootstrap.microcontainer.ServerImpl です。 この実装はカーネル基本ブートストラップの拡張で、BasicXMLDeployer を使用して {jboss.server.config.url}/bootstrap.xml 記述子にて宣言されたブートストラップ beanから MC をブートします。 また、 ServerImpl レジスターは、 org.jboss.bootstrap.spi.Bootstrap インターフェースを実装する Bean のコールバックをインストールします。 bootstrap/profile*.xml 設定には、 Bootstrap インターフェースを実装する ProfileServiceBootstrap Bean が含まれます。
org.jboss.system.server.profileservice.ProfileServiceBootstrapは、org.jboss.bootstrap.spi.Bootstrap インターフェースの実装で現在のプロファイルに紐付けられたデプロイメントをロードします。PROFILE はロードされたプロファイルの名前で、 server -c コマンドライン引数に対応します。 デフォルトの PROFILEdefaultです。

2.2. ホットデプロイメント

JBoss Enterprise Application Platform 5 のホットデプロイメントは、 ProfileService に関連する Profile 実装によって制御されます。 deploy/hdscanner-jboss-beans.xml よりデプロイされた HDScanner Bean はアプリケーションディレクトリ内容の変更についてプロファイルサービスをクエリし、 更新された内容を再デプロイします。 その後、 削除された内容をアンデプロイし、 ProfileService より新しいデプロイメント内容を現在のプロフィールへ追加します。
ホットデプロイメントを一時的、あるいは永続的に無効にしたい場合は、以下のいずれかのメソッドを利用してください。 2 番目のメソッドは最も簡単に元に戻すことができるため、一時的にホットデプロイメントを無効にしたい場合は、この2番目のメソッドの利用が最適です。
  • デプロイメントから hdscanner-jboss-beans.xml ファイルを削除します。
  • hdscanner-jboss-beans.xml ファイルを編集し、scanEnabled 属性を false へ変更します。
以下に、ホットデプロイメントを無効にした hdscanner-jboss-beans.xml ファイルを抜粋しています。
      <?xml version="1.0" encoding="UTF-8"?>
        <!--
            Hot deployment scanning
            
            $Id: hdscanner-jboss-beans.xml 98983 2010-01-04 13:35:41Z emuckenhuber $
        -->
        <deployment xmlns="urn:jboss:bean-deployer:2.0">

            <!-- Hotdeployment of applications -->
            <bean name="HDScanner" class="org.jboss.system.server.profileservice.hotdeploy.HDScanner">
                <property name="deployer"><inject bean="ProfileServiceDeployer"/></property>
                <property name="profileService"><inject bean="ProfileService"/></property>
                <property name="scanPeriod">5000</property>
                <property name="scanThreadName">HDScanner</property>
                <property name="scanEnabled">false</property>
            </bean>

            ...(snip)...

        </deployment>

パート II. JBoss Enterprise Application Platform 5 の設定

第3章 ネットワーク

デフォルトでは、Enterprise Platform は起動時にネットワークアドレスすべてにバインドします。起動時にUDPアドレスだけでなくバインドアドレスを指定することができます。

表3.1 ネットワーク関連のスタートアップオプション

-b [IP-ADDRESS]
アプリケーションサーバーのバインド先のアドレスを指定します。指定されていない場合は、アプリケーションサーバーは全アドレスにバインドします。
-u [IP-ADDRESS]
UDPマルチキャストアドレス(オプション)。指定されていない場合はTCPを利用します。
-m [MULTICAST_PORT_ADDRESS]
UDPマルチキャストポート。JGroups のみが使用します。

3.1. IPv6 のサポート

今後対応される予定ではありますが、Enterprise Application Platform 5 では IPv6 には対応していません。

第4章 EJB3 サービスと Enterprise Application

EJB3 (Enterprise Java Bean 3.0) は、Java EE 5 アプリケーションのコアとなるコンポーネントモデルを提供します。EJB3 bean は、管理コンポーネントでトランザクション、セキュリティ、永続性、ネーミング、依存性注入など Java EE 5 サーバーコンテナーが提供するサービスすべてを有効活用できるよう自動的にワイヤーされている管理コンポーネントです。この管理コンポーネントにより、開発者はビジネスロジックに集中し、横断的関心事 (cross-cutting concern) はコンテナーに設定として任せることができます。アプリケーション開発者として、コンポーネントの作成や破棄はご自身で行う必要があります。Java EE コンテナーから EJB3 bean の名前のみで EJB3 bean を呼び出しでき、適用した設定済みのコンテナーサービスすべてを使いメソッドを呼び出すことができます。Java EE コンテナーの内部、外部を問わず EJB3 bean へアクセスできます。
JBoss Enterprise Application Platform 5 はカスタマイズなしに EJB3 に対応しています。JBoss Enterprise Application Platform 4.2 は J2EE サーバーであるため、EJB3 機能セットすべてに対応していない点に注意してください。
EJB3 コンポーネントのプログラミングモデルに関する詳細は、本書の対応範囲を超えています。EJB3 インターフェースとアノテーションのほとんどが Java EE 5 規格の一部であるため、Java EE 5 準拠の全アプリケーションサーバーと同じです。興味のある方は EJB3 仕様か、EJB3 関連の本が多数ありますのでそちらを参照し、EJB3 プログラミングについて学習してみてください。
本章では、JBoss Enterprise Application Platform 固有となる、EJB3 設定の問題について見ていきます。例えば、JBoss Enterprise Application Platform における EJB3 コンポーネントの JNDI 命名規則、エンティティ bean 向けの Hibernate 永続エンジンのオプション設定、JBoss EJB3 デプロイヤーのカスタムオプションについて触れています。

4.1. セッション bean

セッション bean は、ローカルおよびリモートクライアントにトランザクションサービスを提供する際に幅広く利用されています。セッション bean を記述するには、インターフェースと実装クラスが必要になります。

@Local
public interface MyBeanInt {
  public String doSomething (String para1, int para2);
}

@Stateless
public class MyBean implements MyBeanInt {

  public String doSomething (String para1, int para2) {
    ... implement the logic ...
  } 
  
}    

セッション bean メソッドを呼び出すと、サーバーにあるセキュリティーマネージャーとトランザクションマネージャーがメソッド実行を自動的に管理します。メソッド上のアノテーションを使うことで、メソッド毎にトランザクションあるいはセキュリティプロパティを指定することができます。多くのクライアントで、セッション bean インスタンスを再利用することができます。サーバーが2つのクライアント間で bean の内部ステータスを管理するかどうかにより、セッション bean はステートレスかステートフルか決まります。Bean にリモートビジネスインターフェースがある場合、現在の JVM の外にあるクライアントは、EJB3 bean を呼び出すことができます。これらはすべて bean 上の標準のアノテーションを使い設定可能です。トランザクションあるいはセキュリティプロパティは、Bean がビジネスインターフェースから呼び出された場合のみ有効である点に注意してください。
セッション bean を定義後、クライアントはどのようにそのセッション bean への参照を取得するのでしょうか?前述したとおり、クライアントは、EJB3 コンポーネントを作成あるいは破棄しないため、サーバーが管理している既存のインスタンスへの参照をサーバーに要求するだけです。これは、JNDI 経由でできます。JBoss AS では、セッション bean に対するデフォルトのローカル JNDI 名は bean クラスのデプロイメントパッケージにより変わります。
  • Bean が JBOSS_DIST/default/deploy にあるスタンドアローンの JAR ファイルにデプロイされた場合、Bean はローカルの JNDI 名 MyBean/local 経由でアクセス可能です。ここでは、先ほど示したように、MyBean は bean の実装クラス名です。JBoss AS では Local の JNDI は、java:comp/env/ を起点とする JNDI 名となります。
  • Bean を含む JAR ファイルが EAR ファイルにパッケージされている場合、Bean に対するローカルの JNDI 名は myapp/MyBean/localです。このmyapp はEAR アーカイブファイルのルート名となっています (例:myapp.ear。EJB3 bean の EAR パッケージについては本書で後述されていますので参照してください)。
Bean インタフェースに @Remote のアノテーションがついており、デプロイされているサーバーの外から Bean にアクセスする場合は、もちろん、localremote に変更するべきです。以下は、myapp.ear にパッケージされたWeb アプリケーションで MBean bean の参照を取得し、管理メソッドを呼び出すためのコードスニペットです (例:サーブレットあるいは JSF バッキング bean)。

try {
  InitialContext ctx = new InitialContext();
  MyBeanInt bean = (MyBeanInt) ctx.lookup("myapp/MyBean/local");
} catch (Exception e) {
  e.printStackTrace ();
}

... ...

String result = bean.doSomething("have fun", 1);

... ...

クライアントが JNDI から取得したものは必然的に、Bean インスタンスの「スタブ」あるいは「プロキシ」となります。クライアントがメソッドを呼び出すと、プロキシは、リクエストをサーバーまでどのようにルーティングし、レスポンスをあわせてマーシャリングするか見出します。
デフォルトの JNDI 名が気に入らない場合は、いつでも bean 実装クラスの @LocalBinding アノテーション を使い Bean に独自の JNDI バインディングを指定することが可能です。JNDI バインディングは常に、java:comp/env/ スペースの下では Local となります。例えば、以下の bean クラス定義は、java:comp/env/MyService/MyOwnNameという JNDI 名の下で利用可能な bean インスタンスが返ってきます。

@Stateless
@LocalBinding (jndiBinding="MyService/MyOwnName")
public class MyBean implements MyBeanInt {

  public String doSomething (String para1, int para2) {
    ... implement the logic ...
  } 
  
}    

注記

Java EE 5 は、明示的に JNDI ルックアップを行わずにアノテーションを使うことで、EJB3 bean インスタンスを直接、Web アプリケーションに注入できるようになります。この動作は、JBoss Enterprise Application Platform 4.2 では未対応ですが、JBoss Enterprise Platform は、JBoss Seam と呼ばれる統合フレームワークを提供しています。JBoss Seam では、Java EE 5 が提供しているものをはるかに超える新たなレベルで、EJB3 / JSF 統合が行えます。詳細は、本プラットフォームに同梱されている JBoss Seam のリファレンスガイドを参照してください。

4.2. エンティティ Bean (Java Persistence API)

EJB3 セッション bean により、データを実装しトランザクションメソッドでビジネスロジックにアクセスできるようになります。実際データベースにアクセスするには、EJB3 エンティティ bean とエンティティマネージャー API が必要です。これらはまとめて、Java Persistence API (JPA) と呼ばれています。
EJB3 エンティティ Bean は Plain Old Java Object (POJO) で、関係データベースのテーブルにマッピングします。例えば、以下のエンティティ bean クラスは、Customer という名前の関係テーブルにマッピングします。このテーブルには、name、age、singupdate の3つカラムがあり、bean の各インスタンスは、テーブルの各行に対応します。

@Entity
public class Customer {

  String name;

  public String getName () {
    return name;
  }
  
  public void setName (String name) {
    this.name = name;
  }
  
  int age;
  
  public int getAge () {
    return age;
  }
  
  public void setAge (int age) {
    this.age = age;
  }
  
  Date signupdate;
  
  public Date getSignupdate () {
    return signupdate;
  }
  
  public void setSignupdate (Date signupdate) {
    this.signupdate = signupdate;
  }
}    

単純なデータプロパティ以外に、エンティティ bean には@OneToOne、@OneToMany、@ManyToMany などの関係マッピングアノテーションを持つ、その他のエンティティ bean への参照も含むことができます。これらのエンティティオブジェクトの関係は、自動的に外部キーとしてデータベース内に設定されます。例えば、以下の例では Customer テーブル内の各レコードには該当するレコードが Account テーブルに1つ、Order テーブルに複数あり、Employee テーブルの各レコードには、該当するレコードが Customer テーブルに複数存在します。

@Entity
public class Customer {

  ... ...
  
  Account account;
  
  @OneToOne
  public Account getAccount () {
    return account;
  }
  
  public void setAccount (Accout account) {
    this.account = account;
  }
  
  Employee salesRep;
  
  @ManyToOne
  public Employee getSalesRep () {
    return salesRep;
  }
  
  public void setSalesRep (Employee salesRep) {
    this.salesRep = salesRep;
  }
  
  Vector <Order> orders;
  
  @OneToMany
  public Vector <Order> getOrders () {
    return orders;
  }
  
  public void setOrders (Vector <Order> orders) {
    this.orders = orders;
  }


EntityManager API を使い、エンティティ bean の作成、更新、削除、クエリを行うことができます。EntityManager はプロセス中に基盤のデータベーステーブルを透過的に更新します。@PersistenceContext アノテーションを使い EJB セッション bean で EntityManager オブジェクトを取得することができます。

@PersistenceContext
EntityManager em;

Customer customer = new Customer ();
// populate data in customer

// Save the newly created customer object to DB
em.persist (customer);

// Increase age by 1 and auto save to database
customer.setAge (customer.getAge() + 1);

// delete the customer and its related objects from the DB
em.remove (customer);

// Get all customer records with age > 30 from the DB
List <Customer> customers = em.query (
     "select c from Customer where c.age > 30");

EntityManager API の詳細用途に関しては、本書の対象外となっています。興味のある方は、JPA 文書あるいは Hibernate EntityManager の文書を参照してください。

4.2.1. persistence.xml ファイル

EntityManager API は優れていますが、サーバーはエンティティオブジェクトを保存、更新、クエリすべきデータベースがどれなのか、どのように把握するのでしょうか?性能や問題解決を向上できるように、基盤となる object-relational-mapping エンジンやキャッシュをどのように設定したらいいでしょう。persistence.xml ファイルで、EntityManager を自由自在に設定することができます。
persistence.xml ファイルは、JPA の標準設定ファイルです。このファイルは、エンティティ bean を含む JAR ファイルの META-INF ディレクトリに入れる必要があります。persistence.xml ファイルは、persistence-unit をスコープ化された現在の classloader 内に一意の名前で定義する必要があります。プロバイダー属性は、基盤となる JPA EntityManager 実装を指定します。JBoss Enterprise Application Platform では、デフォルトの JPA プロバイダーは、Hibernate で唯一対応で推奨しているプロバイダーです。jta-data-source は、この永続ユニットのマッピング先のデータベースの JNDI 名を参照します。ここでは、java:/DefaultDS は、JBoss Enterprise Application Platform に埋め込まれている HSQL DB を参照しています。JBoss AS 用に別のデータベースを設定する方法は、14章JBoss Enterprise Application Platform で別のデータベースを使用 を参照してください。

<persistence>
   <persistence-unit name="myapp">
      <provider>org.hibernate.ejb.HibernatePersistence</provider>
      <jta-data-source>java:/DefaultDS</jta-data-source>
      <properties>
         ... ...
      </properties>
   </persistence-unit>
</persistence>          

注記

永続ユニットのインスタンスが複数、同じアプリケーションで定義されている可能性があるため、通常 @PersistenceContext アノテーションに対して明示的にどのユニットを注入したいかを指示する必要があります。例えば、@PersistenceContext(name="myapp\") は、myapp という名前の永続ユニットから EntityManager を注入します。
しかし、スコープ設定された独自のクラスローダーに EAR アプリケーションをデプロイし、全アプリケーションで1つの永続ユニットのみ定義されている場合、 @PersistenceContextの "name" を省略可能です。EAR パッケージとデプロイメントについては、本章で後述していますのでそちらを参照してください。
persistence.xml のプロパティ要素には、基盤永続プロバイダー向けの設定プロパティを含めることができます。JBoss Enterprise Application Platform は Hibernate を EJB3 永続プロバイダーとして利用するため、Hibernate オプションをここで渡すことができます。詳細については、Hibernate と Hibernate EntityManager 文書を参照してください。ここでは、永続エンジンの SQL 方言を HSQL に設定し、アプリケーション起動時にエンティティ bean からテーブルを作成し、アプリケーション停止時にこのテーブルを破棄するという例を提示しているだけです。

<persistence>
   <persistence-unit name="myapp">
      <provider>org.hibernate.ejb.HibernatePersistence</provider>
      <jta-data-source>java:/DefaultDS</jta-data-source>
      <properties>
         property name="hibernate.dialect" 
                  value="org.hibernate.dialect.HSQLDialect"/>
         <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
      </properties>
   </persistence-unit>
</persistence>          

4.2.2. 代わりのデータベースを利用

ビルトインされている HSQL DB 以外の別のデータベースを利用して、エンティティ bean をバックアップする場合、データベースのデータソースをまず定義し、JNDI にてそのデータソースを登録する必要があります。これには、deploy ディレクトリの *-ds.xml ファイルを使います。様々なデータベース向けの *-ds.xml ファイル例は、当サーバーのJBOSS_DIST/docs/examples/jca ディレクトリから入手できます。
次に、persistence.xml で、jta-data-source 属性を変更し、JNDI の新規データソースを参照する必要があります (例:デフォルトの mysql-ds.xml を使い、MySQL 外部データベースを設定する場合は java:/MysqlDS)。
ほとんどの場合、Hibernate は自動的に接続先のデータベースを検出試行した後、そのデータベースに適した SQL を自動選択します。しかし、特に利用頻度の少ないデータベースサーバーなど、常に検出機能が動作するわけでない点がわかっています。そのため、persistence.xml で hibernate.dialect プロパティを明示的に設定するよう推奨しています。以下に JBoss プラットフォームで正式に対応しているデータベースサーバーの Hibernate 方言を示しています。
  • Oracle 9i および 10g: org.hibernate.dialect.Oracle9Dialect
  • Microsoft SQL Server 2005: org.hibernate.dialect.SQLServerDialect
  • PostgresSQL 8.1: org.hibernate.dialect.PostgreSQLDialect
  • MySQL 5.0: org.hibernate.dialect.MySQL5Dialect
  • DB2 8.0: org.hibernate.dialect.DB2Dialect
  • Sybase ASE 12.5: org.hibernate.dialect.SybaseDialect

4.2.3. デフォルトの Hibernate オプション

Hibernate には多数の設定プロパティがあります。persistence.xml ファイルで指定しないプロパティについては、JBoss AS が妥当なデフォルト値セットを提供します。デフォルトの Hibernate プロパティの値は、JBOSS_DIST/server/default/deploy/ejb3.deployer/MEAT-INF/persistence.properties ファイルで指定されます。以下は、JBoss AS 4.2 に同梱されているpersistence.properties ファイルです。コメントアウトされたオプションに注意してください。このファイルでは、persistence.xml ファイルで利用可能なプロパティにどのようなものがあるか、簡単に提示しています。

hibernate.transaction.manager_lookup_class=org.hibernate.transaction.JBossTransactionManagerLookup
#hibernate.connection.release_mode=after_statement
#hibernate.transaction.flush_before_completion=false
#hibernate.transaction.auto_close_session=false
#hibernate.query.factory_class=org.hibernate.hql.ast.ASTQueryTranslatorFactory
#hibernate.hbm2ddl.auto=create-drop
#hibernate.hbm2ddl.auto=create
hibernate.cache.provider_class=org.hibernate.cache.HashtableCacheProvider
# Clustered cache with TreeCache
#hibernate.cache.provider_class=org.jboss.ejb3.entity.TreeCacheProviderHook
#hibernate.treecache.mbean.object_name=jboss.cache:service=EJB3EntityTreeCache
#hibernate.dialect=org.hibernate.dialect.HSQLDialect
hibernate.jndi.java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
hibernate.jndi.java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
hibernate.bytecode.use_reflection_optimizer=false
# I don't think this is honored, but EJB3Deployer uses it
hibernate.bytecode.provider=javassist

4.3. メッセージ駆動型 bean

メッセージ駆動型 bean は、特別な EJB3 bean で、スタブからのプロキシメソッドの呼び出しではなく JMS メッセージを使いサービスリクエストを受信します。そのため、メッセージ駆動型 bean の重要な設定パラメーターは、リッスンする JMS メッセージキューはどれか指定するためのものです。キューに受信メッセージがある場合、サーバーは bean の onMessage() メソッドを呼び出し、このメソッドをメッセージ内で渡し処理を行います。bean クラスは @MessageDriven アノテーションで JMS キューを指定します。このキューはローカルの JNDI java:comp/env/ 名前空間に登録されます。

@MessageDriven(activationConfig =
{
  @ActivationConfigProperty(propertyName="destinationType",
    propertyValue="javax.jms.Queue"),
  @ActivationConfigProperty(propertyName="destination",
    propertyValue="queue/MyQueue")
})
public class MyJmsBean implements MessageListener {

  public void onMessage (Message msg) {
    // ... do something with the msg ...
  }

  // ... ...
}

メッセージ駆動型 bean がデプロイされると、受信メッセージキューが存在しない場合は自動で作成されます。Bean にメッセージを送信するには、標準の JMS API を使ってください。

try {
    InitialContext ctx = new InitialContext();
    queue = (Queue) ctx.lookup("queue/MyQueue");
    QueueConnectionFactory factory =
        (QueueConnectionFactory) ctx.lookup("ConnectionFactory");
    cnn = factory.createQueueConnection();
    sess = cnn.createQueueSession(false,
            QueueSession.AUTO_ACKNOWLEDGE);

} catch (Exception e) {
    e.printStackTrace ();
}
  
TextMessage msg = sess.createTextMessage(...);

sender = sess.createSender(queue);
sender.send(msg);

JMS 仕様あるいは書籍を参照し、JMS API のプログラミングの方法について学習してみてください。

4.4. EJB3 サービスのパッケージとデプロイ

EJB3 bean クラスは通常の JAR ファイルでパッケージされます。標準設定ファイル (セッション bean は ejb-jar.xml、エンティティ bean は persistence.xml など) は、JAR の中にある META-INF ディレクトリにあります。JBoss AS ではスタンドアローンサービスとして、あるいはエンタープライズアプリケーションの一部 (EAR アーカイブ内) として、EJB3 bean をデプロイすることができます。この章では、この2つのデプロイメントオプションについて説明します。

4.4.1. EJB3 JAR のデプロイ

JAR ファイルを JBOSS_DIST/server/default/deploy/ ディレクトリに置くと、自動的にサーバーがピックアップし処理を行います。JAR ファイルに定義されている EJB3 bean はすべて、MyBean/local など JNDI 名を使ってサーバーの内部あるいは外部にデプロイされている他のアプリケーションにて利用できるようになります。この MyBean は、セッション bean の実装クラス名です。このデプロイメントは、JBOSS_DIST/server/default/ejb3.deployer/ の JBoss EJB3 デプロイヤーを使い行われます。デフォルトの EJB3 エンティティマネージャーを設定する際に前述した、META-INF/persistence.properties ファイルは、EJB3 デプロイヤーの中に置かれています。
EJB3 デプロイヤーは自動的にクラスパスの JAR をスキャンし、EJB3 アノテーションを検索します。EJB3 アノテーションを持つクラスが見つかった場合、EJB3 サービスとしてこれらのクラスをデプロイします。しかし、多数の JAR がデプロイされている大規模なアプリケーションをお使いの場合は、クラスパスにあるすべての JAR をスキャンするのに大変時間がかかります。JBOSS_DIST/server/default/ejb3.deployer/META-INF/jboss-service.xml ファイルでは、EJB3 デプロイヤーに EJB3 bean が含まれていないとわかっている JAR を無視するよう指示することができます。JBoss AS で同梱されている EJB 以外の JAR ファイルは jboss.ejb3:service=JarsIgnoredForScanning MBean サービスにすでにリストアップされています。

  ... ...
  <mbean code="org.jboss.ejb3.JarsIgnoredForScanning" 
         name="jboss.ejb3:service=JarsIgnoredForScanning">
      <attribute name="IgnoredJars">
         snmp-adaptor.jar,
         otherimages.jar,
         applet.jar,
         jcommon.jar,
         console-mgr-classes.jar,
         jfreechart.jar,
         juddi-service.jar,
         wsdl4j.jar,
         ... ...
         servlets-webdav.jar
      </attribute>
   </mbean>
  ... ...

サーバーがスキャンで時間を無駄にしないように、お使いのアプリケーションにある EJB3 以外の JAR をこのリストに追加することができます。こうすることで、場合によってはアプリケーションの起動時間が大幅に短縮されることがあります。

4.4.2. EJB3 JAR で EAR をデプロイ

Java EE アプリケーションは、EAR アーカイブとしてデプロイされます。EAR アーカイブは、通常 Web ページ、サーブレット、その他の Web 関連のコンポーネント、WAR コンポーネントにサービス (例:データアクセスやトランザクション) を提供する1 つ以上の EJB3 JAR、アプリケーションが必要とするサポートライブラリ JAR 向けの WAR アーカイブを含む JAR ファイルです。EAR ファイルには application.xml や jboss-app.xml など、配備記述子 があります。以下に一般的な EAR アプリケーションの基本構造を示しました。

myapp.ear
|+ META-INF
   |+ applications.xml and jboss-app.xml
|+ myapp.war
   |+ web pages and JSP /JSF pages
   |+ WEB-INF
      |+ web.xml, jboss-web.xml, faces-config.xml etc.
      |+ lib
         |+ tag library JARs
      |+ classes
         |+ servlets and other classes used by web pages
|+ myapp.jar
   |+ EJB3 bean classes
   |+ META-INF
      |+ ejb-jar.xml and persistence.xml
|+ lib
   |+ Library JARs for the EAR

JBoss AS では他の多くのアプリケーションサーバーとは違い、WAR ファイルのコンポーネントが EJB3 サービスにアクセスできるように web.xml ファイルで EJB 参照を宣言する必要がありません。本章で前述したように、JNDI から直接参照を取得することができます。
一般的な application.xml ファイルは以下の通りです。このファイルは、WAR と EJB3 JAR アーカイブを EAR で宣言し、アプリケーションの Web コンテンツルートを定義します。当然、同じ EAR アプリケーション内に複数の EJB3 モジュールを持たせることができます。application.xml ファイルはオプションで、このアプリケーション内で利用する JAR ファイルの共有クラスパスを定義することも可能です。JAR ファイルの場所は、デフォルトで JBoss AS の lib になっていますが、他のアプリケーションサーバーでは異なる可能性もあります。

<application>
  <display-name>My Application</display-name>

  <module>
    <web>
      <web-uri>myapp.war</web-uri>
      <context-root>/myapp</context-root>
    </web>
  </module>

  <module>
    <ejb>myapp.jar</ejb>
  </module>
  
  <library-directory>lib</library-directory>

</application>

jboss-app.xml ファイルで、EAR アプリケーション向けに JBoss 固有のデプロイメントを設定できます。例えば、EAR 内でモジュールのデプロイメントの順番を指定、SAR (ARchive for MBean) や HAR (Hibernate ARchive for Hibernate objects) など JBoss 固有のアプリケーションモジュールを EAR にデプロイ、このアプリケーションで利用可能なセキュリティドメインと JMX MBean を提供します。jboss-app.xml で利用可能な属性については、DTD : http://www.jboss.org/j2ee/dtd/jboss-app_4_2.dtd を参照してください。
jboss-app.xml の一般的な用途は、他のアプリケーションとの名前の衝突を避けるため、この EAR ファイルを独自にスコープ設定されたクラスローダーにデプロイすべきかを設定することです。お使いの EAR アプリケーションが、独自にスコープ設定されたクラスローダー内にデプロイされ、EJB3 JAR に永続ユニットが1つのみ定義されている場合、@PersistenceContext アノテーションに永続ユニット名を渡す必要なく、@PersistenceContext EntityManager を使い EntityManager をセッション bean に注入することができます。以下のjboss-app.xml は、EAR アプリケーションに対しスコープ設定されたクラスローダー myapp:archive=myapp.を指定しています。

<jboss-app>
      <loader-repository>
      myapp:archive=myapp.ear
      </loader-repository>
</jboss-app>

EAR デプロイメントは、JBOSS_DIST/server/default/deploy/ear-deploy.xml で設定します。このファイルには、以下のような3つの属性が含まれています。

<server>
   <mbean code="org.jboss.deployment.EARDeployer"
          name="jboss.j2ee:service=EARDeployer">
      <!-- 
          A flag indicating if ear deployments should 
           have their own scoped class loader to isolate 
           their classes from other deployments.
      -->
      <attribute name="Isolated">false</attribute>
      
      <!-- 
          A flag indicating if the ear components should 
          have in VM call optimization disabled.
      -->
      <attribute name="CallByValue">false</attribute>
      
      <!-- 
          A flag the enables the default behavior of 
          the ee5 library-directory. If true, the lib 
          contents of an ear are assumed to be the default 
          value for library-directory in the absence of 
          an explicit library-directory. If false, there 
          must be an explicit library-directory.
      -->
      <attribute name="EnablelibDirectoryByDefault">true</attribute>
   </mbean>
</server>

Isolated パラメーターを true に設定した場合、EAR デプロイメントはすべて、デフォルトでスコープ設定されたクラスローダーを持つことになります。jboss-app.xml でクラスローダーを定義する必要はありません。CallByValue 属性は、全 EJB 呼び出しをリモートの呼び出しとして処理するべきかを指定します。リモート呼び出しは、ローカルの参照渡しと比較すると、大幅にパフォーマンスが低下しています。理由は、リモート呼び出しのオブジェクトは、シリアル化、デシリアル化される必要があるためです。アプリケーションの多くは、WAR および EJB3 JAR を同じサーバー上でデプロイするため、この値はデフォルトで false になっており、サーバーはローカルの参照渡しを使い同じ JVM 内にある EJB メソッドを呼び出します。EnablelibDirectoryByDefault 属性は、EAR アーカイブの lib ディレクトリが共有ライブラリ JAR のデフォルトの場所とすべきかを指定します。

第5章 ロギング

ロギングとは、エラーの解決やプラットフォームのコンポーネントの状況を監視するにあたり最も重要なツールです。log4j は、Java 開発者にとって馴染みがあり、柔軟なフレームワークを提供しています。
「ロギングのデフォルト」 には、当プラットフォームに対するデフォルトのログイン動作をカスタマイズする方法について説明しています。その他のカスタマイゼーションについては、「コンポーネント固有のロギング」を参照してください。付録B ロギング情報とレシピ で、ロギングレシピを提供しており、必要に応じてカスタマイズ可能です。

5.1. ロギングのデフォルト

log4j の設定は$JBOSS_HOME/server/PROFILE/conf/jboss-log4j.xml の配備記述子からロードされます。log4j は、アペンダー を使いロギングの動作を制御します。アペンダーは情報をどこにログするか、どのようにログするか指示を出します。jboss-log4j.xml ファイルには、FILE、CONSOLE、SMTPなど、多くのサンプルアペンダーが含まれています。

表5.1 log4j 設定の一般的な指示子

設定オプション 詳細
appender
主なアペンダー。名前、実装クラスを提供します。
errorHandler
特にアペンダーが何らかの理由でログを記述できない場合に、外部クラスを委譲し、ロガーに渡される例外を処理します。
param
アペンダータイプ固有のオプション。この例では、 <param> はファイル名でFILE appender のログを格納します。
layout
ロギングのフォーマットを制御。これを微調整することで、ご利用になりたいログ構文解析ソフトウェアと連携させます。

例5.1 サンプルのアペンダー

<appender name="FILE" class="org.jboss.logging.appender.DailyRollingFileAppender">
  <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
  <param name="File" value="${jboss.server.log.dir}/server.log"/>
  <param name="Append" value="true"/>
  <!-- In AS 5.0.x the server log threshold was set by a system property.
		 In 5.1 and later, the system property sets the priority on the root
		 logger (see <root/> below)
		 <param name="Threshold" value="${jboss.server.log.threshold}"/> -->
 
  <!-- Rollover at midnight each day -->
  <param name="DatePattern" value="'.'yyyy-MM-dd"/>
  <layout class="org.apache.log4j.PatternLayout">
	 <!-- The default pattern: Date Priority [Category] (Thread) Message\n -->
	 <param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n"/>
  </layout>
</appender>
log4j設定の詳細情報については、http://logging.apache.org/log4j/1.2/を参照してください。

5.2. コンポーネント固有のロギング

プラットフォームのコンポーネントによっては、別のロギングオプション、あるいは追加でロギングのカスタマイズメカニズムを利用できます。

5.2.1. Hibernate でのSQLロギング

Hibernate では、SQL ステートメントのロギングを可能にする方法は2種類あります。これらのステートメントは、アプリケーション開発のテストフェーズやデバッグフェーズで最も役立ちます。
1つ目は、コードで明示的に有効にする方法です。
SessionFactory sf = new Configuration()
	 .setProperty("hibernate.show_sql", "true")
	 // ...
	 .buildSessionFactory();
もう1つの方法は、特別な機能を使ってHibernate にて設定を行うことで、SQL メッセージを全て log4j に送信することができます。
log4j.logger.org.hibernate.SQL=DEBUG, SQL_APPENDER
log4j.additivity.org.hibernate.SQL=false
additivity オプションは、これらのログメッセージが親ハンドラーにも反映されるかどうかを制御しますが、このオプションは任意です。

5.2.2. トランザクションサービスのロギング

Enterprise Platform に含まれるTransactionManagerService は、スタンドアローンの Transaction Service と違った形でロギングを処理します。特に、jbossjta-properties.xml にある com.arjuna.common.util.logger property の値をオーバーライドし、log4j_releveler ロガーを強制的に利用します。トランザクションコードの INFO レベルのメッセージは、DEBUG メッセージのような動作をします。そのため、フィルターレベルが DEBUG の場合、これらのメッセージはログファイルにのみ表示されます。その他のログメッセージはすべて通常通りの動作となっています。

第6章 デプロイメント

JBoss Enterprise Application Platform にアプリケーションをデプロイするには、 アプリケーションを $JBOSS_HOME/server/default/deploy ディレクトリにコピーします。defaultallminimal などの他のサーバープロファイルに置き換えることができます (サーバープロファイルについては後ほど説明します)。JBoss Enterprise Application Platform は常に deploy ディレクトリをスキャンし、 新しいアプリケーションや既存アプリケーションへの変更を検知します。これにより、 JBoss Enterprise Application Platform を実行したままアプリケーションのホットデプロイメントをオンザフライで実行できます。

6.1. デプロイ可能なアプリケーションのタイプ

JBoss Enterprise Application Platform 4.x には、 指定のデプロイメントタイプを処理するデプロイヤーがあり、それがデプロイメントを処理する唯一のデプロイヤーでした。 JBoss Enterprise Application Platform 5 では、 メタデータよりランタイムコンポーネントを作成するデプロイヤーによって処理されるまで複数のデプロイヤーがデプロイメントに関連するメタデーターを変換します。
デプロイメントには、 コンポーネントのメタデータがデプロイメントに追加されるようにする記述子が含まれなければなりません。JBoss Enterprise Application Platform のデフォルトでデプロイヤーが存在するデプロイメントタイプは次の通りです。
WAR
WAR アプリケーションアーカイブ (例、 myapp.war) は JAR ファイル内に Java EE Web アプリケーションをパッケージングします。これには、 サーブレットクラス、 ビューページ、 ライブラリ、さらには web.xmlfaces-config.xmljboss-web.xml といった、WEB-INF の配備記述子が含まれます。
EAR
WAR アプリケーションアーカイブ (例、 myapp.war) は JAR ファイル内に Java EE 企業向けアプリケーションをパッケージングします。 通常、Web モジュールの WAR ファイル、 EJB モジュールの JAR ファイル、 application.xml や jboss-app.xml などの META-INF 配備記述子が含まれます。

注記

EJB3 仕様に従い、永続ユニットがEAR ファイルの外部にあり、bean がこの永続ユニットをEAR内に投入しようとすると、EARへの永続ユニットのデプロイは失敗します。この仕様にあわせ、EARファイル内にパッケージされた永続ユニットをデプロイする必要があります。
しかし、JBoss EAP 永続ユニットはEAR外でも存在することはできます。この動作を可能にするには、該当の JBoss AS サーバープロファイルのdeployers/ejb3.deployer/META-INF/jpa-deployer-jboss-beans.xml ファイルにあるPersistenceUnitDependencyResolver beanのbean クラスを変更します。
<!--
Can be DefaultPersistenceUnitDependencyResolver for spec compliant resolving,
InterApplicationPersistenceUnitDependencyResolver for resolving beyond EARs,
or DynamicPersistencePersistenceUnitDependencyResolver which allows configuration via JMX.
-->
<bean name="PersistenceUnitDependencyResolver" class="org.jboss.jpa.resolvers.DynamicPersistenceUnitDependencyResolver"/>
このbean のデフォルト値はDynamicPersistenceUnitDependencyResolverです。このリボルバーにより、仕様に準拠した動作を指定することができ、JMX Console の MBean からこれらの動作を追加で監視可能です。仕様に準拠しないJBoss 変数を使うには、bean をInterApplicationPersistenceUnitDependencyResolverに設定します。
JBoss Microcontainer
JBoss Microcontainer (MC) Bean アーカイブ (拡張子は .beans や .deployer など) は、 META-INF/jboss-beans.xml 記述子と共に POJO デプロイメントを JAR ファイルにパッケージ化します。 この形式は、 JBoss Enterprise Application Platform のコンポーネントデプロイヤによって頻繁に使用されます。
*-jboss-beans.xml は MC Bean 定義を使用してデプロイすることができます。 deploy ディレクトリまたは lib ディレクトリ内に適切な JAR ファイルがあれば、 スタンドアローン XML を使用して MC Bean をデプロイすることができます。
SAR
SAR アプリケーションアーカイブ (myservice.sar など) は、JBoss サービスを JAR ファイルにパッケージ化します。 主に、 MC Beam スタイルのデプロイメントサポートのために更新されていない JBoss Enterprise Application Platform の内部サービスによって使用されます。
*-service.xml は MBean サービス定義を使用してデプロイすることができます。 deploy ディレクトリまたは lib ディレクトリ内に適切な JAR ファイルがあれば、 XML ファイルに指定された MBean を起動することができます。 JMS キューなど、 POJO スタイルのデプロイメントサポートのために更新されていない JBoss Enterprise Application Platform の内部サービスをデプロイする方法になります。
DataSource
*-ds.xml ファイルは外部データベースとの接続を定義します。 これにより内部 JNDI を介して JBoss Enterprise Application Platform 内の全てのアプリケーションとサービスによるデータソースの再利用が可能になります。
HAR
HAR ファイルは、アプリケーション用に Hibernate オブジェクトを定義します。これは SAR ファイルに似ていますが、META-INF ディレクトリにHibernate クラスとマッピングファイル、*-hibernate.xml 配備記述子を含みます。

注記

*-hibernate.xml は、jboss-service.xml と同じ形式を取ります。

例6.1 Hibernate 配備記述子 (*-hibernate.xml)

<hibernate-configuration xmlns="urn:jboss:hibernate-deployer:1.0">
  <session-factory name="java:/hibernate/SessionFactory"
    bean="jboss.test.har:service=Hibernate,testcase=TimersUnitTestCase">
    <property name="datasourceName">OracleDS</property>
    <property name="dialect">org.hibernate.dialect.OracleDialect</property>
    <depends>jboss:service=Naming</depends>
    <depends>jboss:service=TransactionManager</depends>
  </session-factory>
</hibernate-configuration>
*AR
EJB が含まれるJAR ファイルや、 他のサービスオブジェクトを直接 JBoss Enterprise Application Platform にデプロイすることもできます。 JAR ファイルとして認識される拡張子の一覧は、 conf/bootstrap/deployers.xml の JARStructure Bean コンストラクタセットに指定されます。

6.1.1. 展開デプロイメント

WAR、 EAR、MC Bean、 SAR のデプロイメントパッケージは、 META-INF や WEB-INF のようなディレクトリ内の特殊な XML 配備記述子を持つ JAR ファイルです。 JBoss Enterprise Application Platform により、 これらのアーカイブを JAR ファイルではなく展開ディレクトリとしてデプロイすることができるようになります。 これにより、 アプリケーション全体を再デプロイすることなくオンザフライで Web ページなどに変更を加えることができます。 サーバーを再起動せずに展開ディレクトリを再デプロイする必要がある場合は、配備記述子 (WAR 内での WEB-INF/web.xml、 EAR 内での META-INF/application.xml) を touch してタイムスタンプを更新します。

6.2. 標準のサーバープロファイル

各プロファイルは $JBOSS_HOME/server/PROFILE/ という名前のディレクトリに格納されます。各サーバープロファイルのディレクトリを確認すると、プロファイルに含まれるサービスやアプリケーション、ライブラリを確認することができます。

注記

$JBOSS_HOME/server/PROFILE ディレクトリの実際の内容は、サーバープロファイルのサービス実装によって異なります。また、管理層や組み込みサーバーも進化しているため、ディレクトリの内容が変更する可能性もあります。
all
all プロファイルは、クラスタリングサポートや他のエンタープライズ拡張を提供しています。
production
production サーバープロファイルは all プロファイルを基に実稼働環境向けに最適化された設定を提供します。
minimal
企業向けサービスを使用せずにコアサーバーコンテナを起動します。minimal サーバープロファイルは必要なサービスのみを含むJBoss Enterprise Application Platform をカスタマイズ構築する際に基盤として使います。
default
default サーバープロファイルはアプリケーション開発者が最も頻繁に使用するプロファイルで、標準の Java EE 5.0 プログラミング API (Annotations、 JPA、 EJB3 など) をサポートします。

注記

プロファイルがコマンドラインあるいは設定ファイルで指定されていない場合、default サーバープロファイルを使います。
standard
standard サーバープロファイルは Java EE に準拠するようテストされたプロファイルです 。既存設定との主な違いは、 デフォルトでコールバイバリュー (call-by-value) とデプロイメント分離が有効になっていることと、rmiiiopjuddi (all 設定より取得) のサポートが有効になっていることです。
web
web サーバープロファイルは、JBoss Web 向けに実験的に作成された軽量設定で、JavaEE 6 web サーバープロファイルの開発に従っていきます。servlet/jsp コンテナ以外は JTA/JCA と JPA のサポートを提供します。HTTP ポートからのみサーバーへのアクセスが許可されるよう制限されています。 この設定は JavaEE 認定の設定ではなく、今後のリリースで変更になる可能性が高いことにご留意ください。
サービスの詳細や各サーバープロファイルでサポートされる API については本書にて説明していきます。

6.2.1. プロファイルの変更

サーバーが利用するプロファイルを変更したい場合、サーバーがコマンドラインで開始するか、サービスとして開始するかによりメソッドが変わります。
サーバーがコマンドラインで開始された場合、run.sh -c profile のように -c パラメーターで必要なプロファイルを指定します。例えば、Red Hat Enterprise Linux ではrun.sh -c all 、Microsoft Windows では run.bat -c all コマンドがall サーバープロファイルでサーバーを起動します。
サーバーがサービスとして起動された場合は、サービスを使ったプロファイルが再構成し、サービスの停止、開始を行います。プロファイル指定箇所の詳細については『インストールガイド』の『サービスとしてEnterprise Application Platform を起動』 の章を参照してください。

6.3. コンテキストルート

コンテキストルートは、デプロイ済みアプリケーションの URL を決定します。デフォルトでは、コンテキストルートはアプリケーションのディレクトリあるいはアーカイブ構造と同じとなっています。例えば、JSP ページで hello ディレクトリを含む、application.war アーカイブをデプロイした場合、hello アプリケーションのコンテキストルートは、/application/home となります。

手順6.1 デフォルトのコンテキストルートを書き直し

必要であればコンテキストルートを変更することが可能です。コンテキストルートを書きなおす場合、新規コンテキストルートを定義し、サーバーが新規コンテキストを利用できるようにしなければなりません。
  1. 新規のコンテキストルートを定義するには、新しい値を持つ context-root 要素をアプリケーションの配備記述子に追加します。
    • Web アプリケーションのコンテキストアプリケーションを変更するには、context-root 要素をjboss-web.xml ファイルに追加します。

      例6.2 コンテキストルートを定義した jboss-web.xml 例

      <?xml version="1.0"?>
      <jboss-web>
         <context-root>/application-root</context-root>
      </jboss-web>
      localhost のアプリケーション用 URL アドレスは

      http://localhost:8080/application-root

      です。
    • サーブレットのコンテキストルートを変更するには、web.xml ファイルの url-pattern 要素を変更します。

      例6.3 コンテキストルートを定義した web.xml 例

      <?xml version="1.0"?>
      <servlet-mapping>
        <servlet-name>MapRenderer</servlet-name>
        <url-pattern>/servlet-root</url-pattern>
      </servlet-mapping>
      localhost のサーブレット用 URL アドレスは

      http://localhost:8080/application-root/servlet-root

      です。
  2. REWRITE_CONTEXT_CHECK 変数が false に設定されているサーバーを起動するには、run.sh -Dorg.apache.catalina.connector.Response.REWRITE_CONTEXT_CHECK=falseコマンドを実行します。

第7章 マイクロコンテナー

JBoss Enterprise Application Platform 5.0 は、標準的な Java EE 環境を提供するため、 マイクロコンテナーを使用して企業向けサービスと Servlet/JSP コンテナー、 EJB コンテナー、デプロイヤー、管理ユーティリティを統合します。 その他のサービスが必要な場合はサービスを Java EE 上にデプロイすると必要な機能を提供できます。 同様に、 必要でないサービスはサーバープロファイル設定を変更して削除することができます。 サービスデプロイメントの段階で異なるクラスローディングモデルにプラグすれば、Tomcat や GlassFish などの他の環境でさえもマイクロコンテナーを使用して同様の操作を行うことができます。
JBoss Microcontainer は大変軽量で POJO に対応するため、Java ME ランタイム環境にサービスをデプロイするために使用することもできます。これにより、モバイルアプリケーションは完全な JEE アプリケーションサーバーを必要とせず企業向けサービスを利用できるため、モバイルアプリケーションの可能性を新たに広げることになります。他の軽量コンテナと同様に、JBoss Microcontainer は依存関係の挿入を使用して個別の POJO をワイヤーし、サービスを作成します。 情報の場所によりアノテーションまたは XML を使用して設定を行います。 テスト環境を設定する JUnit を拡張するヘルパークラスにより、テストが大変簡単になりました。 これにより、コードを数行使用するだけでテストメソッドより POJO やサービスへアクセスできるようになりました。

注記

マイクロコンテナーアーキテクチャーに関する詳細情報は、docs.redhat.com のマイクロコンテナーユーザガイドを参照してください。

第8章 JNDI ネーミングサービス

ネーミングサービスはエンタープライズ Java アプリケーションにて重要な役割を果たしており、アプリケーションサーバーでオブジェクトやサービスの場所を検索する際に利用する中核インフラストラクチャーを提供しています。また、このサービスは、アプリケーションサーバーの外部にあるクライアントがアプリケーションサーバー内にあるサービスを検索するためのメカニズムでもあります。アプリケーションコードが JBoss Enterprise Application Platform インスタンス内部、外部のいずれであっても、このアプリケーションコードはqueue/IncomingOrders という名称のメッセージキューに接続するだけで、キューの設定詳細に関しては考慮する必要がありません。
クラスター環境では、ネーミングサービスは価値が高くなっています。サービスのクライアントは、どのマシンに常駐しているか把握する必要なしに、クラスターからProductCatalog セッション bean をルックアップできる必要があります。大規模なクラスター化サービス、ローカルリソース、あるいはアプリケーションコンポーネントのいずれかが必要かによって、JNDI ネーミングサービスは、コードが名前別にシステム内のオブジェクトを検索できるよう接着点としての機能を提供します。

8.1. JNDI の概要

JNDI は、Java 開発キットに同梱されている標準の Java API です。JNDI は、DNS、LDAP、Active Directory、RMI レジストリ、COS レジストリ、NIS、ファイルシステムなど、既存の各種ネーミングサービスに対して共通のインターフェースを提供しています。JNDI API はネーミングサービスのアクセスに使用するクライアント API と、ユーザーがネーミングサービスに対して JNDI 実装を作成できるようにするサービスプロバイダーインターフェース (SPI: service provider interface) とに論理的に分割されます。
SPI 層は、中核 JNDI クラスが共通の JNDI クライアントインターフェースを使いネーミングサービスを公開できるように、ネーミングサービスプロバイダーが実装しなければならない抽象化層で、ネーミングサービスに対する JNDI の実装は JNDI プロバイダーと呼んでいます。JBoss ネーミングは SPI クラスをベースとする JNDI 実装例になります。J2EE コンポーネント開発者には JNDI SPI は必要ないので注意してください。
主な JNDI API パッケージは、javax.naming パッケージで、この中にはインターフェースが5個、クラスが10個、例外が数個含まれています。主なクラス1つ (InitialContext) と、インターフェース2つ (Context および Name) が存在します。

8.1.1. 名前

名前の概念は JNDI では欠かせない重要なものとなります。ネーミングシステムにより、従うべき名前の構文が決定します。ユーザーはネーミングシステムの構文を使い、名前の文字列表現をコンポーネントに構文解析することができるようになります。名前はオブジェクトの検索にネーミングシステムで使用されます。最もシンプルに言い替えると、ネーミングシステムは単に一意名を持つオブジェクトの集合なのです。ネーミングシステムでオブジェクトを検索する場合、ネーミングシステムに名前を提示するとネーミングシステムはその名前を持つオブジェクトストアを返します。
例として、UNIX ファイルシステムの命名規則を見ていきます。各ファイルは、ファイルシステムの root を起点とした相対パスで命名され、それぞれのコンポーネントはスラッシュ ("/") で区切られます。このファイルのパスは左から右の順になります。たとえば、パス名 /usr/jboss/readme.txt は、ファイルシステムの root にある usr ディレクトリ配下のjboss ディレクトリ内にある readme.txt ファイルを指します。JBoss Enterprise Application Platform のネーミングは、Unix 形式の命名空間を命名規則として採用しています。
javax.naming.Name インターフェースは、汎用名をコンポーネントの順に表します。合成名 (複数の名前空間にわたる名前) の場合も、複合名の場合も (単一階層のネーミングシステム内で利用される名前) あります。名前のコンポーネントには番号がつけられます。コンポーネント N を持つ名前のインデックスは、0 から N 未満の範囲となっています。最も重要なコンポーネントは、インデックス 0 にあります。また、空の名前にはコンポーネントがありません。
合成名は、複数の名前空間にわたる一連のコンポーネント名です。合成名の例として、scp などの Unix コマンドで通常使われるホスト名とファイルの組み合わせなどでしょう。例えば、以下のコマンドは、localfile.txt を、 ahost.someorg.orgホストにある tmpディレクトリの remotefile.txt ファイルにコピーします。
scp localfile.txt ahost.someorg.org:/tmp/remotefile.txt
複合名は、階層名前空間から抽出されます。複合名の各コンポーネントは原子名 (atomic name) で、 それ以上小さなコンポーネントには分類できない文字列になります。Unix ファイルシステムのファイルパス名が複合名の一例です。ahost.someorg.org:/tmp/remotefile.txt は、DNS と Unix ファイルシステムの名前空間にわたる複合名となっています。また、複合名のコンポーネントは、ahost.someorg.org/tmp/remotefile.txtで、コンポーネントは、ネーミングシステムの名前空間からの文字列名となっています。コンポーネントが階層名前空間から来るものであれば、このコンポーネントは、javax.naming.CompoundName クラスを使って原子パーツにさらに構文解析することができます。JNDI API は、合成名の Nameインターフェースの実装として、javax.naming.CompositeName クラスを提供します。

8.1.2. コンテキスト

javax.naming.Context インターフェースは、ネーミングサービスとやりとりを行うにあたり主要なインターフェースとなっています。Context インターフェースは、名前とオブジェクトのバインディングセットを表します。全コンテキストは紐付けられた命名規則があり、それにより、コンテキストがjavax.naming.Name インスタンスで文字列名を解析する方法を決定します。名前とオブジェクトのバインディングを作成するには、Context のバインドメソッドを呼出し、名前とオブジェクトを引数として指定します。このオブジェクトは、あとでContextのロックアップメソッドを使った名前でリトリーブすることができます。通常、Context で、名前とオブジェクトのバインド、名前のアンバインド、名前とオブジェクトの全バインディングの一覧を取得する操作を行うことができます。Context にバインドするオブジェクトは、それ自体がContextタイプになり得ます。バインドされたContext オブジェクトは、バインドメソッドが呼び出されたところで Context のサブコンテキストとして参照されます。
例として、パス名が/usrで、Unix ファイルシステムではコンテキストとなるファイルディレクトリを見てみましょう。別のファイルディレクトリを起点に指定されたファイルディレクトリはサブコンテキスト (通常サブディレクトリと呼ばれる) となります。/usr/jbossとのパス名を持つファイルディレクトリは、usrのサブコンテキストであるjbossコンテキストを指定します。別の例では、orgなどのDNSドメインはコンテキストで、別のDNS ドメインを起点に指定されたDNS ドメインはサブコンテキストの別例となっています。DNSドメインjboss.orgでは、DNS名は右から左に解析されるため、DNS ドメインjbossorgのサブコンテキストとなります。

8.1.2.1. InitailContext を使ってコンテキストを取得

ネーミングサービスの操作はすべて Context インターフェースの実装で行われます。したがって、使おうとしているネーミングサービスの Context を取得する方法が必要になります。javax.naming.IntialContext クラスは Context インターフェースを実装するので、 ネーミングサービスとのやりとりを開始することができます。
InitialContext を作成する場合、この環境からのプロパティを使って初期化されます。JNDI は以下のソース2つからの値を順にマージすることで、各プロパティの値を決定します。
  • コンストラクターの環境パラメーターから最初に発生したプロパティ、(適切なプロパティに対して)アプレットパラメーターとシステムプロパティ
  • クラスパス上にある全 jndi.properties リソースファイル
上記の 2 ソース両方にある各プロパティに関して、プロパティの値が次のように確定されます。プロパティが JNDI ファクトリ一覧を指定する標準の JNDI プロパティのいずれかの場合、 すべての値がコロンで区切られた単一リストに連結されます。その他のプロパティは最初に見付かった値のみが使用されます。JNDI 環境プロパティを指定する方法としては、 jndi.properties ファイルを使う方法をお勧めします。このファイルによりコードが JNDI プロバイダー固有の情報を外部に配置することができるようになるため、JNDI プロバイダーを変更してもコードの変更や再コンパイルを必要としません。
InitialContext クラスが内部で使用するContext 実装は、ランタイム時に決定されます。デフォルトポリシーは、javax.naming.spi.InitialContextFactory 実装のクラス名を含む環境プロパティ java.naming.factory.initialを使います。ご利用中のネーミングサービスプロバイダーからInitialContextFactory クラス名を取得します。
例8.1「jndi.properties ファイルの例」 で、クライアントアプリケーションがポート 1099 のローカルホストで稼働するJBossNS サービスに接続する際に利用するサンプルのjndi.properties ファイルを提供しています。クライアントアプリケーションは、アプリケーションクラスパスにあるjndi.properties ファイルが必要となるでしょう。これらは、JBossNS JNDI 実装が必要とするプロパティです。その他のJNDI プロバイダーには、別のプロパティと値があります。

例8.1 jndi.properties ファイルの例

### JBossNS properties
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=jnp://localhost:1099
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces

8.2. JBoss Naming Service アーキテクチャー

JBoss Naming Service (JBossNS) アーキテクチャーは、javax.naming.Context インターフェースのJava ソケット/RIM ベース実装となっています。JBossNS はリモートからアクセス可能なクライアント/サーバー実装で、この実装は最適化されており、ソケットを必要とせずに、JBossNS サーバーが稼働している同じVM からアクセスすることができます。グローバルシングルトンとして利用可能なオブジェクト参照を使うことで同じVM アクセスが発生します。図8.1「JBoss Naming Service アーキテクチャーで主要なコンポーネント」 では、JBossNS 実装およびその関係において重要となるキーの一部を図解しています。
JBoss Naming Service アーキテクチャーで主要なコンポーネント

図8.1 JBoss Naming Service アーキテクチャーで主要なコンポーネント

まず、NamingService MBeanから見ていきます。NamingService MBean は、JNDI ネーミングサービスを提供しており、J2EE テクノロジーコンポーネントで広範利用されている主要サービスです。NamingService の設定可能な属性を以下に示します。
  • Port: NamingServiceのポートをリッスンする jnp プロトコル。指定がない場合は、RMI レジストリのデフォルトポートと同じ 1099 がデフォルトになります。
  • RmiPort: RMI ネーミング実装がエクスポートされるRMI ポート。指定がない場合、デフォルトは0で、利用可能なポートはどれでも利用するという意味です。
  • BindAddress: NamingService がリッスンする特定のアドレス。ソケットアドレスの1つに関する接続リクエストしか受け付けない java.net.ServerSocket のマルチホームホスト上で利用可能です。
  • RmiBindAddress: NamingService の RIM サーバー部分がリッスンする特定のアドレスです。ソケットアドレスの1つに関する接続リクエストしか受け付けない java.net.ServerSocket のマルチホームホスト上で利用可能です。指定されていず、BindAddress が指定されている場合、RmiBindAddressBindAddress 値にデフォルト設定されます。
  • Backlog: 受信接続の表示 (接続要求) に対する最大長はbacklog パラメーターに設定します。キューがフルの状態で接続表示を受けると、その接続は拒否されます。
  • clientSocketFactory: オプションのカスタム java.rmi.server.RMIClientSocketFactory 実装クラス名。指定されていない場合、デフォルトのRMIClientSocketFactory が利用されます。
  • ServerSocketFactory: オプションのカスタム java.rmi.server.RMIServerSocketFactory 実装名。指定されていない場合、デフォルトのRMIServerSocketFactory が利用されます。
  • JNPServerSocketFactory: オプションのカスタム javax.net.ServerSocketFactory 実装クラス名。JBoss Naming Service Naming インターフェースのダウンロードをブートストラップするために利用する ServerSocketのファクトリ。指定されていない場合、javax.net.ServerSocketFactory.getDefault() メソッド値が利用されます。
java:compコンテキストへアクセスするスレッドのコンテキストクラスローダーに基づき、このコンテキストへのアクセスが隔離されるように、NamingServicejava:compを作成します。こうすることで J2EE 仕様で必要なアプリケーションコンポーネントのプライベートENC を提供します。このような隔離は、javax.naming.Referenceorg.jboss.naming.ENCFactoryを使用するコンテキストにjavax.naming.ObjectFactoryとしてバインドすることで行うことができます。クライアントがjava:compやサブコンテキストのルックアップを行う場合、ENCFactory はスレッドコンテキストClassLoaderをチェックし、ClassLoader をキーとして使いマップ内でルックアップを実行します。
クラスローダーインスタンスに対しコンテキストインスタンスが存在しない場合、ENCFactory マップ内にコンテキストインスタンスが作成されクラスローダーと紐付けられます。そのため、実行中のコンポーネントスレッドに紐付いた固有のClassLoader を受け取る各コンポーネントにより、正確にアプリケーションコンポーネントのENC を隔離されるか左右されます。
NamingService はその機能をorg.jnp.server.Main MBean に委譲します。MBean が重複する理由には、JBoss Naming Service が最初はスタンドアローンの JNDI 実装として開始され、そのまま実行することができるという点が挙げられます。NamingService MBean はMain インスタンスを JBoss サーバーに埋め込むため、JBossサーバーと同じ VM とJNDI を利用しても、ソケットのオーバーヘッドは発生しません。実際は、NamingService の設定可能な属性は、JBoss Naming Service Main MBean の設定可能な属性なのです。NamingService MBean 上の属性設定は、単に NamingService 内のMain MBean にある該当属性を設定するだけです。NamingService が起動すると、包含するMain MBean を開始し JNDI のネーミングサービスを有効にします。
さらに、NamingService は、JMX detyped 呼出し操作によりNaming インターフェースの操作を公開します。これにより、任意のプロトコルに対する JMX アダプタを経由でネーミングサービスにアクセスできるようになります。HTTP が呼出し操作を使ってネーミングサービスにアクセスする方法について、一例を本章で後述します。
Main MBeanが開始されると、以下のタスクを実行します。
  • org.jnp.naming.NamingService インスタンスをインスタンス化し、これをローカルのVM サーバーインスタンスとして設定します。これは、JBoss サーバーのVM内に作成されたorg.jnp.interfaces.NamingContext インスタンスのいずれかが使用しTCP/IP でのRMI 呼出しが回避されるようにします。
  • 設定されたRmiPortClientSocketFactoryServerSocketFactory 属性を使って、NamingServer インスタンスのorg.jnp.naming.interfaces.Naming RMI インターフェースをエクスポートします。
  • BindAddressPort 属性により与えられたインターフェースをリッスンするソケットを作成します。
  • ソケットで接続を受け取るスレッドを生成します。

8.3. Naming IntialContext ファクトリ

JBoss JNDI プロバイダーは現在、様々なInitialContext ファクトリ実装に対応しています。

8.3.1. 標準のネーミングコンテキストファクトリ

最もよく使われるファクトリは、org.jnp.interfaces.NamingContextFactory実装で、このプロパティには以下が含まれます。
  • java.naming.factory.initial: 最初に使うコンテキストファクトリを指定するための環境プロパティ名。プロパティの値は、最初のコンテキストを作成するファクトリクラスの完全修飾クラス名にする必要があります。これが指定されていない場合、InitialContext オブジェクトが作成されるとjavax.naming.NoInitialContextException がスローされます。
  • java.naming.provider.url: クライアントが使う JBoss JNDI サービスプロバイダーの場所を指定するための環境プロパティ名。NamingContextFactory クラスはこの情報を使いどの JBossNS サーバーに接続するかを把握します。このプロパティの値はURL文字列としてください。JBossNSでは、URL 形式はjnp://host:port/[jndi_path]となっています。URL の jnp: の部分はプロトコルで、これは JBoss が使うソケット/RMI ベースのプロトコルを参照します。URL のjndi_path の部分は、root コンテキストを起点としたオプションのJNDI名となっています (例:appsapps/tmp)。ホストコンポーネント以外はすべてオプションとなっています。デフォルトのポート値が 1099 であるため、以下の例はすべて同じです。
    • jnp://www.jboss.org:1099/
    • www.jboss.org:1099
    • www.jboss.org
  • java.naming.factory.url.pkgs: URL コンテキストファクトリでローディングする際に使うパッケージプレフィックス一覧を指定するための環境プロパティ名。このプロパティの値はファクトリクラスのクラス名につけるプレフィックス一覧をコンマで区切るものとします。このファクトリクラスは、URL コンテキストファクトリを作成します。JBoss JNDI プロバイダーでは、これは org.jboss.naming:org.jnp.interfaces でなければなりません。このプロパティは、JBoss JNDI プロバイダーのjnp:java: URL コンテキストファクトリを検索する際に必須となっています。
  • jnp.socketFactory: ブートストラップソケットを作成するのに利用する javax.net.SocketFactory 実装の完全修飾クラス名。デフォルト値は、org.jnp.interfaces.TimedSocketFactoryで、TimedSocketFactory は、接続と読み込みタイムアウトの使用に対応する単純な SocketFactory 実装となっています。この2つのプロパティは以下により指定されます。
  • jnp.timeout: 接続のタイムアウト(ミリ秒単位)。デフォルト値が0の場合、VM TCP/IP がタイムアウトするまで、接続が停止されます。
  • jnp.sotimeout: 接続されたソケットの読み込みタイムアウト (ミリ秒単位)。デフォルト値が0の場合、読み込みが停止します。これは新しく接続されたソケットでSocket.setSoTimeout に渡される値となっています。
クライアントがこれらの利用可能なJBossNS プロパティを使って InitialContext を作成するとorg.jnp.interfaces.NamingContextFactory オブジェクトを使い今後の操作で利用されるContext インスタンスを作成します。NamingContextFactoryjavax.naming.spi.InitialContextFactory インターフェースのJBossNS 実装となっており、 NamingContextFactory クラスにContextを作成が求められると、グローバル JNDI 名前空間にあるコンテキスト名とInitialContext 環境を使い org.jnp.interfaces.NamingContextインスタンスを作成します。NamingContext インスタンスが実際にJBossNS サーバーに接続するタスクを実行し、 Context インターフェースを実装しています。この環境からのContext.PROVIDER_URL 情報は、どのサーバーからNamingServer RMI 参照を取得するか示しています。
NamingContext インスタンスとNamingServer インスタンスの紐付けは、最初の Context 操作が実行される際に遅延モードで行われます。Context 操作が実行されNamingContext に紐付けられている NamingServer がない場合、その環境プロパティがContext.PROVIDER_URLを定義しているかどうか確認します。Context.PROVIDER_URL は、Context が使う予定の JBossNS サーバーのホストとポートを定義します。プロバイダ URL がある場合、NamingContextNamingContext クラスの静的マップを確認することで、まずホストとポートの組み合わせで入力される Naming インスタンスがすでに作成されていないか確認します。ホストとポートのペアでインスタンスがすでに取得されている場合、単に既存のNaming インスタンスを使います。該当のホストとポートに対して、Naming インスタンスがすでに作成されていない場合、NamingContextjava.net.Socketを使ってホストとポートを接続し、ソケットからjava.rmi.MarshalledObject を読み込み、get メソッドを呼び出すことでサーバーからNaming RMI スタブをリトリーブします。新しく取得したNaming インスタンスは、ホストとポートの組み合わせ配下にある NamingContext サーバーマップでキャッシュ化されます。コンテキストが紐付けられた JNDI 環境にてプロバイダー URL が指定されていない場合、NamingContext は単にMain MBean で設定された VM Naming インスタンスを使用します。
Context インターフェースの NamingContext 実装は、全操作を NamingContext に紐付けられた Naming インスタンスに委譲します。Naming インターフェースを実装する NamingServer クラスはContext ストアとして java.util.Hashtable を使用します。特定の JBossNS サーバーに対する JNDI 名はそれぞれ違っており、各 JNDI 名に固有のNamingServerが1つずつ存在します。NamingServer インスタンスを参照する時点で有効になる一時的な NamingContext インスタンスは 0 またはそれ以上存在します。NamingContext の目的は、NamingContextに渡される JNDI 名の変換を管理する Naming インターフェースアダプターに対し Context として動作することです。JNDI名は相対あるいは URL になり得るので、参照先の JBossNS サーバーのコンテキスト内で絶対名に変換される必要があります。この変換はNamingContext の主要機能となります。

8.3.2. org.jboss.naming.NamingContextFactory

このバージョンの InitialContextFactory 実装は jnp バージョンの単純拡張で、jnp バージョンと違うのは、パブリックスレッドのローカル変数内で InitialContextFactory.getInitialContext(Hashtable env) メソッドに渡す最後の設定を格納する点です。これは、UserTransaction ファクトリなどのEJB ハンドルやその他の JNDI を検知するオブジェクトは作成された時点で効力を発揮する JNDI コンテキストを継続的に追跡しますが、この実装はこれらのEJBハンドルやその他のJNDI-sensitive オブジェクトにより利用されます。vm 境界を越えシリアル化された後でも、この環境をオブジェクトにバインドさせたい場合、org.jboss.naming.NamingContextFactoryを利用してください。現在のVM jndi.properties あるいはシステムプロパティにて定義された環境が必要な場合は、org.jnp.interfaces.NamingContextFactory のバージョンを使ってください。

8.3.3. クラスター環境でのネーミングディスカバリ

クラスター化された JBoss 環境で実行している場合、 Context.PROVIDER_URL 値を指定せず、クライアントが利用可能なネーミングサービスをネットワークにクエリするよう選択することができます。これは、all サーバープロファイルあるいは、org.jboss.ha.framework.server.ClusterPartitionorg.jboss.ha.jndi.HANamingService がデプロイされている同等のサーバープロファイルで稼働している JBoss サーバーでのみ機能します。このディスカバリプロセスでは、ディスカバリアドレス/ポートへマルチキャストリクエストパケットを送信し、ノードからの応答を待機します。この応答は、Naming インターフェースの HA-RMI バージョンとなっています。以下の InitialContext プロパティにより、ディスカバリ設定が変わってきます。
  • jnp.partitionName: クラスターパーティション名のディスカバリは制限される必要があります。複数のクラスターを持つ環境で稼働している場合、 特定のクラスターを対象にネーミングディスカバリを行いたい場合があるかもしれません。デフォルト値なし。これは、クラスターの応答はどれでも受け付けることになります。
  • jnp.discoveryGroup: ディスカバリクエリの送信先マルチキャスト IP アドレス。デフォルトは、230.0.0.4。
  • jnp.discoveryPort: ディスカバリクエリの送信先ポート。デフォルトは 1102。
  • jnp.discoveryTimeout: ディスカバリクエリの応答待機時間 (ミリ秒単位)。デフォルト値は、5000 (5 秒)。
  • jnp.disableDiscovery: ディスカバリプロセスを回避する必要がある場合にたてるフラグ。Context.PROVIDER_URL が指定されていない場合、あるいは指定 URL に有効なネーミングサービスが見付からない場合、ディスカバリは起こります。jnp.disableDiscovery フラグが true の場合、ディスカバリは試行されません。

8.3.4. HTTP InitialContext Factory 実装

JNDI ネーミングサービスは HTTP 経由でアクセス可能です。JNDI クライアントから見ると、これは JNDI Context インターフェースを継続利用しており、透過的な変更になります。Context インターフェース経由の操作は、(JMX 呼び出し操作を使ってリクエストを NamingService に渡す) サーブレットへの HTTP ポストに変換されます。HTTP をアクセスプロトコルとして使用する利点には、HTTP を許可する設定のプロキシやファイアウォールを通過するアクセスの他、 セキュリティをベースとした標準サーブレットロールを使って JNDI サービスへのアクセスセキュリティーを保つ機能などがあります。
HTTP で JNDI にアクセスするには、org.jboss.naming.HttpNamingContextFactory をファクトリ実装として利用します。このファクトリのサポート InitialContext 環境プロパティの完全セットは以下の通りです:
  • java.naming.factory.initial: 初期コンテキストファクトリを指定する環境プロパティ名。org.jboss.naming.HttpNamingContextFactoryでなければなりません。
  • java.naming.provider.url (あるいは Context.PROVIDER_URL): これは JNDI ファクトリの HTTP URL に設定する必要があります。完全な HTTP URL は、JBoss サーブレットコンテナーの公開 URLに/invoker/JNDIFactoryを付け加えたものになるでしょう。例は以下の通りです。
    • http://www.jboss.org:8080/invoker/JNDIFactory
    • http://www.jboss.org/invoker/JNDIFactory
    • https://www.jboss.org/invoker/JNDIFactory
    最初の例は、ポート8080 を使ってサーブレットにアクセスし、2番目は標準の HTTP ポート 80 を使い、3番目はSSL 暗号化接続を使い標準の HTTPS ポート443 へアクセスします。
  • java.naming.factory.url.pkgs: 全 JBoss JNDI プロバイダーに対しorg.jboss.naming:org.jnp.interfacesにしなければなりません。このプロパティは、JBoss JNDI プロバイダーのjnp:java: URL コンテキストファクトリの場所を検索するのに必要となります。
HttpNamingContextFactory によって返された JNDI Context 実装は、JMX バスを介して呼出しをNamingServiceへのに転送し、HTTP経由で返信をマーシャルするブリッジサーブレットに呼出しを委譲するプロキシです。このプロキシが動作するには、ブリッジサーブレットの URL は何かを把握している必要があります。この値は、JBoss Webサーバーがよく知られている公開インターフェースの場合、サーバー側ですでにバインドされている場合もあります。JBoss Web サーバーがファイヤウォールやプロキシ1つ以上を介す場合、プロキシは必要なURL はどれか把握できません。このような場合は、プロキシをクライアントVM にて設定する必要のあるシステムプロパティ値と関連付けます。HTTP 上でJNDIの操作に関する詳細情報は、「HTTP 経由で JNDI にアクセス」を参照してください。

注記

クラスターのパーティションがデフォルトのパーティション名を利用する場合、ディスカバリプロセスは他のクラスターを無視します。そのため、複数のクラスターを利用する場合は、一意のパーティション名 props.put("jnp.partitionName", "ClusterBPartition") を指定するようにしてください。

8.3.5. Login InitialContext Factory 実装

JAAS は、リモートクライアントの認証メソッドとして適しています。しかし、JAAS を使わない他のアプリケーションサーバー環境からの移行が簡素化、容易化されるよう、JBoss ではInitialContext を使うことでセキュリティ証明を渡すことができます。JAAS はバックグラウンドで使用されていますが、クライアントアプリケーションでJAAS インターフェースは明示的に利用されません。
この機能を提供するファクトリクラスは、 org.jboss.security.jndi.LoginInitialContextFactoryで、このファクトリのサポートInitialContext 環境プロパティの全セットは以下の通りです。
  • java.naming.factory.initial: 最初のコンテキストファクトリを指定するための環境プロパティ名。org.jboss.security.jndi.LoginInitialContextFactoryでなければなりません。
  • java.naming.provider.url: NamingContextFactory プロバイダー URL に設定する必要があります。LoginIntialContext は単に、既存のNamingContextFactory の動作に JAAS ログインを追加するNamingContextFactory のラッパーというだけのことです。
  • java.naming.factory.url.pkgs: 全 JBoss JNDI プロバイダーに対しorg.jboss.naming:org.jnp.interfacesにしなければなりません。このプロパティは、JBoss JNDI プロバイダーのjnp:java: URL コンテキストファクトリの場所を検索するのに必要となります。
  • java.naming.security.principal (あるいは Context.SECURITY_PRINCIPAL): 認証主体。これは java.security.Principal 実装あるいは主体名を示す文字列のいずれかです。
  • java.naming.security.credentials (あるいは Context.SECURITY_CREDENTIALS):主体認証に使われる証明書。例:パスワード、セションキーなど
  • java.naming.security.protocol: (Context.SECURITY_PROTOCOL) :JAAS ログインモジュール名を提供し主体や証明書の認証に使用します。

8.3.6. ORBInitialContextFactory

Sun の CosNaming を使用する場合、デフォルトとは違ったネーミングコンテキストファクトリを使用する必要があります。CosNaming は deploy/iiop-service.xml? で設定される ORB を使用せずに JNDI で ORB を検索します。org.jboss.iiop.naming.ORBInitialContextFactory にグローバルなコンテキストファクトリを設定する必要があります。これにより ORB を JBoss の ORB に設定します。この設定は conf/jndi.properties ファイル内で行います。
# DO NOT EDIT THIS FILE UNLESS YOU KNOW WHAT YOU ARE DOING
#
java.naming.factory.initial=org.jboss.iiop.naming.ORBInitialContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces

また、アプリケーションクライアントで CosNaming を利用する場合、ORBInitialContextFactory を利用する必要があります。

8.4. HTTP 経由の JNDI

ソケットブートストラッププロトコルを持つレガシーな RMI/JRMP に加え、JBoss は HTTP 経由の JNDI ネーミングサービスへのアクセスに対するサポートも提供しています。

8.4.1. HTTP 経由で JNDI にアクセス

この機能は、http-invoker.sar により提供されており、http-invoker.sar の構造は以下の通りです。
http-invoker.sar
+- META-INF/jboss-service.xml
+- invoker.war
| +- WEB-INF/jboss-web.xml
| +- WEB-INF/classes/org/jboss/invocation/http/servlet/InvokerServlet.class
| +- WEB-INF/classes/org/jboss/invocation/http/servlet/NamingFactoryServlet.class
| +- WEB-INF/classes/org/jboss/invocation/http/servlet/ReadOnlyAccessFilter.class
| +- WEB-INF/classes/roles.properties
| +- WEB-INF/classes/users.properties
| +- WEB-INF/web.xml
| +- META-INF/MANIFEST.MF
+- META-INF/MANIFEST.MF
jboss-service.xml 記述子は、HttpInvokerHttpInvokerHA MBean を定義します。これらのサービスは、HTTP経由でJMX バスにある適切な対象の MBean へ送信されるメソッド呼出しルーティングを処理します。
http-invoker.war Web アプリケーションには、HTTP トランスポートの詳細を処理するサーブレットが含まれています。NamingFactoryServlet は、JBoss JNDIネーミングサービス javax.naming.Context 実装に対する作成リクエストを処理します。InvokerServlet は、RMI/HTTP クライアントによる呼出しを処理します。ReadOnlyAccessFilter により、JNDIネーミングサービスのセキュリティを確保し、未認証のクライアントに読み取り専用のアクセスを提供する JNDI コンテキストを作成することができるようになります。
JNDI コンテキストに対する HTTP invoker のプロキシ/サーバーの構成

図8.2 JNDI コンテキストに対する HTTP invoker のプロキシ/サーバーの構成

設定について説明する前に、http-invoker サービスの操作について見てみましょう。図8.2「JNDI コンテキストに対する HTTP invoker のプロキシ/サーバーの構成」 で、JBoss JNDIプロキシの構造とJBoss サーバー側のhttp-invokerコンポーネントとの関係に関する論理的な見解を示しています。このプロキシは、Context.INITIAL_CONTEXT_FACTORYプロパティがorg.jboss.naming.HttpNamingContextFactoryに設定され、Context.PROVIDER_URLプロパティがNamingFactoryServletのHTTP URL に設定されているInitialContext を使い、NamingFactoryServlet から取得します。結果として出たプロキシは Context 実装を提供するorg.jnp.interfaces.NamingContext インスタンスに組み込まれます。
プロキシはorg.jboss.invocation.http.interfaces.HttpInvokerProxyのインスタンスで、org.jnp.interfaces.Namingインターフェースを実装します。内部的にHttpInvokerProxy は、HTTP ポスト経由で Naming インターフェースメソッド呼出しをInvokerServlet にマーシャルする invoker を含みます。InvokerServlet は、これらのポストを JMX 呼出しをNamingServiceに変換し、HTTP ポストのレスポンスにて呼出しの応答をプロキシに返します。
設定値によっては、これらのコンポーネントをすべて連携させるよう設定する必要があります。図8.3「設定ファイルと JNDI/HTTP コンポーネント間の関係」で、設定ファイルと該当のコンポーネントの関係を示しています。
設定ファイルと JNDI/HTTP コンポーネント間の関係

図8.3 設定ファイルと JNDI/HTTP コンポーネント間の関係

http-invoker.sar/META-INF/jboss-service.xml 記述子は、NamingServiceHttpInvokerProxy を作成するHttpProxyFactory を定義します。HttpProxyFactory に対する設定が必要な属性には以下が含まれます:
  • InvokerName: conf/jboss-service.xml記述子にて定義される NamingService のJMX ObjectName。JBoss ディストリビューションで使用される標準設定は jboss:service=Naming
  • InvokerURL あるいは InvokerURLPrefix + InvokerURLSuffix + UseHostName:完全な HTTP URL をInvokerURL 属性を使い、InvokerServlet に指定することができます。あるいは、URLのホスト名に依存しない部分を特定し、HttpProxyFactory を入力できます。InvokerURL値の例として、http://jbosshost1.dot.com:8080/invoker/JMXInvokerServletなどが挙げられます。これは以下に分割できます。
    • InvokerURLPrefix: ホスト名の前につく URL のプレフィックス。通常、http:// あるいは https:// (SSL が使われている場合) となっています。
    • InvokerURLSuffix: ホスト名の後につくURL のサフィックス。これには Web サーバーのポート番号、InvokerServletにデプロイされるパスが含まれます。例えば、InvokerURLSuffixInvokerURL の値は、引用符なしの:8080/invoker/JMXInvokerServlet となります。ポート番号は Web コンテナサービス設定により決まります。InvokerServlet へのパスは、http-invoker.sar/invoker.war/WEB-INF/web.xml の記述子にて指定されます。
    • UseHostName: 完全 InvokerURL のホスト名部分を構築する際、ホスト名をホスト IP アドレスの位置に使用するか示すフラグ。True の場合、InetAddress.getLocalHost().getHostName メソッドが使われます。True でなければ、InetAddress.getLocalHost().getHostAddress() メソッドが利用されます。
  • ExportedInterface: プロキシがクライアントに対し公開する org.jnp.interfaces.Naming インターフェース。このプロキシの実際のクライアントは、JBoss JNDI実装のNamingContext クラスで、JBoss JNDIプロバイダーを使う場合、JNDI クライアントはInitialContext ルックアップから取得します。
  • JndiName: プロキシがバインドされる場合の JNDI の名前。このインターフェースが JNDI にバインドされないように、この項目はブランク/空の文字列に設定する必要があります。JNDI を使ってそれ自体をブートストラップすることはできません。これは、NamingFactoryServletの役割になります。
http-invoker.sar/invoker.war/WEB-INF/web.xml 記述子は、初期化パラメーターと共にNamingFactoryServletInvokerServlet のマッピングを定義します。JNDI/HTTP に関連するNamingFactoryServletの設定は JNDIFactory のエントリで以下を定義します。
  • HttpProxyFactory MBean 名をマッピングするnamingProxyMBean の初期化パラメーター。HTTP ポストへの応答時に返す Naming プロキシを取得するために、NamingFactoryServlet がこのパラメーターを利用します。デフォルトのhttp-invoker.sar/META-INF/jboss-service.xml 設定は、名前がjboss:service=invoker,type=http,target=Namingとなります。
  • Naming プロキシ値をクエリするためのnamingProxyMBean 属性名を定義するプロキシ初期化パラメーター。属性名がProxyにデフォルト設定されています。
  • JNDIFactory 設定のサーブレットマッピング。セキュリティー保護されていないマッピングのデフォルト設定は/JNDIFactory/*となっています。これは、 http-invoker.sar/invoker.warのコンテキスト root を起点とした相対パスでデフォルトでは、.war のサフィックスを取ったWAR名となっています。
JNDI/HTTPに関連するInvokerServlet 設定は JMXInvokerServlet で以下を定義します。
  • InvokerServlet のサーブレットマッピング。セキュリティ保護されていないマッピングのデフォルト設定は /JMXInvokerServlet/*で、これは、 http-invoker.sar/invoker.warのコンテキスト root を起点とした相対パスでデフォルトでは、.war のサフィックスを取ったWAR名となっています。

8.4.2. HTTPS でJNDI にアクセス

HTTP/SSL 経由で JNDI にアクセスできるようにするには、Web コンテナーにある SSL コネクタを有効にする必要があります。この詳細については「Tomcat 用にサーブレットコンテナーを統合する」で説明しています。HTTPS URL を JNDI プロバイダー URL として使用するクライアントの簡単な例を使って HTTPS の使いかたを説明します。この例には SSL コネクターの設定を用いますので、SSL コネクターの設定に関する詳細を除き必要なものはすべて含まれています。
また、HTTPS URL を使用するよう HttpProxyFactory 設定構成も提供しています。次の例ではこの設定を提供するためのサンプル例をインストールする http-invoker.sarjboss-service.xml 記述子のセクションを示します。標準 HTTP 設定に相対的に変更されたものは InvokerURLPrefix および InvokerURLSuffix の属性のみで 8443 ポートを使って HTTPS URL を設定します。
<!-- Expose the Naming service interface via HTTPS -->
<mbean code="org.jboss.invocation.http.server.HttpProxyFactory" 
       name="jboss:service=invoker,type=https,target=Naming">
    <!-- The Naming service we are proxying -->
    <attribute name="InvokerName">jboss:service=Naming</attribute>
    <!-- Compose the invoker URL from the cluster node address -->
    <attribute name="InvokerURLPrefix">https://</attribute>
    <attribute name="InvokerURLSuffix">:8443/invoker/JMXInvokerServlet 
</attribute>
    <attribute name="UseHostName">true</attribute>
    <attribute name="ExportedInterface">org.jnp.interfaces.Naming 
</attribute>
    <attribute name="JndiName"/>
    <attribute name="ClientInterceptors">
        <interceptors>
            <interceptor>org.jboss.proxy.ClientMethodInterceptor 
</interceptor>
            <interceptor>org.jboss.proxy.SecurityInterceptor
</interceptor>
            <interceptor>org.jboss.naming.interceptors.ExceptionInterceptor 
</interceptor>
            <interceptor>org.jboss.invocation.InvokerInterceptor 
</interceptor>
        </interceptors>
    </attribute>
</mbean>
少なくとも、HTTPS を使った JNDI クライアントは HTTPS URL プロトコルハンドラーを設定する必要があります。HTTPS 用のJava Secure Socket Extesion (JSSE) を使います。JSSE の文書はHTTPS 使用の要件という面では詳しく説明されていないため、例8.2「トランスポートとしてHTTPS を使う JNDI クライント」にて説明されているクライアントサンプルを設定するには、以下の手順をふむ必要がありました。
  • HTTPS URL のプロトコルハンドラーは Java で利用できるようにする必要があります。JSSE リリースには、com.sun.net.ssl.internal.www.protocolパッケージのHTTPS ハンドラーがあります。HTTPS URLを利用可能にするには、標準のURLプロトコルハンドラーの検索プロパティ java.protocol.handler.pkgs にこのパッケージを含める必要があります。Ant スクリプトにjava.protocol.handler.pkgs プロパティを設定します。
  • SSLを機能させるには、JSSE セキュリティプロバイダーをインストールする必要があります。これは、JSSE jarsを拡張パッケージとしてインストールするか、プログラムでインストールしてください。この例では煩わしい作業が少ないプログラムでの手法を使っています。ExClient コードの18行目で、実施方法が説明されています。
  • JNDI プロバイダー URL は HTTPS をプロトコルとして利用する必要があります。ExClient コードの24-25 行目で、ポート番号8443 が割り当てられたローカルホストへのHTTP/SSL 接続を指定しています。このホスト名とポートは、Web コンテナーの SSL コネクターで定義されています。
  • サーバー証明に対する HTTPS URLのホストネームの検証は無効にする必要があります。デフォルトでは、JSSE HTTPS プロトコルハンドラーが、HTTPS URL のホスト名部分をサーバー証明の共通名をもとに厳密に検証を行います。これは、セキュリティがかかっている Web サイトに接続すると Web ブラウザーが行うチェックと同じです。特定のホスト名ではなく"Chapter 8 SSL Example" の共通名を使用する自己署名サーバー証明を採用しており、これは開発環境やイントラネットで一般的に利用されている場合が多いです。JBoss HttpInvokerProxy は、org.jboss.security.ignoreHttpsHost システムプロパティが存在するか、さらにTrue の値を持っているかを確認するデフォルトのホスト名をオーバーライドします。Ant スクリプトではorg.jboss.security.ignoreHttpsHost プロパティを True に設定します。

例8.2 トランスポートとしてHTTPS を使う JNDI クライント

package org.jboss.chap3.ex1;

import java.security.Security;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
                    
public class ExClient
{
    public static void main(String args[]) throws Exception
    {
        Properties env = new Properties();
        env.setProperty(Context.INITIAL_CONTEXT_FACTORY,
                        "org.jboss.naming.HttpNamingContextFactory");
        env.setProperty(Context.PROVIDER_URL,
                        "https://localhost:8443/invoker/JNDIFactorySSL");

        Context ctx = new InitialContext(env);
        System.out.println("Created InitialContext, env=" + env);

        Object data = ctx.lookup("jmx/invoker/RMIAdaptor");
        System.out.println("lookup(jmx/invoker/RMIAdaptor): " + data);
    }
}
クライアントのテストを実施するには、まず 3 章の例を構築し chap3 設定ファイルセットを作成します。
[examples]$ ant -Dchap=naming config
次に、naming 設定ファイルセットを使って JBoss サーバーを起動します。
[bin]$ sh run.sh -c naming
最後に、以下を使いExClient を実行します。
[examples]$ ant -Dchap=naming -Dex=1 run-example
...
run-example1:

[java] Created InitialContext, env={java.naming. \ 
provider.url=https://localhost:8443/invoker/JNDIFactorySSL, java.naming. \
factory.initial=org.jboss.naming.HttpNamingContextFactory}
     [java] lookup(jmx/invoker/RMIAdaptor): org.jboss.invocation.jrmp. \
     interfaces.JRMPInvokerP
roxy@cac3fa

8.4.3. HTTP 経由の JNDI アクセスでセキュリティを確保

HTTP 経由で JNDI にアクセスする利点の1つに、標準の Web 宣言セキュリティを使うことで JNDI InitialContext ファクトリやネーミング操作へ簡単にかつセキュアにアクセスできる点が挙げられます。サーバー側で JNDI/HTTP トランスポートの処理が2つのサーブレットで実装されているため、これが可能となっています。前述したように、これらのサーブレットは、defaultall サーバープロファイルの deploy ディレクトリにある http-invoker.sar/invoker.war ディレクトリに含まれています。invoker.war/WEB-INF/web.xml の記述子を編集し、セキュリティ保護がされていないサーブレットマッピングを削除することで、JNDI へのセキュアなアクセスが可能になります。例えば、例8.3「JNDI サーブレットへのアクセスをセキュアにするための web.xml 記述子の例」web.xml 記述子では、ユーザ認証がされており、HttpInvokerのロールを持つ場合のみ、invoker.war サーブレットへのアクセスが可能です。

例8.3 JNDI サーブレットへのアクセスをセキュアにするための web.xml 記述子の例

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC
          "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
          "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
    <!-- ### Servlets -->
    <servlet>
        <servlet-name>JMXInvokerServlet</servlet-name>
        <servlet-class>
            org.jboss.invocation.http.servlet.InvokerServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>   <servlet>
        <servlet-name>JNDIFactory</servlet-name>
        <servlet-class>
            org.jboss.invocation.http.servlet.NamingFactoryServlet
        </servlet-class>
        <init-param>
            <param-name>namingProxyMBean</param-name>
            <param-value>jboss:service=invoker,type=http,target=Naming</param-value>
        </init-param>
        <init-param>
            <param-name>proxyAttribute</param-name>
            <param-value>Proxy</param-value>
        </init-param>
        <load-on-startup>2</load-on-startup>
    </servlet>  
    <!-- ### Servlet Mappings -->
    <servlet-mapping>
        <servlet-name>JNDIFactory</servlet-name>
        <url-pattern>/restricted/JNDIFactory/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>JMXInvokerServlet</servlet-name>
        <url-pattern>/restricted/JMXInvokerServlet/*</url-pattern>
    </servlet-mapping>   <security-constraint>
        <web-resource-collection>
            <web-resource-name>HttpInvokers</web-resource-name>
            <description>An example security config that only allows users with
                the role HttpInvoker to access the HTTP invoker servlets </description>
            <url-pattern>/restricted/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>HttpInvoker</role-name>
        </auth-constraint>
    </security-constraint>
    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>JBoss HTTP Invoker</realm-name>
    </login-config>   <security-role>
        <role-name>HttpInvoker</role-name>
    </security-role>
</web-app>
web.xml 記述子が定義するのは、どのサーブレットがセキュアか、どのロールであればセキュリティ保護されているサーブレットにアクセス可能かのみです。これに加え、war 認証、権限付与を処理するセキュリティドメインを定義する必要があります。定義方法はjboss-web.xml 記述子で行い、http-invokerセキュリティドメインの使用例を以下に示しています。
<jboss-web>
    <security-domain>java:/jaas/http-invoker</security-domain>
</jboss-web>
security-domain 要素は、認証、権限付与に使う JAAS ログインモジュール設定用のセキュリティドメイン名を定義しています。

8.4.4. セキュリティ保護されていないコンテキストを読み取り専用にして JNDI へのセキュアなアクセスを確保

JNDI/HTTP ネーミングサービスで利用できる別の機能として、未認証のユーザには読み取り専用モードでアクセスできるコンテキストを定義する機能です。認証層を使うサービスには、これは重要となる可能性があります。例えば、 SRPLoginModule は認証に利用する SRP サーバーインターフェースを検索する必要があります。本項ではここから、JBoss Enterprise Application Platform においてどのように読み取り専用がどのように動作するかを説明していきます。
まず、invoker.sar/WEB-INF/web.xmlReadOnlyJNDIFactory を宣言すると、/invoker/ReadOnlyJNDIFactoryにマッピングします。
<servlet>
    <servlet-name>ReadOnlyJNDIFactory</servlet-name>
    <description>A servlet that exposes the JBoss JNDI Naming service stub
          through http, but only for a single read-only context. The return content 
          is serialized MarshalledValue containing the org.jnp.interfaces.Naming 
          stub.
    </description>
    <servlet-class>org.jboss.invocation.http.servlet.NamingFactoryServlet</servlet-class>
    <init-param>
        <param-name>namingProxyMBean</param-name>
        <param-value>jboss:service=invoker,type=http,target=Naming,readonly=true</param-value>
    </init-param>
    <init-param>
        <param-name>proxyAttribute</param-name>
        <param-value>Proxy</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
</servlet>

<!-- ... -->
                        
<servlet-mapping>
    <servlet-name>ReadOnlyJNDIFactory</servlet-name>
    <url-pattern>/ReadOnlyJNDIFactory/*</url-pattern>
</servlet-mapping>
このファクトリは、invoker へ接続する必要がある JNDI スタブのみを提供します。ここでは、invoker は jboss:service=invoker,type=http,target=Naming,readonly=true となっており、http-invoker.sar/META-INF/jboss-service.xml ファイルにて宣言されます。
   <mbean code="org.jboss.invocation.http.server.HttpProxyFactory"
      name="jboss:service=invoker,type=http,target=Naming,readonly=true">
      <attribute name="InvokerName">jboss:service=Naming</attribute>
      <attribute name="InvokerURLPrefix">http://</attribute>
      <attribute name="InvokerURLSuffix">:8080/invoker/readonly/JMXInvokerServlet</attribute>
      <attribute name="UseHostName">true</attribute>
      <attribute name="ExportedInterface">org.jnp.interfaces.Naming</attribute>
      <attribute name="JndiName"></attribute>
      <attribute name="ClientInterceptors">
          <interceptors>
             <interceptor>org.jboss.proxy.ClientMethodInterceptor</interceptor>
             <interceptor>org.jboss.proxy.SecurityInterceptor</interceptor>
             <interceptor>org.jboss.naming.interceptors.ExceptionInterceptor</interceptor>
             <interceptor>org.jboss.invocation.InvokerInterceptor</interceptor>
          </interceptors>
      </attribute>
   </mbean>
クライアント側のプロキシは、サーバー側にある特定の invoker サーブレットに応答する必要があります。ここでの設定は/invoker/readonly/JMXInvokerServletへの実際の呼出しが含まれています。実際には、これは読み取り専用フィルタが付けられた標準の JMXInvokerServlet となっています。
    <filter>
        <filter-name>ReadOnlyAccessFilter</filter-name>
        <filter-class>org.jboss.invocation.http.servlet.ReadOnlyAccessFilter</filter-class>
        <init-param>
            <param-name>readOnlyContext</param-name>
            <param-value>readonly</param-value>
            <description>The top level JNDI context the filter will enforce
                read-only access on. If specified only Context.lookup operations
                will be allowed on this context. Another other operations or
                lookups on any other context will fail. Do not associate this
                filter with the JMXInvokerServlets if you want unrestricted
                access. </description>
        </init-param>
        <init-param>
            <param-name>invokerName</param-name>
            <param-value>jboss:service=Naming</param-value>
            <description>The JMX ObjectName of the naming service mbean </description>
        </init-param>
    </filter>
    
    <filter-mapping>
        <filter-name>ReadOnlyAccessFilter</filter-name>
        <url-pattern>/readonly/*</url-pattern>
    </filter-mapping>

    <!-- ... -->
    <!-- A mapping for the JMXInvokerServlet that only allows invocations 
            of lookups under a read-only context. This is enforced by the
            ReadOnlyAccessFilter 
            -->
    <servlet-mapping>
        <servlet-name>JMXInvokerServlet</servlet-name>
        <url-pattern>/readonly/JMXInvokerServlet/*</url-pattern>
    </servlet-mapping>
readOnlyContext パラメーターがreadonlyに設定されていると、ReadOnlyJNDIFactoryからJBoss にアクセスする場合、readonly コンテキストのデータにのみアクセスができるようになっています。使用方法を示すコードを以下に示します。
Properties env = new Properties();
env.setProperty(Context.INITIAL_CONTEXT_FACTORY, 
                "org.jboss.naming.HttpNamingContextFactory");
env.setProperty(Context.PROVIDER_URL, 
                "http://localhost:8080/invoker/ReadOnlyJNDIFactory");

Context ctx2 = new InitialContext(env);
Object data = ctx2.lookup("readonly/data");
読み取り専用コンテキスト以外のオブジェクトをルックアップしようとすると失敗します。JBoss にはreadonly コンテキストのデータは含まれていませんので、ご自身で作成しない限りreadonly コンテキストの使い道はありません。

8.5. その他のネーミング MBean

JBoss 内の JBossNS サーバーに組込み設定されているNamingService MBean 以外に、JBoss に同梱されているネーミング関連のMBean サービスがいくつか存在します。JndiBindingServiceMgrNamingAliasExternalContextJNDIViewなどとなっています。

8.5.1. JNDI バインディングマネージャー

JNDI バインディングマネージャーサービスにより、アプリケーションコードで利用できるよう JNDI にオブジェクトを素早くバインドできるようになります。バインディングサービスの MBean クラスはorg.jboss.naming.JNDIBindingServiceMgrとなっており、BindingsConfig属性を1つ含んでいます。この属性は、jndi-binding-service_1_0.xsd スキーマをに基づいた XMLドキュメントを受付けます。BindingsConfig 属性のコンテンツは JbossXB フレームワークを使いアンマーシャルされます。以下は MBean の定義で、JNDI バインディングマネージャーサービスの最も基本的なフォーム利用について示しています。
<mbean code="org.jboss.naming.JNDIBindingServiceMgr" 
       name="jboss.tests:name=example1">
    <attribute name="BindingsConfig" serialDataType="jbxb">
        <jndi:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" 
                       xmlns:jndi="urn:jboss:jndi-binding-service:1.0"
                       xs:schemaLocation="urn:jboss:jndi-binding-service  \
         resource:jndi-binding-service_1_0.xsd"> 
            <jndi:binding name="bindexample/message">
                <jndi:value trim="true">
                    Hello, JNDI!
                </jndi:value>
            </jndi:binding>
        </jndi:bindings>
    </attribute>
</mbean>
これは、JNDI名 bindexample/message でテキスト文字列 "Hello, JNDI!" をバインドします。アプリケーションは、他のJNDI 値の場合と同様にこの値を検索します。trim 属性は、前後のホワイトスペースを無視するよう指定します。この属性は単に説明のためだけに利用しているため、デフォルト値は True となっています。
InitialContext ctx  = new InitialContext();
String         text = (String) ctx.lookup("bindexample/message");
文字列の値自体はあまり興味深いものではありません。JavaBeans プロパティエディターを利用できる場合、type 属性を使って希望のクラス名を指定することができます。
<jndi:binding name="urls/jboss-home">
    <jndi:value type="java.net.URL">http://www.jboss.org</jndi:value>
</jndi:binding>
editor 属性を使って、使用するプロパティエディターを指定することができます。
<jndi:binding name="hosts/localhost">
    <jndi:value editor="org.jboss.util.propertyeditor.InetAddressEditor"> 
        127.0.0.1 
    </jndi:value>
</jndi:binding>
より複雑な構造については、BossXB対応のスキーマを使う場合もあります。以下の例では、java.util.Properties オブジェクトのマッピング方法を説明しています。
<jndi:binding name="maps/testProps">
    <java:properties xmlns:java="urn:jboss:java-properties" 
                     xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
                     xs:schemaLocation="urn:jboss:java-properties \
       resource:java-properties_1_0.xsd">
        <java:property>
            <java:key>key1</java:key>
            <java:value>value1</java:value>
        </java:property>
        <java:property>
            <java:key>key2</java:key>
            <java:value>value2</java:value>
        </java:property>
    </java:properties>
</jndi:binding>

8.5.2. org.jboss.naming.NamingAlias MBean

NamingAlias MBean は、単純なユーティリティサービスで、別のJNDI 名で JNDI javax.naming.LinkRef の形式でエイリアスを作成することができます。これは Unix ファイルシステムのシンボリックリンクに似ています。エイリアスを作成するには、NamingAlias MBeanの設定を jboss-service.xml 設定ファイルに追加します。NamingAlias サービスの設定属性は以下の通りです:
  • FromName: JNDI 下でLinkRefがバインドされる場所
  • ToName: エイリアスの to name。これは、LinkRef が参照するターゲット名となっており、この名前はURL、InitialContextを起点とし解決される相対名、あるいはこの名前の最初の文字がドット (.)の場合リンクがバインドされているコンテキストを起点とした相対名となっています。
以下の例では、JNDI 名QueueConnectionFactoryConnectionFactory という名前にマッピングしています。
<mbean code="org.jboss.naming.NamingAlias" 
       name="jboss.mq:service=NamingAlias,fromName=QueueConnectionFactory">
    <attribute name="ToName">ConnectionFactory</attribute>
    <attribute name="FromName">QueueConnectionFactory</attribute>
</mbean>

8.5.3. org.jboss.naming.ExternalContext MBean

ExternalContext MBean は、外部の JNDI コンテキストを JBoss サーバーのJNDI 名前空間に連携することができます。外部とは、JBoss サーバー VM の内部で動作する JBossNS ネーミングサービスの外部にあるネーミングサービスを指しています。JNDI プロバイダの root コンテキストがシリアル化されていない場合でも、LDAP サーバー、ファイルシステム、DNS サーバーなどを組み込むことができます。ネーミングサービスがリモートアクセスに対応している場合、リモートクライアントに対してもこの連携を用意することができます。
外部の JNDI ネーミングサービスを組み込むには、ExternalContext MBean サービスの設定をjboss-service.xml 設定ファイルに追加する必要があります。ExternalContext サービスの設定可能な属性は以下の通りです。
  • JndiName: 外部コンテキストがバインドされる JNDI 名。
  • RemoteAccess: リモートクライアントが外部のInitialContext を作成できるように、Serializable フォームを使って外部の InitialContext をバインドする必要があるかを示すboolean フラグ。リモートクライアントが JBoss JNDI InitialContext を介して外部のコンテキストを検索する場合、ExternalContext MBeanに渡したものと同じ env プロパティを使い、外部の InitialContext のインスタンスを効果的に作成します。クライアントがnew InitialContext(env) をリモートから実行できる場合のみ、機能します。これには、コンテキストにアクセスしているリモート VM にて、env の Context.PROVIDER_URL 値が解決できなければなりません。これは、LDAP の例で機能するはずです。しかし、ファイルシステムの例では、ファイルシステムのパスが共通のネットワークパスを指定していない限り機能しない場合が多いでしょう。このプロパティが設定されていないと、デフォルトでFalse に設定されます。
  • CacheContext: cacheContext フラグ。True に設定されている場合、MBean の起動後 MBean が停止するまで in memory オブジェクトとして格納されているときにのみ、外部の Context が作成されます。cacheContext が false に設定されている場合、MBean プロパティとInitialContext クラスを使って検索する度に外部の Context が作成されます。クライアントがキャッシュされていないContext を検索する場合、このクライアントは Context 上でclose()を呼び出し、リソース漏れを防ぐはずです。
  • InitialContext: 使用する InitialContext 実装の完全修飾クラス名。以下のいずれかである必要があります:javax.naming.InitialContext, javax.naming.directory.InitialDirContext あるいは javax.naming.ldap.InitialLdapContextInitialLdapContextの場合、null Controls アレイを使用します。デフォルトは、javax.naming.InitialContexとなっています。
  • Properties: Properties 属性には 外部のInitialContextに対する JNDI プロパティが含まれます。ここでの入力値は jndi.properties ファイルに入るテキストと同等のものでなければなりません。
  • PropertiesURL: 外部のプロパティファイルから外部のInitialContext に対するjndi.properties 情報を設定します。これは、URL、文字列あるいはクラスパスのリソース名となっており、以下に例を示します。
    • file:///config/myldap.properties
    • http://config.mycompany.com/myldap.properties
    • /conf/myldap.properties
    • myldap.properties
以下のMBean 定義では、external/ldap/jboss名の配下で、外部の LDAP コンテキストをJBoss JNDI名前空間にバインドしています。
<!-- Bind a remote LDAP server -->
<mbean code="org.jboss.naming.ExternalContext" 
       name="jboss.jndi:service=ExternalContext,jndiName=external/ldap/jboss">
    <attribute name="JndiName">external/ldap/jboss</attribute>
    <attribute name="Properties">
        java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
        java.naming.provider.url=ldap://ldaphost.jboss.org:389/o=jboss.org
        java.naming.security.principal=cn=Directory Manager
        java.naming.security.authentication=simple
        java.naming.security.credentials=secret
    </attribute>
    <attribute name="InitialContext"> javax.naming.ldap.InitialLdapContext </attribute>
    <attribute name="RemoteAccess">true</attribute>
</mbean>
この設定では、以下のコードを使ってJBoss VM内からldap://ldaphost.jboss.org:389/o=jboss.org にある外部のLDAP にアクセスすることができます。
InitialContext iniCtx = new InitialContext();
LdapContext ldapCtx = iniCtx.lookup("external/ldap/jboss");
この場合、RemoteAccess プロパティが true に設定されたため、JBoss サーバー VMの外部にある同じコードを利用すると動作します。False に設定されている場合、リモートクライアントは、外部の InitialContext を再構築できない ObjectFactory と共にReference オブジェクトを受け取るため、動作しません。
<!-- Bind the /usr/local file system directory  -->
<mbean code="org.jboss.naming.ExternalContext" 
       name="jboss.jndi:service=ExternalContext,jndiName=external/fs/usr/local">
    <attribute name="JndiName">external/fs/usr/local</attribute>
    <attribute name="Properties">
        java.naming.factory.initial=com.sun.jndi.fscontext.RefFSContextFactory
        java.naming.provider.url=file:///usr/local
    </attribute>
    <attribute name="InitialContext">javax.naming.IntialContext</attribute>
</mbean>
この設定は、ローカルのファイルシステムディレクトリ/usr/localexternal/fs/usr/local名配下にあるJBoss JNDI名前空間へバインディングしています。
この設定では、以下のコードを使って JBoss VM 内から file:///usr/local にある外部のファイルシステムコンテキストへアクセス可能です。
InitialContext iniCtx = new InitialContext();
                Context ldapCtx = iniCtx.lookup("external/fs/usr/local");

8.5.4. org.jboss.naming.JNDIView MBean

JNDIView MBean では、ユーザは JMX Agent View のインターフェースを使うことで JBoss サーバー内に存在しているように、JNDI 名前空間のツリーを参照することができます。JNDIView MBeanを使って JBoss JNDI 名前空間を参照するには、http インターフェースを使い JMX Agent View に接続します。これはデフォルト設定で、http://localhost:8080/jmx-console/となっています。このページでは、登録済みの MBean をドメイン別に分類し一覧になっているセクションが表示されます。図8.4「設定済みの JBoss MBeans を JMX Console で表示」で示すような表示になるはずです。
設定済みの JBoss MBeans を JMX Console で表示

図8.4 設定済みの JBoss MBeans を JMX Console で表示

JNDIView リンクを選択すると、 JNDIView MBean ビューに移動し、JNDIView MBean の操作一覧が表示されます。これは、図8.5「JNDIView MBean を JMX Console で表示」 で表示されているようなビューになるはずです。
JNDIView MBean を JMX Console で表示

図8.5 JNDIView MBean を JMX Console で表示

リスト操作により、シンプルなテキストビューを使い、JBoss サーバーのJNDI 名前空間を HTML ページとしてダンプします。例としてリスト操作を呼び出すことで、図8.6「JNDIView のリスト操作出力をJMX Console で表示」で示されているようなビューが生成されます。
JNDIView のリスト操作出力をJMX Console で表示

図8.6 JNDIView のリスト操作出力をJMX Console で表示

8.6. J2EE および JNDI - アプリケーションコンポーネント環境

JNDI は J2EE 仕様の基本となります。重要となる使用法のひとつとして、コードがデプロイされる環境からの J2EE コンポーネントコードの分離があります。アプリケーションコンポーネントの環境を使用することでアプリケーションコンポーネントのソースコードにアクセスあるいは、変更を加えずにアプリケーションコンポーネントをカスタマイズすることができるようになります。アプリケーションコンポーネント環境は ENC (エンタープライズネーミングコンテキスト) と呼ばれています。JNDI コンテキストの形式でコンテナーコンポーネントに対して ENC を使用できるようにするのはアプリケーションコンポーネントコンテナーの役割になります。次のようにして、J2EE のライフサイクル内で関連するパーティシパントによって ENC は活用されます。
  • アプリケーションコンポーネントのビジネスロジックは、コード化しENC からの情報にアクセスする必要があります。コンポーネントプロバイダーは、コンポーネントに対して標準の配備記述子を使い、必要とされる ENC エントリを指定します。このエントリは、実行時にコンポーネントが必要とする情報とリソースの宣言をしています。
  • このコンテナーが提供するツールでは、コンポーネントのデプロイヤーを使うことで、コンポーネント開発者が作成したENC 参照をこの参照を満たすデプロイメント環境エンティティへマッピングできます。
  • コンポーネントデプロイヤーは、コンテナツールを使い最終的なデプロイメントができるようコンポーネントを準備します。
  • コンポーネントコンテナーは、デプロイメントパッケージ情報を使ってランタイム時に完全なコンポーネントENC を構築します。
J2EE プラットフォームでJNDI 利用する上での完全仕様については、J2EE 1.4 仕様の5章を参照してください。
アプリケーションコンポーネントのインスタンスは JNDI API を使い ENC を検索します。さらに、このインスタンスは、引数なしのコンストラクタを使ってjavax.naming.InitialContext オブジェクトを作成してからjava:comp/env名配下にあるネーミング環境を検索します。アプリケーションコンポーネントの環境エントリは ENC に直接格納されるか、あるいはサブコンテキスト内に格納されます。 例8.4「ENCアクセスのサンプルコード」 でコンポーネントがENC にアクセスする際に使うコードの典型的な行を示しています。

例8.4 ENCアクセスのサンプルコード

// Obtain the application component's ENC
Context iniCtx = new InitialContext();
Context compEnv = (Context) iniCtx.lookup("java:comp/env");
アプリケーションコンポーネント環境とは、アプリケーションサーバーコンテナの制御スレッドがアプリケーションコンポーネントとやりとりを行っている際にコンポーネントのみがアクセスできるローカル環境です。つまり、EJB Bean1 は EJB Bean2 のENC 要素にアクセスできず、逆方向でも同様にアクセスできなくなっています。同様に、Web アプリケーションWeb1 は、WEb アプリケーションWeb2Bean1、あるいはBean2 のENC 要素にアクセスできません。また、任意のクライアントコードはアプリケーションサーバー VM 内外を問わず実行されている場合、コンポーネントのjava:comp JNDI コンテキストにアクセスできません。ENC の目的は、コンポーネントのデプロイ環境タイプに関係なくアプリケーションコンポーネントが依存できる分離型の読み取り専用名前空間を提供することです。各コンポーネントが独自のENC コンテンツを定義するため、ENC は他のコンポーネントから分離する必要があります。たとえば、コンポーネントABが同名定義していても別のオブジェクトを参照している可能性があります。また、別の例を挙げますと、EJB Bean1 は環境エントリjava:comp/env/red を定義し、RGB 色の赤に対して 16 進数を参照している場合があり、一方で Web アプリケーションWeb1 は、同名をデプロイメント環境言語ロケールの赤表示にバインドしている可能性もあります。
JBoss にはよく利用されるネーミングスコープレベルが3つあります。java:comp配下の名前、java:配下の名前、その他の名前です。前述したように、java:comp コンテキストとそのサブコンテキストは、特定のコンテキストに紐付けられたアプリケーションコンポーネントに対してのみ利用可能になっています。java:直下のサブコンテキストやオブジェクトバインディングは、JBoss サーバーの下層マシン内でのみ表示され、リモートクライアントからは見えません。コンテキストあるいはオブジェクトがシリアル化に対応していれば、その他のコンテキストやオブジェクトバインディングはリモートクライアントに提供されます。これらのネーミングスコープの分離の実施方法については 「JBoss Naming Service アーキテクチャー」を参照してください。
java: コンテキストへのバインディングを制限すると便利な例は、関連データベースプールが常駐するJBoss サーバー内でのみ利用可能なjavax.sql.DataSourceの接続ファクトリでしょう。一方で、EJB ホームインターフェースは、リモートクライアントからアクセスできるはずのグローバルな表示名にバインドされるでしょう。

8.6.1. ENC の使用規則

JNDI を API として使用することで、アプリケーションコンポーネントから相当量の情報を外部化します。アプリケーションコンポーネントが情報のアクセスに使用する JNDI 名は EJB コンポーネント用の標準 ejb-jar.xml 配備記述子および Web コンポーネント用の標準 web.xml 配備記述子内に宣言されます。次のような様々な種類の情報が JNDI 内に格納、検索されます。
  • env-entry 要素により宣言された通りの環境エントリ
  • ejb-refejb-local-ref 要素により宣言された通りのEJB 参照
  • resource-ref 要素が宣言した通りのリソースマネージャー接続ファクトリ参照
  • resource-env-ref 要素に定義された通りのリソース環境参照
配備記述子要素のタイプにはそれぞれ、配下に情報がバインドされる JNDI コンテキストの名前に関する JNDI 使用規則があります。また、標準の配備記述子要素に加え、アプリケーションコンポーネントによって使用される JNDI 名をデプロイメント環境の JNDI 名にマッピングする JBoss サーバー固有の配備記述子要素があります。

8.6.1.1. 環境エントリ

環境エントリは、コンポーネント ENC に格納される情報の中で最もシンプルな形式で、Unix や Windows にあるようなオペレーティングシステムの環境変数に似ています。環境エントリは name-to-value バインディングで、コンポーネントが値を外部化し、名前を使って値を参照することができます。
環境エントリは、標準の配備記述子でenv-entry を使い宣言されます。env-entry要素には以下の子要素が含まれます:
  • エントリの詳細を提供する任意のdescription 要素
  • java:comp/envに相対となるエントリ名を渡すenv-entry-name要素
  • エントリ値の java タイプを与えるenv-entry-type要素。このエントリ値のタイプは以下のいずれかでなければなりません。
    • java.lang.Byte
    • java.lang.Boolean
    • java.lang.Character
    • java.lang.Double
    • java.lang.Float
    • java.lang.Integer
    • java.lang.Long
    • java.lang.Short
    • java.lang.String
  • 文字列としてエントリ値を与えるenv-entry-value 要素
ejb-jar.xml 配備記述子からのenv-entry フラグメントに関する例が例8.5「ejb-jar.xml env-entry のフラグメント例」に提供されています。env-entryは完全名かつ値の指定であるため、JBoss 固有の配備記述子要素はありません。例8.6「ENC env-entry アクセスコード」では、配備記述子で宣言されているmaxExemptions 値、taxRate 値、env-entry 値へアクセスするための、サンプルコードを提示しています。

例8.5 ejb-jar.xml env-entry のフラグメント例

<!-- ... -->
<session>
    <ejb-name>ASessionBean</ejb-name>
    <!-- ... -->
    <env-entry>
        <description>The maximum number of tax exemptions allowed </description>
        <env-entry-name>maxExemptions</env-entry-name>
        <env-entry-type>java.lang.Integer</env-entry-type>
        <env-entry-value>15</env-entry-value>
    </env-entry>
    <env-entry>
        <description>The tax rate </description>
        <env-entry-name>taxRate</env-entry-name>
        <env-entry-type>java.lang.Float</env-entry-type>
        <env-entry-value>0.23</env-entry-value>
    </env-entry>
</session>
<!-- ... -->

例8.6 ENC env-entry アクセスコード

InitialContext iniCtx = new InitialContext();
Context envCtx = (Context) iniCtx.lookup("java:comp/env");
Integer maxExemptions = (Integer) envCtx.lookup("maxExemptions");
Float taxRate = (Float) envCtx.lookup("taxRate");

8.6.1.2. EJB参照

EJBやWeb コンポーネントは通常、他のEJBとやりとりを行います。配下にEJB ホームインターフェースがバインドされるJNDI名はデプロイメント時に決定されるため、デプロイヤーによりリンクされるEJBへの参照をコンポーネント開発者が宣言する方法が必要となります。EJB参照は、この要件を満たしています。
EJB 参照は、アプリケーションコンポーネントのネーミング環境内のリンクで、デプロイされたEJB ホームインターフェースを指定しています。アプリケーションコンポーネントによって使用される名前は、そのコンポーネントをデプロイメント環境にある実際の EJB ホーム名から隔離する論理リンクになります。 J2EE 規格では、 エンタープライズ bean への参照はすべてアプリケーションコンポーネント環境の java:comp/env/ejb コンテキスト内にまとめるよう推奨しています。
EJB 参照は、ejb-ref 要素を使い配備記述子で宣言します。各 ejb-ref 要素は、参照アプリケーションコンポーネントが参照されるエンタープライズ bean に対して持つインターフェース要件を記述します。ejb-ref 要素には以下の子要素が含まれます。
  • 参照の目的を示すオプションのdescription 要素。
  • ejb-ref-name 要素で、java:comp/env コンテキストに対して相対となる参照名を指定します。推奨のjava:comp/env/ejb コンテキスト配下に参照を置くには、ejb-ref-name 値に対して、ejb/link-name形式を使います。
  • EJB の種類を指定するejb-ref-type 要素。Entity あるいは Sessionでなければなりません。
  • EJB ホームインターフェースの完全修飾クラス名を提供するhome 要素。
  • EJB リモートインターフェースの完全修飾クラス名を提供するremote 要素。
  • オプションの ejb-link 要素で同じ EJB JAR または同じ J2EE アプリケーションユニットにある別のエンタープライズ bean に参照をリンクします。ejb-link 値は参照される bean の ejb-name になります。同じ ejb-nameを持つエンタープライズ bean が複数ある場合、値はパス名前を使用して、参照コンポーネントを含む ejb-jar ファイルの場所を指定します。パス名は参照 ejb-jar ファイルに相対的となります。Application Assembler は参照される bean の ejb-name# で区切ってパス名に追加します。これにより同じ名前を持つ複数の bean が一意に識別可能となります。
EJB 参照は、宣言にejb-ref 要素を含むアプリケーションコンポーネントにスコープ設定されます。つまり、EJB 参照は実行時には他のアプリケーションコンポーネントからアクセスできず、他のアプリケーションコンポーネントは名前の衝突を起こさずejb-ref要素を同じejb-ref-name で定義できます。例8.7「ejb-jar.xml 内 ejb-ref 記述子の部分例」 では、ejb-refの使用方法を説明するejb-jar.xml フラグメントを提示しています。例8.7「ejb-jar.xml 内 ejb-ref 記述子の部分例」 にて宣言されているShoppingCartHome 参照にアクセスするためのコード例は、例8.8「ENC ejb-ref アクセスコード」に提供されています。

例8.7 ejb-jar.xml 内 ejb-ref 記述子の部分例

<!-- ... -->
<session>
    <ejb-name>ShoppingCartBean</ejb-name>
    <!-- ...-->
</session>

<session>
    <ejb-name>ProductBeanUser</ejb-name>
    <!--...-->
    <ejb-ref>
        <description>This is a reference to the store products entity </description>
        <ejb-ref-name>ejb/ProductHome</ejb-ref-name>
        <ejb-ref-type>Entity</ejb-ref-type>
        <home>org.jboss.store.ejb.ProductHome</home>
        <remote> org.jboss.store.ejb.Product</remote>
    </ejb-ref>

</session>

<session>
    <ejb-ref>
        <ejb-name>ShoppingCartUser</ejb-name>
        <!--...-->
        <ejb-ref-name>ejb/ShoppingCartHome</ejb-ref-name>
        <ejb-ref-type>Session</ejb-ref-type>
        <home>org.jboss.store.ejb.ShoppingCartHome</home>
        <remote> org.jboss.store.ejb.ShoppingCart</remote>
        <ejb-link>ShoppingCartBean</ejb-link>
    </ejb-ref>
</session>

<entity>
    <description>The Product entity bean </description>
    <ejb-name>ProductBean</ejb-name>
    <!--...-->
</entity>

<!--...-->

例8.8 ENC ejb-ref アクセスコード

InitialContext iniCtx = new InitialContext();
Context ejbCtx = (Context) iniCtx.lookup("java:comp/env/ejb");
ShoppingCartHome home = (ShoppingCartHome) ejbCtx.lookup("ShoppingCartHome");

8.6.1.3. jboss.xml および jboss-web.xml でのEJB 参照

JBoss 固有のjboss.xml EJB 配備記述子はEJB 参照に2通りに作用します。まず、sessionjndi-name の子要素とentity 要素により、ユーザがEJB ホームインターフェースに対してデプロイメントJNDI 名を指定することができます。EJB に対し jndi-namejboss.xml で指定しない場合、ホームインターフェースは、ejb-jar.xmlejb-name 値の配下にバインドされます。例えば、例8.7「ejb-jar.xml 内 ejb-ref 記述子の部分例」 にあるShoppingCartBeanejb-nameを持つセッションEJB では、jboss.xmljndi-name の指定がないため、ホームインターフェースはJNDI 名の配下にバインドされます。
ejb-ref関連のjboss.xml 記述子に関する2つ目の用途は、コンポーネントのENC ejb-ref の参照先を設定します。ejb-link 要素を使って別の企業アプリケーションにあるEJBを参照することはできません。ご利用中のejb-ref が外部のEJBにアクセスする必要がある場合、jboss.xmlejb-ref/jndi-name 要素を使って、配備されたEJB ホームのJNDI 名を指定することができます。
jboss-web.xml 記述子は、Web アプリケーションのENCejb-ref の参照先を設定するためだけに利用されます。JBoss ejb-refのコンテンツモデルは以下の通りです。
  • ejb-jar.xml あるいはweb.xml標準記述子内のejb-ref-name 要素に相当する ejb-ref-name 要素。
  • デプロイメント環境でEJB ホームインターフェースのJNDI 名を指定するjndi-name 要素。
例8.9「jboss.xml ejb-ref の部分例」は、以下の使用点を説明するjboss.xml 記述子の部分例となっています。
  • ProductBeanUserejb-ref のリンク先は、jboss/store/ProductHomeのデプロイメント名に設定されます。
  • ProductBean のデプロイメントJNDI 名は、jboss/store/ProductHomeと設定されます。

例8.9 jboss.xml ejb-ref の部分例

<!-- ... -->
<session>
    <ejb-name>ProductBeanUser</ejb-name>
    <ejb-ref>
        <ejb-ref-name>ejb/ProductHome</ejb-ref-name>
        <jndi-name>jboss/store/ProductHome</jndi-name>
    </ejb-ref>
</session>
                        
<entity>
    <ejb-name>ProductBean</ejb-name>
    <jndi-name>jboss/store/ProductHome</jndi-name>
     <!-- ... -->
</entity>
<!-- ... -->

8.6.1.4. EJB のローカル参照

EJB2.0 は、値セマンティクスによるRMI呼出しを使わないローカルインターフェースを追加していました。これらのインターフェースは、参照セマンティクスによる呼出しを使うため、RMI のシリアル化のオーバーヘッドが起こりません。EJB ローカル参照は、 デプロイされた EJB ローカルホームインターフェースを指すアプリケーションコンポーネントのネーミング環境内のリンクになります。アプリケーションコンポーネントが使う名前は、論理リンクとなっており、デプロイメント環境にあるEJB ローカルホームの実際名からコンポーネントを分離します。J2EE 仕様では、アプリケーションコンポーネント環境のjava:comp/env/ejbコンテキスト内に、エンタープライズ bean への参照をすべて整理するよう推奨しています。
EJB ローカル参照は配備記述子内の ejb-local-ref 要素を使って宣言されます。各 ejb-local-ref 要素は、参照されるエンタープライズ bean に対する、参照アプリケーションのインターフェース要件を記述しています。ejb-local-ref 要素には以下の子要素が含まれます。
  • 参照の目的を示すオプションのdescription 要素。
  • ejb-ref-name 要素で、java:comp/env コンテキストに対して相対となる参照名を指定します。推奨のjava:comp/env/ejb コンテキスト配下に参照を置くには、ejb-ref-name 値に対して、ejb/link-name形式を使います。
  • EJB の種類を指定するejb-ref-type 要素。Entity あるいは Sessionでなければなりません。
  • EJB ローカルホームインターフェースの完全修飾クラス名を提供するlocal-home
  • EJB ローカルインターフェースの完全修飾クラス名を提供するlocal 要素。
  • ejb-jar ファイルまたは、同じJ2EE アプリケーションユニット内にある別のエンタープライズ bean への参照にリンクするejb-link要素。ejb-link 値は、参照されたbean のejb-name となっています。同じejb-nameを持つエンタープライズ bean が複数存在する場合、この値はパス名を使い、参照コンポーネントを含むejb-jarファイルの場所を指定します。Application Assembler は、#で区切られたパス名に参照 bean のejb-name を付けます。これにより、同名を持つ bean が複数あっても一意に識別できるようになります。JBoss では ejb-link 要素を指定し、ローカル参照と対応するEJBを一致させる必要があります。
EJB ローカル参照は、宣言に ejb-local-ref 要素を含むアプリケーションコンポーネントにスコープ化されます。つまり、EJB ローカル参照は、ランタイム時に他のアプリケーションコンポーネントからアクセスできず、別のアプリケーションコンポーネントは名前の衝突なしに同じejb-ref-name を持つejb-local-ref 要素を定義する場合があるのです。例8.10「ejb-jar.xml ejb-local-ref 記述子の部分例」では、ejb-local-ref の用途について例示するejb-jar.xml のフラグメントが提供されています。例8.11「ENC ejb-local-ref アクセスコード」 のコード例にて、例8.10「ejb-jar.xml ejb-local-ref 記述子の部分例」で宣言されるProbeLocalHome 参照へのアクセスについて例示しています。

例8.10 ejb-jar.xml ejb-local-ref 記述子の部分例

    <!-- ... -->
    <session>
        <ejb-name>Probe</ejb-name>
        <home>org.jboss.test.perf.interfaces.ProbeHome</home>
        <remote>org.jboss.test.perf.interfaces.Probe</remote>
        <local-home>org.jboss.test.perf.interfaces.ProbeLocalHome</local-home>
        <local>org.jboss.test.perf.interfaces.ProbeLocal</local>
        <ejb-class>org.jboss.test.perf.ejb.ProbeBean</ejb-class>
        <session-type>Stateless</session-type>
        <transaction-type>Bean</transaction-type>
    </session>
    <session>
        <ejb-name>PerfTestSession</ejb-name>
        <home>org.jboss.test.perf.interfaces.PerfTestSessionHome</home>
        <remote>org.jboss.test.perf.interfaces.PerfTestSession</remote>
        <ejb-class>org.jboss.test.perf.ejb.PerfTestSessionBean</ejb-class>
        <session-type>Stateless</session-type>
        <transaction-type>Container</transaction-type>
        <ejb-ref>
            <ejb-ref-name>ejb/ProbeHome</ejb-ref-name>
            <ejb-ref-type>Session</ejb-ref-type>
            <home>org.jboss.test.perf.interfaces.SessionHome</home>
            <remote>org.jboss.test.perf.interfaces.Session</remote>
            <ejb-link>Probe</ejb-link>
        </ejb-ref>
        <ejb-local-ref>
            <ejb-ref-name>ejb/ProbeLocalHome</ejb-ref-name>
            <ejb-ref-type>Session</ejb-ref-type>
            <local-home>org.jboss.test.perf.interfaces.ProbeLocalHome</local-home>
            <local>org.jboss.test.perf.interfaces.ProbeLocal</local>
            <ejb-link>Probe</ejb-link>
        </ejb-local-ref>
    </session>
    <!-- ... -->

例8.11 ENC ejb-local-ref アクセスコード

InitialContext iniCtx = new InitialContext();
Context ejbCtx = (Context) iniCtx.lookup("java:comp/env/ejb");
ProbeLocalHome home = (ProbeLocalHome) ejbCtx.lookup("ProbeLocalHome");

8.6.1.5. リソースマネージャー接続ファクトリの参照

リソースマネージャー接続ファクトリの参照により、アプリケーションコンポーネントコードはリソースマネージャー接続ファクトリの参照と呼ばれる論理名を使うことで、リソースファクトリを参照することができます。リソースマネージャー接続ファクトリの参照は、標準の配備記述子にてresource-ref 要素により定義されています。Deployer は、jboss.xmljboss-web.xml 記述子を使って、リソースマネージャー接続ファクトリの参照を実際の運用環境にあるリソースマネージャー接続ファクトリにバインドします。
resource-ref 要素は、1つのリソースマネージャー接続ファクトリの参照を記述します。resource-ref 要素は、以下の子要素で構成されます:
  • 参照の目的を示すオプションのdescription 要素。
  • java:comp/env コンテキストを起点とした参照名を指定するres-ref-name 要素。どのサブコンテキストにres-ref-name を配置するかを決定するリソースタイプに基づいた命名規則について、次の段落にて説明します。
  • リソースマネージャー接続ファクトリの完全修飾名を指定するres-type 要素。
  • アプリケーションコンポーネントコードがリソースのサインオンをプログラムで実行するか、あるいはコンテナーがデプロイヤー提供の主体マッピング情報に基づいたリソースへサインオンするか示すres-auth 要素。Application あるいは Containerのいずれかでなければなりません。
  • 任意のres-sharing-scope 要素。現在、JBoss では対応していません。
J2EE 仕様では、リソース管理タイプごとに異なるサブコンテキストを使うことで、リソース管理接続ファクトリの参照をすべて、アプリケーションコンポーネント環境のサブコンテキスト内にまとめるよう推奨されています。サブコンテキスト名に推奨されるリソース管理タイプは次の通りです。
  • JDBC DataSource 参照は、java:comp/env/jdbc のサブコンテキストで宣言する必要があります。
  • JMS 接続ファクトリはjava:comp/env/jms サブコンテキストで宣言する必要があります。
  • JavaMail 接続ファクトリはjava:comp/env/mail サブコンテキストにて宣言する必要があります。
  • URL 接続ファクトリは、java:comp/env/url サブコンテキストにて宣言する必要があります。
例8.12「web.xml resource-ref 記述子のフラグメント」 は、resource-ref 要素の用途を示すweb.xml 記述子のフラグメント例です。例8.13「ENC resource-ref アクセスのサンプルコード」 は、アプリケーションコンポーネントが resource-refにより宣言されている DefaultMail リソースへアクセスする際に使うコードを提供しています。

例8.12 web.xml resource-ref 記述子のフラグメント

<web>
    <!-- ... -->
    <servlet>
        <servlet-name>AServlet</servlet-name>
        <!-- ... -->
    </servlet>
    <!-- ... -->
    <!-- JDBC DataSources (java:comp/env/jdbc) -->
    <resource-ref>
        <description>The default DS</description>
        <res-ref-name>jdbc/DefaultDS</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>
    <!-- JavaMail Connection Factories (java:comp/env/mail) -->
    <resource-ref>
        <description>Default Mail</description>
        <res-ref-name>mail/DefaultMail</res-ref-name>
        <res-type>javax.mail.Session</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>
    <!-- JMS Connection Factories (java:comp/env/jms) -->
    <resource-ref>
        <description>Default QueueFactory</description>
        <res-ref-name>jms/QueueFactory</res-ref-name>
        <res-type>javax.jms.QueueConnectionFactory</res-type>
        <res-auth>Container</res-auth>
    </resource-ref> 
<web>

例8.13 ENC resource-ref アクセスのサンプルコード

Context initCtx = new InitialContext();
javax.mail.Session s = (javax.mail.Session)
initCtx.lookup("java:comp/env/mail/DefaultMail");

8.6.1.6. jboss.xml と jboss-web.xml でのリソースマネージャー接続ファクトリの接続

JBoss jboss.xml EJB 配備記述子とjboss-web.xml Web アプリケーションの配備記述子の目的は、jboss-web.xml 要素により定義された論理名からJBoss でデプロイされるリソースファクトリのJNDI 名へのリンクを提供することです。jboss.xml あるいはjboss-web.xml 記述子にresource-ref 要素を提供することでリンク可能です。JBoss resource-ref 要素には、以下の子要素が含まれています:
  • res-ref-name要素。これは、ejb-jar.xml あるいは web.xml の標準記述子にある該当のresource-ref 要素のres-ref-name と一致しなければなりません。
  • 任意のres-type 要素。リソースマネージャー接続ファクトリの完全修飾クラス名を指定します。
  • jndi-name要素。これは、JBoss にデプロイされるように、リソースファクトリのJNDI 名を指定します。
  • res-url要素。これは、resource-refがタイプjava.net.URLの場合にURL文字列を指定します。
例8.14「jboss-web.xml resource-ref 記述子の例」は、jboss-web.xml のサンプル記述子を提示しています。このフラグメントでは例8.12「web.xml resource-ref 記述子のフラグメント」にあるresource-ref要素のサンプルマッピングが示されています。

例8.14 jboss-web.xml resource-ref 記述子の例

<jboss-web>
    <!-- ... -->
    <resource-ref>
        <res-ref-name>jdbc/DefaultDS</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <jndi-name>java:/DefaultDS</jndi-name>
    </resource-ref>
    <resource-ref>
        <res-ref-name>mail/DefaultMail</res-ref-name>
        <res-type>javax.mail.Session</res-type>
        <jndi-name>java:/Mail</jndi-name>
    </resource-ref>
    <resource-ref>
        <res-ref-name>jms/QueueFactory</res-ref-name>
        <res-type>javax.jms.QueueConnectionFactory</res-type>
        <jndi-name>QueueConnectionFactory</jndi-name>
    </resource-ref>
    <!-- ... -->
</jboss-web>

8.6.1.7. リソース環境の参照

リソース環境の参照は、論理名を使ってリソース (例:JMS デスティネーション) と紐付いた管理オブジェクトを参照する要素です。リソース環境の参照は、標準の配備記述子にてresource-env-ref 要素で定義されています。Deployerは、jboss.xmljboss-web.xml記述子を使うことで、リソース環境の参照を対象の運用環境にある実際の管理オブジェクトの場所にバインドします。
resource-env-ref 要素はそれぞれ、参照される管理オブジェクトに対し参照するアプリケーションコンポーネントが必要とする要件を記述します。resource-env-ref 要素には、以下の子要素が含まれます:
  • 参照の目的を示すオプションのdescription 要素。
  • java:comp/env コンテキストを起点とした参照名を指定するresource-env-ref-name 要素。規則は関連のリソースファクトリタイプに対応するサブコンテキスト内にその名前を配置します。たとえば、MyQueue という名前の JMS キュー参照は jms/MyQueueresource-env-ref-name を持っているはずです。
  • 参照されるオブジェクトの完全修飾クラス名を指定するresource-env-ref-type 要素。例えば、JMS キューの場合、値はjavax.jms.Queueとなります。
例8.15「ejb-jar.xml resource-env-ref のフラグメント例」 は、セッション bean によるresource-ref-env要素の宣言例を示しています。例8.16「ENC resource-env-ref アクセスコード」 では、resource-env-refにより宣言されたStockInfo キューを検索する方法を示すコードを提供しています。

例8.15 ejb-jar.xml resource-env-ref のフラグメント例

<session>
    <ejb-name>MyBean</ejb-name>
    <!-- ... -->
    <resource-env-ref>
        <description>This is a reference to a JMS queue used in the
            processing of Stock info
        </description>
        <resource-env-ref-name>jms/StockInfo</resource-env-ref-name>
        <resource-env-ref-type>javax.jms.Queue</resource-env-ref-type>
    </resource-env-ref>
    <!-- ... -->
</session>

例8.16 ENC resource-env-ref アクセスコード

InitialContext iniCtx = new InitialContext();
javax.jms.Queue q = (javax.jms.Queue)
envCtx.lookup("java:comp/env/jms/StockInfo");

8.6.1.8. リソース環境参照と jboss.xml、jboss-web.xml

JBoss jboss.xml EJB 配備記述子とjboss-web.xml Web アプリケーションの配備記述子の目的は、resource-env-ref-name 要素により定義された論理名からJBoss でデプロイされる管理オブジェクトのJNDI 名へのリンクを提供することです。jboss.xml あるいはjboss-web.xml 記述子にresource-env-ref 要素を提供することでリンク可能です。JBoss jboss-web.xml 要素には、以下の子要素が含まれています:
  • resource-env-ref-name 要素。ejb-jar.xml あるいは web.xml の標準記述子からの該当のresource-env-ref 要素にあるresource-env-ref-name と一致しなければなりません。
  • JBoss でデプロイされるようにリソースのJNDI 名を指定するjndi-name 要素。
例8.17「jboss.xml resource-env-ref 記述子のフラグメント例」 では、StockInforesource-env-refに関するマッピングサンプルを示すjboss.xml 記述子の例を提供しています。

例8.17 jboss.xml resource-env-ref 記述子のフラグメント例

<session>
    <ejb-name>MyBean</ejb-name>
    <!-- ... -->
    <resource-env-ref>
        <resource-env-ref-name>jms/StockInfo</resource-env-ref-name>
        <jndi-name>queue/StockInfoQueue</jndi-name>
    </resource-env-ref>
    <!-- ... -->
</session>

第9章 Web サービス

Web サービスは、現在の Web コマースの運営方法を決める主な要因となっています。Web サービスは、大小のデータのチャンクを送信しアプリケーション同士が通信できるようにします。
Web アプリケーションは、 コンピューターネットワーク上やワールドワイドウェブ上のアプリケーションのやりとりをサポートするソフトウェアアプリケーションです。 通常、Web サービスは、 オブジェクト、 コンピュータープログラム、 ビジネスプロセス、 データベースなどへマップする XML ドキュメントを介してやりとりを行います。 アプリケーションは XML サードパーティ形式のメッセージを Web サービスに送信し、 Web サービスはこのメッセージを対応するプログラムへ送信します 。応答は要件を基に受信され、 Web サービスは受信したメッセージを XML 形式で必要とするプログラムやアプリケーションへ送信します。Web サービスは、 サプライチェーン管理やビジネス統合などさまざまな目的に使用できます。
JBossWS は JBoss Enterprise Application Platform の一部として同梱される Web サービスのフレームワークです。 Java Platform Enteprise Edition 5 (Java EE 5) をターゲットとし、 Java にWeb サービスを実装するためのプログラミングモデルやランタイムアーキテクチャーを定義する JAX-WS 仕様を実装します。 JAX-RPC もサポートされますが (J2EE 1.4 の Web サービス仕様)、 JBossWS は JAX-WS に主力を置きます。

警告

JAX-RPCは、JBoss Web Services CXF スタックには対応していません。

9.1. Web サービスの必要性

Web サービス技術を適切に導入すると、 企業向けシステムの通信を向上することができます。 よく設計されたコントラクトに焦点を置くと、 開発者はサービス機能の抽象ビューを確立することができます。 コントラクトが書かれた標準的な方法を考慮すると、 サードパーティシステムとの通信を実現できるため、 最終的にビジネス間の統合をサポートします。 プロバイダーとコンシューマーが合意するコントラクトの内容はすべて明確で標準的です。 また、 実装間の依存関係を軽減するため、 主要な変更を行わなくても他のコンシューマーが提供されるサービスを簡単に使用することができます。
Web サービスの相互運用性はサービスの再使用と構成を向上するため、 内部異種サブシステムの Web サービス技術を取り入れる企業システムには別の利点があります。 異なるソフトウェア言語を使用して別の企業部門によって開発されるため、 Web サービスによって機能全体を書き直す必要がなくなります。

9.2. Web サーバーとは

Web サービスは、ソフトウェアシステム通信すべてに対するソリューションではありません。
現在、疎結合で粗粒度の通信、メッセージ (文書) の交換に利用するためにWeb サービスが利用されています。近年、 多くの仕様 (WS-*) が検討され、信頼できるメッセージングやメッセージレベルセキュリティ、 クロスサービストランザクションなど、標準的な WS 関連の上級アスペクトの確立が最終的に承諾されました。Web サービス仕様には、サービスコントラクト参照を集めるレジストリの概念も含まれており、 サービス実装の検索を簡単に行うことができます。
そのため、 Web サービスの技術プラットフォームはリモートプロシージャー呼び出しを行う最新の方法としてだけでなく、 複雑な企業向け通信に適合します。

9.3. Document/Literal

ドキュメントスタイルの Web サービスでは、 2 者が XML スキーマで適切に定義される複雑なビジネス文書の交換に同意することになります。 たとえば、 ー方が発注書の記載があるドキュメントを送信し、 相手側がその発注書の状況を記載する文書で応答(即座または後に)します。 SOAP メッセージのペイロードは XML スキーマに対して認証可能な XML ドキュメントです。このドキュメントは SOAP バインディングのスタイル属性で定義されます。
<binding name='EndpointInterfaceBinding' type='tns:EndpointInterface'>
   <soap:binding style='document' transport='http://schemas.xmlsoap.org/soap/http'/>
   <operation name='concat'>
      <soap:operation soapAction=''/>
      <input>
         <soap:body use='literal'/>
      </input>
      <output>
         <soap:body use='literal'/>
      </output>
   </operation>
</binding>
ドキュメントスタイルの Web サービスでは、 各メッセージのペイロードは XML スキーマでの複合タイプで定義されます。
<complexType name='concatType'>
   <sequence>
      <element name='String_1' nillable='true' type='string'/>
      <element name='long_1' type='long'/>
   </sequence>
</complexType>
<element name='concat' type='tns:concatType'/>
そのため、メッセージの部分はスキーマからの要素を参照しなければなりません。
<message name='EndpointInterface_concat'>
   <part name='parameters' element='tns:concat'/>
</message>
次のメッセージ定義は無効となります。
<message name='EndpointInterface_concat'>
   <part name='parameters' type='tns:concatType'/>
</message>

9.4. Document/Literal (Bare)

Bare とは Java ドメインからの実装詳細になります。 抽象 コントラクト (swdl+スキーマなど) 内や SOAP メッセージレベルでは bare エンドポイントは認識されません。 bare のエンドポイントまたはクライアントはドキュメントのペイロード全体を表す Java bean を使用します。
@WebService
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public class DocBareServiceImpl
{
   @WebMethod
   public SubmitBareResponse submitPO(SubmitBareRequest poRequest)
   {
      ...
   }
}
ペイロードを表している Java bean は JAXB アノテーションを含んでおり、 このアノテーションがメッセージ上でペイロードがどのように表されるかを定義しているのが要点になります。
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "SubmitBareRequest", namespace="http://soapbinding.samples.jaxws.ws.test.jboss.org/", propOrder = { "product" })
@XmlRootElement(namespace="http://soapbinding.samples.jaxws.ws.test.jboss.org/", name = "SubmitPO")
public class SubmitBareRequest
{
   @XmlElement(namespace="http://soapbinding.samples.jaxws.ws.test.jboss.org/",  required = true)
   private String product;

   ...
}

9.5. Document/Literal (Wrapped)

Wrapped とは Java ドメインからの実装詳細になります。 抽象 コントラクト (swdl+スキーマなど) 内や SOAP メッセージレベルでは wrapped エンドポイントは認識されません。 wrapped のエンドポイントやクライアントは個別のドキュメントペイロードプロパティを使用します。 wrapped はデフォルトであるため、 明示的に宣言する必要はありません。
@WebService
public class DocWrappedServiceImpl
{
   @WebMethod
   @RequestWrapper (className="org.somepackage.SubmitPO")
   @ResponseWrapper (className="org.somepackage.SubmitPOResponse")
   public String submitPO(String product, int quantity)
   {
   ...
   }
}

注記

JBossWS では、 要求および応答のラッパーアノテーションは必要ありません。目的にあったデフォルトを使用し要求に従い生成されます。

9.6. RPC/Literal

RPC ではエンドポイント操作に名前を付けるラッパー要素があります。 親 RPC の子要素は個別のパラメーターです。 SOAP ボディーは次のような簡単なルールによって構築されます。
  • ポートタイプ操作名がエンドポイントメソッド名を定義する。
  • メッセージ部分はエンドポイントメソッドパラメーターである。
TPC は SOAP バインディングのスタイル属性によって定義されます。
<binding name='EndpointInterfaceBinding' type='tns:EndpointInterface'>
   <soap:binding style='rpc' transport='http://schemas.xmlsoap.org/soap/http'/>
   <operation name='echo'>
      <soap:operation soapAction=''/>
      <input>
         <soap:body namespace='http://org.jboss.ws/samples/jsr181pojo' use='literal'/>
      </input>
      <output>
         <soap:body namespace='http://org.jboss.ws/samples/jsr181pojo' use='literal'/>
      </output>
   </operation>
</binding>
RPC スタイルの Web サービスでは、 portType が操作の名前を付けます (例: エンドポイント上の java メソッド)。
<portType name='EndpointInterface'>
   <operation name='echo' parameterOrder='String_1'>
      <input message='tns:EndpointInterface_echo'/>
      <output message='tns:EndpointInterface_echoResponse'/>
   </operation>
</portType>
個別のメッセージ部分によって操作パラメーターが定義されます。
<message name='EndpointInterface_echo'>
   <part name='String_1' type='xsd:string'/>
</message>
<message name='EndpointInterface_echoResponse'>
   <part name='result' type='xsd:string'/>
</message>

注記

SOAP メッセージペイロード全体を認証できる複雑なタイプは、 XML スキーマにはありません。
@WebService
@SOAPBinding(style = SOAPBinding.Style.RPC)
public class JSEBean01
{
   @WebMethod
   @WebResult(name="result")
   public String echo(@WebParam(name="String_1") String input)
   {
   ...
   }
}
RPC パラメーターの要素名は JAX-WS Annotations#javax.jws.WebParam、 RPC 戻り値の要素名は JAX-WS Annotations#javax.jws.WebResult を使用して定義することができます。

9.7. RPC/Encoded

SOAP エンコーディングスタイルは SOAP-1.1 仕様の 5 章により定義されます。相互運用性に関する固有の問題が存在し、これは修正ができません。Basic Profile-1.04.1.7 SOAP encodingStyle Attribute でこのエンコーディングスタイルを禁止しています。JBossWS は、RPC/Encoded に基本対応しています。これは、Literal エンコーディングに未対応のSOAP スタックとの簡単な相互運用シナリオに対し現状提供されています。具体的には、JBossWS は以下に対応しません。
  • 要素の参照
  • bean プロパティとしての soap 配列

注記

本項は、JBoss Web Services CXF スタックと連携する際に利用するべきではありません。

9.8. Web サービスのエンドポイント

JAX-WS は Web サービスエンドポイントの Web サービスエンドポイントの開発モデルを大幅に簡略化します。 エンドポイント実装 bean は JAX-WS アノテーションが付けられサーバーにデプロイされます。 サーバーは自動的にクライアントが消費する抽象コントラクトを (wsdl+スキーマなど) を生成して発行します。 すべてのマーシャルおよびアンマーシャルは JAXB に委任されます。

9.9. POJO (Plain old Java Object)

簡単な POJO エンドポイント実装を見てみましょう。 エンドポイントに関連するメタデータはすべて JSR-181 アノテーションより提供されます。
@WebService
@SOAPBinding(style = SOAPBinding.Style.RPC)
public class JSEBean01
{
   @WebMethod
   public String echo(String input)
   {
    ...
   }
}

9.10. Web アプリケーションとしてのエンドポイント

JAX-WS java サービスエンドポイント (JSE) は Web アプリケーションとしてデプロイされます。
<web-app ...>
   <servlet>
      <servlet-name>TestService</servlet-name>
      <servlet-class>org.jboss.test.ws.jaxws.samples.jsr181pojo.JSEBean01</servlet-class>
   </servlet>
   <servlet-mapping>
      <servlet-name>TestService</servlet-name>
      <url-pattern>/*</url-pattern>
   </servlet-mapping>
</web-app>

9.11. エンドポイントのパッケージ化

JSR-181 java サービスエンドポイント (JSE) は Web アプリケーションとして *.war ファイルにパッケージ化されます。
<war warfile="${build.dir}/libs/jbossws-samples-jsr181pojo.war" webxml="${build.resources.dir}/samples/jsr181pojo/WEB-INF/web.xml">
   <classes dir="${build.dir}/classes">
      <include name="org/jboss/test/ws/samples/jsr181pojo/JSEBean01.class"/>
   </classes>
</war>

注記

エンドポイント実装 bean と web.xml ファイルのみが必要となります。

9.12. 生成された WSDL にアクセス

正しくデプロイされたサービスエンドポイントはサービスエンドポイントマネージャーに表示されます。 サービスエンドポイントマネージャーには生成された WSDL へのリンクもあります。
http://yourhost:8080/jbossws/services
また、JBoss ツールを使用してオフラインで抽象コントラクトを生成することも可能です。詳細については Top Down (wsconsume の利用) を参照してください。

9.13. EJB3 ステートレスセッション Bean (SLSB)

JAX-WS プログラミングモデルはPlain old Java Object (POJO) のエンドポイント上と同じアノテーションセットを EJB3 ステートレスセッション bean でもサポートします。EJB-2.1 エンドポイントには JAX-RPC プログラミングモデルを使い対応しています。
@Stateless
@Remote(EJB3RemoteInterface.class)
@RemoteBinding(jndiBinding = "/ejb3/EJB3EndpointInterface")
   
@WebService
@SOAPBinding(style = SOAPBinding.Style.RPC)
public class EJB3Bean01 implements EJB3RemoteInterface
{
   @WebMethod
   public String echo(String input)
   {
   ...
   }
}
上記には、 リモートインターフェース上とエンドポイント操作上の両方で 1 つのメソッドを公開する EJB-3.0 ステートレスセッション bean があります。
エンドポイントのパッケージ化

JSR-181 EJB サービスのエンドポイントは通常の ejb デプロイメントとしてパッケージ化されます。

<jar jarfile="${build.dir}/libs/jbossws-samples-jsr181ejb.jar">
   <fileset dir="${build.dir}/classes">
      <include name="org/jboss/test/ws/samples/jsr181ejb/EJB3Bean01.class"/>
      <include name="org/jboss/test/ws/samples/jsr181ejb/EJB3RemoteInterface.class"/>
   </fileset>
</jar>
生成された WSDL にアクセス

正しくデプロイされたサービスエンドポイントはサービスエンドポイントマネージャーに表示されます。 サービスエンドポイントマネージャーには生成された WSDL へのリンクもあります。

  http://yourhost:8080/jbossws/services
また、JBossWS ツールを使用してオフラインで抽象コントラクトを生成することも可能です。 詳細については Top Down (wsconsumeを利用) を参照してください。

9.14. エンドポイントプロバイダー

JAX-WS のサービスは一般的にネイティブの Java サービスエンドポイントインターフェース (SEI) を実装し、 おそらく WSDL ポートタイプから直接あるいはアノテーションを使うことによってマッピングされます。
Java SEI は、 XML ベースのメッセージで使用するため Java オブジェクトとその XML 表記間で行われる変換の詳細を隠す Java 中心の高レベルの抽出を提供します。 ただし、 XML メッセージレベルでサービスの動作が可能となる方が望ましい場合もあります。 この場合プロバイダーインターフェースは SEI に代替を提供し、 XML メッセージレベルでの動作を好むサービスによる実装が可能になります。
Provider ベースのサービスインスタンスの呼び出しメソッドはサービスに対して受け取られる各メッセージごとに呼びだされます。
@WebServiceProvider
@ServiceMode(value = Service.Mode.PAYLOAD)
public class ProviderBeanPayload implements Provider<Source>
{
   public Source invoke(Source req)
   {
      // Access the entire request PAYLOAD and return the response PAYLOAD
   }
}
注記、 Service.Mode.PAYLOAD はデフォルトとなり、 明示的に宣言される必要はありません。 また、 Service.Mode.MESSAGE を使って SOAP 全体にアクセスすることもできます (MESSAGE で Provider は SOAP ヘッダーも見ることができます)。

9.15. WebServiceContext

WebServiceContext はエンドポイントが初期化される時点で設定できるインジェクションが可能リソースとして扱われます。 WebServiceContext オブジェクトは次に、 同じエンドポイントオブジェクト宛ての複数の要求処理に同時使用されているスレッド数に関係なく、 スレッドローカル情報を使用して正しい情報を返します。
@WebService
public class EndpointJSE
{
   @Resource
   WebServiceContext wsCtx;
 
   @WebMethod
   public String testGetMessageContext()
   {
      SOAPMessageContext jaxwsContext = (SOAPMessageContext)wsCtx.getMessageContext();
      return jaxwsContext != null ? "pass" : "fail";
   }
   ...
   @WebMethod
   public String testGetUserPrincipal()
   {
      Principal principal = wsCtx.getUserPrincipal();
      return principal.getName();
   }
  
   @WebMethod
   public boolean testIsUserInRole(String role)
   {
      return wsCtx.isUserInRole(role);
   }
}

9.16. Web サービスのクライアント

9.16.1. サービス

Service は WSDL サービスを表す抽象になります。 WSDL サービスは関連ポートの集合で、 それぞれが特定のプロトコルにバインドするポートタイプから構成されます。 また、特定のエンドポイントアドレスで使用可能になります。
ほとんどのクライアントの場合、 WSDL から生成されるスタブセットを使って開始します。 これらのうちのひとつはサービスになり、 そのサービスと動作させるためにそのクラスのオブジェクトを作成します (以下の 「静的な場合」 を参照)。

9.16.1.1. サービスの使用

静的な場合

ほとんどのクライアントは WSDL ファイルで開始し、 wsconsume のような jbossws ツールを使っていくつかのスタブを生成します。 これは通常、 膨大なファイル数となり、 そのうちのひとつがツリーのトップになります。 これがサービス実装クラスです。

生成される実装クラスは、1 つは引数なしでもうひとつは 2 つの引数を持ちそれぞれ wsdl の場所 (java.net.URL) とサービス名 (jvax.xml.namespace.QName) を表す 2 つのパブリックコンストラクターを持つことになると認識できます。
通常、 引数なしのコンストラクタを使用します。 この場合、 WSDL の場所とサービス名は WSDL にあります。 これらは生成されるクラスを修飾する WebServiceClient アノテーションから黙示的に設定されます。
次のコードスニペットは生成されたクラスから生成されるコンストラクターを示しています。
// Generated Service Class
  
@WebServiceClient(name="StockQuoteService", targetNamespace="http://example.com/stocks", wsdlLocation="http://example.com/stocks.wsdl")
public class StockQuoteService extends javax.xml.ws.Service 
{

   public StockQuoteService() 
   {
      super(new URL("http://example.com/stocks.wsdl"), new QName("http://example.com/stocks", "StockQuoteService"));
   }
  
   public StockQuoteService(String wsdlLocation, QName serviceName) 
   {
      super(wsdlLocation, serviceName);
   }
  
   ...
}
ダイナミックプロキシ の章には、サービスからのポート取得方法やポート上での操作の呼び出し方法について説明されています。XML ペイロードを直接作業する必要がある場合や SOAP メッセージ全体の XML 表記を作業する必要がある場合は、ディスパッチ をご覧ください。
動的な場合

動的な場合、 何も生成されないと Web サービスクライアントは Service.create を使って Service インスタンスを作成します。 次のコードでこのプロセスを示します。

URL wsdlLocation = new URL("http://example.org/my.wsdl");
QName serviceName = new QName("http://example.org/sample", "MyService");
Service service = Service.create(wsdlLocation, serviceName);
このような JBossWS の使用方法は推奨されていません。

9.16.1.2. ハンドラーリゾルバー

JAX-WS はハンドラーとして知られるメッセージ処理モジュール用の柔軟なプラグインフレームワークを提供しており、 JAX-WS ランタイムシステムの機能拡張に使用することができます。 Handler Framework ではハンドラーフレームワークについて詳細に説明されています。 Service インスタンスは、 サービス毎やポート毎、 プロトコルバインディング毎にハンドラーセットを設定することができる getHandlerResolver メソッドと setHandlerResolver メソッドのペアで HandlerResolver へのアクセスを提供します。
Service インスタンスがプロキシまたは Dispatch インスタンスの作成に使用されると、 現在そのサービスで登録されているハンドラーリゾルバーが要求されるハンドラーチェーンの作成に使用されます。続いて起こる Service インスタンス用に設定されるハンドラーリゾルバーへの変更は前に作成されたプロキシあるいは Dispatch のインスタンスにあるハンドラーには影響しません。

9.16.1.3. Executor

Service インスタンスは java.util.concurrent.Executor で設定することができます。 次にエグゼキューターを使ってアプリケーションが要求するすべての非同期のコールバックが呼び出されます。ServicesetExecutorgetExecutor のメソッドを使ってサービス用に設定されるエグゼキューターを編集して読み出すことができます。

9.16.2. 動的なプロキシ

ServicegetPort メソッドの 1 つを使ってクライアントプロキシのインスタンスを作成することができます。
/** 
 * The getPort method returns a proxy. A service client
 * uses this proxy to invoke operations on the target
 * service endpoint. The <code>serviceEndpointInterface</code>
 * specifies the service endpoint interface that is supported by
 * the created dynamic proxy instance.
 */
public <T> T getPort(QName portName, Class<T> serviceEndpointInterface)
{
...
}
  
/** 
 * The getPort method returns a proxy. The parameter
 * <code>serviceEndpointInterface</code> specifies the service
 * endpoint interface that is supported by the returned proxy.
 * In the implementation of this method, the JAX-WS
 * runtime system takes the responsibility of selecting a protocol
 * binding (and a port) and configuring the proxy accordingly.
 * The returned proxy should not be reconfigured by the client.
 *
 */
public <T> T getPort(Class<T> serviceEndpointInterface)
{
...
}
サービスエンドポイントインターフェース (SEI) は通常ツールを使って生成されます。 詳細については Top Down (Using wsconsume) を参照してください。
生成される静的な Service は通常、型指定されたメソッドも提供しポートを取得します。これらのメソッドは SEI を実装する動的なプロキシも返します。
@WebServiceClient(name = "TestEndpointService", targetNamespace = "http://org.jboss.ws/wsref", 
  wsdlLocation = "http://localhost.localdomain:8080/jaxws-samples-webserviceref?wsdl")
public class TestEndpointService extends Service
{
   ...
   
   public TestEndpointService(URL wsdlLocation, QName serviceName) {
      super(wsdlLocation, serviceName);
   }
   
   @WebEndpoint(name = "TestEndpointPort")
   public TestEndpoint getTestEndpointPort() 
   {
      return (TestEndpoint)super.getPort(TESTENDPOINTPORT, TestEndpoint.class);
   }
}

9.16.3. WebServiceRef

WebServiceRef アノテーションは Web サービスに対する参照の宣言に使用されます。 JSR-250 にある javax.annotation.Resource で範例されるリソースパターンに従います。
WebServiceRef アノテーションには 2 通りの使い方があります。
  1. タイプが生成されたサービスクラスである参照を定義します。 この場合、 タイプと値要素はいずれも生成されたサービスクラス型を参照します。 さらに、 その参照タイプがアノテーションが適用されるフィールド/メソッド宣言で推測できる場合、 タイプおよび値要素はデフォルトの値 (Object.class) とすることもできます。 タイプが推測できない場合は、 最低でもタイプ要素がデフォルト以外の値でなければなりません。
  2. タイプが SEI の参照を定義します。 この場合、 その参照タイプがアノテーションが付けられたフィールド/メソッド宣言から推測できればタイプ要素はデフォルトでも構いませんが、 値要素は常に存在しなければならず、生成されたサービスクラスタイプ (javax.xml.ws.Service のサブタイプ)を参照しなければなりません。 wsdlLocation 要素が存在する場合、 参照され生成されたサービスクラスの WebService アノテーションに指定された theWSDL の場所情報よりも優先されます。
public class EJB3Client implements EJB3Remote
{
   @WebServiceRef
   public TestEndpointService service4;
   
   @WebServiceRef
   public TestEndpoint port3;
}
WebServiceRef のカスタマイズ

JBoss Enterprise Application Platform 5.0 は WebServiceRef アノテーションへのオーバーライドや拡張を多数提供します。以下のようなものが含まれます。

  • コンテナ管理ポートを解決するために使用されるべきポートの定義
  • Stub オブジェクトに対するデフォルトの Stub プロパティ設定の定義
  • 最終的に使用される WSDL ドキュメントの URL 定義
例:
<service-ref>
   <service-ref-name>OrganizationService</service-ref-name>
   <wsdl-override>file:/wsdlRepository/organization-service.wsdl</wsdl-override>
</service-ref>
.. 
<service-ref>
   <service-ref-name>OrganizationService</service-ref-name>
   <config-name>Secure Client Config</config-name>
   <config-file>META-INF/jbossws-client-config.xml</config-file>
   <handler-chain>META-INF/jbossws-client-handlers.xml</handler-chain>
</service-ref>
  
<service-ref>
   <service-ref-name>SecureService</service-ref-name>
   <service-class-name>org.jboss.tests.ws.jaxws.webserviceref.SecureEndpointService</service-class-name>
   <service-qname>{http://org.jboss.ws/wsref}SecureEndpointService</service-qname>
   <port-info>
      <service-endpoint-interface>org.jboss.tests.ws.jaxws.webserviceref.SecureEndpoint</service-endpoint-interface>
      <port-qname>{http://org.jboss.ws/wsref}SecureEndpointPort</port-qname>
      <stub-property>
         <name>javax.xml.ws.security.auth.username</name>
         <value>kermit</value>
      </stub-property>
      <stub-property>
         <name>javax.xml.ws.security.auth.password</name>
         <value>thefrog</value>
      </stub-property>
   </port-info>
</service-ref>

9.16.4. Dispatch

XML Web サービスはサービスとサービスクライアント間の通信に XML メッセージを使用します。 高レベルの JAX-WS API は Java メソッド呼び出しとそれに対応する XML メッセージの変換詳細を隠すよう設計されていますが、 XML メッセージレベルでの動作が望ましい場合もあります。 Dispatch インターフェースはこのモードでの通信に対するサポートを提供しています。
Dispatch は 2 種類の使用モードに対応しています。 javax.xml.ws.Service.Mode.MESSAGEjavax.xml.ws.Service.Mode.PAYLOAD はそれぞれ次のように識別されます。
Message

このモードでは、 クライアントアプリケーションは直接プロトコル固有のメッセージ構造と動作します。 例、 SOAP プロトコルバインディングと併用する場合、 クライアントアプリケーションは直接 SOAP メッセージと動作します。

Message Payload

このモードでは、 クライアントアプリケーションはメッセージ自体ではなくメッセージのペイロードと動作します。 例、 SOAP プロトコルバインディングと併用する場合、 クライアントアプリケーションは SOAP メッセージ全体ではなく SOAP Body の内容と動作します。

Dispatch はクライアントが XML としてメッセージのペイロードまたはメッセージを構築し、 目的のメッセージまたはペイロードの構造の詳細な知識を必要とする低レベルの API になります。 Dispatch はあらゆるタイプのメッセージまたはメッセージペイロードの入出力に対応する汎用クラスになります。
Service service = Service.create(wsdlURL, serviceName);
Dispatch dispatch = service.createDispatch(portName, StreamSource.class, Mode.PAYLOAD);
  
String payload = "<ns1:ping xmlns:ns1='http://oneway.samples.jaxws.ws.test.jboss.org/'/>";
dispatch.invokeOneWay(new StreamSource(new StringReader(payload)));
  
payload = "<ns1:feedback xmlns:ns1='http://oneway.samples.jaxws.ws.test.jboss.org/'/>";
Source retObj = (Source)dispatch.invoke(new StreamSource(new StringReader(payload)));

9.16.5. 非同期の呼び出し

BindingProvider インターフェースはクライアントによる使用を目的としたプロトコルバインディングを提供するコンポーネントを表し、 プロキシによって実装、 Dispatch インターフェースによって拡張されます。
BindingProvider インスタンスは非同期の動作機能を提供することができます。 使用した場合、 動作が完了するとレスポンスコンテキストは更新されないなど、 呼び出し時に非同期の動作呼び出しが BindingProvider インスタンスから分離されます。 代わりに、 別のレスポンスコンテキストが Response インターフェースを使って利用できるようになります。
public void testInvokeAsync() throws Exception
{
   URL wsdlURL = new URL("http://" + getServerHost() + ":8080/jaxws-samples-asynchronous?wsdl");
   QName serviceName = new QName(targetNS, "TestEndpointService");
   Service service = Service.create(wsdlURL, serviceName);
   TestEndpoint port = service.getPort(TestEndpoint.class);
  
   Response response = port.echoAsync("Async");
  
   // access future
   String retStr = (String) response.get();
   assertEquals("Async", retStr);
}

9.16.6. Oneway 呼び出し

@Oneway は特定の Web メソッドが入力メッセージのみで出力をもたないことを示します。 一般的にone-way (一方向) メソッドは実際のビジネスメソッドを実行する前に、制御のスレッドを呼び出し元のアプリケーションに返します。
@WebService (name="PingEndpoint")
@SOAPBinding(style = SOAPBinding.Style.RPC)
public class PingEndpointImpl
{
   private static String feedback;
   ...
   @WebMethod
   @Oneway
   public void ping()
   {
      log.info("ping");
      feedback = "ok";
   }
   ...
   @WebMethod
   public String feedback()
   {
   log.info("feedback");
   return feedback;
   }
}

9.17. 共通 API

本項は Web サービスエンドポイントWeb サービスクライアント に同等に当てはまる概念について説明しています。

9.17.1. ハンドラーフレームワーク

ハンドラーフレームワークは JAX-WS プロトコルバインディングによってクライアントおよびサーバー側両方のランタイムで実装されます。 バインディングプロバイダーとして集合的に知られるプロキシおよび Dispatch インスタンスはそれぞれプロトコルバインディングを使ってその抽出機能を特定のプロトコルにバインドします。
クライアントおよびサーバー側ハンドラーはハンドラーチェーンとして知られる順序付けされた一覧に並べられます。 ハンドラーチェーン内のハンドラ群はメッセージが送信または受信される度に呼び出されます。 インバウンドメッセージはバインディングプロバイダー処理の前に処理されます。 アウトバウンドメッセージはあらゆるバインディングプロバイダー処理の後に処理されます。
ハンドラーは、 インバウンドメッセージとアウトバウンドメッセージにアクセスして編集、 およびプロパティセットの管理を行うメソッドを提供するメッセージコンテキストで呼び出されます。 メッセージコンテキストのプロパティはハンドラー間での通信やハンドラーとクライアントおよびサービス実装間での通信を容易にするために使用することができます。 異なるメッセージコンテキストタイプで異なるタイプのハンドラーが呼び出されます。

9.17.1.1. 論理ハンドラー

メッセージコンテキストプロパティおよびメッセージペイロードでのみ動作するハンドラです。 論理ハンドラーはプロトコルにとらわれないため、 メッセージのプロトコル固有部分には作用できません。 論理ハンドラーは javax.xml.ws.handler.LogicalHandler を実装するハンドラーになります。

9.17.1.2. プロトコルハンドラー

メッセージコンテキストプロパティおよびプロトコル固有メッセージでのみ動作するハンドラです。 プロトコルハンドラは特定のプロトコルに固有となるため、 メッセージのプロトコル特定部分にアクセスして変更することができます。 プロトコルハンドラーは javax.xml.ws.handler.LogicalHandler 以外の javax.xml.ws.handler.Handler から生じたあらゆるインターフェースを実装するハンドラーになります。

9.17.1.3. サービスエンドポイントのハンドラー

サービスエンドポイントで、 ハンドラーは @HandlerChain アノテーションを使って定義されます。
@WebService
@HandlerChain(file = "jaxws-server-source-handlers.xml")
public class SOAPEndpointSourceImpl
{
...
}
ハンドラーチェーンファイルの場所は 2 種類の形式に対応しています。
1. externalForm での完全な java.net.URL。 (例、 http://myhandlers.foo.com/handlerfile1.xml)
2. ソースファイルまたはクラスファイルからの相対パス。 (例、 bar/handlerfile1.xml)

9.17.1.4. サービスクライアントのハンドラー

クライアント側で、 ハンドラーは SEI で @HandlerChain アノテーションを使用して、 あるいは API を使って動的に設定することができます。
Service service = Service.create(wsdlURL, serviceName);
Endpoint port = (Endpoint)service.getPort(Endpoint.class);
  
BindingProvider bindingProvider = (BindingProvider)port;
List<Handler> handlerChain = new ArrayList<Handler>();
handlerChain.add(new LogHandler());
handlerChain.add(new AuthorizationHandler());
handlerChain.add(new RoutingHandler());
bindingProvider.getBinding().setHandlerChain(handlerChain); // important!

9.17.2. メッセージコンテキスト

MessageContext はすべての JAX-WS メッセージコンテキスト群のスーパーインターフェースになります。 追加のメソッドおよび定数で Map<String,Object> を拡張しハンドラーチェーン内のハンドラ群が一連の処理に関連する状態を共有できるようにするプロパティセットを管理します。 たとえば、 任意のハンドラーは、 そのハンドラーチェーン内の 1 つまたは複数の他のハンドラーが続いて get メソッド経由で取得する可能性のあるメッセージコンテキスト内に 1 プロパティを挿入するために put メソッドを使うことができます。
プロパティは APPLICATION または HANDLER としてスコープされます。 特定のエンドポイントに関連するすべてのハンドラーに対してすべてのプロパティを使用できます。 例えば、 論理ハンドラーがメッセージコンテキストにプロパティを挿入すると、 実行中チェーンのすべてのプロトコルハンドラーはそのプロパティを使用できます。 APPLICATION にスコープされたプロパティは、 クライアントアプリケーションやサービスエンドポイント実装に対しても使用できます。 プロパティのデフォルトスコープは HANDLER です。

9.17.2.1. メッセージコンテキストへのアクセス

ユーザーは、 @WebService アノテーションよりハンドラーまたはエンドポイントのメッセージコンテクストへアクセスすることができます。

9.17.2.2. 論理メッセージコンテキスト

LogicalMessageContext は呼び出し時に Logical Handlers へ渡されます。 LogicalMessageContext は、 メッセージペイロードを取得し変更するメソッドを用いて MessageContext を拡張し、 メッセージのプロトコル固有アスペクトへのアクセスは提供しません。 プロトコルバインディングは、 論理メッセージコンテキストより使用できるメッセージのコンポーネントを定義します。 SOAP バインディングは、 SOAP バインディングにデプロイされた論理ハンドラは SOAP ボディーの内容にはアクセス可能で、 SOAP ヘッダにはアクセスできないことを定義します。 XML/HTTP バインディングは、 論理ハンドラーがメッセージの XML ペイロード全体にアクセスできることを定義します。

9.17.2.3. SOAP メッセージコンテキスト

呼び出し時に SOAPMessageContext は SOAP handlers へ渡されます。 SOAPMessageContext は、 SOAP メッセージペイロードを取得し変更するメソッドを用いて MessageContext を拡張します。

9.17.3. 障害の処理

実装は SOAPFaultException をスローすることがあります。
public void throwSoapFaultException()
{
   SOAPFactory factory = SOAPFactory.newInstance();
   SOAPFault fault = factory.createFault("this is a fault string!", new QName("http://foo", "FooCode"));
   fault.setFaultActor("mr.actor");
   fault.addDetail().addChildElement("test");
   throw new SOAPFaultException(fault);
}
または、 アプリケーション固有のユーザー例外の場合は次のようになります。
public void throwApplicationException() throws UserException
{
   throw new UserException("validation", 123, "Some validation error");
}

注記

後者の場合、 JBossWS は必要な障害ラッパーの bean がデプロイの一部にない場合ランタイム時に生成します。

9.18. DataBinding

9.18.1. アノテーションが付けられていないクラスで JAXB を使用

JAXB は Java バインディングの Java アノテーションに大きく影響されます。 現在、 外部バインディング設定はサポートしていません。
これをサポートするため、 JAXBContext 作成中に RuntimeInlineAnnotationReader 実装を指定できる AXB RI 機能で構築しました (JAXBRIContext を参照)。
この機能は、「JAXB アノテーション導入」と呼ばれ、 通常消費のために使用することができます。 例えば、 SVN よりチェックアウトやビルド、あるいは 使用することができます。
詳細なドキュメントは次をご覧ください。

9.19. 添付

JBoss-WS4EE は SwA (SOAP with Attachments) と呼ばれる廃止された添付に依存しています。 SwA には WS-I Basic Profile では禁止されている soap/encoding を使用する必要があります。 JBossWS は WS-I AP 1.0と MTOM へのサポートを提供します。

9.19.1. MTOM/XOP

本セクションでは、 特定タイプのコンテンツを持つ XML 情報セットの連続化をより効率的に行う方法として Message Transmission Optimization Mechanism (MTOM) および XML-binary Optimized Packaging (XOP) について説明していきます。 関連する仕様は以下の通りです。

9.19.1.1. 対応 MTOM パラメータータイプ

image/jpeg
java.awt.Image
text/xml
javax.xml.transform.Source
application/xml
javax.xml.transform.Source
application/octet-stream
javax.activation.DataHandler
上記の表では対応エンドポイントパラメーターのタイプ一覧を示しています。 推奨される手段は javax.activation.DataHandler クラスを使用してバイナリデータをサービスエンドポイントパラメーターとして表す方法です。

注記

Microsoft エンドポイントはあらゆるデータを application/octet-stream として送信する傾向にあります。 この曖昧性に容易に対処できる唯一の Java タイプは javax.activation.DataHandler になります。

9.19.1.2. エンドポイントごとに MTOM を有効にする方法

サーバー側で、 MTOM 処理は@BindingType アノテーションで有効にされます。 JBossWS は SOAP1.1 および SOAP1.2 を処理します。 いずれも MTOM があってもなくても使用できます。
MTOM が有効化されたサービス実装
package org.jboss.test.ws.jaxws.samples.xop.doclit;
  
import javax.ejb.Remote;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.xml.ws.BindingType;
  
@Remote
@WebService(targetNamespace = "http://org.jboss.ws/xop/doclit")
@SOAPBinding(style = SOAPBinding.Style.DOCUMENT, parameterStyle = SOAPBinding.ParameterStyle.BARE)
@BindingType(value="http://schemas.xmlsoap.org/wsdl/soap/http?mtom=true")                         (1)
public interface MTOMEndpoint
{
...
}
  1. MTOM 有効の SOAP 1.1 バインディング ID
MTOM が有効化されたクライアント
Web サービスクライアントは前述と同じ方法を使用するか、 または MTOM の有効化を Binding API に依存することができます (org.jboss.test.ws.jaxws.samples.xop.doclit.XOPTestCase からの抜粋):
...
Service service = Service.create(wsdlURL, serviceName);
port = service.getPort(MTOMEndpoint.class);
  
// enable MTOM
binding = (SOAPBinding)((BindingProvider)port).getBinding();
binding.setMTOMEnabled(true);

注記

デプロイメントのデフォルト設定に JBossWS 設定テンプレートを使用します。

9.19.2. SwaRef

WS-I Attachment Profile 1.0swaRef 使って MIME 添付の部分を参照するメカニズムを定義します。 このメカニズムでは、 タイプ wsi:swaRef の XML 要素のコンテントは MIME 添付として送信され、 SOAP Body 内側の要素は RFC 2111 で定義されるように CID URI スキームでこの添付への参照を格納します。

9.19.2.1. SwaRef と JAX-WS エンドポイントを併用

JAX-WS エンドポイントはすべてのマーシャル/アンマーシャルを JAXB API に委任します。 DataHandler タイプに対して SwaRef エンコーディングを有効にする最もシンプルな方法は、 以下のようにペイロード bean に @XmlAttachmentRef アノテーションを付ける方法です。
/**
 * Payload bean that will use SwaRef encoding
 */
@XmlRootElement
public class DocumentPayload
{
   private DataHandler data;
  
   public DocumentPayload()
   {
   }
  
   public DocumentPayload(DataHandler data)
   {
      this.data = data;
   }
  
   @XmlElement
   @XmlAttachmentRef
   public DataHandler getData()
   {
      return data;
   }
  
   public void setData(DataHandler data)
   {
      this.data = data;
   }
}
エンドポイントをラップしたドキュメントでは、 サービスエンドポイントインターフェースで @XmlAttachmentRef アノテーションを指定することさえ可能です。
@WebService
public interface DocWrappedEndpoint
{
   @WebMethod
   DocumentPayload beanAnnotation(DocumentPayload dhw, String test);
  
   @WebMethod
   @XmlAttachmentRef
   DataHandler parameterAnnotation(@XmlAttachmentRef DataHandler data, String test);
  
}
次にメッセージは CID で添付部分を参照することになります。
<env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>
   <env:Header/>
   <env:Body>
      <ns2:parameterAnnotation xmlns:ns2='http://swaref.samples.jaxws.ws.test.jboss.org/'>
         <arg0>cid:0-1180017772935-32455963@ws.jboss.org</arg0>
         <arg1>Wrapped test</arg1>
      </ns2:parameterAnnotation>
   </env:Body>
</env:Envelope>

9.19.2.2. WSDL から開始

コントラクトから開始する方法を選択した場合は、 SwaRef エンコーディングを使用すべきあらゆる要素宣言が単純に wsi:swaRef スキーマタイプを参照することを確認する必要があります。
<element name="data" type="wsi:swaRef" 
xmlns:wsi="http://ws-i.org/profiles/basic/1.1/xsd"/>
いずれの wsi:swaRef スキーマタイプも次に DataHandler にマッピングされます。

9.20. ツール

JBossWS で提供される JAX-WS ツールはさまざまな方法で使用することができます。 まず、 サーバー側デプロイメントについて考察してからクライアントを見ていきます。 Web Service Endpoint (サーバー側) を開発する場合、 Java (bottom-up 開発) から開始するか、 サービスを定義する抽出コントラクト (WSDL) から開始するか (top-down 開発) を選択するオプションがあります。 これが新しいサービスなら (既存コントラクトがない) bottom-up の方が時間的に早くなり、 サービスが正しく起動して実行するようクラスにいくつかアノテーションを追加するだけになります。 しかし、 既に定義されているコントラクトがあるサービスを開発する場合は、 提供されているツールがアノテーション付きコードを生成するため top-down の方法を選択した方がずっと簡単になります。
Bottom-up を使用した場合:
  • すでに存在する EJB3 bean を Web Service として公開
  • 新しいサービスを提供する、 コントラクトの生成が必要
Top-down を使用した場合:
  • 旧式クライアントとの互換性を維持しながら既存 Web サービスの実装を置き換える
  • サードパーティによって指定されるコントラクトに適合するサービスを公開する (例:定義済みのプロトコルを使ってコールバックを行うベンダー)
  • 前もって手動で開発した WSDL と XML スキーマを厳守するサービスを作成する
次の JAX-WS コマンドラインツールが JBossWS に含まれています。
コマンド
内容
移植性のある JAX-WS アーチファクトを生成し、 抽象規定を提供します。 bottom-up 開発で使用されます。
抽象規定 (SWDL と Schema ファイル) を摂取して、 サーバーおよびクライアントの両方にアーチファクトを生成します。 top-down およびクライアント開発に使用されます。
JBossWS クラスパスを使って Java クライアント (1 つの main メソッドを持つ) を実行します。 

9.20.1. Bottom-Up (wsprovide を使用)

bottom-up の方法では使用するサービスに Java コードを開発してそれに JAX-WS アノテーションを付ける必要があります。 これらのアノテーションはサービス用に生成されるコントラクトのカスタマイズに使用できます。 たとえば、 マッピングするオペレーション名は何にしても構いません。 しかし、 アノテーションはすべて目的に合ったデフォルトを持つので、 @WebService アノテーションのみが必要になります。
次のように単一クラスを作成するなどできるだけシンプルにすることができます。
package echo;
  
@javax.jws.WebService
public class Echo
{
   public String echo(String input)
   {
      return input;
   }
}
JSE または EJB3 のデプロイメントはこのクラス使って構築することができるため、 JBossWS にデプロイが必要となる Java コードはこれのみになります。 WSDL および「ラッパークラス」と呼ばれるその他すべての Java アーチファクトはデプロイ時にユーザーによって生成されます。 これは JAX-WS の仕様外で、 オフラインツールを使用したラッパークラスの生成が必要となります。 これはベンダーの実装問題に対処するためで、開発者に対して一連の追加ステップによる負担をかけないようにするため生成しています。 ただし、 他のアプリケーションサーバーに対しても移植性のあるデプロイメントにしたい場合は、 ツールを使って生成されるクラスを追加する必要があります。
これが wsprovide ツールの主要な目的となり、 移植性のある JAX-WS アーチファクトを生成します。 さらに、 サービスに抽象規定 (WSDL ファイル) を「提供」するために使用することもできます。 「-w」オプションを使って wsprovide を呼び出して、これを取得することができます。
$ javac -d . -classpath jboss-jaxws.jar Echo.java
$ wsprovide -w echo.Echo
Generating WSDL:
EchoService.wsdl
Writing Classes:
echo/jaxws/Echo.class
echo/jaxws/EchoResponse.class
WSDL をよく見てみると EchoService という名前のサービスがわかります。
<service name='EchoService'>
   <port binding='tns:EchoBinding' name='EchoPort'>
      <soap:address location='REPLACE_WITH_ACTUAL_URL'/>
   </port>
</service>
期待通り、 このサービスはあるオペレーション、 「echo」を定義しています。
<portType name='Echo'>
   <operation name='echo' parameterOrder='echo'>
      <input message='tns:Echo_echo'/>
      <output message='tns:Echo_echoResponse'/>
   </operation>
</portType>

注記

JBossWS の開発時にはこのツールを実行する必要はないことを念頭においてください。 これは、 移植性のあるアーチファクトやサービス用の抽象規定を生成する場合にのみ必要になります。
JBoss Enterprise Application Platform 上にデプロイメントに対する POJO エンドポイントを作成してみましょう。 簡単な web.xml を作成する必要があります。
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
  
   <servlet>
      <servlet-name>Echo</servlet-name>
      <servlet-class>echo.Echo</servlet-class>
   </servlet>
  
   <servlet-mapping>
      <servlet-name>Echo</servlet-name>
      <url-pattern>/Echo</url-pattern>
   </servlet-mapping>
</web-app>
これで web.xml および単一クラスを使用して WAR を作成できるようになりました。
$ mkdir -p WEB-INF/classes
$ cp -rp echo WEB-INF/classes/
$ cp web.xml WEB-INF
$ jar cvf echo.war WEB-INF
added manifest
adding: WEB-INF/(in = 0) (out= 0)(stored 0%)
adding: WEB-INF/classes/(in = 0) (out= 0)(stored 0%)
adding: WEB-INF/classes/echo/(in = 0) (out= 0)(stored 0%)
adding: WEB-INF/classes/echo/Echo.class(in = 340) (out= 247)(deflated 27%)
adding: WEB-INF/web.xml(in = 576) (out= 271)(deflated 52%)
次に war をデプロイします。
 cp echo.war <replaceable>$JBOSS_HOME</replaceable>/server/default/deploy
JBossWS はデプロイ時に内部的に wsprovide を呼び出し、 WSDL を生成します。 デプロイメントに成功すれば、 デフォルトの設定を使用していることになり、 http://localhost:8080/echo/Echo?wsdl にあるはずです。
移植性のある JAX-WS デプロイメントの場合、 先に生成されるラッパークラスをデプロイメントに追加することができます。

9.20.2. Top-Down (wsconsume を使用)

top-down の開発はサービスの抽象規定で開始し、 これは WSDL ファイルおよび 0 またはそれ以上のスキーマファイルを含みます。 wsconsume ツールは次にこの規定を消費するため使用され、 それを定義するアノテーションが付けられた Java クラス (およびオプションでソース) を生成します。

注記

wsconsume は Unix システム上の symlinks との動作には問題があるようです。
bottom-up の例から WSDL ファイルを使用して、 このサービスを厳守する新しい Java 実装を生成することが可能です。 「-k」オプションは単にクラスを提供するだけではなく、 生成される Java ソースファイルを維持するために wsconsume に渡されます。
  
$ wsconsume -k EchoService.wsdl
echo/Echo.java
echo/EchoResponse.java
echo/EchoService.java
echo/Echo_Type.java
echo/ObjectFactory.java
echo/package-info.java
echo/Echo.java
echo/EchoResponse.java
echo/EchoService.java
echo/Echo_Type.java
echo/ObjectFactory.java
echo/package-info.java
次の表では各生成ファイルの目的を示します。
ファイル
目的
Echo.java
Service Endpoint Interface
Echo_Type.java
要求メッセージに対するラッパー bean
EchoResponse.java
レスポンスメッセージに対するラッパー bean
ObjectFactory.java
JAXB XML レジストリ
package-info.java
JAXB パッケージアノテーションのホルダー
EchoService.java
JAX-WS クライアントによってのみ使用される
Service Endpoint Interface をよく見てみると、 同じコントラクトに対して評価するのに、 bottom-up の例での手動で記述されたクラスにあるアノテーションより明示的であるのに気づくはずです。
@WebService(name = "Echo", targetNamespace = "http://echo/")
public interface Echo
{
   @WebMethod
   @WebResult(targetNamespace = "")
   @RequestWrapper(localName = "echo", targetNamespace = "http://echo/", className = "echo.Echo_Type")
   @ResponseWrapper(localName = "echoResponse", targetNamespace = "http://echo/", className = "echo.EchoResponse")
   public String echo(@WebParam(name = "arg0", targetNamespace = "") String arg0);
}
ここにないのは (パッケージング以外) その実装クラスのみで、 上記のインターフェースを使って記述することができます。
package echo;
  
@javax.jws.WebService(endpointInterface="echo.Echo")
public class EchoImpl implements Echo
{
   public String echo(String arg0)
   {
      return arg0;
   }
}

9.20.3. クライアント側

クライアント側について詳細に説明する前に、Web サービスの中心となる分離の概念を理解することが重要となります。このような方法で利用可能ですが、Web サービスは内部 RPC に対して最も適応しているわけではなく、これに関しては (CORBA や RMI など)さらに優れた技術が存在します。Web サービスは相互運用性のある粗粒子の通信向けに開発されています。Web サービスのやりとりを行うパーティシパントが、特定の場所で特定のオペレーティングシステムを使用し、もしくは特定のプログラミング言語で記述されているとの前提、保証はありません。そのため、 クライアントとサーバーの実装を明確に分離することが重要となります。 抽象コントラクトの定義のみを共通になるようにするだけでいいのです。何らかの理由でソフトウェアがこの原理に従わない場合は、Web サービスを使用すべきではありません。 このような理由により、クライアントが同じサーバーで稼働している場合でも、クライアントの開発技法としてトップダウンアプローチを用いることが推奨されます。
wsprovide によってオフラインで生成されたものではなくデプロイされた WSDL を使用して、 トップダウンの項のプロセスを再度確認してみましょう。soap:address に対する正しい値を取得するためだけにこれを実行します。 この値はコンテナ設定の内容が基になるため、 デプロイ時に算出されなければなりません。WSDL ファイルを編集することもできますが、 パスが正しくなるよう注意してください。
オフラインバージョン:
<service name='EchoService'>
   <port binding='tns:EchoBinding' name='EchoPort'>
      <soap:address location='REPLACE_WITH_ACTUAL_URL'/>
   </port>
</service>
オンラインバージョン:
<service name="EchoService">
   <port binding="tns:EchoBinding" name="EchoPort">
      <soap:address location="http://localhost.localdomain:8080/echo/Echo"/>
   </port>
</service>
wsconsume を用いてオンラインでデプロイしたバージョンを使用する:
$ wsconsume -k http://localhost:8080/echo/Echo?wsdl
echo/Echo.java
echo/EchoResponse.java
echo/EchoService.java
echo/Echo_Type.java
echo/ObjectFactory.java
echo/package-info.java
echo/Echo.java
echo/EchoResponse.java
echo/EchoService.java
echo/Echo_Type.java
echo/ObjectFactory.java
echo/package-info.java
EchoService.java は top-down セクションでは確認しなかったクラスでした。 WSDL の取得先となる場所を格納する方法に注目してください。
@WebServiceClient(name = "EchoService", targetNamespace = "http://echo/", wsdlLocation = "http://localhost:8080/echo/Echo?wsdl")
public class EchoService extends Service
{
   private final static URL ECHOSERVICE_WSDL_LOCATION;
  
   static
   {
      URL url = null;
      try
      {
         url = new URL("http://localhost:8080/echo/Echo?wsdl");
      }
      catch (MalformedURLException e)
      {
         e.printStackTrace();
      }
      ECHOSERVICE_WSDL_LOCATION = url;
   }
  
   public EchoService(URL wsdlLocation, QName serviceName)
   {
      super(wsdlLocation, serviceName);
   }
  
   public EchoService()
   {
      super(ECHOSERVICE_WSDL_LOCATION, new QName("http://echo/", "EchoService"));
   }
  
   @WebEndpoint(name = "EchoPort")
   public Echo getEchoPort()
   {
      return (Echo)super.getPort(new QName("http://echo/", "EchoPort"), Echo.class);
   }
}
ご覧のように、 上記は JAX-WS、 javax.xml.ws.Service 内のメインクライアントエントリポイントを拡張するクラスを生成しました。 Service を直接使用できる一方、 設定情報を提供してくれるためこちらの方がずっと簡単になります。 本当に注意しなければならないメソッドは getEchoPort() メソッドのみで、 Service Endpoint Interface のインスタンスを返します。 これであらゆる WS オペレーションが返されるインターフェースでメソッドを呼び出すだけで呼び出し可能になります。

注記

実稼働アプリケーションでリモート WSDL URL へ参照することは推奨されません。 参照すると Service Object をインスタンス化する度にネットワーク I/O が発生するためです。 保存したローカルコピーに対してツールを使用するか、 URL バージョンのコンストラクタを使用して新しい WSDL の場所を提供するようにします。
あとはクライアントを記述してコンパイルするだけです。
import echo.*;
..
public class EchoClient
{
   public static void main(String args[])
   {
      if (args.length != 1)
      {
         System.err.println("usage: EchoClient <message>");
         System.exit(1);
      }
  
      EchoService service = new EchoService();
      Echo echo = service.getEchoPort();
      System.out.println("Server said: " + echo.echo(args[0]));
   } 
}
これで wsrunclient ツールを使って簡単に実行できるようになります。 これは必要なクラスパスで java を呼び出す便利なツールです。
$ wsrunclient EchoClient 'Hello World!'
Server said: Hello World!
起動時のオペレーションのエンドポイントアドレス変更は簡単です。 以下のように ENDPOINT_ADDRESS_PROPERTY を設定します。
...
EchoService service = new EchoService();
Echo echo = service.getEchoPort();
  
/* Set NEW Endpoint Location */
String endpointURL = "http://NEW_ENDPOINT_URL";
BindingProvider bp = (BindingProvider)echo;
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointURL);
  
System.out.println("Server said: " + echo.echo(args[0]));
...

9.20.4. コマンドライン & Ant タスク参照

9.20.5. JAX-WS バインディングのカスタマイズ

バインディングカスタマイズの導入
バインディングカスタマイズのファイル用スキーマは次をご覧ください。

9.21. Web サービスの拡張

9.21.1. WS-Addressing

本項では、 WS-Addressing を使用してステートフルサービスのエンドポイントを提供する方法について説明しています。

9.21.1.1. 仕様

WS-Addressing は W3C Candidate Recommendation 17 August 2005 にある次の仕様の組み合わせで定義されます。 WS-Addressing API は JSR-224 - Java API for XML-Based Web Services (JAX-WS) で標準化されます。

9.21.1.2. エンドポイントの処理

注記

以下の情報は、JBoss Web Services CXF スタックと併用するべきではありません。
次のエンドポイント実装はステートフルの一般的なショッピングカートアプリケーション用のオペレーションセットを持っています。
@WebService(name = "StatefulEndpoint", targetNamespace = "http://org.jboss.ws/samples/wsaddressing", serviceName = "TestService")
@Addressing(enabled=true, required=true)
@SOAPBinding(style = SOAPBinding.Style.RPC)
public class StatefulEndpointImpl implements StatefulEndpoint, ServiceLifecycle
{
   @WebMethod
   public void addItem(String item)
   { ... }
  
   @WebMethod
   public void checkout()
   { ... }
  
   @WebMethod
   public String getItems()
   { ... }
}
JAX-WS 2.1 で定義された javax.xml.ws.soap.Addressing アノテーションを使用してサーバー側のアドレッシングハンドラーを有効にします。

9.21.1.3. クライアントの処理

クライアントは JAX-WS 2.1 API の javax.xml.ws.soap.AddressingFeature を使用して WS-Addressing を有効にします。
Service service = Service.create(wsdlURL, serviceName);
port1 = (StatefulEndpoint)service.getPort(StatefulEndpoint.class,  new AddressingFeature());
ステートフルエンドポイントに接続しているクライアント
public class AddressingStatefulTestCase extends JBossWSTest
{
   ...
   public void testAddItem() throws Exception
   {
      port1.addItem("Ice Cream");
      port1.addItem("Ferrari");
  
      port2.addItem("Mars Bar");
      port2.addItem("Porsche");
   }
  
   public void testGetItems() throws Exception
   {
      String items1 = port1.getItems();
      assertEquals("[Ice Cream, Ferrari]", items1);
  
      String items2 = port2.getItems();
      assertEquals("[Mars Bar, Porsche]", items2);
   }
}
SOAP メッセージの交換
以下で交換されている SOAP メッセージを確認できます。
<env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>
<env:Header xmlns:wsa='http://schemas.xmlsoap.org/ws/2004/08/addressing'>
<wsa:To>uri:jbossws-samples-wsaddr/TestService</wsa:To>
<wsa:Action>http://org.jboss.ws/addressing/stateful/action</wsa:Action>
<wsa:ReferenceParameters>
<ns1:clientid xmlns:ns1='http://somens'>clientid-1</ns1:clientid>
</wsa:ReferenceParameters>
</env:Header>
<env:Body>
<ns1:addItem xmlns:ns1='http://org.jboss.ws/samples/wsaddr'>
<String_1>Ice Cream</String_1>
</ns1:addItem>
</env:Body>
</env:Envelope>
  
<env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>
<env:Header xmlns:wsa='http://schemas.xmlsoap.org/ws/2004/08/addressing'>
<wsa:To>http://www.w3.org/2005/08/addressing/anonymous</wsa:To>
<wsa:Action>http://org.jboss.ws/addressing/stateful/actionReply</wsa:Action>
<ns1:clientid xmlns:ns1='http://somens'>clientid-1</ns1:clientid>
</env:Header>
<env:Body>
<ns1:addItemResponse xmlns:ns1='http://org.jboss.ws/samples/wsaddr'/>
</env:Body>
</env:Envelope>
  
...
  
<env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>
<env:Header xmlns:wsa='http://schemas.xmlsoap.org/ws/2004/08/addressing'>
<wsa:To>uri:jbossws-samples-wsaddr/TestService</wsa:To>
<wsa:Action>http://org.jboss.ws/addressing/stateful/action</wsa:Action>
<wsa:ReferenceParameters>
<ns1:clientid xmlns:ns1='http://somens'>clientid-1</ns1:clientid>
</wsa:ReferenceParameters>
</env:Header>
<env:Body>
<ns1:getItems xmlns:ns1='http://org.jboss.ws/samples/wsaddr'/>
</env:Body>
</env:Envelope>
  
<env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>
<env:Header xmlns:wsa='http://schemas.xmlsoap.org/ws/2004/08/addressing'>
<wsa:To>http://www.w3.org/2005/08/addressing/anonymous</wsa:To>
<wsa:Action>http://org.jboss.ws/addressing/stateful/actionReply</wsa:Action>
<ns1:clientid xmlns:ns1='http://somens'>clientid-1</ns1:clientid>
</env:Header>
<env:Body>
<ns1:getItemsResponse xmlns:ns1='http://org.jboss.ws/samples/wsaddr'>
<result>[Ice Cream, Ferrari]</result>
</ns1:getItemsResponse>
</env:Body>
</env:Envelope>

9.21.2. WS-Security

WS-Security はメッセージレベルのセキュリティを処理します。承認、暗号化、Web サービスのデジタル署名処理の標準化を行います。SSL などのトランスポートセキュリティモデルとは異なり、WS-Security はセキュリティを直接 Web サービスメッセージの要素に適用します。結果、あらゆるメッセージモデル (ポイントツーポイント、マルチホップリレーなど) が使用できるようになるため ご利用中のWeb サービスの柔軟性が向上されます。
本章ではシンプルな SOAP メッセージの署名と暗号化を行うため WS-Security の使用方法を説明します。
仕様
WS-Security は次の仕様の組み合わせで定義されます。

9.21.2.1. エンドポイント設定

JBoss WS はハンドラーを使用して WS-security でエンコード化されたリクエストを識別しセキュリティコンポーネントを呼び出すことでメッセージの署名と暗号化を行います。セキュリティ処理を可能にするため、クライアントおよびサーバー側は該当するハンドラー設定を含む必要があります。事前定義されている JAX-WS Endpoint Configuration または JAX-WS Client Configuration をそれぞれ参照することが推奨されます。

注記

エンドポイント設定と WSSE 宣言の両方を設定する必要があります。個別に設定していきます。

9.21.2.2. サーバー側 WSSE 宣言 (jboss-wsse-server.xml)

この例ではメッセージボディを署名するためクライアントおよびサーバーの両方を設定しています。 また、 クライアントとサーバーはいずれも相手からこれを必要とします。 このため、 クライアントまたはサーバーいずれかのセキュリティ配備記述子を削除すると、もう一方がそのメッセージは正しいセキュリティ要件を満たしていなかったことを伝える障害を送出するのがわかります。
<jboss-ws-security xmlns="http://www.jboss.com/ws-security/config" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.jboss.com/ws-security/config 
http://www.jboss.com/ws-security/schema/jboss-ws-security_1_0.xsd">
(1)  <key-store-file>WEB-INF/wsse.keystore</key-store-file>
(2)  <key-store-password>jbossws</key-store-password>
(3)  <trust-store-file>WEB-INF/wsse.truststore</trust-store-file>
(4)  <trust-store-password>jbossws</trust-store-password>
(5)  <config>
(6)     <sign type="x509v3" alias="wsse"/>
(7)     <requires>
(8)        <signature/>
        </requires>
     </config>
</jboss-ws-security>
  1. これは、使用したいキーストアは war ファイルにある WEB-INF/wsse.keystore であることを指定します。
  2. ストアパスワードは「jbossws」であることを指定しています。 パスワードは {EXT} と {CLASS} のコマンドを使って暗号化することができます。 使用方法についてはサンプルをご覧ください。
  3. これは、使用したいキーストアは war ファイルにある WEB-INF/wsse.truststore であることを指定します。
  4. 信頼できるストアパスワードも「jbossws」であることを指定しています。 パスワードは {EXT} と {CLASS} のコマンドを使って暗号化することができます。 使用方法についてはサンプルをご覧ください。
  5. root config ブロックはここから開始します。 root config ブロックはこの war ファイル内のすべてのサービスに対してデフォルト設定となります。
  6. サーバーはすべてのレスポンスのメッセージボディに署名しなければならないという意味になります。 Type は X.509v3 証明書 (標準の証明書) を使用しているという意味です。 エイリアスオプションは、 署名に使用する証明書とキーの組み合わせは「wsse」エイリアス配下のキーストアにあることを示しています。
  7. オプションの requires ブロックはここから開始します。 このブロックはサーバーがメッセージを受信するときに満たされる必要のある全セキュリティ要件を指定します。
  8. この war ファイル内の Web サービスはすべて署名すべきメッセージボディを必要とします。
デフォルトではエンドポイントは WS-Security 設定を使用しません。 専用の @EndpointConfig アノテーションを使って設定名を指定します。 使用できる設定名の一覧は JAX-WS_Endpoint_Configuration をご覧ください。
@WebService
@EndpointConfig(configName = "Standard WSSecurity Endpoint")
public class HelloJavaBean
{
...
}

9.21.2.3. クライアント側 WSSE 宣言 (jboss-wsse-client.xml)

<jboss-ws-security xmlns="http://www.jboss.com/ws-security/config" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.jboss.com/ws-security/config 
http://www.jboss.com/ws-security/schema/jboss-ws-security_1_0.xsd">
(1)  <config>
(2)     <sign type="x509v3" alias="wsse"/>
(3)     <requires>
(4)        <signature/>
        </requires>
     </config>
</jboss-ws-security>
  1. root config ブロックはここから開始します。 root config ブロックはすべての Web サービスクライアントに対してデフォルトの設定となります (Call、 Proxy オブジェクト)。
  2. クライアントは送信するすべての要求のメッセージボディに署名しなければならないという意味になります。 Type は X.509v3 証明書 (標準の証明書) を使用しようとしていることを意味します。 エイリアスオプションは署名に使用する証明書とキーの組み合わせが「wsse」エイリアス配下のキーストアにあることを示しています。
  3. オプションの requires ブロックはここから開始します。 このブロックはクライアントがレスポンスを受信するときに満たされなければならない全セキュリティ要件を指定します。
  4. すべての Web サービスクライアントは署名されているレスポンスメッセージを受信しなければならないという意味になります。
9.21.2.3.1. クライアント側キーストアの設定
クライアントアプリケーションは代わりに wsse System プロパティを使用するため、 キーストアや信頼できるストアは指定しませんでした。 これが Web または ejb クライアントの場合なら (war ファイルまたは ejb ファイル内の webservice クライアントの意)、クライアントの記述子にこれらを指定することになります。
以下に JBoss WS の例からの抜粋を示します。
<sysproperty key="org.jboss.ws.wsse.keyStore"
value="${tests.output.dir}/resources/jaxrpc/samples/wssecurity/wsse.keystore"/>
<sysproperty key="org.jboss.ws.wsse.trustStore" 
value="${tests.output.dir}/resources/jaxrpc/samples/wssecurity/wsse.truststore"/>
<sysproperty key="org.jboss.ws.wsse.keyStorePassword" value="jbossws"/>
<sysproperty key="org.jboss.ws.wsse.trustStorePassword" value="jbossws"/>
<sysproperty key="org.jboss.ws.wsse.keyStoreType" value="jks"/>
<sysproperty key="org.jboss.ws.wsse.trustStoreType" value="jks"/>
SOAP メッセージの交換
下記には、 セキュリティヘッダーの詳細が省略されている受信 SOAP メッセージがあります。 SOAP ボディは平文のままですがセキュリティヘッダーが署名されているため送信中に操作されないという仕組みです。
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header>
<wsse:Security env:mustUnderstand="1" ...>
<wsu:Timestamp wsu:Id="timestamp">...</wsu:Timestamp>
<wsse:BinarySecurityToken ...>
...
</wsse:BinarySecurityToken>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
...
</ds:Signature>
</wsse:Security>
</env:Header>
<env:Body wsu:Id="element-1-1140197309843-12388840" ...>
<ns1:echoUserType xmlns:ns1="http://org.jboss.ws/samples/wssecurity">
<UserType_1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<msg>Kermit</msg>
</UserType_1>
</ns1:echoUserType>
</env:Body>
</env:Envelope>

9.21.2.4. BouncyCastle JCE プロバイダーのインストール

下記の情報は オリジナルはThe Legion of the Bouncy Castle より提供されています。
java.security プロパティファイルにエントリを追加すると静的登録よりプロバイダーを環境の一部として設定することができます。 java.security プロパティセキュリティファイルは、 $JAVA_HOME/jre/lib/security/java.security にあります ($JAVA_HOME は JDK および JRE ディストリビューションの場所に置き換えます)。 このファイルに詳細手順が記載されていますが、 主に次の行を追加することになります。
security.provider.<n>=org.bouncycastle.jce.provider.BouncyCastleProvider
<n> はプロバイダーを配置したい場所になります。

注記

Sun 提供のプロバイダーが 1 番目にならないと問題が発生する可能性があります。
プロバイダー jar を格納する場所はユーザーが決めることができますが、 jdk5 の場合は $JAVA_HOME/jre/lib/ext に格納するのがよいでしょう。 ウインドウの下は通常 Java の JRE インストールと JDK インストールになるはずです。 正しくインストールされたにも拘らず動作しない場合は、プロバイダーインストールが使用されていない可能性が高いでしょう。

9.21.2.5. Username Token 認証JBOSSCC-50

Username Token を使ってクライアントを認証する必要がある場合、JAAS 統合は受け取ったトークンと設定済みのJBoss JAAS セキュリティドメインを照合します。

例9.1 ユーザー名トークンの基本設定

この機能を実装するには、<jboss-ws-security>要素を以下の情報を含んだjboss-wsse-client.xml に貼り付ける必要があります。
<jboss-ws-security xmlns="http://www.jboss.com/ws-security/config"
                         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                         xsi:schemaLocation="http://www.jboss.com/ws-security/config 
                         http://www.jboss.com/ws-security/schema/jboss-ws-security_1_0.xsd">
     <config>
(1)    <username/>
(2)    <timestamp ttl="300"/>
     </config>
</jboss-ws-security>
2 行目では、メッセージ内に<timestamp> 要素が存在していなければならず、そのメッセージは300秒よりも古くてはいけないと、指定しています。時間の制限 (秒) を使ってリプレイ攻撃を回避します。
その後、両方のヘッダーが一致するように、jboss-wsse-server.xml ファイルにて同じ<timestamp> 要素と seconds 属性を指定する必要があります。また、<requires/> 要素を指定しこの条件を強化する必要があります。
<jboss-ws-security xmlns="http://www.jboss.com/ws-security/config"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://www.jboss.com/ws-security/config
                   http://www.jboss.com/ws-security/schema/jboss-ws-security_1_0.xsd">
     <config>
          <timestamp ttl="300"/>
          <requires/>
     </config>
</jboss-ws-security>

警告

この設定例では、シンプルテキストのユーザー情報がSOAPヘッダで送信されることになります。JBossWS Secure Transportの実装を検討してください。
パスワードダイジェスト、Nonce、タイムスタンプ

例9.1「ユーザー名トークンの基本設定」では、平文としてクライアントのパスワードが送信されます。さらにリプレイ攻撃から保護されるようダイジェストパスワードnonceタイムスタンプの組み合わせを使うことが可能です。

パスワードダイジェストを有効にするには、例9.2「パスワードダイジェストの有効化」で説明されているように以下の項目を実装する必要があります:

例9.2 パスワードダイジェストの有効化

jboss-wsse-client.xml ファイルの<username> 要素にて:
  • digestPassword 属性を有効化
  • nonces および timestampsを有効化
<jboss-ws-security xmlns="http://www.jboss.com/ws-security/config"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.jboss.com/ws-security/config
    http://www.jboss.com/ws-security/schema/jboss-ws-security_1_0.xsd">
  <config>
(3)     <username digestPassword="true" useNonce="true" useCreated="true"/>
       <timestamp ttl="300"/>
  </config>
</jboss-ws-security>
また、login-config.xml ファイルで、Username Token モジュールオプションを実装する必要があります。

例9.3 UsernameTokenCallback モジュール

<application-policy name="JBossWSDigest">
  <authentication>
    <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required">
      <module-option name="usersProperties">META-INF/jbossws-users.properties</module-option>
      <module-option name="rolesProperties">META-INF/jbossws-roles.properties</module-option>
      <module-option name="hashAlgorithm">SHA</module-option>
      <module-option name="hashEncoding">BASE64</module-option>
      <module-option name="hashUserPassword">false</module-option>
      <module-option name="hashStorePassword">true</module-option>
      <module-option name="storeDigestCallback">org.jboss.ws.extensions.security.auth.callback.UsernameTokenCallback</module-option>
      <module-option name="unauthenticatedIdentity">anonymous</module-option>
    </login-module>
  </authentication>
</application-policy>
より高度なカスタムのログインモジュールを使い、リプレイ攻撃に対するセキュリティを高めたい場合があるかもしれません。以下を実装していると、ご自身のカスタムログインモジュールを利用することができます。
  • UsernameTokenCallback コールバックをログインモジュールにプラグします。
  • org.jboss.security.auth.spi.UsernamePasswordLoginModuleを継承します。
  • 例9.3「UsernameTokenCallback モジュール」で示されているように、ハッシュ属性 (hashAlgorithmhashEncodinghashUserPasswordhashStorePassword)を設定します。
拡張調整:Nonce ファクトリ

Nonce が作成され、その後サーバー側でチェック、格納される方法により、リプレイ攻撃に対するセキュリティレベルが左右されます。現在、JBossWS では、サーバー側で受け取ったトークンをキャッシュ化しないという Nonce ストアの基本実装が同梱されています。

NonceFactoryNonceStoreインターフェースを実装することでご利用中のモジュールにより複雑な実装をプラグすることができます。これらのインターフェースorg.jboss.ws.extensions.security.nonceパッケージにあります。
これらのインターフェースを含めると、jboss-wsse-server.xml ファイルの<nonce-factory-class> 要素を使ってご利用中のファクトリクラスを指定します。
拡張調整:タイムスタンプの検証

wsse:Security ヘッダーに Timestamp がある場合、ヘッダー検証にあたり時間比較における誤差の許容範囲はありません。メッセージが少しでも未来の時間に作成されている場合、メッセージの有効期限が切れている場合は拒否されます。 <timestamp-verification>と呼ばれる新しい要素が wsse 設定では利用可能です。例9.4「<timestamp-verification> 設定」 では、<timestamp-verification>要素に必要な属性について説明しています。

例9.4 <timestamp-verification> 設定

<timestamp-verification> 要素属性により、'Timestamp' ヘッダーの'Created' あるいは 'Expires' 要素を検証時に利用する許容範囲 (秒) を指定できます。
<jboss-ws-security xmlns='http://www.jboss.com/ws-security/config'
                   xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
                   xsi:schemaLocation='http://www.jboss.com/ws-security/config     
                   http://www.jboss.com/ws-security/schema/jboss-ws-security_1_0.xsd'>
  <timestamp-verification createdTolerance="5" warnCreated="false" expiresTolerance="10" warnExpires="false" />
</jboss-ws-security>
createdTolerance
どの程度先のメッセージであれば承認されるか、その秒数。デフォルト値は 0 になります。
expiresTolerance
Expired と分類されてからメッセージが拒否されるまでの秒数。デフォルト値は 0 になります。
warnCreated
'Created' が未来の値のメッセージを承認した場合、警告メッセージをログに残すかどうかを指定します。デフォルト値は、trueです。
warnExpires
'Expired' の値が過去のメッセージを承認した場合、警告メッセージをログに残すかどうかを指定します。デフォルト値は、trueです。

注記

warnCreated および warnExpires属性を使い、通常は拒否されているメッセージで承認したものを特定することができます。このデータを使うことで、クライアントのメッセージを拒否することなしにサーバータイムと同期されていないクライアントを特定することができます。
9.21.2.5.1. セキュアトランスポート

9.21.2.6. X509 Certificate Token

X509v3 証明書を使うことで、メッセージの署名と暗号化を両方行うことができます。
暗号化

暗号化の設定には、例9.5「X509 暗号化設定」の項目を指定する必要があります。クライアント、サーバーともに同じ設定となります。

例9.5 X509 暗号化設定

<jboss-ws-security xmlns="http://www.jboss.com/ws-security/config"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://www.jboss.com/ws-security/config
                   http://www.jboss.com/ws-security/schema/jboss-ws-security_1_0.xsd">
(1) <key-store-file>WEB-INF/bob-sign_enc.jks</key-store-file>
    <key-store-password>password</key-store-password>
    <key-store-type>jks</key-store-type>
    <trust-store-file>WEB-INF/wsse10.truststore</trust-store-file>
    <trust-store-password>password</trust-store-password>

    <config>
     <timestamp ttl="300"/>
(2)     <sign type="x509v3" alias="1" includeTimestamp="true"/>
(3)     <encrypt type="x509v3"
              alias="alice"
              algorithm="aes-256"
              keyWrapAlgorithm="rsa_oaep"
              tokenReference="keyIdentifier" />
(4)         <requires>
            <signature/>
              <encryption/>      
            </requires>
    </config>
</jboss-ws-security>
サーバー設定には、以下の暗号化情報が含まれます:
  1. キーストアおよびトラストストア情報:各ストアの場所、パスワード、ストアの種類
  2. 署名設定:使用する証明書と鍵のペアのエイリアスを提供する必要があります。includeTimestamp は、改竄を防ぐためにtimestamp を署名するか指定します。
  3. 暗号化設定:使用する証明書とキーのペアのエイリアスを提供する必要があります。詳細については、アルゴリズム を参照してください。
  4. オプションのセキュリティ要件:受信メッセージは両方、署名、暗号化する必要があります。
動的暗号化

複数のクライアントに返信する場合、サービスプロバイダは、正しい公開鍵を使って宛先に基づいて、メッセージを暗号化する必要があります。JBossWS で WS-Security をネーティブ実装すると、受信メッセージで受け取り (確認された) 署名から正しい鍵を取得し利用します。

例9.6 動的暗号化の設定

動的暗号化を設定するには、サーバー側 (1) で暗号化のエイリアスを指定せず、署名が必要である (2) と宣言します。
<jboss-ws-security xmlns="http://www.jboss.com/ws-security/config"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://www.jboss.com/ws-security/config
                   http://www.jboss.com/ws-security/schema/jboss-ws-security_1_0.xsd">
    <key-store-file>WEB-INF/bob-sign_enc.jks</key-store-file>
    <key-store-password>password</key-store-password>
    <key-store-type>jks</key-store-type>
    <trust-store-file>WEB-INF/wsse10.truststore</trust-store-file>
    <trust-store-password>password</trust-store-password>

    <config>
     <timestamp ttl="300"/>
        <sign type="x509v3" alias="1" includeTimestamp="true"/>
(1)     <encrypt type="x509v3"
              algorithm="aes-256"
              keyWrapAlgorithm="rsa_oaep"
               tokenReference="keyIdentifier" />
            <requires>
(2)         <signature/>
              <encryption/>      
           </requires>
    </config>
</jboss-ws-security>
アルゴリズム

<encrypt> 要素が宣言されていれば必ず、非対称暗号化および対称暗号化が行われます。生成された対称暗号鍵を使ってメッセージデータを暗号化します。この鍵は、受取側の公開鍵で暗号化 (ラップ)された後に SOAP ヘッダーに書き込まれます。暗号化アルゴリズムとキーラップアルゴリズム両方を設定することが可能です。

対応している暗号化アルゴリズムには以下が含まれます:
  • AES 128 (aes-128) (デフォルト)
  • AES 192 (aes-192)
  • AES 256 (aes-256)
  • Triple DES (triple-des)
対応のキーラップアルゴリズムには以下が含まれます:
  • RSA v1.5 (rsa_15) (デフォルト)
  • RSA OAEP (rsa_oaep)

注記

(aes-256などの) 強力なアルゴリズムを実行するには、Unlimited Strength Java(TM) Cryptography Extensionのインストールが必要となる可能性があります。国によってはアプリケーションで利用できる暗号強度に制限が課せられている場合もありますので、責任を持って各管轄に適した暗号化レベルを選択するようにしてください。
暗号化トークンの参照

相互運用できるように、利用する暗号化トークンへの参照タイプを設定する必要があるかもしれません。例えば、ローカルのバイナリセキュリティートークンはJBossWS でデフォルトの参照タイプとして利用されていますが、Microsoft Indigo はこのトークンへの直接参照に対応していません。

この参照を設定するには、<encrypt> 要素のtokenReference 属性を指定します。tokenReference 属性の値は以下の通りです:
  • directReference (デフォルト)
  • keyIdentifier:X509 SubjectKeyIdentifier参照を使いトークンデータを指定します。
  • x509IssuerSerial:X509 とシリアル番号でエンドエンティティ (EE: End Entity) 証明書を一意に識別します。

注記

X509 Token Profile に関する包括的な情報は、Oasis.org docs portalの『WSS X501 Certificate Token Profile 1.0』文書でご覧いただけます。
ターゲットの設定

JBossWS では、署名あるいは暗号化を必要とする要素を正確に制御することができます。これにより、同じサービス上でやりとりがされているが、(e-メールアドレスなど)セキュリティレベルが高くないその他の情報ではなく、重要なデータのみ (クレジットカード番号など) を暗号化することができます。設定方法は、暗号化したい SOAP 要素の修飾名 (qname) を指定します。デフォルトの動作は、SOAP のボディ全体を暗号化します。

<encrypt type="x509v3" alias="alice">
  <targets>
    <target type="qname">{http://www.my-company.com/cc}CardNumber</target>
    <target type="qname">{http://www.my-company.com/cc}CardExpiration</target>
    <target type="qname" contentOnly="true">{http://www.my-company.com/cc}CustomerData</target>
  </targets>
</encrypt>
ペイロードのキャリッジリターン (CR)

XML パーサーが特殊文字を解析する仕方が原因で、キャリッジリターン (\r) を含む署名済みのメッセージペイロードで署名照合エラーが発生する可能性があります。この問題を回避するには、ペイロードを送る前にカスタムエンコーディングを実装するようにします。そうするとユーザーはメッセージを暗号化するか、あるいはJBossWS によりメッセージのメッセージの正準正規化を強制的に行うことができます。

MessageContextでtrueに設定されている場合、org.jboss.ws.DOMContentCanonicalNormalization プロパティはペイロードを正規化できます。このプロパティは、クライアント側で呼び出す直前にエンドポイント実装に設定する必要があります。

9.21.2.7. JAAS の統合

WS-Security を実装すると、JAAS 統合により J2EE の宣言セキュリティを行うことができます。ユーザーのアイデンティティや認証情報は、サーバーのwsse 設定ファイルにあるパラメーターに従い、受信メッセージの wsse ヘッダーから取得します。特定のセキュリティドメイン用に設定された JAAS ログインモジュールを委譲することで認証と権限付与が行われます。
Username Token

Username Token Profile により、呼出し元のユーザー名、パスワードを指定することができます。wsse サーバーの設定ファイルを使って、設定済みのログインモジュールにて認証、権限付与を行う際にこれらの情報を活用することができます。

<jboss-ws-security xmlns="http://www.jboss.com/ws-security/config"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.jboss.com/ws-security/config
                      http://www.jboss.com/ws-security/schema/jboss-ws-security_1_0.xsd">
  <config>
    <username/>
    <authenticate>
      <usernameAuth/>
    </authenticate>
  </config>
</jboss-ws-security>

注記

JBossWS 3.0.2 Native 以前では、指定時は呼出し側の主体と認証情報を設定するために、Username Token が常に使われていました。つまり、認証タグが指定されずに User Token が利用されている場合、後方互換ができるようこの動作も保持されます。
X.509 Certificate Token

JBossWS の以前のバージョンでは、指定時は呼出し側の主体と認証情報を設定するために、Username Token が常に使われていました。つまり、<authenticate> 要素が指定され User Token が使われている場合、後方互換ができるようこの動作が残されています。

<jboss-ws-security xmlns="http://www.jboss.com/ws-security/config"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.jboss.com/ws-security/config
                      http://www.jboss.com/ws-security/schema/jboss-ws-security_1_0.xsd">
  <key-store-file>META-INF/bob-sign.jks</key-store-file>
  <key-store-password>password</key-store-password>
  <key-store-type>jks</key-store-type>
  <trust-store-file>META-INF/wsse10.truststore</trust-store-file>
  <trust-store-password>password</trust-store-password>
  <config>
    <sign type="x509v3" alias="1" includeTimestamp="false"/>
    <requires>
      <signature/>
    </requires>
    <authenticate>
(1)   <signatureCertAuth certificatePrincipal="org.jboss.security.auth.certs.SubjectCNMapping"/>
    </authenticate>
  </config>
</jboss-ws-security>
オプションの certificatePrincipal 要素 (1) はクラスを使い X509 証明の属性から主体をリトリーブします。選択したクラスは、CertificatePrincipalを継承する必要があります。属性が指定されていない場合に使うデフォルトのクラスは、org.jboss.security.auth.certs.SubjectDNMappingとなっています。
例9.7「BaseCertLoginModule セキュリティドメイン」に記載されているように、設定済みのセキュリティドメインにBaseCertLoginModuleを正しく設定する必要があります。

例9.7 BaseCertLoginModule セキュリティドメイン

以下は、CertRolesLoginModule を持つセキュリティドメインのコード例で、(指定のjbossws-roles.properties ファイルを使うことで)認証も有効にします。
<application-policy name="JBossWSCert">
  <authentication>
    <login-module code="org.jboss.security.auth.spi.CertRolesLoginModule" flag="required">
      <module-option name="rolesProperties">jbossws-roles.properties</module-option>
      <module-option name="unauthenticatedIdentity">anonymous</module-option>
      <module-option name="securityDomain">java:/jaas/JBossWSCert</module-option>
    </login-module>
  </authentication>
</application-policy>
BaseCertLoginModule は、中央キーストアを使いユーザーを認証します。例9.8「BaseCertLoginModule キーストア」で示されているように、 org.jboss.security.plugins.JaasSecurityDomain MBean を使ってこのストアを設定します。

例9.8 BaseCertLoginModule キーストア

<mbean code="org.jboss.security.plugins.JaasSecurityDomain"
       name="jboss.security:service=SecurityDomain">
  <constructor>
    <arg type="java.lang.String" value="JBossWSCert"/>
  </constructor>
  <attribute name="KeyStoreURL">resource:META-INF/keystore.jks</attribute>
  <attribute name="KeyStorePass">password</attribute>
  <depends>jboss.security:service=JaasSecurityManager</depends>
</mbean>
認証時に、指定したCertificatePrincipal マッピングクラスは、紐付けられた wsse ヘッダーから取得した主体を使いキーストアにアクセスします。証明書があり、wsse ヘッダーで指定したものと同じであれば、ユーザー認証に成功します。

9.21.2.8. POJO エンドポイント認証および権限付与JBOSSCC-50

WS-Security が取得した証明書は通常、他のセキュリティがかかったリソースを呼び出す場合、EJB エンドポイントあるいは POJO エンドポイントに対して使います。POJO エンドポイントの確認に認証、権限付与ができるようになります。

重要

EJB コンテナーがデプロイされた bean のセキュリティ要件を処理するため、EJB ベースのエンドポイントに対し認証や権限付与を有効化するべきではありません。

手順9.1 POJO 認証や権限付与を有効化

この手順では、POJO エンドポイントの認証や権限付与を有効にする際に必要となる追加設定について説明しています。
  1. Web アーカイブにてセキュリティドメインを定義

    POJO を含む WAR にてセキュリティドメインを定義する必要があります。
    /WEB-INF フォルダーの jboss-web 配備記述子で<security-domain> を指定します。
    <jboss-web>
      <security-domain>java:/jaas/JBossWS</security-domain>
    </jboss-web>
  2. jboss-wsse-server.xml <authorize> 要素を設定します。

    <config> 要素内の<authorize> 要素を指定します。
    <config> 要素をグローバル、ポート固有、あるいはオペレーション固有のいずれかに定義することが可能です。
    <authorize> 要素には、<unchecked/> 要素あるいは、1つ以上の<role>要素を含める必要があります。各<role> 要素には、有効な RoleName 名を含む必要があります。
    認証タイプは、Unchecked と役割ベース認証の2種類から選択し実装することができます。
    Unchecked 認証

    この認証手順でユーザーのユーザー名やパスワードを照合しますが、役割の確認はそれ以上行われません。ユーザーのユーザー名やパスワードが無効の場合、リクエストは拒否されます。

    例9.9 Unchecked 認証

    <jboss-ws-security>
      
      <config>
        <authorize>      
          <unchecked/>
        </authorize>
      </config>
      
    </jboss-ws-security>
    役割ベースの認証

    Unchecked 認証のようにユーザー名とパスワードを使いユーザー認証が行われます。ユーザーのユーザー名やパスワードが照合されると、ユーザーの認証情報が再確認され、<role> 要素で指定された役割のうち少なくとも1つがユーザーに割り当てられるようにします。

    注記

    ユーザー名とパスワードあるいは証明書がリクエストメッセージで提示されていない場合でも、認証、権限付与が進められます。このシナリオでは、セキュリティドメインのログインモジュールが匿名のアイデンティティで設定されている場合、認証が進む場合があります。

    例9.10 役割ベースの認証

    <jboss-ws-security>
      
      <config>
        <authorize>      
          <role>friend</role>
          <role>family</role>
        </authorize>
      </config>
      
    </jboss-ws-security>

9.21.3. XML レジストリ

J2EE 5.0 は JAXR (Java API for XML Registries) のサポートを義務付けています。J2EE 5.0 認定の Application Server を持つ XML Registry を含むのは任意です。JBoss EAP には JBoss は Apache jUDDI レジストリである UDDI v2.0 規格のレジストリが同梱されています。また、 Apache Scout の統合により JAXR Capability Level 0 (UDDI レジストリ) にも対応しています。
「XML レジストリ」は JBoss での jUDDI レジストリ設定方法を説明し、いくつかのサンプルコードで jUDDI レジストリの発行および問い合わせに JAXR API を使用する概略を示します。

9.21.3.1. Apache jUDDI の設定

jUDDI レジストリの構成はallサーバープロファイルの juddi-service.sar アーカイブにデプロイされる MBean Service により行われます。このサービスの設定は juddi-service.sar 内の META-INF ディレクトリにある jboss-service.xml で行うことができます。
変更可能な設定アイテムを個別に見ていきます。
DataSources の設定
<!-- Datasource to Database -->
<attribute name="DataSourceUrl">java:/DefaultDS</attribute>
データベーステーブル (起動時に作成されるべきか、 停止時にドロップされるべきか、 起動時にドロップされるべきかなど)
<!-- Should all tables be created on Start-->
<attribute name="CreateOnStart">false</attribute>
<!-- Should all tables be dropped on Stop-->
<attribute name="DropOnStop">true</attribute>
<!-- Should all tables be dropped on Start-->
<attribute name="DropOnStart">false</attribute>
JNDI でバインドされるべき JAXR Connection ファクトリ (バインドされるべきか? どの名前の配下で?)
<!-- Should I bind a Context to which JaxrConnectionFactory bound-->
<attribute name="ShouldBindJaxr">true</attribute>
  
<!-- Context to which JaxrConnectionFactory to bind to. If you have remote clients, please bind it to the global namespace(default behavior). 
To just cater to clients running on the same VM as JBoss, change to java:/JAXR -->
<attribute name="BindJaxr">JAXR</attribute>
その他共通の設定
jUDDI レジストリへのアクセスを承認されたユーザーを追加します。 (1 行に sql 挿入ステートメントを追加する)
Look at the script META-INF/ddl/juddi_data.ddl for more details. Example for a user 'jboss'
  
INSERT INTO PUBLISHER (PUBLISHER_ID,PUBLISHER_NAME,
EMAIL_ADDRESS,IS_ENABLED,IS_ADMIN) 
VALUES ('jboss','JBoss User','jboss@xxx','true','true');

9.21.3.2. JBoss JAXR の設定

本セクションでは、 JAXR API の実行に必要とされる設定について説明していきます。 JAXR 設定は JVM に渡される System プロパティに依存します。 必要とされる System プロパティは次の通りです。
javax.xml.registry.ConnectionFactoryClass=org.apache.ws.scout.registry.
ConnectionFactoryImpl 
jaxr.query.url=http://localhost:8080/juddi/inquiry 
jaxr.publish.url=http://localhost:8080/juddi/publish
scout.proxy.transportClass=org.jboss.jaxr.scout.transport.SaajTransport
ホスト名を「localhost」から UDDI サービス/JBoss Server のホスト名に変更するのを忘れないようにしてください。
System プロパティを次のようにして JVM に渡すことができます。
  • クライアントコードが JBoss の内側で実行している場合は (おそらくサーブレットか EJB)、 run.sh または run.bat のスクリプトにある System プロパティを "-D" オプションを使って java プロセスに渡す必要があります。
  • クライアントコードが外部 JVM で実行している場合は、 「-D」オプションとして java プロセスにプロパティを渡すか、 明示的にクライアントコードに設定する (推奨しません) ことができます。
System.setProperty(propertyname, propertyvalue);

9.21.3.3. JAXR サンプルコード

API には JAXR Publish API と JAXR Inquiry API の 2 つのカテゴリーがあります。 すべての JAXR クライアントコードが使用する重要な JAXR インターフェースは次の通りです。
  • J2EE 5.0 JavaDoc の javax.xml.registry.RegistryService より抜粋: 「これは JAXR プロバイダーにより実装される第一インターフェースになります。 レジストリクライアントはこのインターフェースをレジストリへの Connection から取得することができます。 JAXR プロバイダーにより実装される各種の機能固有インターフェースを見つけるためにクライアントによって使用されるメソッドを提供します。」
  • J2EE 5.0 JavaDoc の javax.xml.registry.BusinessLifeCycleManager より抜粋: 「Registry Service により公開される BusinessLifeCycleManager インターフェースはビジネスレベル API の一部として Registry のライフサイクル管理機能を実装します。 Connection インターフェースはクライアントの代わりにその状態とコンテキストを維持するため提供される認証情報はないので注意してください。」
  • J2EE 5.0 JavaDoc の javax.xml.registry.BusinessQueryManager より抜粋: 「Registry Service により公開される BusinessQueryManager インターフェースはビジネススタイルのクエリーインターフェースを実装します。 集中クエリーインターフェースとも呼ばれます。」
JAXR API の使用中に行われる共通のプログラミングタスクをいくつか見てみます。
レジストリへの JAXR Connection を取得します。
String queryurl = System.getProperty("jaxr.query.url", "http://localhost:8080/juddi/inquiry");
String puburl = System.getProperty("jaxr.publish.url", "http://localhost:8080/juddi/publish");
.. 
Properties props = new Properties();
props.setProperty("javax.xml.registry.queryManagerURL", queryurl);
props.setProperty("javax.xml.registry.lifeCycleManagerURL", puburl);
  
String transportClass = System.getProperty("scout.proxy.transportClass", "org.jboss.jaxr.scout.transport.SaajTransport");
System.setProperty("scout.proxy.transportClass", transportClass);
  
// Create the connection, passing it the configuration properties
factory = ConnectionFactory.newInstance();
factory.setProperties(props);
connection = factory.createConnection();
レジストリと認証を行います。
/**
 * Does authentication with the uddi registry
 */
protected void login() throws JAXRException
{
   PasswordAuthentication passwdAuth = new PasswordAuthentication(userid, passwd.toCharArray());
   Set creds = new HashSet();
   creds.add(passwdAuth);
  
   connection.setCredentials(creds);
}
Business を保存します。
/**
 * Creates a Jaxr Organization with 1 or more services
 */
protected Organization createOrganization(String orgname) throws JAXRException
{
   Organization org = blm.createOrganization(getIString(orgname));
   org.setDescription(getIString("JBoss Inc"));
   Service service = blm.createService(getIString("JBOSS JAXR Service"));
   service.setDescription(getIString("Services of XML Registry"));
   //Create serviceBinding
   ServiceBinding serviceBinding = blm.createServiceBinding();
   serviceBinding.setDescription(blm.createInternationalString("Test Service Binding"));
  
   //Turn validation of URI off
   serviceBinding.setValidateURI(false);
   serviceBinding.setAccessURI("http://testjboss.org");
   ...
   // Add the serviceBinding to the service
   service.addServiceBinding(serviceBinding);
  
   User user = blm.createUser();
   org.setPrimaryContact(user);
   PersonName personName = blm.createPersonName("Anil S");
   TelephoneNumber telephoneNumber = blm.createTelephoneNumber();
   telephoneNumber.setNumber("111-111-7777");
   telephoneNumber.setType(null);
   PostalAddress address = blm.createPostalAddress("111", "My Drive", "BuckHead", "GA", "USA", "1111-111", "");
   Collection postalAddresses = new ArrayList();
   postalAddresses.add(address);
   Collection emailAddresses = new ArrayList();
   EmailAddress emailAddress = blm.createEmailAddress("anil@apache.org");
   emailAddresses.add(emailAddress);
  
   Collection numbers = new ArrayList();
   numbers.add(telephoneNumber);
   user.setPersonName(personName);
   user.setPostalAddresses(postalAddresses);
   user.setEmailAddresses(emailAddresses);
   user.setTelephoneNumbers(numbers);
  
   ClassificationScheme cScheme = getClassificationScheme("ntis-gov:naics", "");
   Key cKey = blm.createKey("uuid:C0B9FE13-324F-413D-5A5B-2004DB8E5CC2");
   cScheme.setKey(cKey);
   Classification classification = blm.createClassification(cScheme, "Computer Systems Design and Related Services", "5415");
   org.addClassification(classification);
   ClassificationScheme cScheme1 = getClassificationScheme("D-U-N-S", "");
   Key cKey1 = blm.createKey("uuid:3367C81E-FF1F-4D5A-B202-3EB13AD02423");
   cScheme1.setKey(cKey1);
   ExternalIdentifier ei = blm.createExternalIdentifier(cScheme1, "D-U-N-S number", "08-146-6849");
   org.addExternalIdentifier(ei);
   org.addService(service);

   return org;
}
Business を問い合わせます。
/**
 * Locale aware Search a business in the registry
 */
public void searchBusiness(String bizname) throws JAXRException
{
   try
   {
      // Get registry service and business query manager
      this.getJAXREssentials();
  
      // Define find qualifiers and name patterns
      Collection findQualifiers = new ArrayList();
      findQualifiers.add(FindQualifier.SORT_BY_NAME_ASC);
      Collection namePatterns = new ArrayList();
      String pattern = "%" + bizname + "%";
      LocalizedString ls = blm.createLocalizedString(Locale.getDefault(), pattern);
      namePatterns.add(ls);
  
      // Find based upon qualifier type and values
      BulkResponse response = bqm.findOrganizations(findQualifiers, namePatterns, null, null, null, null);
  
      // check how many organisation we have matched
      Collection orgs = response.getCollection();
      if (orgs == null)
      {
         log.debug(" -- Matched 0 orgs");
      }
      else
      {
         log.debug(" -- Matched " + orgs.size() + " organizations -- ");
  
         // then step through them
         for (Iterator orgIter = orgs.iterator(); orgIter.hasNext();)
         {
            Organization org = (Organization)orgIter.next();
            log.debug("Org name: " + getName(org));
            log.debug("Org description: " + getDescription(org));
            log.debug("Org key id: " + getKey(org));
            checkUser(org);
            checkServices(org);
         }
      }
   }
   finally
   {
      connection.close();
   }
}
これ以外の JAXR API を使用するコード例については、 リソースセクションにあるリソースを参照してください。

9.21.3.4. トラブルシューティング

  • JAXR からレジストリに接続できません。 inquiry を確認して JAXR ConnectionFactory に渡された url を公開してください。
  • jUDDI レジストリに接続できません。 jUDDI 設定を確認して server.log にエラーがないかチェックしてください。 また、 jUDDI レジストリは「all」構成でのみ使用可能になるので注意してください。
  • jUDDI レジストリに対して認証できません。 章の前半の説明通りに、 認証ユーザーを jUDDI データベースに追加しましたか?
  • クライアントと UDDI レジストリの間を移動中の SOAP メッセージを表示させたいのですが。 tcpmon ツールを使って移動中のメッセージを表示してください。 TCPMon

9.22. JBossWS の拡張

本セクションは JAX-WS に対する登録商標の JBoss 拡張について説明しています。

9.22.1. 登録商標のアノテーション

標準のアノテーションセットについては JAX-WS Annotations をご覧ください。

9.22.1.1. EndpointConfig

/**
 * Defines an endpoint or client configuration. 
 * This annotation is valid on an endpoint implementaion bean or a SEI.
 */
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.TYPE })
public @interface EndpointConfig
{
   ... 
   /**
    * The optional config-name element gives the configuration name that must be present in
    * the configuration given by element config-file.
    * 
    * Server side default: Standard Endpoint
    * Client side default: Standard Client
    */
   String configName() default "";
   ...
   /**
    * The optional config-file element is a URL or resource name for the configuration.
    *
    * Server side default: standard-jaxws-endpoint-config.xml
    * Client side default: standard-jaxws-client-config.xml
    */
   String configFile() default "";
}

9.22.1.2. WebContext

/**
 * Provides web context specific meta data to EJB based web service endpoints.
 *
 * @author thomas.diesler@jboss.org
 * @since 26-Apr-2005
 */
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.TYPE })
public @interface WebContext
{
   ... 
   /** 
    * The contextRoot element specifies the context root that the web service endpoint is deployed to.
    * If it is not specified it will be derived from the deployment short name.
    * 
    * Applies to server side port components only. 
    */
   String contextRoot() default "";
   ...
   /** 
    * The virtual hosts that the web service endpoint is deployed to.
    * 
    * Applies to server side port components only.
    */
   String[] virtualHosts() default {};
    
   /** 
    * Relative path that is appended to the contextRoot to form fully qualified
    * endpoint address for the web service endpoint.
    * 
    * Applies to server side port components only. 
    */
   String urlPattern() default "";
    
   /**
    * The authMethod is used to configure the authentication mechanism for the web service. 
    * As a prerequisite to gaining access to any web service which are protected by an authorization
    * constraint, a user must have authenticated using the configured mechanism.
    *
    * Legal values for this element are "BASIC", or "CLIENT-CERT".
    */
   String authMethod() default "";
   
   /**
    * The transportGuarantee specifies that the communication
    * between client and server should be NONE, INTEGRAL, or
    * CONFIDENTIAL. NONE means that the application does not require any
    * transport guarantees. A value of INTEGRAL means that the application
    * requires that the data sent between the client and server be sent in
    * such a way that it can't be changed in transit. CONFIDENTIAL means
    * that the application requires that the data be transmitted in a
    * fashion that prevents other entities from observing the contents of
    * the transmission. In most cases, the presence of the INTEGRAL or
    * CONFIDENTIAL flag will indicate that the use of SSL is required.
    */
   String transportGuarantee() default "";
    
   /**
    * A secure endpoint does not by default publish it's wsdl on an unsecure transport.
    * You can override this behaviour by explicitly setting the secureWSDLAccess flag to false.
    * 
    * Protect access to WSDL. See http://jira.jboss.org/jira/browse/JBWS-723   
    */
   boolean secureWSDLAccess() default true;
}

9.22.1.3. SecurityDomain

/**
 * Annotation for specifying the JBoss security domain for an EJB
 */
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME)
public @interface SecurityDomain
{
   /**
    * The required name for the security domain.
    * 
    * Do not use the JNDI name
    * 
    *    Good: "MyDomain"
    *    Bad:  "java:/jaas/MyDomain"
    */
   String value();
   
   /**
    * The name for the unauthenticated pricipal
    */
   String unauthenticatedPrincipal() default "";
}

9.23. Web サービス付録

注記

この情報は JBoss Web Services CXF Stack で利用可能です。

第10章 JBoss AOP

JBoss AOP は 100% Pure Java のアスペクト指向フレームワークで、すべてのプログラミング環境で使用することができ、アプリケーションサーバーと密に統合することが可能です。通常のオブジェクト指向プログラムでの対応が難しい場合でも、アスペクトはコードベースを簡単にモジュール化することができます アプリケーションロジックやシステムコードからクリーンに分離することができ、統合ポイントをソフトウェアへ公開する素晴らしい方法を提供します。 JDK 1.5 アノテーションを組み合わせると、コード生成にアノテーションのみを使用せずに、 クリーンでプラグ可能な方法で Java 言語を拡張できます。
JBoss AOP はフレームワークであるだけでなく、アノテーションやポイントカット表現経由で適用され、ランタイム時に動的に適用されるパッケージ済みのアスペクトセットでもあります。これには、キャッシング、非同期通信、トランザクション、セキュリティ、リモーティングなど、多数含まれます。
アスペクトは、 メソッド、 クラス、 オブジェクト階層、 オブジェクトモデル全体に散在する共通の機能です。 構造があるような動作をしますが、従来のオブジェクト指向技術では構造をコードで表現することはできません。
例えば、 メトリックスは共通のアスペクトの 1 つです。 アプリケーションより有用なログを生成するには、 コード全体に通知メッセージを散在させなければなりません。 しかし、 メトリックスはクラスやオブジェクトモデルが考慮されるものではありません。 顧客やアカウントを表すわけではなく、 ビジネスルールを実現しません。 メトリックスは直交で、 実際のアプリケーションとは無関係です。 

10.1. 主な用語

ジョインポイント

ジョインポイントとは Java プログラム内のポイントのことです。 メソッドの呼び出し、 コンストラクタの実行、 フィールドのアクセスはすべてジョインポイントとなります。 ジョインポイントは、 イベントがメソッド呼び出し、 コンストラクタコール、 フィールドアクセスなどである特定の Java イベントと考えることができます。

呼び出し

呼び出しは、 ランタイム時のジョインポイントをカプセル化する JBoss AOP クラスです。 呼び出されたメソッドやメソッドの引数などの情報が含まれます。

アドバイス

アドバイスは、 特定のジョインポイントが実行された時に呼び出されるメソッドのことです (メソッドが呼び出された時にトリガーされる動作など)。 インターセプションを行うコードと考えることもできます。 アドバイスは「イベントハンドラー」とも類似しています。 

ポイントカット

ポイントカットは AOP の表現言語です。 正規表現が文字列と一致するように、 ポイントカット表現もジョインポイントと一致します。 

イントロダクション

イントロダクションは Java クラスのタイプや構造を変更します。 既存のクラスにインターフェースを実装するよう強制、あるいは アノテーションを追加するために使用できます。 

アスペクト

アスペクトは、 アドバイス、 ポイントカット定義、 ミックスイン、 その他 JBoss AOP コンストラクトの数をカプセル化するプレーン Java クラスです。 

インターセプター

インターセプターinvoke という名前のアドバイスのみを持つアスペクトです。 インターフェースを実装するようクラスを強制してコードをチェックしたい場合に実装できるインターフェースです。 インターセプターは移植可能で、 EJB や JMX MBean など他の JBoss 環境で再使用することができます。

AOP では、 メトリックスなどの機能は横断的関心事 (crosscutting concern) と呼ばれます。 これは、オブジェクトモデルの複数のポイントを「横断」しながらも明確に異なる動作であるためです。 開発方法では、 横断的関心事を抽象化し、 カプセル化することが推奨されます。
アプリケーションにコードを追加し、 特定メソッドの呼び出しに掛かる時間を測定するとしましょう。 プレーン Java では、 以下のようなコードになるはずです。
public class BankAccountDAO
{
 public void withdraw(double amount)
 {
  long startTime = System.currentTimeMillis();
  try
  {
   // Actual method body...
  }
  finally
  {
   long endTime = System.currentTimeMillis() - startTime;
   System.out.println("withdraw took: " + endTime);
  }
 }
}
このコードでも動作しますが、いくつかの問題があります。
  1. try/finally ブロックのコードを手作業でベンチマーク対象のメソッドやコンストラクターすべてに追加する必要があるため、 メトリクスの有効化や無効化が大変難しくなります。
  2. プロファイリングコードをアプリケーション全体に散在させるべきではありません。try/finally ブロック内にタイミングが含まれるようにしなければならないため、 コードが膨張して読みにくくなります。
  3. この機能を拡張してメソッドや失敗数が含まれるようにし、 これらの統計を高性能なレポートメカニズムに登録したい場合、 多くのファイルを変更する必要があります。
コードベース全体にメトリクスが分散されるため、 メトリクスに対するこのアプローチは維持や拡張が大変難しくなります。 多くの場合、 メトリクスをクラスに追加するのに OOP が最良の方法であるとは言えません。
アスペクト指向プログラミングは、 このような動作機能をカプセル化する方法を提供します。 これにより、 メトリクスのような動作をコードの「周り」に追加することができます。 例えば、 コードの実際のボディーを実行する前に BankAccountDAO への呼び出しがメトリクスアスペクトを通過するよう指定するププログラム制御を AOP は提供します。

10.2. JBoss AOP でアスペクトを作成

簡単に説明すると、すべての AOP フレームワークは、横断的関心事を実装する方法とプログラムコンストラクト (プログラミング言語またはタグのセット) の 2 つを定義し、コードスニペットの適用方法を指定します。JBoss AOP、横断的関心事、ユーザーがどのように JBoss Enterprise Application Platform でメトリクスアスペクトを実装できるか見てみましょう。
独自の Java クラスにメトリクス機能をカプセル化することが JBoss AOP にメトリックスアスペクトを作成する最初のステップになります。 以下のコードは、 最初のコード例の BankAccountDAO.withdraw() メソッドにある try/finally ブロックを JBoss AOP インターセプタークラスの実装である Metrics に抽出します。
次のリストは JBoss AOP インターセプターへのメトリクス実装を表しています。
01. public class Metrics implements org.jboss.aop.advice.Interceptor
02. {
03.   public Object invoke(Invocation invocation) throws Throwable
04.   {
05.     long startTime = System.currentTimeMillis();
06.     try
07.     {
08.       return invocation.invokeNext();
09.     }
10.     finally
11.     {
12.       long endTime = System.currentTimeMillis() - startTime;
13.       java.lang.reflect.Method m = ((MethodInvocation)invocation).method;
14.       System.out.println("method " + m.toString() + " time: " + endTime + "ms");
15.     }
16.   }
17. }
JBoss AOP では、 Metrics クラスが withdraw()をラップします。 呼び出しコードが withdraw() を呼び出すと、 AOP フレームワークがメソッドコールをパーツに分解し、 パーツを呼び出しオブジェクトにカプセル化します。 その後、 呼び出しコードと実際のメソッドボディーの間に存在するすべてのアスペクトをフレームワークが呼び出します。
AOP フレームワークによるメソッドコールの分解が終了すると、 3 行目でMetricsの呼び出しメソッドを呼び出します。 8 行目は実際のメソッドをラップし、実際のメソッドへ委譲します。try/finally ブロックを使用してタイミングを実行します。 13 行目は Invocation オブジェクトからメソッドコールのコンテキスト情報を取得します。 14 行目はメソッド名と算出されたメトリクスを表示します。
独自のオブジェクト内に Metrics コードが存在することにより、後で追加の測定を簡単に拡張し取得することができます。アスペクトにカプセル化されたメトリクスの適用方法を見てみましょう。

10.3. JBoss AOP でアスペクトを適応

アスペクトを適用するには、アスペクトコードの実行時を定義します。実行のポイントはポイントカットと呼ばれます。ポイントカットは正規表現と似ています。正規表現は文字列とマッチさせますが、ポイントカット表現はアプリケーション内のイベントやポイント とマッチさせます。例えば、有効なポイントカット定義は「JDBC メソッド executeQuery() への呼び出しに対し、SQL 構文を検証するアスペクトを呼び出す」のようになります。
フィールドアクセスやメソッドコール、コンストラクタコールなどがエントリポイントとなります。 スローされた例外などがイベントとなります。 AOP 実装によっては、 ポイントカットの指定にクエリに似た言語を使用するものもあります。 その他の AOP 実装はタグを使用します。 JBoss AOP は両方を使用します。
次のリストは JBoss AOP における Metrics 例のポイントカットの定義方法を示しています。
1 <interceptor name="SimpleInterceptor" class="com.mc.Metrics"/>
2 <bind pointcut="execution (public void com.mc.BankAccountDAO->withdraw(double amount))" >
3     <interceptor-ref name="SimpleInterceptor" />
4 </bind>
5 <bind pointcut="execution (* com.mc.billing.->(..))">
6     <interceptor-ref name="com.mc.Metrics" />
7 </bind>
1 行目は interceptor クラスへの インターセプター名のマッピングを定義しています。2-4 行目は、特定のBankAccountDAO.withdraw() メソッドに metrics アスペクトを適用するポイントカットを定義します。5-7 行目は com.mc.billing パッケージにおける全クラスの全メソッドへ metrics アスペクトを適用する一般的なポイントカットを定義します。XML を希望しない場合は、オプションのアノテーションマッピングもあります。詳細は JBoss AOP の参照文書をご覧ください。
JBoss AOP には Java アプリケーションの様々なポイントやイベントを定義するために使用できるポイントカット表現のセットが多くあります。 ポイントを定義した後にアスペクトを適用することができます。 アプリケーション内の特定の Java クラスにアスペクトを適用することができますが、 複雑な複合的なポイントカットを使用し、 1 つの表現内に複数のクラスを指定することもできます。
この例の通り、 AOP では横断的動作を 1 つのオブジェクトにまとめ、 ビジネスロジックに関係ない機能でコードを複雑化することなく簡単に適応することができます。 共通の横断的関心事は 1 つの場所で維持拡張できます。
BankAccountDAO クラス内のコードはプロファイルされた事を認識しません。 プロファイリングはアスペクト指向プログラマーが直交した関心事 (orthogonal concern) として考えるものの一部です。 本章の始めにあるオブジェクト指向プログラミングのコードスニペットでは、 プロファイリングがアプリケーションコードの一部となっています。 AOP ではこのコードを削除することが可能です。 近年のミドルウェアは透明性を約束していますが、 AOP も確実に透明性を提供します。
直交した動作は開発後に追加することもできます。 オブジェクト指向コードでは、 監視とプロファイリングは開発時に追加されなければなりません。 AOP では、 開発者や管理者がコードに触れることなく必要に応じて簡単に監視やメトリックスを追加することができます。 これは目立った機能ではありませんが、 この分離により、 横断するコードの上下にアスペクトを階層化することができるため、 AOP の重要機能の一部になります。 階層化により、 必要な時に機能を追加削除できます。 例えば、 ベンチマークを実行する時のみメトリクスを有効にし、 実稼働時に削除するとします。 AOP では、 コードを編集、 再コンパイル、 再パッケージすることなく、 これを実行することができます。

10.4. AOP アプリケーションのパッケージ

AOP アプリケーションをJBoss Enterprise Application Platform にデプロイするには、 AOP アプリケーションをパッケージ化する必要があります。 AOP は SAR (MBean) と同様にパッケージ化されます。 XML ファイルを署名 *-aop.xml とパッケージと共に直接 deploy/ ディレクトリにデプロイするか (これにより jboss-aop.deployer ファイルにある base-aop.xml が利用できます)、 クラスを格納する JAR ファイルに XML ファイルが含まれるようにすることができます。 JAR に XML ファイルが含まれるようにする場合、 ファイルの拡張子は .aop でなければなりません。 また、jboss-aop.xml ファイルは META-INF ディレクトリに含まれなければなりません (例: META-INF/jboss-aop.xml)。
JBoss Enterprise Application Platform 5 では、 使用するスキーマを指定しないと情報が正しく構文解析されないため、 必ず指定してください。 スキーマを指定するには、 次のように xmlns="urn:jboss:aop-beans:1:0 属性をルート aop 要素に追加します。
<aop xmlns="urn:jboss:aop-beans:1.0">
</aop>
.aop JAR ファイルを使った既定の例を超えるものを作成するには、XML バインディング設定を格納する AOP ファイルが含まれるトップレベルのデプロイメントを作成します。 例えば、EAR ファイルまたは WAR ファイルに AOP ファイルを保持することができます。 AOP ファイル内にある META-INF/jboss-aop.xml ファイルに指定されたバインディングは、 WAR ファイル全体のすべてのクラスに影響します。
EAR ファイル内の AOP ファイルを取得するには、 次の例のように Java モジュールとして .ear/META-INF/application.xml にリストされなければなりません。
<?xml version='1.0'  encoding='UTF-8'?>
<!DOCTYPE application PUBLIC '-//Sun Microsystems, Inc.//DTD J2EE Application 1.2//EN''http://java.sun.com/j2ee/dtds/application_1_2.dtd'>
 
<application>
    <display-name>AOP in JBoss example</display-name>
    <module>
        <java>example.aop</java>
    </module>
    <module>
        <ejb>aopexampleejb.jar</ejb>
    </module>
    <module>
        <web>
            <web-uri>aopexample.war</web-uri>
            <context-root>/aopexample</context-root>
        </web>
    </module>
</application>

重要

JBoss Enterprise Application Platform 5 では、 .ear ファイルの内容は application.xml にある一覧の順番通りにデプロイされます。 ロード時の組み入れを使用する場合は、 ejb クラスや servlet などがロードされる前にバインディングがシステムに存在するよう、 アドバイスされたクラスがデプロイされる前に example.aop ファイルにリストされているバインディングがデプロイされなければなりません。 これには、 application.xml の最初に AOP ファイルを記載します。 .sar ファイルや .war ファイルなど、 他のタイプのアーカイブは最初にデプロイされるため、 特別な処置は必要ありません。

10.5. JBoss AspectManager サービス

AspectManager サービスは、 http://localhost:8080/jmx-console の JMX コンソールを使用してランタイム時に管理することができます。 AspectManager サービスは ObjectName jboss.aop:service=AspectManager で登録されています。 起動時に設定を行いたい場合は、 設定ファイルを編集する必要があります。
JBoss Enterprise Application Platform 5 では、 AspectManager サービスは JBoss Microcontainer bean を使用して設定されます。 設定ファイルは jboss-as/server/PROFILE/conf/bootstrap/aop.xml です。 AspectManager サービスは次の XML にてデプロイされます。
    <bean name="AspectManager" class="org.jboss.aop.deployers.AspectManagerJDK5">
     
    <property name="jbossIntegration"><inject bean="AOPJBossIntegration"/></property>
                               
    <property name="enableLoadtimeWeaving">false</property>
    <!-- only relevant when EnableLoadtimeWeaving is true.
    When transformer is on, every loaded class gets transformed.
    If AOP can't find the class, then it throws an exception.  
    Sometimes, classes may not have all the classes they reference.  
    So, the Suppressing is needed.  (For instance, JBoss cache in the default configuration) -->
    
    <property name="suppressTransformationErrors">true</property>
    
    <property name="prune">true</property>
    
    <property name="include">org.jboss.test., org.jboss.injbossaop.</property>
    
    <property name="exclude">org.jboss.</property>
    <!-- This avoids instrumentation of hibernate cglib enhanced proxies
    
    <property name="ignore">*$$EnhancerByCGLIB$$*</property> -->
    
    <property name="optimized">true</property>
    
    <property name="verbose">false</property>
    <!-- Available choices for this attribute are: org.jboss.aop.instrument.ClassicInstrumentor (default)
    org.jboss.aop.instrument.GeneratedAdvisorInstrumentor -->
    
    <!-- <property name="instrumentor">org.jboss.aop.instrument.ClassicInstrumentor</property>-->
    
    <!-- By default the deployment of the aspects contained in 
    ../deployers/jboss-aop-jboss5.deployer/base-aspects.xml
    are not deployed. To turn on deployment uncomment this property
    <property name="useBaseXml">true</property>-->
</bean>
AspectManager サービスのクラス変更については後ほど説明します。 クラスを変更するには、 bean 要素の class 属性の内容を置き換えます。

10.6. Sun JDK を使用した JBoss Enterprise Application Platform におけるロード時の変換

JBoss Enterprise Application Platform は JDK と特別に統合し、 ロード時の変換を実行します。 本項では、 この使用法を説明します。
JBoss Enterprise Application Platform 5 と Sun JDK でロード時の変換を実行したい場合は、次の手順に従ってください。
  • enableLoadtimeWeaving 属性/プロパティを true に設定します。 JBoss Application Server はデフォルトでは AOP ファイルのロード時のバイトコード操作を実行しないため、 この設定を行う必要があります。 suppressTransformationErrorstrue に設定されている場合、 バイトコード変換に失敗するとエラー警告のみが生成されます。 JBoss デプロイメントにクラスが参照する全てのクラスが存在しないことがあるため、 このフラグが必要となります。
  • pluggable-instrumentor.jar を JBoss AOP ディストリビューションの lib/ ディレクトリから JBoss Enterprise Application Platform の bin/ ディレクトリへコピーします。
  • 次に run.sh または run.bat (OS によって異なります) を編集し、 下記を JAVA_OPTS 環境変数に追加します。
    set JAVA_OPTS=%JAVA_OPTS% -Dprogram.name=%PROGNAME% -javaagent:pluggable-instrumentor.jar
    

重要

AspectManager サービスのクラスは、 -javaagent オプションが機能する org.jboss.aop.deployers.AspectManagerJDK5 または org.jboss.aop.deployment.AspectManagerServiceJDK5 でなければなりません。

10.7. JRockit

JRockit は、 「Sun JDK を使用した JBoss Enterprise Application Platform におけるロード時の変換」 に記載されている -javaagent スイッチもサポートします。 このスイッチを使用する場合、 「Sun JDK を使用した JBoss Enterprise Application Platform におけるロード時の変換」 の手順に従ってください。 JRockit はクラスがロードされる際のインターセプトに対する独自のフレームワークも持っており、 -javaagent スイッチよりも高速である場合があります。 特別な JRockit フックを使用してロード時の変換を実行する場合は、 次の手順に従ってください。
  • enableLoadtimeWeaving 属性/プロパティを true に設定します。 JBoss アプリケーションサーバーはデフォルトでは AOP ファイルのロード時のバイトコード操作を実行しないため、 この設定を行う必要があります。 suppressTransformationErrors に設定されている場合、 バイトコード変換に失敗するとエラー警告のみが生成されます。 JBoss デプロイメントにクラスが参照する全てのクラスが存在しないことがあるため、 このフラグが必要となります。
  • jrockit-pluggable-instrumentor.jarを JBoss AOP ディストリビューションの lib/ ディレクトリから JBoss Enterprise Application Platform の bin/ ディレクトリへコピーします。
  • 次に run.sh または run.bat (OS によって異なります) を編集し、 下記を JAVA_OPTS 環境変数と JBOSS_CLASSPATH 環境変数に追加します。
    # Setup JBoss specific properties
    
    JAVA_OPTS="$JAVA_OPTS -Dprogram.name=$PROGNAME \
    
    -Xmanagement:class=org.jboss.aop.hook.JRockitPluggableClassPreProcessor"
    
    JBOSS_CLASSPATH="$JBOSS_CLASSPATH:jrockit-pluggable-instrumentor.jar"
    
  • JRockit の特別なフックに対応するため、 AspectManager サービスのクラスを JBoss Enterprise Application Platform 5 上で org.jboss.aop.deployers.AspectManagerJRockit に設定するか、 org.jboss.aop.deployment.AspectManagerService に設定します。

10.8. JBoss Enterprise Application Platform 環境でロード時のパフォーマンスを改善

JBoss Enterprise Application Platform におけるロード時のウィービングのパフォーマンスを調整するルールは、 スタンドアローン Java の場合と同じです。 pruning、 optimized、 include、 exclude などのスイッチは、 本章の始めで説明した jboss-5.x.x.GA/server/xxx/conf/aop.xml ファイルより設定できます。

10.9. AOP をクラスローダーへスコープ

JBoss のすべてのデプロイメントは、 デフォルトでアプリケーションサーバー全体に対してグローバルになっています。 そのため、deploy ディレクトリにある EAR、 SAR、 JAR はデプロイされた別のアーカイブからクラスを可視できます。 同様に、 AOP のバインディングは仮想マシン全体に対してグローバルになっています。 globalの可視性はトップレベルデプロイメント毎に無効にすることができます。

10.9.1. スコープされたクラスローダーの一部としてデプロイ

次のプロセスは、 今後の JBoss AOP バージョンで変更する可能性があります。 スコープされたアーカイブの一部として AOP ファイルをデプロイする場合、.aop/META-INF/jboss-aop.xml ファイル内に適用されるバインディングなどは、スクープされたアーカイブ内でクラスのみに適用され、 アプリケーションサーバーのそれ以外のものには適用されません。 -aop.xml ファイルをサービスアーカイブ( SAR) の一部としてデプロイする方法もあります。 この場合でも、 SAR がスコープされていると、 -aop.xml ファイルに格納されたバインディングは SAR ファイルの内容のみに適用されます。 現在、 スタンドアローンの -aop.xml ファイルをデプロイあるいは、すでに添付されたデプロイメントに添付することはできません。 スタンドアロン -aop.xml ファイルはアプリケーションサーバー全体のクラスに適用されます。

10.9.2. スコープされたデプロイメントへ添付

クラスローダー分離を使用するアプリケーションがある場合、 クラスを準備していれば後に AOP ファイルをデプロイメントに添付できます。 jboss-app.xml ファイルを使用しスコープされた EAR ファイルとスコープされたローダーレポジトリ jboss.test:service=scoped があるとします。
<jboss-app>
    <loader-repository>
        jboss.test:service=scoped
    </loader-repository>
</jboss-app>
この場合、 アスペクトや設定が含まれる AOP ファイルを後でデプロイし、 デプロイメントをスコープされた EAR に添付することができます。 これを実行するには、AOP ファイルの META-INF/jboss-aop.xml> にある loader-repository を使用します。
<?xml version="1.0" encoding="UTF-8"?>
<aop>
    <loader-repository>jboss.test:service=scoped</loader-repository>
                                    
    <!-- Aspects and bindings --> 
</aop>
上記は、 前に説明した AOP ファイルを EAR の一部としてデプロイする方法と同じ効果がありますが、 アスペクトをスコープされたアプリケーションにホットデプロイすることが可能です。

第11章 トランザクション管理

本章では、JBoss Transaction Service の主要設定オプションに関し簡単に説明します。詳細情報は、『JBoss Transactions Administration Guide』 を参照してください。

11.1. 概要

JBoss Enterprise Application Platform のトランザクションサポートは、JBossTransaction Serviceによって提供されます。JBossTransaction Service は、十分に考慮・開発されたモジュラー、規格ベースかつ、設定自在のトランザクションマネージャーです。デフォルトでは、サーバーはインストールされたJBossTransaction Service のローカル専用JTAモジュールにて稼働します。このモジュールは、EJB コンテナーなどの他の内部コンポーネントによる使用、さらにはアプリケーションによる直接使用に向けた標準的なJTA API の実装を提供します。関係データベースやメッセージキューなど1つ以上のXA リソースマネージャーが関係するACID トランザクションの調整に適しています。
JBoss Transaction Service トランザクションモジュールについても、JBoss Enterprise Application Platform に2つオプションが追加されています。 これらのモジュールをデプロイすると、必要であれば次のような追加機能を提供することができます。
JBoss Transaction Service JTS
トランザクションマネージャーは、リモート IIOP メソッドの呼び出し上でトランザクションコンテキストを分散でき、複数の JVM に対応する単一の分散トランザクションを作成することができます。 複数のサーバーにわたる大型のアプリケーションや、 CORBA ベースのシステムで実行されているトランザクションビジネスロジックとの規格ベースの相互運用に対して有用です。このモジュールの機能は標準的なJTA API から利用できるため、トランザクションビジネスロジックへの変更を必要とせず、 簡単に代わりの導入ができます。この機能の有効化に関する詳細情報は「JTS Module の利用」 を参照してください。
JBoss Transaction Service XTS
WS-AtomicTransaction (WS-AT)WS-BusinessActivity (WS-BA) 仕様を実装する XML ベースの Transaction Manager です。 この追加モジュールは JTA または JTS が提供するコアトランザクションサポートや JBossWS Native が提供する Web サービス機能は使用します。JBossTransaction Service XTS はアプリケーションとしてサーバー内にデプロイされます。 アプリケーションは JTS とほぼ同じ要領で WS-AT を使用して標準的な分散 ACID トランザクションを提供することもありますが、 CORBA ではなく Web サービストランスポートを使用します。 WS-BA 実装は、さらに代替の補償ベーストランザクションモデルを提供します。 このトランザクションモデルは、長期実行される疎結合のビジネスプロセスの調整に適しています 。XTS は、 通常はローカル WS-AT 実装や WS-BA 実装が内部でのみアクセスする WS-Coordination (WS-C) サービスも実装します。しかし、この WS-C サービスは、 別の JBoss サーバーインスタンスや JBoss 以外のコンテナに作成された WS-AT や WS-BA トランザクションのリモート調整を提供するためにも使用されます。XTS を有効にするには、「XTS モジュールの利用」 を参照してください。

11.2. 必須設定

JBossTS JTA のデフォルト設定は、トランザクションマネージャー独自のプロパティファイルやアプリケーションサーバーのデプロイメント設定を組み合わせて管理されます。 設定ファイルは $JBOSS_HOME/server/PROFILE/conf/jbossts-properties.xml にあります。 設定ファイルには、 最も一般的に使用されるプロパティのデフォルト設定が格納されています。 その他の設定について多数、付属の JBossTransaction Service 管理ガイドに説明されています。各設定にはハードコードされたデフォルトがありますが、設定ファイルがないとシステムが正しく機能しない場合があります。追加設定は$JBOSS_HOME/server/PROFILE/deploy/transaction-jboss-beans.xml にある Microcontainer bean 設定の一部として行うこともできます。これにより、 トランザクションマネージャーがサーバープロファイル全体の設定に結合されるため、随時トランザクション設定ファイルの設定よりもアプリケーションサーバー固有の値が優先されます。 特に、Service Binding Manager を使用してポートのバインディグ情報を設定し、選択された他のプロパティより優先させます。 設定プロパティはサーバーの初期化時に JBossTransaction Service によって読み取られ、 その後設定ファイルに加えられた変更は、 サーバーが再起動するまで有効になりません。

表11.1 JBoss Transaction Service で最も重要なプロパティ

プロパティ名
デフォルト値
詳細
transactionTimeout
300 秒
秒単位のデフォルト時間で、この時間が経過した後トランザクションはタイムアウトし、ロールバックされます。ご利用中の環境やワークロードにあわせて、これを調節してください。
トランザクションが非同期的に処理される点に驚かれるかもしれませんが、設計的にこのように決定され、コードによりユーザ側で対応する必要があります。
objectStoreDir
トランザクションデータがログ化されるディレクトリ。システム障害が発生した場合にトランザクションを完了するにはトランザクションログが必要となり、このログは信頼性のあるストレージに設置される必要があります。通常、トランザクション毎に1ファイル生成され、各ファイルはサイズ的には数キロバイトとなっています。パフォーマンスが最適化されるよう、これらのファイルはディレクトリツリー全体で分散されています。RAIDコントローラを使っている場合、データベースの格納デバイスとほぼ同じ方法でライトスルーキャッシュ用に設定する必要があります。トランザクションがロールバックされる場合あるいは、リソースを1つしか含まない場合、トランザクションログの書き込みは自動的にスキップされます。
max-pool-size
Java EE Connector Architectureコンテナは、リカバリが実行されるEISに対し、専用の物理接続を開いた状態に保ちます。そのため、max-pool-size を(接続可能な最大数ー1)を設定してください。

表11.2 JBoss Transaction Service の追加プロパティ

プロパティ名
デフォルト値
詳細
com.arjuna.common.util.logging.DebugLevel
0x00000000 はロギングなしと同等。
トランザクションマネージャーのコードベースに対する内部ログの閾値を決定します。サーバー全体の log4j ロギング設定から独立しており、外部からのログ入力が表示されないように抑える役割を果たします。デフォルト値が有効であれば、INFO や WARN メッセージは表示され、この設定により最適なパフォーマンスが実現されます。0xffffffff により完全なデバッグロギングが有効になり、この設定をするとログファイルのサイズが大きくなります。
内部の DebugLevel チェックを渡すログメッセージがサーバーのロギングシステムに渡されさらに処理されます。理論的には、完全なデバッグ機能はオンの状態にでき、log4j を使ってロギングの切/入が可能ですが、実際にはこれはパフォーマンスに影響を与えます。
com.arjuna.ats.arjuna.coordinator.commitOnePhase
YES
トランザクションに単一のリソースのみが登録されている場合に、トランザクションマネージャーは自動的に1フェーズコミットの最適化をトランザクション完了プロトコルへ適用しするかを決定します。デフォルトでは、トランザクションログの書き込みを回避するため、この設定は有効になっています。
com.arjuna.ats.arjuna.objectstore.transactionSync
ON
この設定は、 トランザクションの終了中にディスクへのトランザクションログのフラッシングを制御します。 デフォルト値では、各コミットトランザクションに対して FileDescriptor.sync 呼び出しが実行されます。リカバリ保証や ACID プロパティの提供に、この動作は必要となります。これらの機能がアプリケーションにとって重要でない場合、このプロパティを向こうにすることでパフォーマンスが向上しますが、通常、トランザクションを全く利用しないようにアプリケーションを記述するほうが良いため、この方法は推奨されません。
com.arjuna.ats.arjuna.xa.nodeIdentifier
com.arjuna.ats.jta.xaRecoveryNode
これらのプロパティはトランザクションリカバリシステムの動作を決定します。 サーバーのクラッシュが発生した時にリカバリが行われトランザクションが正しく解決されるようにするため、 適切な設定が必要となります。 詳細は、JBoss Transaction 管理ガイドの リカバリの章を参照してください。
com.arjuna.ats.arjuna.coordinator.enableStatistics
NO
トランザクション統計の収集を有効にします。この統計は、 FileDescriptor.sync あるいは該当の JMX MBean でメソッドを使うことで参照できます。デフォルトでは無効になっています。

11.3. トランザクションリソース

Transaction Service は、 様々なリソースマネージャーによって提供される XAResource 実装を利用しトランザクションステートの更新を調整します。 リソースマネージャーは、 データベース、 メッセージキュー、 サードパーティ JCA リソースアダプターなどを含むことがあります。 JBoss Enterprise Application Platform での使用が認定された JDBC データベースドライバーやデータベースの一覧は http://www.jboss.com/products/platforms/application/supportedconfigurations/ を参照してください。 規格準拠の JDBC ドライバーの多くは正しく機能するはずですが、ベンダーによって XA 仕様の解釈が異なるため、認定を受けていないドライバーを使う場合は徹底的なテストを行う必要があります。
データベース接続プールは、アプリケーションサーバーの Datasource ファイルで設定します。これらのファイルは、-ds.xml などのファイル名にします。<xa-datasource> プロパティを使うデータソースは自動的にトランザクションマネージャーとやりとりを行います。JNDI でこのようなデータソースを検索し、 getConnection を呼び出すことで取得した接続は自動的に進行中のトランザクションに参加します。これは、データアクセスに対してトランザクション保証が必要な場合、推奨されるユースケースとなっています。
XA トランザクションに対応できないデータベースを利用している場合、<local-xa-datasource> を使い接続プールをデプロイできます。この種類のデータソースは、「最終リソースコミット最適化 (LRCO: Last Resource Commit Optimization) 」 を使い管理トランザクションに参加し、より制限のあるトランザクション保証を提供します。<no-tx-datasource> から取得した接続は、トランザクションマネージャーとやり取りを行わないため、このような接続で実施される作業については、JDBC API を使いアプリケーション側から明示的にコミットあるいはロールバックを行う必要があります。
多くのデータベースでは、XA リソースマネージャーとして機能できるようになるまでに追加設定が必要となります。データベース設定に関するベンダー固有の情報は、付録A ベンダー固有のデータソース定義 にあります。追加設定の説明については、ご利用中のデータベースに同梱されているデータベースアドミニストレーターや文書を参照してください。さらに、XA リカバリの適切な設定方法に関する情報は、JBoss Transactions 管理ガイドを参照してください。
JBoss Messaging は XA 対応ドライバーを提供しており、XA トランザクションに参加できます。 詳細については、JBoss Messaging ユーザガイドを参照してください。

11.4. 最終リソースコミット最適化 (LRCO: Last Resource Commit Optimization)

XA トランザクションプロトコルは、2フェーズのコミットプロトコルを用いることで ACID プロパティを提供するように設計されていますが、モデルが常に正しいというわけではありません。時には、XA 非対応のリソースマネージャーがトランザクションに参加できるようにする必要がある場合もあります。これは通常、分散トランザクションに対応していないデータストアを使う場合に該当します。
このような場合、Last Resource Commit Optimization (LRCO)と呼ばれる技術を使うことができます。これは、Last Resource Gambit と呼ばれることもあります。この技術を使用すると、1 フェーズ対応リソースがトランザクションの prepare フェーズの最後に処理され、その時にコミットが試行されます。コミットに成功すると、トランザクションログが書き込まれ、残りのリソースはフェーズ 2 コミットに進みます。最後のリソースのコミットに失敗すると、トランザクションはロールバックされます。このプロトコルにより、 ほとんどのトランザクションは普通通りに完了しますが、エラーの種類によっては不整合なトランザクション結果が生じる原因となります。そのため、 他に手段がない場合のみ LRCO を使ってください。トランザクションに単一の <local-tx-datasource> が使用される場合、LRCO が自動的に適用されます。その他の場合、特別なマーカーインターフェースを使用して最終リソースを指定することが可能です。詳細は JBoss Transactions のプログラマーガイドを参照してください。
同じトランザクションに1フェーズリソースを複数使うと、トランザクション的に安全ではないため、推奨されません。JBoss Transaction Service は、2番目のこのようなリソースをエラーとして登録するよう試行し、トランザクションを終了します。この種のエラーは JBoss Application Server のレガシーバージョンから移行する際に最も頻繁に見られます。できる限り、<local-tx-datasource> は <xa-datasource> に変換しこの問題を解決します。

11.5. トランザクションタイムアウトの処理

リソースの無限ロッキングを防ぐため、 <xa-datasource> トランザクションマネージャーは指定の間隔後に完了しなかったインフライトトランザクションを停止します。これは、TransactionReaper が調整するバックグラウンドプロセスのセットによって停止が実行されます。リーパーは、範囲内で動作している可能性があるスレッドへ割り込まずにトランザクションをロールバックします。これにより、任意コードを実行するスレッドへの割り込みが原因で発生する不安定性を防ぐことができます。また、ビジネスロジックスレッドがネットワーク I/O 呼び出しなど割り込みできない操作を実行している場合、トランザクションを適時に停止できるようにします。 しかし、 この方法はマルチスレッド化されたトランザクションの処理を想定していないコードで、 予想外の動作が実行される原因となることがあります。予想外のトランザクション状況の変化により、他のトランザクション対応コンポーネントなどから警告やエラーメッセージが出力されることがありますが、 トランザクションの結果へは影響しないはずです。トランザクションタイムアウトの値を適切に調節することでこの問題を最小限に抑えることができます。詳細については、15章DataSource の設定 を参照してください。

11.6. リカバリ設定

設定を強固なものにするため、障害、リカバリに対応するため JBoss Transaction Service を正しく設定することが重要です。これについて、『JBoss Transactions Administration Guide』 "Resource Recovery in JBoss Transaction Service"の章にて詳細に説明しています。

11.7. Transaction Service のよくある質問

本章では、JBoss Transaction Service の設定に関する問題で最も一般的なものをいくつか挙げていきます。
問: デバッグロギングを有効にしましたが何もログに残されていません。
問: サーバーログに WARN Adding multiple last resources is disallowed. が表示されトランザクションが停止されました。なぜでしょうか。
問: サーバーが予期せず停止しました。現在、再稼働していますが、 ログに次のようなメッセージが記録されています: WARN [com.arjuna.ats.jta.logging.loggerI18N] [com.arjuna.ats.internal.jta.resources.arjunacore.norecoveryxa] Could not find new XAResource to use for recovering non-serializable XAResource.
問: トランザクションに時間がかかり、 時々予期しないことが発生します。 サーバーログには次が含まれています: WARN [arjLoggerI18N] [BasicAction_58] - Abort of action id ... invoked while multiple threads active within it.
問:
デバッグロギングを有効にしましたが何もログに残されていません。
答:
JBossTS は2レベルのフィルターを使ってログステートメントを送信します。
  1. ログは、JBoss Transaction Service の独自のロギング抽象層を経由します。
  2. ログは、JBoss Enterprise Application Platform's log4j のロギングシステムを経由します。
ログステートメントを表示するには両方のフィルターを通る必要があります。よくある間違いとしてロギングシステムの片方だけを有効にすることです。詳細情報は、表11.2「JBoss Transaction Service の追加プロパティ」 を参照してください。
問:
サーバーログに WARN Adding multiple last resources is disallowed. が表示されトランザクションが停止されました。なぜでしょうか。
答:
おそらく <local-xa-datasource> を使っており、1フェーズ対応のパーティシパントを1つ以上使おうとしている可能性があります。この設定は回避すべきです。詳細情報については 「最終リソースコミット最適化 (LRCO: Last Resource Commit Optimization) 」 を参照してください。さらに懸念がありましたら、Global Support Services にお問い合わせください。
問:
サーバーが予期せず停止しました。現在、再稼働していますが、 ログに次のようなメッセージが記録されています: WARN [com.arjuna.ats.jta.logging.loggerI18N] [com.arjuna.ats.internal.jta.resources.arjunacore.norecoveryxa] Could not find new XAResource to use for recovering non-serializable XAResource.
答:
リカバリ用に全リソースマネージャーを設定していないのかもしれません。リソースマネージャーをリカバリさせる設定に関する詳細は、JBoss Transaction Administration Guide のリカバリの章を参照してください。
問:
トランザクションに時間がかかり、 時々予期しないことが発生します。 サーバーログには次が含まれています: WARN [arjLoggerI18N] [BasicAction_58] - Abort of action id ... invoked while multiple threads active within it.
答:
タイムアウトの時間を過ぎるとトランザクションはロールバックされることがあります。これは、バックグランドのスレッドにより実行されますが、割り込みを予期しているアプリケーションコードが混乱することがあります。詳細は、「トランザクションタイムアウトの処理」 を参照してください。
上記以外の質問がある場合、他の JBoss Transaction ガイドを参照いただくか、Global Support Services にご連絡ください。

11.8. JTS Module の利用

様々なサーバーのビジネスロジック間でトランザクションを伝搬する必要がある場合、JTS API を使うことができます。直接利用することができますが、通常は標準の JTA クラス経由でアクセスします。デフォルトであるローカルのみの JTA 実装と完全互換となっており、必要なクラスはすでに設置されています。JTA と JTS モジュール間の移動はjbossts-properties.xml ファイルを変更するだけです。
サンプルの jbossts-properties.xml ファイルは、$JBOSS_HOME/docs/examples/transactions/ ディレクトリに置かれています。 transactions-jboss-beans.xml など、他のファイルに加える必要のある変更については、同じディレクトリにある README.txt を参照してください。全ステップを自動で実行するために、ANT スクリプトが提供されていますが、このスクリプトを実行する前に README.txt を注意して参照していただき、既存の設定のバックアップを取るよう推奨しています。
JTS では、CORBA ORB サービスも含めるにはサーバー設定が必要です。例で参照されている "all" サーバープロファイルから始めるといいでしょう。JTS や JTA のどちらを選ぶかにより、サーバー全体に影響を与えます。JTS は追加リソースが必要ないため、必要な場合のみ使ってください。
アプリケーションの起動時、JTA を使う設定になっているサーバーは、以下のようなログファイルを出力します:
      INFO [TransactionManagerService] JBossTS Transaction Service (JTA version - ...)
JTS が有効な場合、このようなメッセージが表示されます。
      INFO [TransactionManagerService] JBossTS Transaction Service (JTS version - ...)

11.9. XTS モジュールの利用

JBoss Transaction Service の Web Service コンポーネントである XTS をインストールし、Enterprise Application Platform でホストされる Web サービスに WS-AT や WS-BA サポートを提供することができます。このモジュールは、$JBOSS_HOME/docs/examples/transactions/Service Archive (.sar) としてパッケージ化されています。

手順11.1 XTS モジュールのインストール

  1. jbossxts.sar/と呼ばれる$JBOSS_HOME/server/[name]/deploy/ ディレクトリ にサブディレクトリを作成します。
  2. この新しいディレクトリに、ZIP アーカイブの .sar を解凍します。
  3. JBoss Enterprise Application Platform を再起動し、このモジュールを有効にします。
サーバーは JBossWS Nativeに加え、JTA あるいは JTS モジュールを利用する必要があります。

注記

現在のところ XTS は、CXF などの 別の JBossWS バックエンドと連携するようにはなっていません。デフォルトの XTS 設定はデプロイメントの多くに手気市訂鱒。EAP 設定から自動的にネットワークインターフェースやポートバインディングに関する情報を検出します。トランザクションコーディネーターを別のホストで使う必要のあるアプリケーションをデプロイメントする場合のみ、手動での設定変更が必要です。詳細情報は、JBoss Web Service Transactions のプログラマーガイドを参照してください。
開発者は、XTS Servcie Archive に含まれている jbossxts-api.jar にリンクすることもできますが、クラスローディングの問題を回避するにはこのファイルをご利用中のアプリケーションとパッケージ化するべきではありません。これ以外の JAR ファイルにはすべて内部実装クラスが含まれているため、直接利用するべきではありません。
詳細な設定情報については、$JBOSS_HOME/docs/examples/transactions/README.txtをご覧ください。JBoss Web Services Transactions ユーザーガイドには、ご利用中のアプリケーションでの XTS 利用に関する情報が含まれています。

11.10. トランザクション管理コンソール

Transaction Management Console は、$JBOSS_HOME/docs/example/transactions/ に含まれる簡単な GUI ツールですが、これは未対応で試験的なプロトタイプとして提供されています。Transaction Management Console の機能や、用途に関する情報は、README.txt を参照してください。

11.11. コンポーネント (トライアル)

JBoss Enterprise Application Platform に含まれる JBoss Transaction Service の対応コンポーネントに加え、継続的に機能強化作業が行われており、最終的に本製品の今後のリリースに追加される可能性もあります。それまでの間、これらのプロトタイプコンポーネントは、http://jboss.org のコミュニティー Web サイトから入手できます。

警告

これらの機能が正しく動作するかは保証されておらず、Enterprise Application Platform のサポート契約にも含まれていないため注意する必要がありますが、利用可能な拡張機能によっては、開発初期段階のプロジェクトには役立つかもしれません。これらプロトタイプをダウンロードするユーザーは、「ソースコードとアップグレード」に従ってモジュールの互換性に関する制限を認識するようにしてください。
txbridge
Web Services トランザクションの範囲内で、EJB といった従来のトランザクションコンポーネントを呼び出す機能が必要な場合もあります。反対に従来のトランザクション系アプリケーションによっては、トランザクショナルな Web サービスを呼び出す必要がある可能性もあります。Transaction Bridge (txbridge) は、この2種類のトランザクショナルサービスを連携する仕組みを提供しています。
BA フレームワーク
XTS API は、非常に低いレベルで稼働しており、開発者は WS-BA を絡めたトランザクションインフラストラクチャーの作業を行う必要があります。BA フレームワークは、ハイレベルのアノテーションを用意しており、JBoss Transaction Service がこのようなインフラストラクチャーに対応できるようにしています。そのため、開発者は、ビジネスロジックにさらに焦点をあてることができます。

11.12. ソースコードとアップグレード

トランザクション関連の問題の多くは、サーバーからデバッグロギング情報を提示いただいてから、Global Support Services で検証されます。
しかし、独自のツールをお使いいただき、ご自身でソースコードをデバッグあるいはレビューすることも可能です。http://anonsvn.jboss.org/repos/labs/labs/jbosstm/の Subversion レポジトリを使い、ソースコードをダウンロードすることができます。Enterprise Application Platform は起動時に以下のような文字列を利用し Transaction Service のバージョンを出力します。 
      INFO [TransactionManagerService] JBossTS Transaction Service (JTA version - tag:JBOSSTS_4_6_1_GA_CP02) - JBoss Inc.
tag 要素は、Subversion レポジトリの /tags/ 以下のツリーに対応します。バージョンは、Enterprise Application Platform 自体のバージョンではなく、 Enterprise Application Platform にて利用される JBoss Transaction Service コンポーネントのバージョンであることに注意してください。ソースから Enterprise Application Platform を構築する場合は、component-matix/pom.xmlファイルの文字列 version.jboss.jbossts を検索しバージョンを確認することができます。

警告

ご利用中の Enterprise Application Platform で提供されている JBossTS のバージョン以外をインストールすることはサポート対象外となっています。JBoss Transaction Service のコンポーネントは別にパッケージされていますが、Enterprise Application Platform が提供しているバージョン以外はサポート対象外となります。

第12章 リモーティング

JBoss Remoting の主な目的は、プラグ可能なトランスポートとマーシャラーを使用するネットワークベースの呼び出しと関連サービスの多くに単一の API を提供することです。 JBoss Remoting のAPI は、 同期および非同期のリモート呼び出し、プッシュ型およびプル型のコールバック、 リモーティングサーバーの自動ディスカバリなどを行う機能を提供します。 これにより、 異なるニーズに対して異なるトランスポートを追加できるようにしながら、 リモート呼び出しに同じ API を維持するようにします。 また、 異なるニーズに対してコードの変更でなく設定の変更のみが必要となります。
Remoting にはそのまま使用できる複数のトランスポート (bisocket、 http、 rmi、 ソケット、サーブレット、これらの SSL が有効になったもの)、 標準かつ圧縮データマーシャラー、標準の jdk シリアル化と JBoss Serialization を切り替える設定可能機能を提供します。リモートクラスローディングも可能で、接続障害通知の大規模な機能も持っています。 さらに、単一の JVM に配置されるクライアント/サーバー呼び出しに対し参照渡しの最適化を実行し、 マルチホーム化されたサーバーを実装します。
Enterprise Application Platform では Remoting は EJB2、 EJB3、 Messaging サブシステムのトランスポート層を提供します。 Remoting の設定の多くは事前に決定され、 固定されていますが、 Remoting 設定の変更方法を知っていると便利な場合があります。

12.1. 背景

Remoting サーバーは、 トランスポート固有のサーバー呼出しをラップし設定するコネクターによって構成されます。 コネクターは次のような InvokerLocator ストリングによって示されます。
    socket://bluemonkeydiamond.com:8888/?timeout=10000&serialization=jboss
この例では、 ソケットトランスポートを使用しているサーバーはホスト bluemonkeydiamond.com の 8888 番ポートでアクセス可能で、 ソケットタイムアウト値 10000 と JBoss Serialization を使用するようサーバーが設定されています。 Remoting クライアントは InvokerLocator を使用して一定のサーバーに接続できます。
Enterprise Application Platform では、Remoting サーバーとクライアントは表面よりかなり深い位置で作成され、設定ファイルからのみアクセス可能です。また、SLSB などが JNDI ディレクトリからダウンロードされた場合、InvokerLocator のコピーもダウンロードされるため、 適切な Remoting サーバーへの連絡方法を認識します。サーバーとクライアントが InvokerLocator を共有するため、InvokerLocator のパラメーターがクライアントとサーバーの両方を設定することに注意してください。

12.2. JBoss Remoting の設定

Remoting コネクターの作成や設定に使用できる XML ファイルには 2 つの種類があります。 コネクターを MBean として定義するには、 ファイル名が *-service.xml 形式のファイルを使用します。 コネクターを POJO として定義するには、 ファイル名が *-jboss-beans.xml 形式のファイルを使用します。

12.2.1. MBean

JBoss Messaging JMS サブシステムでは、Remoting サーバーはファイル remoting-bisocket-service.xml で設定されます。以下はこのファイルを省略したものになります。
    <mbean code="org.jboss.remoting.transport.Connector"
            name="jboss.messaging:service=Connector,transport=bisocket"
            display-name="Bisocket Transport Connector">
      <attribute name="Configuration">
        <config>
          <invoker transport="bisocket">         
            <attribute name="marshaller" isParam="true">org.jboss.jms.wireformat.JMSWireFormat</attribute>
            <attribute name="unmarshaller" isParam="true">org.jboss.jms.wireformat.JMSWireFormat</attribute>            
            <attribute name="serverBindAddress">${jboss.bind.address}</attribute>
            <attribute name="serverBindPort">4457</attribute>
            <attribute name="callbackTimeout">10000</attribute>
                 ...     
          </invoker>
              ...
        </config>
      </attribute>
    </mbean>
この設定ファイルから次のような情報を得ることができます。
  • このサーバーは bisocket トランスポートを使用
  • ホスト ${jboss.bind.address}; の 4457 番ポートで稼働
  • JBoss Messaging は独自のマーシャリングアルゴリズムを使用
InvokerLocator はこのファイルに由来しています。 ここで重要なのは、 InvokerLocator にパラメーターが含まれるかを 「isParam」 属性が判断するということです。「isParam」 が省略されるか、false に設定されると、 パラメーターが適用されるのはサーバーのみでクライアントには通信されません。 Remoting サーバーの InvokerLocator に bluemonkeydiamond.com という ${jboss.bind.address} がある場合、 次のようになります。
      bisocket://bluemonkeydiamond.com:4457/?marshaller=
      org.jboss.jms.wireformat.JMSWireFormat&
      unmarshaller=org.jboss.jms.wireformat.JMSWireFormat
InvokerLocator には「callbackTimeout」パラメーターは含まれていません。

12.2.2. POJO

org.jboss.remoting.ServerConfiguration POJO のように同じコネクターを設定することができます。
     <bean name="JBMConnector" class="org.jboss.remoting.transport.Connector">
       <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX
        (name="jboss.messaging:service=Connector,transport=bisocket",
        exposedInterface=org.jboss.remoting.transport.ConnectorMBean.class,
        registerDirectly=true)</annotation>
       <property name="serverConfiguration"><inject bean="JBMConfiguration"/></property>
     </bean>
     
     <!-- Remoting server configuration -->
     <bean name="JBMConfiguration" class="org.jboss.remoting.ServerConfiguration">
       <constructor>
         <parameter>bisocket</parameter>
       </constructor>
     
        <!-- Parameters visible to both client and server -->
       <property name="invokerLocatorParameters">
         <map keyClass="java.lang.String" valueClass="java.lang.String">
           <entry>
             <key>serverBindAddress</key>
             <value>
               <value-factory bean="ServiceBindingManager" method="getStringBinding">
                 <parameter>JBMConnector</parameter>
                 <parameter>${host}</parameter>
               </value-factory>
             </value>
           </entry>
           <entry>
             <key>serverBindPort</key>
             <value>
               <value-factory bean="ServiceBindingManager" method="getStringBinding">
                 <parameter>JBMConnector</parameter>
                 <parameter>${port}</parameter>
               </value-factory>
             </value>
           </entry>
              ...
           <entry><key>marshaller</key> <value>org.jboss.jms.wireformat.JMSWireFormat</value></entry>
           <entry><key>unmarshaller</key> <value>org.jboss.jms.wireformat.JMSWireFormat</value></entry>
         </map
       </property>
       
       <!-- Parameters visible only to server -->
       <property name="serverParameters">
         <map keyClass="java.lang.String" valueClass="java.lang.String">
           <entry><key>callbackTimeout</key> <value>10000</value></entry>
         </map>
       </property>
                                  
        ...
     </bean>
このバージョンでは、設定情報は JBMConfiguration ServerConfiguration POJO に表現され、 JBMConnector org.jboss.remoting.transport.Connector POJO に挿入されます。構文は Microcontainer の構文ですが、本章の範囲外となりますので、詳細は 7章マイクロコンテナー を参照してください。また、MBean バージョンのバリエーションの 1 つが ServiceBindingManager の使用になりますが、これも本章の範囲外となります。@org.jboss.aop.microcontainer.aspects.jmx.JMX アノテーションによって、JBMConnector が「jboss.messaging:service=Connector,transport=bisocket」という名前の MBean として表示されるようになります。

12.3. マルチホーム化されたサーバー

Remoting は複数のインターフェースにバインドされるサーバーを作成することができます。 このファシリティの適応例として、 1 つのサーバーをインターネットに面するインターフェースと LAN に面する別のインターフェースにバインドすることができます。 例えば、 前述の POJO 例に POJO を追加して (1) 変更することができます。
   
   <bean name="homes1" class="java.lang.StringBuffer">
      <constructor>
         <parameter class="java.lang.String">
            <value-factory bean="ServiceBindingManager" method="getStringBinding">
               <parameter>JBMConnector:bindingHome1</parameter>
               <parameter>${host}:${port}</parameter>
            </value-factory>
         </parameter>
      </constructor>
   </bean>
   
   <bean name="homes2" class="java.lang.StringBuffer">
      <constructor factoryMethod="append">
         <factory bean="homes1"/>
         <parameter>
            <value-factory bean="ServiceBindingManager" method="getStringBinding">
               <parameter>JBMConnector:bindingHome2</parameter>
               <parameter>!${host}:${port}</parameter>
            </value-factory>
         </parameter>
      </constructor>
   </bean>
これにより、StringBuffer の値が 「external.acme.com:5555!internal.acme.com:4444」のようになります (JBMConnector:bindingHome1 and JBMConnector:bindingHome2 のServiceBindingManager 設定値による)。また、 「serverBindAddress」 パラメーターと 「serverBindPort」 パラメーターが次に置き換えられます (2)。
    <entry>
      <key>homes</key>
      <value><value-factory bean="homes2" method="toString"/></value>
    </entry>
これにより、StringBuffer が文字列「external.acme.com:5555!internal.acme.com:4444」 に変換され、 JBMConnector に挿入されます。結果、 InvokerLocator は次のようになります。
    bisocket://multihome/?homes=external.acme.com:5555!internal.acme.com:
    4444&marshaller=org.jboss.jms.wireformat.JMSWireFormat&
    unmarshaller=org.jboss.jms.wireformat.JMSWireFormat

12.4. アドレス変換

ファイアウォールを変換するアドレスよりサーバーへアクセスしなければならない場合があります。 Remoting サーバーは、 バインドするアドレス/ポートとクライアントが使用するアドレス/ポートの両方で設定することができます。 追加で 「clientConnectAddress」 と 「clientConnectPort」 の 2 つのパラメーターが使用されます。 「serverBindAddress」 と 「serverBindPort」 の値はサーバーの作成に使用されます。 「clientConnectAddress」 と 「clientConnectPort」の値は InvokerLocator で使用され、 クライアントにサーバーの場所を伝えます。 また、 マルチホームサーバー向けの 「connecthome」 パラメーターもあります。この場合、 サーバーの設定に 「home」 が使用され、 「connecthome」 がクライアントにサーバーの場所を伝えます。

12.5. 設定ファイルの場所

サポートされるサブシステムの実際の Remoting 設定ファイルは次の通りです。
EJB2: $JBOSS_HOME/server/$CONFIG/deploy/remoting-jboss-beans.xml
EJB3: $JBOSS_HOME/server/$CONFIG/deploy/ejb3-connectors-jboss-beans.xml
JBM: $JBOSS_HOME/server/$CONFIG/deploy/messaging/remoting-bisocket-service.xml

12.6. 詳細情報

その他の詳細情報は、 http://www.jboss.org/jbossremoting/docs/guide/2.5/html/index.html の Remoting ガイドを参照してください。

第13章 JBoss Messaging

JBoss Messaging の使用に関する最新情報は、 http://www.redhat.com/docs/en-US/JBoss_Enterprise_Application_Platform/ の 『JBoss Messaging User Guide』 を参照してください。

第14章 JBoss Enterprise Application Platform で別のデータベースを使用

14.1. 代わりのデータベースの使用法

JBoss はデフォルトのデータベースとして Hypersonic データベースを使用します。Hypersonic データベースの使用は開発やプロトタイピングには便利ですが、 実稼働環境で使用するには、 通常は別のデータベースが必要となります。 本章では、 JBoss Enterprise Application Platform が代替データベースを使用するよう設定する方法を説明します。 JBoss Enterprise Application Platform 上で正式サポートされるデータベースすべてを対象とします。認定データベースの総合一覧は、http://www.jboss.com/products/platforms/application/supportedconfigurations/を参照してください。
本章では、 JBoss Enterprise Application Platform 内の全サービスをサポートするため代替データベースを使用する方法について説明します。 これには、EJB や JMS など全システムレベルのサービスが含まれます。 JBoss Enterprise Application Platform にデプロイされている各アプリケーション (WAR や EAR など) に対して、適切なデータソース接続を設定すれば、バックエンドのデータベースも使用することができます。
外部データベースのインストールは本書の対象外となっています。ご利用中のデータベースのベンダーが提供するツールを使い、空のデータベースを設定してください。データベースへ接続するために当プラットフォームが使用するデータソースを作成するには、データベース名、接続 URL、ユーザー名、パスワードが必要になります。

14.2. JDBC ドライバーのインストール

選択した外部データベースを使うには、ご利用中のデータベースに JDBC ドライバーもインストールする必要があります。JDBC ドライバーは、JAR ファイルで $JBOSS_HOME/server/PROFILE/lib ディレクトリに設置する必要があります。また、 PROFILE を利用予定のサーバープロファイルで置き換えます。
JBoss Enterprise Application Platform が起動すると、このファイルがロードされるため、JBoss Enterprise Application Platform が稼働中であれば、一旦終了し再起動してください。適切な JDBC ドライバーについては以下の一覧を参照してください。認定済みの JBoss Enterprise Application Platform データベースドライバーの総合一覧については、http://www.jboss.com/products/platforms/application/supportedconfigurations/#JEAP5-0 を参照してください。このリンクが壊れている場合、JIRA の本書の項目から報告してください。ただし、Red Hat ではこういった外部リンクの管理は行っておりませんので、ご注意ください。ご利用中のデータベース向けの最新版ドライバーについてはデータベースベンダーにお問い合わせください。

JBDC ドライバーのダウンロード先

MySQL
http://www.mysql.com/products/connector/ からダウンロード
PostgreSQL
http://jdbc.postgresql.org/ からダウンロード
Oracle
IBM
Sybase
Sybase jConnect 製品ページ http://www.sybase.com/products/allproductsa-z/softwaredeveloperkit/jconnect からダウンロード

注記

このドライバーで Sybase データベースを使うと、ドライバーの PreparedStatement クラスでの制限が原因でMaxParams 属性を 481 以上に設定することができません。
Microsoft
MSDN Web サイト http://msdn.microsoft.com/data/jdbc/ からダウンロード

14.2.1. Sybase に関する注記

JBoss のサービスによっては、作成されたデフォルトテーブルに対し null の値を使用することもあるため、 Sybase Adaptive Server はデフォルトで null を許可するように設定する必要があります。
sp_dboption db_name, "allow nulls by default", true
その他のオプションについては、Sybase のマニュアルを参照してください。
さらに、データベースに格納される文字や画像の値は非常に大きくなる可能性があります。選択した一覧に文字と画像の値が両方含まれる場合、返されるデータの長さ制限は、@@textsize のグローバル変数で決定されます。この変数のデフォルト設定は、Adaptive Server へアクセスするのに利用するソフトウェアによって変わります。JDBC ドライバーについては、デフォルト値は 32 キロバイトとなっています。

14.2.1.1. JAVA サービスの有効化

JMS、CMP、タイマーなど、Sybase で設定された Java サービスを使用するには、 Sybase Adaptive Server 上で Java が有効になっている必要があります。Java を有効にする方法:
sp_configure "enable java",1
詳細は、Sybase のマニュアルを参照してください。
Sybase Adaptive Server に対して、Java が有効でない場合、コンソールに以下のエラーメッセージが表示される可能性があります。
com.sybase.jdbc2.jdbc.SybSQLException: Cannot run this command because Java services are not
        enabled. A user with System Administrator (SA) role must reconfigure the system to enable Java

14.2.1.2. CMP の設定

System Adaptive Server Enterprise で、ユーザ定義の Java オブジェクトにCMP (Container Managed Persistence: コンテナー管理の永続性) を使用するには、ご利用中のデータベースに Java クラスをインストールする必要があります。システムテーブル sysxtypes には、各拡張 Java-SQL データタイプに対して 1 つの行が含まれており、このテーブルは、Java が有効な Adaptive Server のみに利用されます。Java のために有効になっている Adaptive Server のみに使用されます。installjava プログラムを使用して java クラスをインストールしてください。
installjava -f <jar-file-name> -S<sybase-server> -U<super-user> -P<super-pass> -D<db-name>
別のオプションについては、Sybase の installjava マニュアルを参照してください。

14.2.1.3. Java クラスのインストール

  1. Java クラスをインストールするには、必要な権限を持つスーパーユーザーになる必要があります。
  2. インストールする JAR ファイルは圧縮せずに作成する必要があります。
  3. インストールしてサーバー内で使用する Java クラスは JDK 1.2.2 でコンパイル されている必要があります。より新しい JDK で1つのクラスをコンパイルしても、 installjava ユーティリティを使用してサーバーにインストールできますが、 そのクラスの使用を試す時に、 java.lang.ClassFormatError 例外が発生します。 これは、Sybase Adaptive Server が内部で古い JVM を使用しているため、 それと同じもので Java クラスをコンパイルする必要があるからです。

14.2.1.4. Sybase v15.0.3 向けにデフォルトの @@textsize を増加

データベースから返されるデフォルトの最大テキストサイズの値に問題があると、JBoss Messaging 上でテストの一部が失敗してしまう可能性があります。この問題を修正するには、デフォルトの @@textsize を 32768 (バイト) から 2147483647 (バイト) に変更してください。
<connection-url> ディレクティブの中にある sybase-ds.xml に変更を加えます。サンプルの sybase-ds.xml ファイルは、JBOSS_DIST/jboss-as/docs/examples/jca/ に置かれています。

重要

ディレクティブ値としてデータベースへの全 URL を指定します。[domain] を Sybase Database をホストしているドメイン名か IP アドレスと置き換え、[port] をリクエストを受け取るよう設定されたポートと置き換えてください。
<connection-url>jdbc:sybase:[domain]:[port]/db_name?SQLINITSTRING=set TextSize 2147483647</connection-url>

14.2.2. JDBC DataSource の設定

データソースは、簡素化された JCA Datasource 設定仕様に対応します。
データソースは、別のデプロイ可能なアプリケーションやリソースと共に$JBOSS_HOME/server/PROFILE/deploy ディレクトリに設置する必要があります。このファイルは、DBNAME-ds.xmlの標準ネーミングスキームを使います。
認定済みのデータベースすべてに対するデータソース例は、$JBOSS_HOME/docs/examples/jca ディレクトリに保存されています。ご利用中のデータベースに対応するデータソースを編集し、アプリケーションサーバーを再起動する前にdeploy/ ディレクトリにコピーします。
データソース設定に関する情報については、15章DataSource の設定 を参照してください。ご利用中のデータベースに対応させるには、少なくともconnection-urluser-namepassword を変更する必要があります。

14.3. 一般的なデータベース関連のタスク

14.3.1. セキュリティとプーリング

ResourceAdapter<reauthentication-support> がある場合を除き、 複数のセキュリティ ID を使用すると各 ID に対してサブプールが作成されます。

注記

最小および最大プールサイズはサブプールごとの容量になります。 ID の数が多い場合はこれらのパラメーターに注意してください。

14.3.2. JMS サービス用にデータベースを変更

JBoss Enterprise Application Platform の JMS サービスは関係データベースを使用してメッセージを永続します。パフォーマンス向上のため、 JMS サービスを変更して外部データベースを有効活用するようにします。それには、 外部データベースに応じてファイル $JBOSS_HOME/server/PROFILE/deploy/messaging/$DATABASE-persistence-service.xml をファイル $DATABASE-persistence-service.xml に置き換える必要があります。
  • MySQL: mysql-persistence-service.xml
  • PostgreSQL: postgresql-persistence-service.xml
  • Oracle: oracle-persistence-service.xml
  • DB2: db2-persistence-service.xml
  • Sybase: sybase-persistence-service.xml
  • MS SQL Server: mssql-persistence-service.xml

14.3.3. CMP サービスで外部キーのサポート

次に、 fk-constraint プロパティが true になるよう、$JBOSS_HOME/server/PROFILE/conf/standardjbosscmp-jdbc.xml ファイルを変更する必要があります。 JBoss Enterprise Application Platform 上でサポートする全ての外部データベースに対して変更する必要があります。 このファイルは、 JBoss Enterprise Application Platform にデプロイされた EJB2 CMP Bean のデータベース接続設定を構成します。
<fk-constraint>true</fk-constraint>

14.3.4. Java Persistence API 用にデータベースダイアレクトを指定

Java Persistence API (JPA) エンティティマネージャーは EJB3 エンティティ Bean をバックエンドデータベースに保存できます。 Hibernate は JBoss Enterprise Application Platform に JPA 実装を提供します。 Hibernate は、 付録にある下記データベースのダイアレクトなど多くのデータベースで動作する、 ダイアレクト自動検知メカニズムを持っています。 代替データベースに特定のダイアレクトが必要な場合は、 $JBOSS_HOME/server/PROFILE/deployers/ejb3.deployer/META-INF/jpa-deployers-jboss-beans.xml ファイルにデータベースファイルを設定することができます。 このファイルを設定するには、 マップエントリ hibernate.dialect に関連するタグセットをアンコメントし、 設定するデータベースに応じて次の値に変更する必要があります。
  • Oracle 10g: org.hibernate.dialect.Oracle10gDialect
  • Oracle 11g: org.hibernate.dialect.Oracle10gDialect
  • Microsoft SQL Server 2005: org.hibernate.dialect.SQLServerDialect
  • Microsoft SQL Server 2008: org.hibernate.dialect.SQLServerDialect
  • PostgresSQL 8.2.3: org.hibernate.dialect.PostgreSQLDialect
  • PostgresSQL 8.3.7: org.hibernate.dialect.PostgreSQLDialect
  • MySQL 5.0: org.hibernate.dialect.MySQL5InnoDBDialect
  • MySQL 5.1: org.hibernate.dialect.MySQL5InnoDBDialect
  • DB2 9.1: org.hibernate.dialect.DB2Dialect
  • Sybase ASE 15: org.hibernate.dialect.SybaseASE15Dialect

14.3.5. 外部データベースを使用するよう他の JBoss Enterprise Application Platform サービスを変更

JMS や CMP や JPA 以外にも、まだ他の JBoss サービス群を外部データベースと組み合わせる 必要があります。それには2つの方法があります。1つは、簡単ですが柔軟性がありません。 もう1つは、柔軟性に富みますがより多くのステップを必要とします。ここで、それらの 2つのアプローチを別々に説明していきましょう。

14.3.5.1. 簡単な方法

簡単な方法とは、外部データベース用の JNDI 名を DefaultDS に変更することです。ほとんどの JBoss サービスはデフォルトで DefaultDS を使用するように設定されています。そのため、 DataSource 名を変更するだけで、 各サービス用に個別設定を変更する必要はありません。
JNDI 名を変更するには、 外部データベースの *-ds.xml ファイルを開き、 jndi-name プロパティの値を DefaultDS に変更します。 例えば、 mysql-ds.xml では、 MySqlDSDefaultDS などに変更することになります。 この後、 DefaultDS 定義の重複を避けるために、 $JBOSS_HOME/server/PROFILE/deploy/hsqldb-ds.xml ファイルを削除する必要があります。
messaging/$DATABASE-persistence-service.xml ファイルでは、PersistenceManagers MBean の depends タグのデータソース名も DefaultDS に変更する必要があります。例えば、mysql-persistence-service.xml ファイルの場合、MySqlDSDefaultDS に変更します。
<mbean 
            code="org.jboss.messaging.core.jmx.JDBCPersistenceManagerService" 
            name="jboss.messaging:service=PersistenceManager" 
            xmbean-dd="xmdesc/JDBCPersistenceManager-xmbean.xml">
            
            <depends>jboss.jca:service=DataSourceBinding,name=DefaultDS</depends>

14.3.5.2. より柔軟な方法

外部 datasource を DefaultDS に変更することは便利です。 しかし、DefaultDS が常にファクトリデフォルトの HSQL DB を ポイントすることを想定してしまうアプリケーションがある場合、このやり方は アプリケーションを破損する可能性があります。また、DefaultDS 目的地を 変更することは、全ての JBoss サービスが外部データベースを使用することを強制することになります。 その場合、 一部のサービス用のみに外部データベースを使用したい時に問題になるでしょう。
より安全で柔軟に JBoss Enterprise Application Platform サービスを外部データベースに組み合わせるには、標準の JBoss サービスすべての DefaultDS を、 手作業で *-ds.xml ファイル内で定義されたデータソース JNDI 名 (mysql-ds.xml 内の MySqlDS など) に変更します。DefaultDS を含むファイルの完全一覧は次の通りです。 これら全てを更新して全 JBoss サービスで外部データベースを使用するか、 一部を更新してサービスごとに異なる組み合わせのデータソースを使用するようにします。
  • $JBOSS_HOME/server/PROFILE/conf/login-config.xml: このファイルは Java EE コンテナーで管理するセキュリティサービス内で使用されます。
  • $JBOSS_HOME/server/PROFILE/conf/standardjbosscmp-jdbc.xml: このファイルは EJB コンテナー内で CMP Bean を設定します。
  • $JBOSS_HOME/server/PROFILE/deploy/ejb2-timer-service.xml: このファイルは EJB タイマーサービスを設定します。
  • $JBOSS_HOME/server/PROFILE/deploy/juddi-service.sar/META-INF/jboss-service.xml: このファイルは UUDI サービスを設定します。
  • $JBOSS_HOME/server/PROFILE/deploy/juddi-service.sar/juddi.war/WEB-INF/jboss-web.xml: このファイルは UUDI サービスを設定します。
  • $JBOSS_HOME/server/PROFILE/deploy/juddi-service.sar/juddi.war/WEB-INF/juddi.properties: このファイルは UUDI サービスを設定します。
  • $JBOSS_HOME/server/PROFILE/deploy/uuid-key-generator.sar/META-INF/jboss-service.xml: このファイルは UUDI サービスを設定します。
  • $JBOSS_HOME/server/PROFILE/deploy/messaging/messaging-jboss-beans.xml および $JBOSS_HOME/server/PROFILE/deploy/messaging/persistence-service.xml: これらのファイルは前述の通り JMS 永続サービスを設定します。

14.3.6. Oracle DataBases に関する注記

本章で説明する設定は、 JBoss Enterprise Application Platform がサーバーの起動時に外部データベース内で 必要なテーブルを自動的に作成することを前提としています。 ほとんどの場合で問題ありませんが、 Oracle のようにデータベースによっては、 同じデータベースサーバーを使用して複数の JBoss Enterprise Application Platform インスタンスをサポートすると軽度な問題が発生することがあります。
Oracle データベースは schemaname.tablename形式のテーブルを作成します。JBoss Enterprise Application Platform で必要となる TIMERS テーブルと HILOSEQUENCES テーブルが別のスキーマ上に既に存在する場合、 スキーマ上には作成されません。この問題を回避するには、$JBOSS_HOME/server/PROFILE/deploy/ejb2-timer-service.xml ファイルを編集し、 テーブル名を TIMERS から schemaname2.tablename などのように変更します。
          <mbean code="org.jboss.ejb.txtimer.DatabasePersistencePolicy" 
          name="jboss.ejb:service=EJBTimerService,persistencePolicy=database">
          <!-- DataSourceBinding ObjectName -->
          <depends optional-attribute-name="DataSource">
          jboss.jca:service=DataSourceBinding,name=DefaultDS
          </depends>
          <!-- The plugin that handles database persistence -->
          <attribute name="DatabasePersistencePlugin">
          org.jboss.ejb.txtimer.GeneralPurposeDatabasePersistencePlugin
          </attribute>
          <!-- The timers table name -->
          <attribute name="TimersTable">TIMERS</attribute>
          </mbean>
同様に、$JBOSS_HOME/server/PROFILE/deploy/uuid-key-generator.sar/META-INF/jboss-service.xml ファイルも編集し、テーブル名を HILOSEQUENCES から schemaname2.tablename のように変更します。
 <!-- HiLoKeyGeneratorFactory --> <mbean
          code="org.jboss.ejb.plugins.keygenerator.hilo.HiLoKeyGeneratorFactory"
          name="jboss:service=KeyGeneratorFactory,type=HiLo">
          
          <depends>jboss:service=TransactionManager</depends>
          
          <!-- Attributes common to HiLo factory instances -->
          
          <!-- DataSource JNDI name -->
          <depends optional-attribute-name="DataSource">jboss.jca:service=DataSourceBinding,name=DefaultDS</depends>
          
          <!-- table name -->
          <attribute name="TableName">HILOSEQUENCES</attribute>

重要

Oracle 11g R1 で稼働する場合 、Oracle JDBC driver version 11.1.0.7.0 が原因で、JBoss Messaging Test Suite が SQLException ("Bigger type length than Maximum") を返し問題が発生します。
これは、Oracle JDBC ドライバー 11.1.0.7.0 の再発バグが原因となっています。
Oracle 11g R1、Oracle RAC 11g R1、Oracle RAC 11g R2 では、Orace JDBC ドライバーのバージョン 11.2.0.1.0 を使うように推奨されます。

第15章 DataSource の設定

警告

デフォルトの永続化設定は Hypersonic (HSQLDB) でそのまま機能するため、JBoss Enterprise Platform はカスタマイズなしにそのまま稼働することができます。ただし、Hypersonic は実稼働環境で対応していないため、実稼働環境で利用すべきではありません。
Hypersonic Database の既知の問題は以下のとおりです:
  • トランザクション分離がない
  • スレッドおよびソケットがリークする (connection.close() はリソースの整理を行いません)
  • 持続品質 (ログは通常、障害後は壊れてしまい自動回復ができなくなります)
  • データベースの破損
  • 負荷がかけられた際の安定性 (過剰なデータを処理すると、データベース処理は停止されます)
  • クラスター化環境では実行不可
サポートが必要であれば、『スタートガイド』 の「別のデータベースを利用」の章を確認してください。
DataSource は <datasources> 要素内に定義されます。正確な要素は、必要とされるデータソースの種類により変化します。

15.1. DataSource の種類

DataSource 定義

<no-tx-datasource>
JTA トランザクションには関与せず、java.sql.Driver を使用します。
<local-tx-datasource>
2相コミットには対応しておらず、java.sql.Driver を使用します。単一データベースあるいは非 XA 対応リソースに適しています。
<xa-datasource>
2 相コミットをサポートせず、javax.sql.XADataSource を使用します。

15.2. DataSource パラメーター

一般的な DataSource パラメーター

<mbean>
標準的な JBoss MBean デプロイメント
<depends>
このConnectionFactory または DataSource デプロイメントが依存する MBean サービスの ObjectName です。
<jndi-name>
DataSource がバインドされる JNDI 名です。
<use-java-context>
jndi-name のプレフィックスを java: とすべきかを示す Boolean 値です。このプレフィックスは JBoss Enterprise Application Platform の仮想マシン内からしか DataSource にアクセスできなくなります。デフォルトは true です。
<user-name>
データソースへの接続作成時に使用されるユーザー名です。

注記

セキュリティ設定されている場合は利用されません。
<password>
Datasource への接続が作成される際に使用されるパスワードです。

注記

セキュリティ設定されている場合は利用されません。
<transaction-isolation>
接続のデフォルトトランザクション分離です。指定しないとデータベースが提供するデフォルト値が使用されます。

<transaction-isolation> に対し可能な値

  • TRANSACTION_READ_UNCOMMITTED
  • TRANSACTION_READ_COMMITTED
  • TRANSACTION_REPEATABLE_READ
  • TRANSACTION_SERIALIZABLE
  • TRANSACTION_NONE
<new-connection-sql>
新規接続に対して実行される SQL ステートメントです。接続スキーマの設定などに使用できます。
<check-valid-connection-sql>
有効であるかを確認するため、プールからチェックアウトされる前に実行される SQL ステートメントです。この SQL ステートメントが失敗すると接続が閉じられ、新しい接続が作成されます。
<valid-connection-checker-class-name>
ベンダー固有のメカニズムを使用して接続が有効かを確認するクラスです。
<exception-sorter-class-name>
ベンダー固有のメッセージを解析し、SQL エラーが致命的でこの接続を破棄するかを判断するクラスです。空の場合、致命的エラーとして処理されるエラーはありません。
<track-statements>
閉じられていない Statement や ResultSet を監視し、閉じられていない場合に警告を発行するかを指定します。デフォルト値は NOWARN です。
<prepared-statement-cache-size>
後続のリクエストで閉じずに再利用する、接続毎の prepared ステートメントの数です。ステートメントは Least Recently Used (LRU) キャッシュに保存されます。デフォルト値は 0 で、これはキャッシュが保持されないということです。
<share-prepared-statements>
<prepared-statement-cache-size> が非ゼロの場合、同じトランザクション内の 2 つのリクエストが同じステートメントを返すべきであるかを指定します。デフォルトは FALSE です。

例15.1 <share-prepared-statements>の利用

目的は、ドライバーが自動コミットセマンティックをローカルトランザクションに適応してしまうこのドライバーの動作を回避することです。
       Connection c = dataSource.getConnection(); // auto-commit == false
       PreparedStatement ps1 = c.prepareStatement(...);
       ResultSet rs1 = ps1.executeQuery();
       PreparedStatement ps2 = c.prepareStatement(...);
       ResultSet rs2 = ps2.executeQuery();
これは、prepared ステートメントが同じであることを想定しています。 ドライバーによっては ps2.executeQuery() が自動的に rs1 を閉じてしまうため、背後に 真の prepared ステートメントが2つ必要となります。 これは、 クエリの再実行が自動的に新しいトランザクションを開始する、 自動コミットセマンテックのみが目的でなければなりません。 仕様に準拠するドライバーの場合、TRUE を設定して同じ真の prepared ステートメントを共有することができます。
<set-tx-query-timeout>
トランザクションがタイムアウトするまでの残り時間を基にクエリのタイムアウトを有効にするか指定します。 デフォルトは FALSE です。
<query-timeout>
クエリがタイムアウトするまでの最大時間 (秒)。<set-tx-query-timeout>を TRUE に設定することでこの値をオーバーライドすることができます。
<type-mapping>
conf/standardjbosscmp.xml 内の型マッピングへのポインターです。この要素は、<metadata> の子要素です。JBoss4 からのレガシー。
<validate-on-match>
プール外の接続を確認した場合など、JCA 層が管理された接続と一致する場合にこの接続を検証するかどうか指定します。<background-validation>を追加することで、これは必要なくなります。通常、<background-validation> に TRUE を指定するとともに、<validate-on-match> に TRUE を指定する必要はありません。デフォルト値は、TRUEです。
<prefill>
接続プールに最小接続数を事前に入力を試みるかを指定します。supporting pool (OnePool) のみがこの機能をサポートします。このプールが事前入力に対応しない場合、ログに警告が記録されます。デフォルトは TRUE となっています。
<background-validation>
バックグラウンドの接続検証は、接続を検証する際の RDBMS システム上の全体的な負荷を軽減します。この機能を使用すると、EAP はプール内の現在の接続が別のスレッド (ConnectionValidator) であるかをチェックします。<background-validation-minutes>は、TRUE に設定されているこの値により変わります。デフォルトは FALSE です。
<background-validation-millis>
バックグラウンドの接続検証は、 接続を検証する際の RDBMS システム上の全体的な負荷を軽減します。 このパラメーターを設定すると、 JBoss はプール内の現在の接続を個別のスレッド(ConnectionValidator) として検証しようとします。 パラメーターの値が ConnectionValidator の実行周期 (ミリ秒単位) を定義します (この値は <idle-timeout-minutes とは違う値でなければなりません)。
<idle-timeout-minutes>
アイドル状態の接続が閉じられるまでの最大時間 (分単位) を示します。値が0 の場合はタイムアウトが無効となります。デフォルトは 15 です。
<track-connection-by-tx>
トランザクションの最後に接続をプールに戻すの代わりに、接続をトランザクションにロックすべきかを指定します。以前のリリースでは、 ローカル接続ファクトリのデフォルト値は true で、 XA 接続ファクトリのデフォルト値は false でした。現在、 ローカル接続ファクトリと XA 接続ファクトリ両方のデフォルト値が true となり、要素は廃止されました。
<interleaving>
XA 接続ファクトリのインターリービングを有効にします。
<background-validation-minutes>
ConnectionValidator が実行される頻度 (分単位) になります。デフォルトは 15 になります。

注記

<min-pool-size> を最小プールサイズセットに指定していない限り、これを、<idle-timeout-minutes>よりも小さい値に設定する必要があります。
<url-delimiter>, <url-property>, <url-selector-strategy-class-name>
データベースのフェールオーバーを処理するパラメーター。JBoss Enterprise Application Platform 現在、これらのパラメーターは主なデータソース設定の一部として設定されています。以前のバージョンでは、 <url-delimiter> は <url-delimeter>として表示されていました。
<stale-connection-checker-class-name>
異常な接続を通知する SQLExceptionorg.jboss.resource.adapter.jdbc.StateConnectionExceptionの例外をスローするかを決定する org.jboss.resource.adapter.jdbc.StateConnectionChecker 実装です。
<max-pool-size>
プール内で接続可能な最大数です。定義されていない場合は、デフォルトは 10 となっています。datasource の定義例 ($JBOSS_HOME/server/PROFILE/hsqldb-ds.xml) の値は、20 に設定されています。
<min-pool-size>
プールで保持される最小接続数です。<prefill> が TRUE でない限り、プールが<min-pool-size>まで埋まった時点で最初に利用されるまで、プールは空ままとなります。アイドルによるタイムアウトが原因で、プールサイズが<min-pool-size> 以下に下がった場合、プールは<min-pool-size>まで補充されます。デフォルトは、0となっています。
<blocking-timeout-millis>
すべての接続がチェックアウトされた時、接続が使用できるまで待機する時間になります。デフォルトは 30000 (30 秒) になります。
<use-fast-fail>
以前の試行が失敗あるいはフェールオーバーが開始された場合でも、プールからの接続取得を試行するかを指定します。これは、SQL 検証の実行に時間とリソースが多くかかるようなパフォーマンスの問題に対処するためです。デフォルトは、FALSEとなっています。

javax.sql.XADataSource を使用するためのパラメーター

<connection-url>
JDBC ドライバー接続の URL ストリングです。
<driver-class>
java.sql.Driver を実装する JDBC ドライバークラスです。
<connection-property>
java.sql.Driver から取得した接続を設定するために使用されます。

例15.2 例:<connection-property>

       <connection-property name="char.encoding">UTF-8</connection-property>

javax.sql.XADataSource を使用するためのパラメーター

<xa-datasource-class>
XADataSource を実装するクラスです。
<xa-datasource-property>
XADataSource の設定に使用されるプロパティです。

例15.3 例: <xa-datasource-property> の宣言

<xa-datasource-property name="IfxWAITTIME">10</xa-datasource-property>
<xa-datasource-property name="IfxIFXHOST">myhost.mydomain.com</xa-datasource-property>
<xa-datasource-property name="PortNumber">1557</xa-datasource-property>
<xa-datasource-property name="DatabaseName">mydb</xa-datasource-property>
<xa-datasource-property name="ServerName">myserver</xa-datasource-property>
<xa-resource-timeout>
0 でない場合、XAResource.setTransactionTimeout() を経過した秒数になります。
<isSameRM-override-value>
FALSE に設定した場合、Oracle データベースの問題の一部を修正します。
<no-tx-separate-pools>
トランザクショナル接続と非トランザクショナル接続を別々にプールします。

警告

このオプションを使うと、実際のプールが2つ作成されるため、合計のプール容量がmax-pool-sizeの2倍になります。
Oracle の問題を修正するために利用されます。

セキュリティパラメーター

<application-managed-security>
getConnection に渡されたユーザー名とパスワードを使用するか、 アプリケーションによる createConnection リクエストを使用します。
<security-domain>
conf/login-module.xml に設定されている確認されたログインモジュールを使用します。
<security-domain-and-application>
conf/login-module.xml に設定されている確認されたログインモジュールや、 アプリケーション (JMS のキューやトピックなど) によって提供される他の接続要求情報を使用します。

JCA レイヤーにてXAをリカバリするためのパラメーター

<recover-user-name>
リカバリ操作を行うことのできる認証情報を持つユーザー
<recover-password>
リカバリ操作を行うことのできるユーザー (認証情報付き) のパスワード
<recover-security-domain>
リカバリ用のセキュリティドメイン
<no-recover>
リカバリからのデータソースを除外
JCA レイヤーにてXAをリカバリするためのパラメーターのフィールドに、non-recover と対となるフォールバック値(<user-name>,< password> and <security-domain>)を入力する必要があります。

15.3. データソースの例

データベース固有の例については、付録A ベンダー固有のデータソース定義 を参照してください。

15.3.1. 汎用データソースの例

例15.4 汎用データソースの例

          <datasources>
  <local-tx-datasource>
    <jndi-name>GenericDS</jndi-name>
    <connection-url>[jdbc: url for use with Driver class]</connection-url>
    <driver-class>[fully qualified class name of java.sql.Driver implementation]</driver-class>
    <user-name>x</user-name>
    <password>y</password>
    <!-- you can include connection properties that will get passed in 
	 the DriverManager.getConnection(props) call-->
    <!-- look at your Driver docs to see what these might be -->
    <connection-property name="char.encoding">UTF-8</connection-property>
    <transaction-isolation>TRANSACTION_SERIALIZABLE</transaction-isolation>

    <!--pooling parameters-->
    <min-pool-size>5</min-pool-size>
    <max-pool-size>100</max-pool-size>
    <blocking-timeout-millis>5000</blocking-timeout-millis>
    <idle-timeout-minutes>15</idle-timeout-minutes>
    <!-- sql to call when connection is created
	 <new-connection-sql>some arbitrary sql</new-connection-sql>
    -->

    <!-- sql to call on an existing pooled connection when it is obtained from pool 
	 <check-valid-connection-sql>some arbitrary sql</check-valid-connection-sql>
    -->

    <set-tx-query-timeout></set-tx-query-timeout>
    <query-timeout>300</query-timeout> <!-- maximum of 5 minutes for queries -->

    <!-- pooling criteria.  USE AT MOST ONE-->
    <!--  If you don't use JAAS login modules or explicit login 
	 getConnection(usr,pw) but rely on user/pw specified above, 
	 don't specify anything here -->

    <!-- If you supply the usr/pw from a JAAS login module -->
    <security-domain>MyRealm</security-domain>

    <!-- if your app supplies the usr/pw explicitly getConnection(usr, pw) -->
    <application-managed-security></application-managed-security>

    <!--Anonymous depends elements are copied verbatim into the ConnectionManager mbean config-->
    <depends>myapp.service:service=DoSomethingService</depends>

  </local-tx-datasource>

  <!-- you can include regular mbean configurations like this one -->
  <mbean code="org.jboss.tm.XidFactory" 
	 name="jboss:service=XidFactory">
    <attribute name="Pad">true</attribute>
  </mbean>


  <!-- Here's an xa example -->
  <xa-datasource>
    <jndi-name>GenericXADS</jndi-name>
    <xa-datasource-class>[fully qualified name of class implementing javax.sql.XADataSource goes here]</xa-datasource-class>
    <xa-datasource-property name="SomeProperty">SomePropertyValue</xa-datasource-property>
    <xa-datasource-property name="SomeOtherProperty">SomeOtherValue</xa-datasource-property>

    <user-name>x</user-name>
    <password>y</password>
    <transaction-isolation>TRANSACTION_SERIALIZABLE</transaction-isolation>



    <!--pooling parameters-->
    <min-pool-size>5</min-pool-size>
    <max-pool-size>100</max-pool-size>
    <blocking-timeout-millis>5000</blocking-timeout-millis>
    <idle-timeout-minutes>15</idle-timeout-minutes>
    <!-- sql to call when connection is created
	 <new-connection-sql>some arbitrary sql</new-connection-sql>
    -->

    <!-- sql to call on an existing pooled connection when it is obtained from pool 
	 <check-valid-connection-sql>some arbitrary sql</check-valid-connection-sql>
    -->


    <!-- pooling criteria.  USE AT MOST ONE-->
    <!--  If you don't use JAAS login modules or explicit login 
	 getConnection(usr,pw) but rely on user/pw specified above, 
	 don't specify anything here -->

    <!-- If you supply the usr/pw from a JAAS login module -->
    <security-domain></security-domain>

    <!-- if your app supplies the usr/pw explicitly getConnection(usr, pw) -->
    <application-managed-security></application-managed-security>

  </xa-datasource>

</datasources>
				
				
				
				

15.3.2. リモート使用向けのDataSource の設定

JBoss EAP はリモートのクライアントからDataSource へのアクセスに対応しています。クライアントが JNDI より DataSource をルックアップできるように変更するには、例15.5「リモート利用向けの DataSource の設定」 を参照してください。これは、 use-java-context=false を指定します。

例15.5 リモート利用向けの DataSource の設定

   <datasources>
     <local-tx-datasource>
       <jndi-name>GenericDS</jndi-name>
       <use-java-context>false</use-java-context>
       <connection-url>...</connection-url>
       ...
これにより、DataSource がデフォルトの java:/GenericDS ではなく GenericDS という JNDI 名でバインドされるため、EAP サーバーと同じ Virtual Machine へのルックアップが制限されます。

注記

実稼働環境では、<use-java-context> 設定の利用は推奨されません。接続プールへのリモートアクセスが必要となり、接続がシリアル化可能でないため予期せぬ問題が発生する可能性があります。また、(クラッシュやネットワーク障害など)信頼性に欠ける場合、接続リークの原因となる可能性があるため、トランザクション伝搬はサポートされません。DataSource へのリモートでアクセスするには、リモートセッション Bean ファサードからのアクセスが推奨されます。

15.3.3. ログインモジュールを使用するようDataSource を設定

手順15.1 ログインモジュールを使用するようDataSource を設定

  1. データソースについて、<security-domain-parameter> を XML ファイルに追加します。

         <datasources>
           <local-tx-datasource>
             ...
             <security-domain>MyDomain</security-domain>
             ...
           </local-tx-datasource>
         </datasources>
    
  2. login-config.xml ファイルにアプリケーションポリシーを追加します。

    認証セクションにはログインモジュールの設定が含まれるようにしなければなりません。例えば、 データベースパスワードを暗号化する場合、 SecureIdentityLoginModule ログインモジュールを使用します。
    <application-policy name="MyDomain">
       <authentication>
          <login-module code="org.jboss.resource.security.SecureIdentityLoginModule" flag="required">
             <module-option name="username">scott</module-option>
             <module-option name="password">-170dd0fbd8c13748</module-option>
             <module-option name="managedConnectionFactoryName">jboss.jca:service=LocalTxCM,name=OracleDSJAAS</module-option>
          </login-module>
       </authentication>
    </application-policy>
    
  3. Web アプリケーションからデータソース接続をフェッチするつもりであれば、Web アプリケーションに対する認証を有効化し、Subject が生成されるようにする必要があります。
  4. ユーザーが無名で接続する機能が必要な場合、 application-policyに別のログインモジュールを追加しセキュリティ証明書を生成します。
  5. UsersRolesLoginModule モジュールをチェーンの最初に追加します。usersPropertiesrolesProperties パラメーターをダミーファイルに移動することができます。
    <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required">
       <module-option name="unauthenticatedIdentity">nobody</module-option>
       <module-option name="usersProperties">props/users.properties</module-option>
       <module-option name="rolesProperties">props/roles.properties</module-option>
    </login-module>
    

第16章 プーリング

16.1. 戦略

JBossJCAManagedConnectionPool を使用してプーリングを実行します。ManagedConnectionPool は、選択された戦略やその他のプーリングパラメーターに応じて、サブプールで構成されます。
xml
mbean
内部名
詳細
 
ByNothing
OnePool
同等の接続の単一プール。
<application-managed-security/>
ByApplication
PoolByCRI
allocateConnection() より接続プロパティを使用。
<security-domain/>
ByContainer
PoolBySubject
サブジェクト (事前設定のサブジェクトまたは EJB/Web ログインサブジェクト) 毎のプール。
<security-domain-and-applicaton/>
ByContainerAndApplicaton
PoolBySubjectAndCri
サブジェクト毎と接続プロパティの組み合わせ。

注記

xml 名を見るとセキュリティに関連しているように見えますが、違います。
<security-domain-and-application/> では、サブジェクトは常に CRI の createConnection(user, password) からのユーザーやパスワードより優先されます。
(
ConnectionRequestInfo
)

16.2. トランザクションスティッキネス

<track-connection-by-tx/> フラグを用いると、 プール (またはサブプール) からの同じ接続をトランザクション中に強制的に再利用することができます。

注記

これは「ローカル」トランザクションのみサポートされる動作となります。 JBoss Enterprise Application Platform 5 ではデフォルトでトランザクションスティッキネスが有効になっているため、この要素は廃止されました。 XA ユーザーは <interleaving/> 要素で明示的にインターリービングを有効にできます。

16.3. Oracle での回避法

Oracle は、 JTA トランザクション内部および外部でのXA 接続の使用を好みません。 この問題を回避するには、 <no-tx-separate-pools/> を使用して異なるコンテキストに対して個別のサブプールを作成します。

16.4. プールアクセス

プールは同時使用のためにあります。
同時に (またはプールからの接続を使用して) 最大 <max-pool-size/> のスレッド数がプール内に存在することができます。
スレッド数がこの制限に達すると、 No Managed Connections Available をスローする前にスレッドはプールを使用するため <blocking-timeout-seconds/> の期間待機します。
例外をスローする前にプールが接続の取得を再試行するようにするには、 <allocation-retry/> 要素と <allocation-retry-wait-millis/> 要素を使用します。

16.5. プールの充填

プール内の接続数はプールの大きさによって制御されます。
  • <min-pool-size/> - 接続数がこの値を下回ると新しい接続が作成されます。
  • <max-pool-size/> - この値を越える数の接続は作成されません。
  • <prefill/> - 4.0.5 に機能要求が実装されました。 注意: OnePool? または ByNothing? プーリング基準のみがこの機能をサポートします。
プールの充填は、 アプリケーションスレッドをブロックするのではなく、 個別の「Pool Filler」スレッドによって行われます。

重要

最初の利用では、接続プールを充填は min-pool-size までに制限されます。

16.6. アイドル接続

ピーク期間の終了後に未使用の接続をリープ処理したい場合など、 アイドル状態の接続を閉じるよう接続を設定することができます。 これには、 <idle-timeout-minutes/> を使用します。
アイドル状態の確認は、 LRU (Least Recently Used) 方式で個別の「Idle Remover」によって実行されます。 idle-timeout-minutes の期間使用されていない接続に対し、 idle-timeout-minutes を 2 で割った周期で確認が実行されます。
プール自体は MRU (Most Recently Used) 方式で操作します。 これにより、 余分な接続を簡単に特定することができます。
アイドル状態の接続を閉じたため、 プールにある接続の数が min-pool-size を下回ってしまった場合、 新規の接続が作成されます。

注記

長期実行しているトランザクションが存在し、 インターリービングを使用している場合 (track-connection-by-tx を使用しない場合など)、 アイドルタイムアウトの値がトランザクションタイムアウトの値より大きくなるようにしてください。 インターリービングを使用している場合、 他のユーザーが使用できるよう接続がプールに戻されます。 戻された接続が使用されなかった場合、 トランザクションがコミットされる前に削除される候補となります。

16.7. 停止接続

JDBC プロトコルは接続が切断されていると自然な connectionErrorOccured() イベントを提供しません。 停止された接続や切断された接続のチェックをサポートするには、 複数のプラグインがあります。

16.7.1. 有効な接続チェック

最も簡単な形式は 「クイック」SQL ステートメントを実行するだけです:
<check-valid-connection-sql>select 1 from dual</check-valid-connection-sql>
これは、接続をアプリケーションに渡す前に行います。これに失敗した場合、 選択できる接続がなくなるまで他の接続が選択され、 選択できる接続がなくなった時点で新しい接続が作成されます。
より性能が高いと思われるチェックを実行するにはベンダー固有の機能を使用します。例えば、以下でOracle または MySQLの pingDatabase() を行います。
<valid-connection-checker-class-name/>

16.7.2. SQL クエリ中のエラー

クエリ中に接続が切断されたかをチェックするには、通常の SQLExceptions ではなく、 SQLException のエラーコードやエラーメッセージより FATAL エラーを確認します。これらのコードやメッセージはベンダー固有の場合があります。例:
<exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
FATAL エラーに関しては、接続が終了します。

16.7.3. プールの変更/終了/フラッシュ

  • プールの 変更または flush() 
  • プールを終了するか、アンデプロイすると、 最初にフラッシュされます。

16.7.4. その他プーリング

サードパーティのプール - 知識があり理解している場合のみ参照してください。

第17章 よくある質問 (FAQ) 

17.1. Oracle XA の問題

以下を確認してください。
  1. conf/jboss-service.xml の XidFactory が pad=true になっていますか。
  2. oracle-xa-ds.xml に <track-connection-by-tx/> がありますか (JBoss Enterprise Application Platform 5.x ではデフォルトで有効におり、 要素が廃止されたため必要ありません)。
  3. oracle-xa-ds.xml に <isSameRM-override-value>false</isSameRM-override-value> がありますか。
  4. oracle-xa-ds.xml に <no-tx-separate-pools/> がありますか。
  5. jbosscmp-jdbc.xml が使用している Oracle と同じバージョンを指定していますか。
  6. 接続する Oracle サーバーに XA がありますか。
XA サポート向けの Oracle データベースを設定すると、 Oracle データベースが XA リソースをサポートするよう設定することができます。 これにより、 JDBC 2.0 対応の Oracle ドライバーを使用することができます。 Oracle データベースを XA 向けに初期化するには、 次の手順に従ってください。
Oracle JServer がご利用中のデータベースにインストールされているようにしてください。 インストールされていない場合は、Oracle データベース設定アシスタントを使用して追加する必要があります。 「Change an Existing DB」を選択し、 Oracle JServer を追加したいデータベースを指定します。 「Next」、「Oracle JServer」、「Finish」を順に選択します。 以前設定したデータベース設定が Oracle JServer に適していない場合、あるいは十分でない場合は、 追加のパラメーターを入力するよう求められます。 データベース設定ファイルinit.ora\oracle\admin\<your_db_name>\pfileディレクトリにあります。 データベース上で initxa.sql を実行します。 デフォルトでは、 このスクリプトファイルは \oracle\ora81\javavm\install にあります。 ファイル実行中にエラーが発生した場合は、 手作業でファイルから SQL ステートメントを実行する必要があります。 DBA Studio を使用してパッケージと JAVA_XA という名前のパッケージボディーを SYS スキーマに作成し、 このパッケージのシノニム (名前は同様に JAVA_XA) を PUBLIC スキーマに作成します。

パート III. クラスタリングガイド

第18章 概要とクイックスタート

クラスタリングにより、アプリケーションクライアントに単一のビューを提供しつつ、1 つのアプリケーションを複数の並列サーバー (クラスターノード) で実行することができるようになります。 負荷は複数のサーバーに分散されるため、1 つまたは複数のサーバーに障害が発生した場合でも、障害が発生しなかったクラスターノードからアプリケーションにアクセスすることができます。 クラスターにノードを追加するだけでパフォーマンスを向上させることができるクラスタリングはスケーラブルな企業向けアプリケーションに欠かせません。また、クラスタリングインフラストラクチャーが高可用性を実現するのに必要な冗長性をサポートするため、クラスタリングは可用性の高い企業アプリケーションを実現するためにも重要です。
production サーバープロファイルの一部として、 JBoss Enterprise Application Platform にはそのまま使用できるクラスタリングサポートが含まれています。production サーバープロファイルには次のサポートが含まれています。
  • スケーラブルでフォールトトレラントな JNDI 実装 (HA-JNDI)。
  • 次を含む Web 層クラスタリング。
    • ステートレプリケーションによる Web セッションステートの高可用性。
    • ハードウェアロードバランサーやソフトウェアロードバランサーとの統合が可能( mod_jk や JK ベースのソフトウェアロードバランサーとの特殊な統合など)。
    • クラスター全体のシングルサインオンサポート。
  • ステートフル Bean およびステートレス Bean に対する、EJB3 とEJB2 両方の EJB セッション Bean クラスタリング
  • JPA/Hibernate エンティティに対する分散キャッシュ。
  • ノード上で Bean に変更があった時にクラスター全体でキャッシュエントリを無効化し、 クラスター全体におけるローカル EJB2 エンティティキャッシュの整合性を維持するフレームワーク。
  • 分散 JMS キューと JBoss Messaging によるトピック。
  • クラスターの複数のノード上でサービスかアプリケーションをデプロイし、1 つのノード上のみでアクティブにすることを HA シングルトンと呼びます。
  • Farm サービスにて、デプロイされたコンテンツの同期化をクラスターのすべてのノード上で維持します。
クラスタリングガイド は、 JBoss Enterprise Application Platform におけるクラスタリング機能の使用方法を深く理解することを目的としています。 最初に、 JBoss Enterprise Application Platform のクラスタリングをお試しいただくため、 基本的な「クイックスタート」の手順を紹介し、 JBoss Enterprise Application Platform クラスタリングの仕組みを理解していただくため、 基礎的な情報を提供します。 次に、クラスター機能を使用して JEE サービスをクラスターする方法について詳しく説明します。 最後に、 JGroups と JBoss Cache の上級設定、 JBoss Enterprise Application Platform クラスタリングの基礎となる技術について詳しく説明します。

18.1. クイックスタートガイド

本項の目的は、 JBoss Enterprise Application Platform のクラスタリングを使用するために最低必要な情報を提供することです。 本項に記載されている内容の多くは、 本項以降で詳しく説明されています。

18.1.1. 最初の準備

JBoss Enterprise Application Platform クラスターがサーバーのセットとして動作するよう準備するには、 次の手順に従います。
  • JBoss Enterprise Application Platform をすべてのサーバーにインストールします。 JBoss のダウンロードを各サーバー上のファイルシステムに展開するのが最も簡単な方法です。
    複数の JBoss Enterprise Application Platform インスタンスを単一のサーバーで実行したい場合は、 完全な JBoss ディストリビューションをファイルシステムの複数の場所にインストールするか、production サーバープロファイルのコピーを作成します。例えば、JBoss ディストリビューションのルートが /var/jboss に展開された場合、次を行います。
    $ cd /var/jboss/server
    $ cp -r production node1
    $ cp -r production node2
  • 各ノードに対して、ソケットをバインドするアドレスを決定します。 クラスター化の有無に関係なく、 JBoss を起動する際に、 ソケットがトラフィックをリッスンするアドレスを JBoss に伝える必要があります (デフォルトは localhost で、 安全ですがクラスター内ではあまり実用的ではありません)。 そのため、 アドレスを決める必要があります。
  • マルチキャストが動作しているか確認します。 デフォルトでは、 JBoss Enterprise Application Platform はほとんどのクラスタ内での通信で UDP マルチキャストを使用します。 各サーバーのネットワーク設定がマルチキャストをサポートし、 サーバー間のスイッチやルーターに対してマルチキャストサポートが有効になっているようにしてください。 1 つのサーバー用で複数のノードを実行したい場合は、 サーバーのルーティングテーブルにマルチキャストルートが含まれているようにしてください。 マルチキャストが動作しているかを確認する JGroups の分析ツールの使用方法など、詳細は http://www.jgroups.org のJGroups ドキュメントを参照してください。

    注記

    JBoss Enterprise Application Platform のクラスタリングは UDP マルチキャストの使用を必要としません。 クラスター内での通信で TCP ユニキャストを使用するよう再設定することもできます。
  • ノード毎に一意の整数 "ServerPeerID" を決定します。 これは JBoss Messaging のクラスタリングに必要で、JBoss Messaging を実行しない場合は必要ありません (サーバープロファイルの deploy ディレクトリから JBM を削除する場合など)。JBM を実行する場合、 クラスターの各ノードには"ServerPeerID" と呼ばれる固有の整数 ID が必要になります。

    重要

    簡単な 「1, 2, 3, ..., x」のようなネーミングスキームで構いませんが、値は 0 から 1023 の範囲でなければなりません。この範囲外の値になると、ServerPeer 起動サービスで java.lang.IllegalArgumentExceptionが発生します。
    「JBoss Enterprise Application Platform クラスターの起動」にて、ServerPeerID の使用方法について説明します。
上記が必須の手順となりますが、 クラスターをネットワークで実行されている他の JBoss Enterprise Application Platform クラスターから適切に分離するため、 次の 2 つのオプション手順が推奨されます。
  • クラスターに対して固有の名前を選択します。 JBoss Enterprise Application Platform クラスターのデフォルトの名前は 「DefaultPartition」です。 ご自分の環境の各クラスターに対して異なる名前を付けてください (「QAPartition」や「BobsDevPartition」など)。 名前に「Partition」を使用する必要はありませんが、 慣例的に使用されます。 クラスターの周囲で送信されるすべてのメッセージに名前が含まれるため、 パフォーマンスを考慮して短い名前を付けるようにしてください。 選択した名前の使用方法については次の項で取り上げます。
  • クラスターに対して固有のマルチキャストアドレスを選択します。 デフォルトでは、 JBoss Enterprise Application Platform はほとんどのクラスタ内の通信に UDP マルチキャストを使用します。 実行する各クラスターに対して異なるマルチキャストアドレスを選択してください。 一般的に、 マルチキャストアドレスには 239.255.x.y の形式を使用するのがよいでしょう。 マルチキャストアドレスの割り当てについては、 http://www.29west.com/docs/THPM/multicast-address-assignment.html を参照してください。 選択したアドレスの使用方法については、 次の項で説明します。
クラスターの分離についての詳細は、 「JGroups チャネルの分離」 を参照してください。

18.1.2. JBoss Enterprise Application Platform クラスターの起動

JBoss サーバークラスターを開始する一番簡単な方法は、 各インスタンスに -c production コマンドラインオプションを使用して同じローカルネットワーク上で複数の JBoss インスタンスを開始することです。これらのサーバーインスタンスは相互に検出を行い、自動的に 1 つのクラスターを形成します。
ここで、 いくつかの異なるシナリオを見てみましょう。すべてのシナリオで 2 ノードクラスターを 1 つ作成し、 最初のノードは 1、 2 つ目のノードは 2 とします。クラスターの名前を「DocsPartition」とし、 239.255.100.100 をマルチキャストアドレスとして使用するようにします。 シナリオは例の提示を目的としています。例として最も単純であるため 2 ノードのクラスターを使用しますが、 2 ノードがサイズ的に最適であるとは限りません。
  • シナリオ 1: 個別のマシン上のノード
    このシナリオは実稼働環境では最も一般的なシナリオです。 マシン名は「node1」と「node2」で、 node1 の IP アドレスは 192.168.0.101、 node2 の IP アドレスは 192.168.0.102 とします。 node1 の ServerPeerID は 1 、 node2 の ServerPeerID は 2 とし、 各マシンの /var/jboss に JBoss がインストールされているとします。
    node1 で JBoss を開始します。
    $ cd /var/jboss/bin
    $ ./run.sh -c production -g DocsPartition -u 239.255.100.100 \
        -b 192.168.0.101 -Djboss.messaging.ServerPeerID=1
    node2 でも同様ですが、 -b の値と ServerPeerID の値が異なります。
    $ cd /var/jboss/bin
    $ ./run.sh -c production -g DocsPartition -u 239.255.100.100 \
        -b 192.168.0.102 -Djboss.messaging.ServerPeerID=2
    -c スイッチは、 クラスタリングサポートが含まれる production 設定の使用を指示します。 -g スイッチは、 クラスター名を設定します。 -u スイッチはクラスター内での通信で使用されるマルチキャストアドレスを設定します。 -b スイッチはソケットがバインドされるアドレスを設定します。 -D スイッチは、 JBoss Messaging が固有の ID を取得するシステムプロパティ jboss.messaging.ServerPeerID を設定します。
  • シナリオ 2: 単一のマルチホームサーバー上の 2 ノード
    同じマシンで複数のノードを実行することは開発環境では一般的で、 実稼働環境でもシナリオ 1 を併用して使用されます (すべてのノードを単一マシン上の実稼働クラスタで実行することは、 マシン自体が単一障害点となるため通常推奨されません)。 このシナリオでは、 マシンがマルチホーム化されています (複数の IP アドレスを持っている状態)。 これにより、 各JBoss インスタンスを異なるアドレスにバインドできるため、 ノードがソケットを開ける際の競合を防ぐことができます。
    単一のマシンに アドレスとして 192.168.0.101192.168.0.102 が割り当てられ、 シナリオ 1 と同様に 2 つの JBoss インスタンスが同じアドレスと ServerPeerIDs を使用するとします。 シナリオ 1 との違いは、 Enterprise Application Platform インスタンスが独自のワークエリアを持つようにすることです。 そのため、 production 設定を使用せずに、 前項で production よりコピーした node1 設定と node2 設定を使用するようにします。
    最初のインスタンスを起動するため、 コンソールウインドウを開いて次を実行します。
    $ cd /var/jboss/bin
    $ ./run.sh -c node1 -g DocsPartition -u 239.255.100.100 \
        -b 192.168.0.101 -Djboss.messaging.ServerPeerID=1
    2 つ目のインスタンスも同様ですが、 -b 値、 -c 値、 ServerPeerID が異なります。
    $ cd /var/jboss/bin
    $ ./run.sh -c node2 -g DocsPartition -u 239.255.100.100 \
        -b 192.168.0.102 -Djboss.messaging.ServerPeerID=2
  • シナリオ 3: マルチホーム化されていない単一サーバー上の 2 ノード
    シナリオ 2 と似ていますが、 マシンの IP アドレスは 1 つのみになります。 2 つのプロセスはソケットと同じアドレスやポートにバインドできないため、 2 つのインスタンスに異なるポートを使用するよう JBoss に伝える必要があります。 これには、 jboss.service.binding.set システムプロパティを設定して ServiceBindingManager サービスを設定します。
    最初のインスタンスを起動するため、 コンソールウインドウを開いて次を実行します。
    $ cd /var/jboss/bin
    $ ./run.sh -c node1 -g DocsPartition -u 239.255.100.100 \
        -b 192.168.0.101 -Djboss.messaging.ServerPeerID=1 \
        -Djboss.service.binding.set=ports-default
    2 つ目のインスタンスには次を実行します。
    $ cd /var/jboss/bin
    $ ./run.sh -c node2 -g DocsPartition -u 239.255.100.100 \
        -b 192.168.0.101 -Djboss.messaging.ServerPeerID=2 \
        -Djboss.service.binding.set=ports-01
    これは、 最初のノード上にある ServiceBindingManager に標準のポートセット (1099 番ポート上の JNDI など) を使用するよう指示します。 2 つ目のノードは、 標準のポート番号から 100 を引いた番号 (1199 番ポート上の JNDI など) を持つ各ポートのデフォルトである ports-01 を使用します。 ServiceBindingManager 設定の全体については、 conf/bindingservice.beans/META-INF/bindings-jboss-beans.xml ファイルを参照してください。
    この設定は異なるポートを使用し、 管理が複雑になるため、 実稼働環境への使用は推奨されません。 クラスタリングを使用したいのにワークステーションをマルチホーム化できない開発環境では一般的なシナリオとなります。

    注記

    技術的に、 ports-default はデフォルト値であるため、 node1 のコマンドラインに-Djboss.service.binding.set=ports-default を含める必要はありませんが、 慣れていないユーザーはすべてのサーバーで統一されたコマンドライン引数を使用した方が簡単でしょう。
これで終了です。 JBoss Enterprise Application Platform サーバーのクラスターを開始し、 実行することができるようになります。

18.1.3. Web アプリケーションクラスタリングのクイックスタート

JBoss Enterprise Application Platform は、クラスターにある 1 つ以上のノードに各ユーザーの HttpSession ステートのバックアップコピーが保存されるクラスタ化された Web セッションをサポートします。 セッションを処理する 1 次ノードに障害が発生あるいは停止した場合、 クラスターの別のノードがバックアップコピーにアクセスし、 セッションの後続要求を処理することができます。Web 層クラスタリングの詳細は 『HTTP コネクター負荷分散ガイド』 を参照してください。
Web 層クラスタリングには 2 つの側面があります。
  • 外部ロードバランサーの設定。Web アプリケーションは、 JBoss Enterprise Application Platform インスタンスのクラスター全体で HTTP 要求を負荷分散するため、 外部ロードバランサーを必要とします (その理由については、 「外部ロードバランサーアーキテクチャー」 を参照)。 JBoss Enterprise Application Platform 自体は HTTP ロードバランサーとして機能しないため、 ハードウェアロードバランサーかソフトウェアロードバランサーを設定する必要があります。 選択できるロードバランサーは多く存在するため、 ロードバランサーの設定方法については本クイックスタートの範囲外となります。 よく使用される mod_jk ソフトウェアロードバランサーの設定についての詳細は、 『HTTPコネクター負荷分散ガイド』を参照してください。
  • クラスタリングに対する Web アプリケーションの設定。 これには、特定の Web アプリケーションに対する希望のクラスタリング動作を JBoss に伝える必要があります。 それには、 空の distributable 要素をアプリケーションの web.xml ファイルに追加します。
    <?xml version="1.0"?> 
    <web-app  xmlns="http://java.sun.com/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
                                  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
              version="2.5">
              
        <distributable/>
        
    </web-app>
    上記を実行すれば、 ほとんどのアプリケーションでデフォルトの JBoss Enterprise Application Platform のWeb セッションクラスタリング動作を実行できるはずです。詳細設定オプションについては、『HTTP コネクター負荷分散ガイド』を参照してください。

18.1.4. EJB セッション Bean クラスタリングのクイックスタート

JBoss Enterprise Application Platform は、 クラスター全体で Bean の要求が分散されるクラスターされた EJB セッション Bean をサポートします。 ステートフル Bean については、 Bean ステートのバックアップコピーは 1 つ以上のクラスターノードで維持されるため、特定のセッションを処理しているノードに障害が発生あるいは停止した場合に高可用性を提供できます。 EJB2 Bean と EJB3 Bean 両方のクラスタリングがサポートされます。
EJB3 セッション Bean の場合、 org.jboss.ejb3.annotation.Clustered アノテーションをステートフル Bean またはステートレス Bean の Bean クラスに追加します。
@javax.ejb.Stateless
@org.jboss.ejb3.annotation.Clustered
public class MyBean implements MySessionInt {
   
   public void test() {
      // Do something cool
   }
}
EJB2 セッション Bean や、アノテーションでなく XML 設定を使用したい EJB3 Bean の場合、 JBoss 固有の配備記述子である jboss.xml の Bean のセクションに、 clustered 要素を追加します。
<jboss>    
    <enterprise-beans>      
        <session>        
            <ejb-name>example.StatelessSession</ejb-name>        
            <jndi-name>example.StatelessSession</jndi-name>        
            <clustered>true</clustered>
        </session>
    </enterprise-beans>
</jboss>
詳細の設定オプションについては、22章クラスター化されたセッション EJB を参照してください。

18.1.5. エンティティクラスタリングのクイックスタート

JBoss Enterprise Application Platform 5 のクラスタリングで大幅に改善された機能の 1 つが、 Hibernate 3.3 で導入された 2 次エンティティキャッシングに対して新しい Hibernate/JBoss Cache 統合を使用することです。 JPA/Hibernate コンテキストでは、 2 次キャッシュは、トランザクションの範囲外で保持されたコンテンツを持つキャッシュを参照します。 データベースの読み取り回数を減らすと、 2 次キャッシュのパフォーマンスが改良されることがあります。 常に 2 次キャッシュを有効にしてアプリケーションの負荷をテストし、無効にしてから特定のアプリケーションに対して有益であるか確認するようにしてください。
複数の JBoss Enterprise Application Platform インスタンスを使用して JPA/Hibernate アプリケーションを実行し、 2 次キャッシュを使用する場合、 クラスター対応のキャッシュを使用しなければなりせん。 クラスター対応のキャッシュを使用しないと、 サーバー B 上のアクティビティがエンティティを更新した後でもサーバー A 上のキャッシュは古いデータを保持することになります。
JBoss Enterprise Application Platform は、 JBoss Cache を基にしたクラスター対応の 2 次レベルを提供します。 JBoss Enterprise Application Platform の標準の Hibernate ベース JPA プロバイダーが JBoss Cache での 2 次キャッシングを有効にするには、 persistence.xml を次のように設定します。
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
   http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
   version="1.0"> 
   <persistence-unit name="somename" transaction-type="JTA">
      <jta-data-source>java:/SomeDS</jta-data-source>
      <properties>
         <property name="hibernate.cache.use_second_level_cache" value="true"/>
         <property name="hibernate.cache.region.factory_class" 
                   value="org.hibernate.cache.jbc2.JndiMultiplexedJBossCacheRegionFactory"/>
         <property name="hibernate.cache.region.jbc2.cachefactory" value="java:CacheManager"/>
         <!-- Other configuration options ... -->
      </properties>
   </persistence-unit>
</persistence>
これにより、 Hibernate が JBoss Cache ベースの 2 次キャッシュを使用するよう指示しますが、 キャッシュするエンティティは指定されていません。 キャッシュするエンティティを指示するには、 org.hibernate.annotations.Cache アノテーションをエンティティクラスに追加します。
package org.example.entities;
 
import java.io.Serializable;
import javax.persistence.Entity;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
 
@Entity
@Cache(usage=CacheConcurrencyStrategy.TRANSACTIONAL)
public class Account implements Serializable {
詳細設定オプションや、 JPA でない Hibernate アプリケーションを同様に設定する方法については、 23章クラスター化した Entity EJB を参照してください。

注記

クラスタリングは JPA/Hibernate の 2 次キャッシュのオーバーヘッドを大幅に増加させます。 そのため、 2 次キャッシングがクラスター化されていないアプリケーションに有益であってもクラスター化されたアプリケーションにも有益であるとは限りません。 クラスター化された 2 次キャッシングが総合的に有益である場合、 頻繁に変更されるエンティティタイプはクラスター化されていない場合に有益でもクラスター化されていると有益でないこともあります。 常にアプリケーションの負荷をテストするようにしてください。

第19章 クラスタリングの概念

次項では、JBoss のクラスタリングサービスの基礎となる基本概念について説明します。 この概念を先に理解してから残りのクラスタリングガイドを読むようにするとよいでしょう。

19.1. クラスター定義

クラスターは、お互いにやりとりし、目的を共有する一連のノードです。JBoss Application Server クラスター (パーティションとも呼ばれます) では、ノードは JBoss Enterprise Application Server インスタンスです。ノード間の通信は、クラスター内のノードを追跡する中核的な機能を提供し、クラスターメンバー間のメッセージを安定的に交換する JGroups Channel とともに JGroups グループ通信ライブラリによって処理されます。同じ設定と名前を持つ JGroups Channel は動的にお互いのノードを検索し、グループを形成することができます。このため、同じネットワークの 2 つの AS インスタンスで「run -c production」を実行するだけで、ノードがクラスターを形成するようになります。各 Enerprise Application Platform は同じデフォルト設定で Channel (実際には複数) を開始し、その結果、お互いのノードが動的に検索され、クラスターが形成されます。ノードは、他のクラスターメンバーと同じ設定と名前で Channel を開始または停止するだけでいつでもクラスターに動的に追加、あるいはクラスターから動的に削除できます。
同じ Enterprise Application Platform インスタンス上で、別サービスが独自の Channel を作成することができます。Enterprise Application Platform 5 の production サーバープロファイルを標準起動すると、 2 つの異なるサービスが合計 4 つのチャネルを作成します。JBoss Messaging が 2 つのチャネルを作成し、 HAPartition と呼ばれるコアの汎用クラスタリングサービスも 2 つのチャネルを作成します。 クラスター化された Web アプリケーションやクラスター化された EJB3 SFSB、クラスター化された JPA/Hibernate エンティティキャッシュをデプロイすると、追加のチャネルが作成されます。 Enterprise Application Platform が接続するチャネルは、大きく 3 つに分類されます (HAPartition サービスが使用する汎用チャネル、特別用途のキャッシングやクラスター全体のステートレプリケーション向けに JBoss Cache が作成したチャネル、 JBoss Messaging が使用する 2 つのチャネル)。
したがって、2 つの Enterprise Application Platform 5.0.x インスタンスで run -c production を実行すると、お互いのチャネルが検索され、概念的な cluster が形成されます。これは 2 ノードクラスターと考えると分かりやすいですが、実際には 4 つのチャネル、したがって 4 つの 2 ノードクラスターであると理解することが重要です。
同じネットワーク上でサービスがクラスタリングしたい異なるセットのサーバーがあるとします。 図19.1「クラスターとサーバーノード」 は、 3 つのセットに分割された JBoss サーバーインスタンスのネットワーク例です。 3 番目のセットにはノードが 1 つしかありません。 このようなトポロジは、 ノードのセット内でチャネル設定と名前が一致するようクラスターを形成するようにして設定します。 この場合、 チャネル設定と名前が他のチャネル設定と名前のマッチと異なるようにし、 同じネットワークの別のチャンネルとも異なるようにします。 Enterprise Application Platform はこの設定をなるべく簡単にします。 クラスター化するサーバーは、 同じ値をコマンドラインの -g (パーティション名) と -u (マルチキャストアドレス) 起動スイッチに渡すことだけが必要になります。 各サーバーセットには異なる値を選択する必要があります。「JGroups 設定」と「JGroups チャネルの分離」の項に、 検索したいピアのみを見つけるようEnterprise Application Platform を設定する方法が説明されています。
クラスターとサーバーノード

図19.1 クラスターとサーバーノード

19.2. サービスアーキテクチャー

各ノードで JGroups 設定によって定義されるクラスタリングのトポグラフィはシステム管理者にとって非常に重要となります。 アプリケーション開発者の場合は、 クライアントアプリケーションの観点から見るクラスターアーキテクチャーの方が関心が高いと思います。 JBoss Enterprise Application Platform ではクライアント側インターセプター (スマートプロキシまたはスタブとも呼ばれます) と外部ロードバランサーの 2 つの基本クラスタリングアーキテクチャーが使用されています。 アプリケーションが使用するアーキテクチャーは、 クライアントのタイプによって異なります。

19.2.1. クライアント側インターセプターアーキテクチャー

JNDI、EJB、JMS、RMI、JBoss Remoting などの JBoss Enterprise Application Platform によって提供されるリモートサービスの多くは、クライアントによるリモートプロキシオブジェクトの取得 (ルックアップやダウンロードなど) を必要とします。 プロキシオブジェクトはサーバーによって生成され、 サービスのビジネスインターフェースを実装します。 次にクライアントはプロキシオブジェクトに対してローカルメソッド呼び出しを行います。 プロキシは自動的に呼び出しをネットワーク全体にルーティングし、 サーバー内で管理されるサービスオブジェクトに対して呼び出されます。 プロキシオブジェクトは、 適切なサーバーノードやマーシャル呼び出しパラメーター、 アンマーシャル呼び出し結果を検索する方法を見いだし、 結果を呼び出し側クライアントに返します。 クラスター化された環境では、 サーバーによって生成されたプロキシオブジェクトには、 クラスター内の複数のノードに呼び出しをルーティングする方法を認識するインターセプターが含まれています。
プロキシのクラスタリング論理はクラスターに関する最新のナレッジに対応しています。 例えば、 使用可能な全サーバーノードの IP アドレス、 ノード全体に負荷を分散させるアルゴリズム (次項を参照)、 目的のノードが使用できない場合に要求をフェイルオーバーする方法などを認識しています。 各サービス要求を処理する際にクラスタトポロジが変更されると、 サーバーノードはクラスター内の最終変更にてプロキシを更新します。 例えば、 クラスターからノードがドロップアウトすると、次にクラスタのアクティブなノードに接続した時に各プロキシが新しいトポロジで更新されます。 プロキシのクラスタリング論理で行われる操作はすべてクライアントアプリケーションに対して透過的となります。 図19.2「クラスタリング用クライアント側インターセプター (プロキシ) アーキテクチャー」 は、 クライアント側のインターセプタークラスタリングアーキテクチャーになります。
クラスタリング用クライアント側インターセプター (プロキシ) アーキテクチャー

図19.2 クラスタリング用クライアント側インターセプター (プロキシ) アーキテクチャー

19.2.2. 外部ロードバランサーアーキテクチャー

HTTP ベースの JBoss サービスはクライアントによるダウンロードを必要としません。 クライアント (Web ブラウザーなど) は、 HTTP プロトコルを使用して直接要求を送信、あるいは 応答を受信します。 この場合、 外部ロードバランサーがすべての要求を処理し、 クラスター内複数のノードに要求を送信する必要があります。 クライアントはロードバランサーへの接続方法のみ認識している必要があります。 クライアントはロードバランサーへのコンタクト方法のみ理解する必要があり、 ロードバランサー背後の JBoss Enterprise Application Platform インスタンスについては認識しません。 ロードバランサーは論理的にはクラスターの一部ですが、クライアントや JBoss Enterprise Application Platform インスタンスと同じプロセスで実行されていないため、「外部」と呼ばれます。 ロードバランサーはソフトウェアかハードウェアに実装できます。 ハードウェアロードバランサーのベンダーは数多く存在します。 mod_jk Apache モジュールはソフトウェアロードバランサーの良い例です。 外部ロードバランサーはクラスター設定を理解する独自のメカニズムを実装し、 独自の負荷分散ポリシーやフェイルオーバーポリシーを提供します。 図19.3「クラスタリング用外部ロードバランサーアーキテクチャー」 は外部ロードバランサーのクラスタリングアーキテクチャーになります。
クラスタリング用外部ロードバランサーアーキテクチャー

図19.3 クラスタリング用外部ロードバランサーアーキテクチャー

外部ロードバランサーに伴う問題は、 ロードバランサー自体が単一点障害になり得ることです。 クラスターサービス全体が高可用性を維持するよう注意深く監視する必要があります。

19.3. 負荷分散ポリシー

JBoss クライアント側インターセプター (スタブ) とロードバランサーはいずれも負荷分散ポリシーを使用して新しい要求を送信するサーバーノードを確定します。 この項では JBoss Enterprise Application Platform 内で使用可能な負荷分散ポリシーについて説明します。

19.3.1. クライアント側インターセプターアーキテクチャー

JBoss Enterprise Application Platform 5 では、 クライアント側インターセプターアーキテクチャーが使用されている時に次の負荷分散オプションを使用できます。 クライアント側スタブは目的のサービスを提供するすべてのノードの一覧を保持します。 各要求に対してこの一覧からノードを選択することが負荷分散ポリシーの役割です。 各ポリシーは 2 つの実装クラスを持っています。 1 つは、 レガシー分離呼び出しアーキテクチャーを使用する EJB2 のようなレガシーサービスが使用するための実装クラスです。 もう 1 つは AOP ベースの呼び出しを使用する EJB3 のようなサービスのための実装クラスになります。
  • Round-Robin: 各呼び出しは、 ノードの一覧の順に新しいノードへ配信されます。 最初のターゲットノードは一覧より無作為に選択されます。 org.jboss.ha.framework.interfaces.RoundRobin (レガシー) と org.jboss.ha.client.loadbalance.RoundRobin (EJB3) によって実装されます。
  • Random-Robin: 各呼び出しに対して一覧よりターゲットノードを無作為に選択します。 org.jboss.ha.framework.interfaces.RandomRobin (レガシー) と org.jboss.ha.client.loadbalance.RandomRobin (EJB3) によって実装されます。
  • First Available: 使用可能なターゲットノードの 1 つがメインターゲットとして選択されてから全てのコールに使用されます。 選択されるメンバーはクラスター内のメンバーの一覧から無作為に選択されます。 ターゲットノードの一覧が変更されると (1 ノードが起動または停止したため)、 現在選択されているノードが使用可能である場合を除き、 ポリシーによって新しいターゲットノードが選択されます。 各クライアント側プロキシは、他のプロキシに関係なく独自のターゲットノードを選択します。 そのため、 特定のクライアントが同じターゲットサービス (EJB など) に対して 2 つのプロキシをダウンロードする場合、各プロキシは独立してターゲットを選択します。 これが「セッションアフィニティ」または「スティッキーセッション」を提供するポリシーの例となります (ターゲットノードは確立されると変更されないため)。 org.jboss.ha.framework.interfaces.FirstAvailable (レガシー) や org.jboss.ha.client.loadbalance.aop.FirstAvailable (EJB3) によって実装されます。
  • First Available Identical All Proxies: 「First Available」 ポリシーと同じ動作になりますが、 選択されるターゲットノードは同じターゲットサービスに関連付けられた同じクライアント側 VM のすべてのプロキシで共有されます。 そのため、 特定のクライアントが同じターゲットサービス (EJB など) に対して 2 つのプロキシをダウンロードする場合、 各プロキシは同じターゲットを使用します。 org.jboss.ha.framework.interfaces.FirstAvailableIdenticalAllProxies (レガシー) や org.jboss.ha.client.loadbalance.aop.FirstAvailableIdenticalAllProxies (EJB3) によって実装されます。
上記のいずれもが org.jboss.ha.framework.interfaces.LoadBalancePolicy インターフェースを実装します。ユーザーは特殊な動作を必要とする場合にこの単純なインターフェースの独自の実装を自由に作成できます。後半のセクションでは、さまざまなサービスによって使用される負荷分散ポリシーの設定方法について説明します。

19.3.2. 外部ロードバランサーアーキテクチャー

JBoss Enterprise Application Platform 5 では新しく "TransactionSticky" 負荷分散ポリシーが導入されました。 これらのポリシーは、 トランザクションの範囲内で発生するすべての呼び出しを同じノードにルーティングする (ノードが存在する場合) など、 新しい動作を標準のポリシーに追加します。 レガシー分離呼び出しアーキテクチャーがベースであるため、 EJB3 のような AOP ベースのサービスでは使用できません。
  • Transaction-Sticky Round-Robin: Round-Robin のトランザクションスティッキー変異です。 org.jboss.ha.framework.interfaces.TransactionStickyRoundRobin によって実装されます。
  • Transaction-Sticky Random-Robin: Random-Robin のトランザクションスティッキー変異です。 org.jboss.ha.framework.interfaces.TransactionStickyRandomRobin によって実装されます。
  • Transaction-Sticky First Available: First Available のトランザクションスティッキー変異のです。 org.jboss.ha.framework.interfaces.TransactionStickyFirstAvailable によって実装されます。
  • Transaction-Sticky First Available Identical All Proxies: First Available Identical All Proxies のトランザクションスティッキー変異です。 org.jboss.ha.framework.interfaces.TransactionStickyFirstAvailableIdenticalAllProxies によって実装されます。
上記はすべて簡単なインターフェースの実装となります。ユーザーは特殊な動作を必要とする場合に独自の実装を自由に作成することができます。 後半の項では、さまざまなサービスによって使用される負荷分散ポリシーの設定方法について説明します。

第20章 ビルディングブロックのクラスター化 

JBoss Enterprise Application Platform のクラスタリング機能は、コア機能の多くを提供するローレベルライブラリの上にビルドされています。 図20.1「JBoss Enterprise Application Platform のクラスタリングアーキテクチャー」 に主な機能が記載されています。
JBoss Enterprise Application Platform のクラスタリングアーキテクチャー

図20.1 JBoss Enterprise Application Platform のクラスタリングアーキテクチャー

JGroups は、 信頼できるポイントツーポイント通信やポイントツーマルチポイント通信向けのツールキットです。 JGroups は JBoss Enterprise Application Platform クラスターにおけるノード間のクラスター関連の通信に使用されます。
JBoss Cache は、 大変柔軟なクラスター化されたトランザクションキャッシングライブラリです。 Enterprise Application Platform のクラスタリングサービスの多くが、 メモリ内にステートをキャッシュする必要があります。 この際、 再作成 (Web セッションの内容など) できない場合にステートのバックアップコピーが別のノードで使用できるよう、高可用性を維持し、クラスターの各ノードにキャッシュされたデータの一貫性を維持する必要があります 。JBoss Cache は、JBoss Enterprise Application Platform のクラスター化サービスのこのような懸念に対応します。JBoss Cache は JGroups を使用してグループ通信の要件に対応します。 POJO Cache は JBoss Cache のコアの延長で、 クラスターされた Web セッションステートのきめ細かいレプリケーションをサポートするため JBoss Enterprise Application Platform によって使用されます。 JBoss Enterprise Application Platform が JBoss Cache や POJO Cache をどのように使用するかについては、 「JBoss Cache による分散キャッシング」 を参照してください。
HAPartition は JGroups の上部にあるアダプターで、 複数のサービスが JGroups チャネルを使用できるようにします。 HAPartition は、 クラスターメンバ上で実行されている HAParition ベースのサービスに対する分散レジストリをサポートします。 クラスターメンバーシップやクラスターされたサービスのレジストリが変更した時に、 リスナーに通知を行います。 HAPartition の詳細は 「HAPartition サービス」 を参照してください。
他の高レベルクラスタリングサービスは JBoss Cache か HAPartition を使用します。 HA-JNDI は JBoss Cache と HAPartition の両方を使用します。 例外は JBoss Messaging のクラスタリング機能で、 JGroups と直接対話します。

20.1. JGroups とのグループ通信

JGroups は、 JBoss Enterprise Application Platform クラスタに対する基礎のグループ通信サポートを提供します。 ピアとグループ通信する必要がある JBoss Enterprise Application Platform は JGroups Channel を取得し、 通信するために使用します。 Channel は、どのノードがグループのメンバーであるかを管理し、 ノードの障害を検出して、 すべてのグループメンバに対してメッセージを失わないよう先着 (FIFO) 順にメッセージを発信します。 また、フロー制御を提供し、低速のメッセージ受信者が高速のメッセージ送信者によって圧倒されないようにします。
JGroups Channel の特徴は、 JGroups Channel を構成するプロトコルのセットによって決まります。 各プロトコルはグループ通信タスク全体の 1 つのアスペクトを処理します。 例えば、 UDP プロトコルは UDP データグラムの送受信の詳細に対応します。 UDP プロトコルを使用する Channel は UDP ユニキャストとマルチキャストと通信することができます。 TCP プロトコルを使用する Channel は、 すべてのメッセージに対して TCP ユニキャストを使用することができます。 JGroups は多くのプロトコルをサポートしていますが (詳細は 「JGroups チャネルのプロトコルスタックを設定」 を参照)、 Enterprise Application Platform には多くのニーズに対応するチャネル設定のデフォルトセットが同梱されています。
デフォルトでは、Enterprise Application PlatformのJGroupsチャネルがすべてUDPマルチキャストを利用します(TCPベースのJBoss Messaging チャネルは例外)。サーバーに対するデフォルトのマルチキャストタイプを変更するには、$JBOSS_HOME/bin/run.confを作成し、そのファイルを開きJAVA_OPTS="$JAVA_OPTS -Djboss.default.jgroups.stack=<METHOD>"を追加します。

20.1.1. チャネルファクトリサービス

JBoss Enterprise Application Platform 5 と以前のリリースとの大きな違いは、 クラスタリングサービスが必要とする JGroups Channel (分散 HttpSession キャッシュによって使用されるチャネルなど) が、 コンシュームするサービスの設定の一部として詳細に設定にされなくなり、 コンシュームするサービスによって直接インスタンス化されなくなったことです。 その代わりに、 名前付きチャネル設定のレジストリおよび Channel インスタンスのファクトリとして、 新しい ChannelFactory サービスが使用されるようになりました。 チャネルが必要なサービスは ChannelFactory よりチャネルをリクエストし、 希望する設定の名前を渡します。
ChannelFactory サービスは server/production/deploy/cluster/jgroups-channelfactory.sar にデプロイされます。 ChannelFactory サービスは起動時に名前 (UDP や TCP など) によって識別される様々な標準 JGroups 設定が含まれる server/production/deploy/cluster/jgroups-channelfactory.sar/META-INF/jgroups-channelfactory-stacks.xml ファイルを構文解析します。チャネルが必要なサービスはチャネルファクトリにアクセスし、特定の名前付き設定を持つチャネルを要求します。

注記

複数のサービスが ChannelFactory より同じ設定名を持つチャネルをリクエストした場合、 同じ基礎のチャネルへの参照はこれらのサービスには提供されません。 各サービスへ独自のチャネルが提供されますが、 チャネルの設定はすべて同じになります。 この場合、 これらのチャネルが同じマルチキャストアドレスやポートを使用する場合など、 チャネル同士がグループを形成しないようにする方法が論理的な問題となります。そのため、 コンシュームするサービスがチャネルに接続し、 サービスに固有の cluster_name 引数を Channel.connect(String cluster_name) メソッドに渡します。 ネットワーク上で受信したメッセージが意図されたものであるかを判断する要素の 1 つとして、 チャネルは cluster_name を使用します。

20.1.1.1. 標準のプロトコルスタック設定

Enterprise Application Platform 5 に同梱される標準のプロトコルスタック設定は以下のようになります。すべての設定が実際に使用されるわけではありません。 同梱される多くはデフォルトのサーバープロファイルを変更したいユーザー向けの設定となります。 変更されていない本来の Enterprise Application Platform 5 の production サーバープロファイルで実際に使用される設定は、udpjbm-controljbm-data になります。JBoss Messaging 以外のクラスタリングサービスは udp を使用します。
新しいスタック設定を追加するには、 新しい stack 要素を server/production/deploy/cluster/jgroups-channelfactory.sar/META-INF/jgroups-channelfactory-stacks.xml ファイルに追加します。 このファイルを編集すると、既存設定の動作を変更できます。 追加や変更を行う前に、 Enterprise Application Platform に同梱される標準設定を確認してみてください。 ニーズに合った標準設定があるかもしれません。 また、 設定を編集する前にどのサービスがこの設定を利用しているか把握し、影響を受ける全サービスに対して、変更したい設定が適切であるよう確認します。特定のサービスに対して変更が不適切な場合、 新しい設定を作成して一部のサービスが新しい設定を使用するよう変更した方がよいかもしれません。
  • udp
    UDP マルチキャストベースのスタックは、 異なるチャンネルによって共有されることを目的としています。 同期グループ RPC の待ち時間が長くなるため、 メッセージのバンドルは無効になっています。 非同期 RPC のみを大量に呼び出すサービス (REPL_ASYNC 向けに設定された JBoss Cache など) の場合、 次のようにキャッシュが udp-async スタックを使用するよう設定するとパフォーマンスを改善できるでしょう。 同期 RPC のみを呼び出すサービス (REPL_SYNC や INVALIDATION_SYNC 向けに設定された JBoss Cache など) の場合、 フロー制御が含まれない次の udp-sync スタックを使用するとパフォーマンスを改善できるでしょう。
  • udp-async
    前述のデフォルトの udp スタックと同じですが、 トランスポートプロトコルでメッセージバンドルが有効になっています (enable_bundling=true)。 メッセージのバインドによりパフォーマンスが改善できる大量の非同期 RPC (REPL_ASYNC 向けに設定された大量の JBoss Cache インスタンスなど) を呼び出すサービスに対して有用です。
  • udp-sync
    フロー制御やメッセージバンドルがない UDP マルチキャストベースのスタックです。 同期呼び出しが使用され、 メッセージの量 (メッセージ比率とサイズ) が大きくない場合、 udp の代わりに使用することができます。持続率が高い状態でメッセージを送信する場合、 メモリが不足することがあるため、 この設定は使用しないでください。
  • tcp
    フロー制御とメッセージバンドルを持つ TCP ベースのスタックです。TCP スタックは通常、 ネットワークで IP マルチキャストが使用できない場合に使用します (ルーターがマルチキャストを破棄する場合など)。
  • tcp-sync
    フロー制御やメッセージバインドがない TCP ベースのスタックです。 TCP スタックは通常、 ネットワークで IP マルチキャストが使用できない場合に使用します (ルーターがマルチキャストを破棄する場合など)。 同期呼び出しが使用され、 メッセージの量 (メッセージ比率とサイズ) が大きくない場合、 前述の tcp の代わりにこの設定を使用するようにしてください。高い持続率でメッセージを送信する場合、 メモリが不足することがあるため、 この設定は使用しないでください。
  • jbm-control
    JBoss Messaging の制御チャネル向けに最適化されたスタックです。 デフォルトでは、 前述の udp スタックがデフォルトで使用する UDP トランスポートプロトコル設定と同じ設定が使用されます。 これにより、 JBoss Messaging の制御チャネルが、 他の標準 JBoss Enterprise Application Platform のクラスタされたサービスが使用するソケットやネットワークバッファー、 スレッドプールを使用できるようになります (「JGroups 共有トランスポート」 を参照してください)。
  • jbm-data
    JBoss Messaging データチャネル向けに最適化された TCP ベースのスタックです。

20.1.1.2. プロトコルスタック設定の変更

デフォルトでは、JBoss Messaging 以外のクラスタリングサービスはすべてudp プロトコルスタック設定を利用します。TCPベースの設定を利用したい場合、system property jboss.default.jgroups.stackをtcp の値(-Djboss.default.jgroups.stack=tcp)に設定してください。この変更により、JGroups チャネルを使うサービスのほとんどをTCPベースの設定に構成します。tcp をデフォルトのプロトコルスタックにするには、Linux プラットフォームでは $JBOSS_HOME/bin/run.confにあるJAVA_OPTS の環境変数に、またWindows プラットフォームでは$JBOSS_HOME/bin/run.conf.batにある環境変数をこのシステムプロパティを追加します。
tcp スタックは、ピア検出に (MPING層経由で) UDPマルチキャストを使います。こうすることで、スタックが環境固有のホスト設定を避け、カスタマイズなしに使うことができます。UDPマルチキャストを利用できない場合、非UDPベースのピア検出層 (TCPPING層)に変更し、必要と考えられるクラスターノードのアドレス/ポートを設定する必要があります。jgroups-channelfactory-stacks.xml からプロトコルスタック設定を変更できます。このファイルには、両ピア検出層の定義をを含みます。デフォルトでは、MPING層の定義はアンコメントされ、TCPPING層はコメントされています。非UDPベースのピア検出に切り替えるには、MPING層をコメント、TCPPING層をアンコメントし、設定します。MPINGおよびTCPPINGの詳細情報は、「ディスカバリプロトコル」 を参照してください。

20.1.1.3. JBoss Messagingのプロトコルスタック設定

JBoss Messagingはデフォルトでjbm-control および jbm-data プロトコルスタック設定を利用します。jbm-control プロトコルスタックは、完全にUDPベースとなっており、jbm-data はUDPマルチキャストを採用するMPING検出プロトコルを使います。そのため、JBoss Messaging でTCPベースの設定のみを使いたい場合は、JBoss Messaging コントロールチャネルをjbm-control スタックの代わりにtcp プロトコルスタックを使用するよう設定し、jbm-data プロトコルスタックがMPING層の代わりにTCPPING層を利用するように変更しなければなりません。
JBoss Messaging コントロールチャネルをtcp プロトコルスタックを使うように設定するには、deploy/messaging/RDMS-persistence-service.xmlファイルを開き(RDMS の値はメッセージの永続化に利用している関係データベース管理システムにより変わります)、org.jboss.messaging.core.jmx.MessagingPostOfficeService mbeanのControlChannelName 属性値をtcpに変更します。
<!--<attribute name="ControlChannelName">jbm-control</attribute>-->
<attribute name="ControlChannelName">tcp</attribute>
MPING層ではなくTCPPING層を使うようにjbm-data プロトコルスタック定義を変更するには、/server/PROFILE/deploy/cluster/jgroups-channelfactory.sar/META-INF/jgroups-channelfactory-stacks.xml を開き、例20.1「TCPPING 定義を持つjbm-data プロトコルスタックの定義」に示されているようにMPING層を同等のTCPPING層に置き換えます。

例20.1 TCPPING 定義を持つjbm-data プロトコルスタックの定義

<!--
<MPING timeout="3000"
      num_initial_members="3"
      mcast_addr="${jboss.jgroups.tcp.mping_mcast_addr:230.11.11.11}"
      mcast_port="${jgroups.tcp.mping_mcast_port:45700}"
      ip_ttl="${jgroups.udp.ip_ttl:2}"/>
-->
<TCPPING timeout="5000"
      initial_hosts="${jbm.data.tcpping.initial_hosts:localhost[7900],localhost[7901]}"
      port_range="1"
      num_initial_members="3"/>
定義済みポートが他のTCPPING層で使われているポートと矛盾しないようにしてください。システムプロパティ-Djbm.data.tcpping.initial_hosts を使い、JAVA_OPTSからこの層の初期ホストを設定することができます。

20.1.2. JGroups 共有トランスポート

Enterprise Application Platform 上で実行される JGroups ベースのクラスタリングサービスの数が年を追って増加したため、これらのチャネルが使用するリソース (特にソケットとスレッド) を共有する必要性が問題となりました。 Enterprise Application Platform 5 の production 設定は、起動時に 4 つの JGroups チャネルに接続します。分散可能な Web アプリケーション、クラスターされた EJB3 SFSB、 クラスターされた JPA/Hibernate 2 次キャッシュがすべて使用されると合計で 7 つまたは 8 つの JGroups チャネルが接続されます。 チャネルの数が多くリソースが大幅に消費されることがあるため、 ネットワーク環境が設定にクラスター分離を必要とする場合、 設定が大変困難になります。
Enterprise Application Platform 5 より、 JGroups がチャネル間のトランスポートプロトコルインスタンスの共有をサポートするようになりました。 JGroups チャネルは、 個別のプロトコルのスタックにより構成され、各プロトコルはチャネル動作の 1 つのアスペクトを担当しています。ト ランスポートプロトコルは、 実際にメッセージをネットワーク上で送信、あるいはネットワークより受信するプロトコルです。 共有が望ましいリソース (ソケットとスレッドプール) はトランスポートプロトコルにより管理されているため、 チャネル間でトランスポートプロトコルを共有すると、 JGroups のリソースを効率的に共有することができます。
トランスポートプロトコルの共有を設定するには、 singleton_name="someName" 属性をプロトコルの設定に追加します。 トランスポートプロトコル設定が同じ singleton_name 値を使用するすべてのチャネルがトランスポートを共有します。 スタック内の他のプロトコルは共有されません。 図20.2「共有トランスポートを使用するサービス」 では、 仮想マシンで 4 つのサービスが実行され、 各サービスが独自のチャネルを持っています。 3 つのサービスがトランスポートを共有し、 1 つのサービスは独自のトランスポートを使用しています。
共有トランスポートを使用するサービス

図20.2 共有トランスポートを使用するサービス

Enterprise Application Platform 5 の ChannelFactory が使用するプロトコルスタック設定にはすべて singleton_name が設定されています。 スタックのチャネルを作成する前に singleton_name が含まれていない ChannelFactory にスタックを追加すると、 「unnamed_customStack」 のように 「unnamed_」 ストリングにスタック名を連結して ChannelFactory が合成的に singleton_name を作成します。

20.2. JBoss Cache による分散キャッシング

JBoss Cache は、 アプリケーションサーバー環境やスタンドアローンで使用できるフル機能の分散キャッシュフレームワークです。 JBoss Cache は、 以下を含む JBoss Enterprise Application Platform クラスターの多くの標準クラスター化サービスが使用する基礎の分散キャッシングサポートを提供します。
  • クラスター化された Web アプリケーションセッションのレプリケーション
  • クラスター化された EJB3 ステートフルセッション Bean のレプリケーション
  • JPA および Hibernate エンティティのクラスター化されたキャッシング
  • クラスター化されたシングルサインオン
  • HA-JNDI レプリケートツリー
  • DistributedStateService
アプリケーションのカスタム使用のために独自の JBoss Cache インスタンスや POJO Cache インスタンスを作成することもできます。 詳細は、 28章JBoss Cache の設定とデプロイメント を参照してください。

20.2.1. JBoss Enterprise Application Platform の CacheManager サービス

JBoss Enterprise Application Platform の標準のクラスター化されたサービスの多くは JBoss Cache を使用してクラスタ全体で一貫的なステートを維持します。 異なるサービス (Web セッションクラスタリングや JPA/Hibernate エンティティの 2 次レベルキャッシングなど) は異なる JBoss Cache インスタンスを使用し、 各キャッシュは使用するサービスに合わせて設定されます。 Enterprise Application Platform 4 では、 各キャッシュが個別に deploy/ ディレクトリへデプロイされたため、 次のような欠点がありました。
  • エンドユーザーが必要ないキャッシュもデプロイされ、 各キャッシュが JGroup チャネルを作成しました。 例えば、 クラスター化された EJB3 SFSB がなくても、 保存されるキャッシュが開始されました。
  • キャッシュはキャッシュを使用するサービスの内部的な詳細であるため、 ファーストクラスのデプロイメントとするべきではありません。
  • サービスは JMX ルックアップよりキャッシュを検索するのですが、管理インターフェースを公開する目的以外で JMX を使用することは、JBoss Enterprise Application Platform 5 の方針に反します。
JBoss Enterprise Application Platform 5 では、散在するキャッシュデプロイメントが、$JBOSS_HOME/server/production/deploy/cluster/jboss-cache-manager.sar よりデプロイされる新しい CacheManager サービスに置き換えられました。 CacheManager はファクトリで、JBoss Cache インスタンスのレジストリです。 キャッシュが必要なサービスは、 名前を用いてキャッシュマネージャーにキャッシュを要求します。 キャッシュマネージャがキャッシュを作成し (キャッシュが作成されていなかった場合)、返します。キャッシュマネージャーは作成したキャッシュの参照を保持するため、 同じキャッシュ設定名をリクエストするすべてのサービスが同じキャッシュを共有します。 サービスは使用を終えたキャッシュをキャッシュマネージャーに解放します。 キャッシュマネージャは各キャッシュを使用するサービスの数を把握し、すべてのサービスがキャッシュを解放した後にキャッシュを停止し破棄します。

20.2.1.1. 標準のキャッシュ設定

次の標準 JBoss Cache 設定が JBoss Enterprise Application Platform 5 に同梱されます。 ニーズに合わせて別の設定を追加するか、これらの設定を編集してキャッシュの動作を調整することができます。 追加や変更を行うには、 deploy/cluster/jboss-cache-manager.sar/META-INF/jboss-cache-manager-jboss-beans.xml ファイルを編集します (詳細は 「CacheManager サービスによるデプロイメント」 を参照)。 ただし、 これらの設定は使用目的に合わせて最適化されているため、 本ガイドの各サービスに対する章に明確に説明がない限り、 変更しない方がよいでしょう。
  • standard-session-cache
    Web セッションに使用される標準のキャッシュです。
  • field-granularity-session-cache
    FIELD 粒度の Web セッションに使用される標準のキャッシュです。
  • sfsb-cache
    EJB3 SFSB キャッシングに使用される標準のキャッシュです。
  • ha-partition
    Web の階層のクラスター化されたシングルサインオン、 HA-JNDI、 分散ステートによって使用されます。
  • mvcc-entity
    JBoss Cache の MVCC ロッキングを使用する JPA/Hibernate エンティティ/コレクションキャッシングに適切な設定です (下記の注記を参照)。
  • optimistic-entity
    JBoss Cache の楽観的ロッキングを使用する JPA/Hibernate のエンティティ/コレクションキャッシングに適切な設定です (下記の注記を参照)。
  • pessimistic-entity
    JBoss Cache の悲観的ロッキングを使用する JPA/Hibernate のエンティティ/コレクションキャッシングに適切な設定です (下記の注記を参照)。
  • mvcc-entity-repeatable
    「mvcc-entity」と同じですが、READ_COMMITTED ではなく JBoss Cache の REPEATABLE_READ 分離レベルを使用します (下記の注記を参照)。
  • pessimistic-entity-repeatable
    「pessimistic-entity」と同じですが、READ_COMMITTED ではなく JBoss Cache の REPEATABLE_READ 分離レベルを使用します (下記の注記を参照)。
  • local-query
    JPA/Hibernate のクエリ結果のキャッシングに適切な設定です。 クエリの結果はレプリケートしません。 このキャッシュのクエリ結果が有効であるかを検証するために Hibernate が使用するタイムスタンプデータを保存しないでください。
  • replicated-query
    JPA/Hibernate のクエリ結果のキャッシングに適切な設定です。 クエリの結果をレプリケートします。 このキャッシュのクエリ結果が有効であるかを検証するために Hibernate が使用するタイムスタンプデータを保存しないでください。
  • timestamps-cache
    JPA/Hibernate のクエリ結果キャッシングの一部としてキャッシュされるタイムスタンプデータに適切な設定です。 クエリ結果自体が local-query のような非リプリケーションキャッシュを使用する場合でも、 クエリ結果キャッシングが使用される時はレプリケートされたタイムスタンプのキャッシュが必要となります。 
  • mvcc-shared
    JPA/Hibernate のエンティティ、コレクション、クエリ結果、タイムスタンプキャッシングで共有されるキャッシュに適切な設定です。最も非効率なモードである REPL_SYNC キャッシュモードが必要となるため、推奨される設定ではありません。 また、 起動時にフルステート転送が必要となるため、高価になることがあります。JBoss 4 では共有キャッシュのみが使用できたため、後方互換性を理由に維持されています。JBoss Cache の MVCC ロックを使用します。
  • optimistic-shared
    JPA/Hibernate のエンティティ、コレクション、クエリ結果、タイムスタンプキャッシングで共有されるキャッシュに適切な設定です。最も非効率なモードである REPL_SYNC キャッシュモードが必要となるため、推奨される設定ではありません。 また、起動時にフルステート転送が必要となるため、高価になることがあります。 JBoss 4 では共有キャッシュのみが使用できたため、後方互換性を理由に維持されています。JBoss Cache の 楽観的ロックを使用します。
  • pessimistic-shared
    JPA/Hibernate のエンティティ、 コレクション、 クエリ結果、 タイムスタンプキャッシングで共有されるキャッシュに適切な設定です。 最も非効率なモードである REPL_SYNC キャッシュモードが必要となるため、 推奨される設定ではありません。 また、 起動時にフルステート転送が必要となるため、高価になることがあります。 JBoss 4 では共有キャッシュのみが使用できたため、後方互換性を理由に維持されています。JBoss Cache の悲観的ロックを使用します。
  • mvcc-shared-repeatable
    「mvcc-shared」と同じですが、READ_COMMITTED ではなく JBoss Cache の REPEATABLE_READ 分離レベルを使用します (下記の注記を参照)。
  • pessimistic-shared-repeatable
    「pessimistic-shared」と同じですが、 READ_COMMITTED ではなく JBoss Cache の REPEATABLE_READ 分離レベルを使用します (下記の注記を参照)。

注記

JBoss Cache のロッキングスキームに関する詳しい情報は 「並行アクセス」 を参照してください。

注記

JPA/Hibernate の 2 次レベルキャッシングでは、 アプリケーションがE ntityManager/Hibernate セッションからエンティティを追放または削除し、 同じトランザクション内で繰り返し再度読み取りする場合のみ REPEATABLE_READ が有用です。 そうでない場合、 セッションの内部キャッシュが repeatable-read のセマンティックを提供します。

20.2.1.2. キャッシュ設定エイリアス

キャッシュの登録名以外の名前でルックアップできるようにするなど、 CacheManager はキャッシュのエイリアスもサポートします。 エイリアスは、 異なるキャッシュ設定名が設定されているサービス間でキャッシュを共有するのに便利です。 また、 Enterprise Application Platform 4 よりポートされるレガシー EJB3 アプリケーション設定のサポートにも便利です。
エイリアスは jboss-cache-manager-jboss-beans.xml ファイルの 「CacheManager Bean」 を編集して設定することができます。 次の設定は、 Enterprise Application Platform 5 の標準的なエイリアスになります。
<bean name="CacheManager" class="org.jboss.ha.cachemanager.CacheManager">

    . . .

    <!-- Aliases for cache names. Allows caches to be shared across 
         services that may expect different cache configuration names. -->
    <property name="configAliases">
       <map keyClass="java.lang.String" valueClass="java.lang.String">
          <!-- Use the HAPartition cache for ClusteredSSO caching -->
          <entry>
             <key>clustered-sso</key>
             <value>ha-partition</value>
          </entry>
          <!-- Handle the legacy name for the EJB3 SFSB cache -->
          <entry>
             <key>jboss.cache:service=EJB3SFSBClusteredCache</key>
             <value>sfsb-cache</value>
          </entry>
          <!-- Handle the legacy name for the EJB3 Entity cache -->
          <entry>
             <key>jboss.cache:service=EJB3EntityTreeCache</key>
             <value>mvcc-shared</value>
          </entry>
       </map>
    </property>
    
    . . .
    
</bean>

20.3. HAPartition サービス

HAPartition は、Enterprise Application Platform クラスタリングでのさまざまなタスクに使用される汎用的なサービスです。要するに、HAPartition は、1 つまたは複数のクラスタメンバに対する RPC 呼び出しの実行/受信をサポートする JGroups Channel の上部に構築された抽象層です。 HAPartition を使用するサービスは単一の Channel や多重 RPC 呼び出しを共有できるため、設定を簡易化することができ、各サービスが独自の Channel を作成するランタイムオーバーヘッドが発生しなくなります。 また、HAPartition はどのクラスタリングサービスがどのクラスタメンバで実行されているかを記録する分散レジストリもサポートし、クラスタメンバーシップやクラスター化されたサービスレジストリが変更されたときに該当するリスナに通知します。さらに、HAPartition は、スマートなクライアントサイドクラスタプロキシ、EJB 2 SFSB レプリケーションおよびエンティティキャッシュ管理、ファーミング、HA-JNDI、HA シングルトンなどの、本書でこれから説明する多くの重要なクラスタリングサービスを形成します。
次のスニペットは標準の JBoss Enterprise Application Platform ディストリビューションにパッケージされた HAPartition サービスの定義を表しています。 この設定は、 server/production/deploy/cluster/hapartition-jboss-beans.xml ファイルにあります。
<bean name="HAPartitionCacheHandler" class="org.jboss.ha.framework.server.HAPartitionCacheHandlerImpl">
 <property name="cacheManager"><inject bean="CacheManager"/></property>
 <property name="cacheConfigName">ha-partition</property>
</bean>
<bean name="HAPartition" class="org.jboss.ha.framework.server.ClusterPartition">
 <depends>jboss:service=Naming</depends>
 <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX
      (name="jboss:service=HAPartition,partition=${jboss.partition.name:DefaultPartition}", exposedInterface=org.jboss.ha.framework.server.ClusterPartitionMBean.class, registerDirectly=true)</annotation>
           
 <!-- ClusterPartition requires a Cache for state management -->
           
 <property name="cacheHandler"><inject bean="HAPartitionCacheHandler"/></property>
           
 <!-- Name of the partition being built -->
           
 <property name="partitionName">${jboss.partition.name:DefaultPartition}</property>
           
 <!-- The address used to determine the node name -->
           
 <property name="nodeAddress">${jboss.bind.address}</property>
           
  <!-- Max time (in ms) to wait for state transfer to complete. Increase for large states -->
           
 <property name="stateTransferTimeout">30000</property>
           
 <!-- Max time (in ms) to wait for RPC calls to complete. -->
           
 <property name="methodCallTimeout">60000</property>
           
 <!-- Optionally provide a thread source to allow async connect of our channel -->
           
 <property name="threadPool"><inject bean="jboss.system:service=ThreadPool"/></property>
 <property name="distributedStateImpl">
 <bean name="DistributedState" class="org.jboss.ha.framework.server.DistributedStateImpl">         
             
    <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX
    (name="jboss:service=DistributedState,partitionName=${jboss.partition.name:DefaultPartition}", exposedInterface=org.jboss.ha.framework.server.DistributedStateImplMBean.class, registerDirectly=true)</annotation>
             
  <property name="cacheHandler"><inject bean="HAPartitionCacheHandler"/></property>                  
 </bean>
 </property>
</bean>
上記の多くは定型的な定義ですが、 次にエンドユーザーに適切な主なポイントについて説明します。 上記では、 HAPartitionCacheHandlerHAPartition の 2 つの Bean が定義されています。
HAPartition Bean は次の設定プロパティを公開します。
  • PartitionName はクラスター名を指定する任意の属性です。 デフォルト値は DefaultPartition です。-g (または --partition) コマンドラインスイッチを使用して、 サーバー起動時にこの値を設定します。

    注記

    MCBean:ServerConfig プロファイルサービスコンポーネントにあるpartitionName を使う場合、システムは当プロパティに対して null 値を返します。MCBean:HAPartition 管理のコンポーネントからのPartionName を使い正しい値を取得します。
  • nodeAddress は未使用のため、 無視しても問題ありません。
  • stateTransferTimeout は初期のアプリケーションステート転送のタイムアウト値 (ミリ秒単位) を指定します。 ステート転送は、 サービスの起動時にすでに実行されているクラスタメンバから初期のアプリケーションステートのシリアライズされたコピーを取得するプロセスを意味します。 デフォルト値は 30000 です。
  • methodCallTimeout は、 別のクラスターメンバーからグループ RPC への応答を取得する時のタイムアウト値( ミリ秒単位) を指定します。 デフォルト値は 60000 です。
HAPartitionCacheHandler は HAPartition とJBoss Cache の統合を手助けする小さなユーティリティサービスです (「JBoss Enterprise Application Platform の CacheManager サービス」 を参照)。 HAPartition はJBoss Cache を使用する DistributedState と呼ばれる子サービスを公開します (「DistributedState サービス」参照)。 HAPartitionCacheHandler は、 DistributedState のキャッシュが使用する JGroups Channel と HAPartition が直接使用する Channel 間の設定が一貫性を保つようにします。
  • cacheConfigName は、 HAPartition 関連のキャッシュに使用する JBoss Cache 設定の名前になります。 HAPartition が使用するべきである JGroups プロトコルスタック設定の名前も間接的に指定します。 JGroups プロトコルスタックの設定方法は、 「JGroups の統合」 を参照してください。
ノードがクラスターを形成するには、 ノードの PartitionName が同じでなければなりません。 また、 HAPartitionCacheHandlercacheConfigName が同じ JBoss Cache 設定を指定しなければなりません。 どちらかの要素を一部のノードで変更すると、クラスターが適切に動作しなくなります。
ご使用のブラウザーでクラスター内いずれかの JBoss インスタンスの JMX コンソール (http://hostname:8080/jmx-console/ など) にアクセスしてから jboss:service=HAPartition,partition=DefaultPartition MBean (-g 起動スイッチを使用する場合はご使用のパーティション名が反映されるよう MBean 名を変更) をクリックすると現在のクラスタ情報を表示することができます。 現在のクラスターメンバーの IP アドレス一覧は CurrentView フィールドに表示されます。

注記

1 つの JBoss サーバーインスタンスを複数の HAPartitions に同時に置くことは技術的には可能ですが、 管理が複雑になるため一般的には推奨されません。

20.3.1. DistributedReplicantManager サービス

DistributedReplicantManager (DRM) サービスは、 HAPartition.getDistributedReplicantManager() メソッドにより HAPartition ユーザーが使用できる HAPartition サービスのコンポーネントの 1 つです。 通常、 JBoss Enterprise Application Platform のユーザーは直接 DRM を利用することはありません。 ここでは、 Enterprise Application Platform のクラスタリング内部がどのように動作するかを詳しく知りたいユーザー向けに説明します。
DRM は HAPartition ユーザーが特定のキーでオブジェクトを登録できるようにします。 これにより、 クラスターのメンバーによりそのキーで登録したオブジェクトのセットを呼び出し側が利用できるようにします。 DRM は通知のメカニズムも提供するため、 レジストリの内容が変更された時にリスナへ通知を行うこともできます。
JBoss Enterprise Application Platform の DRM には主に 2 つの使用法があります。
  • クラスター化されたスマートプロキシ
    クラスター化された EJB の名前など、クラスター化されたスマートプロキシを必要とするサービスの名前がキーとなります (「クライアント側インターセプターアーキテクチャー」 を参照)。 各ノードが DRM に保存する値オブジェクトは「ターゲット」と呼ばれます。 スマートプロキシのトランスポート層はこのターゲットを使用してノードへコンタクトします (RMI スタブ、 HTTP URL、 JBoss Remoting の InvokerLocator など)。 クラスター化されたスマートプロキシを構築するファクトリが DRM にアクセスして、プロキシに挿入するべきである「ターゲット」のセットを取得し、クラスター内のすべてのノードと通信できるようにします。
  • HASingleton
    高可用シングルトンとして機能する必要があるサービスの名前がキーとなります (HASingleton の章を参照)。 各ノードが DRM に保存する値オブジェクトは、 トークンとして動作するストリングで、 ノードにサービスがデプロイされていることを示します。 そのため、 HA シングルトンサービスの「マスター」ノードの候補になります。
両方の場合で、 オブジェクトが登録されたキーが特定のクラスタ化サービスを識別します。 クラスタ内のすべてのノードがすべてのキーでオブジェクトを登録する必要はありません。 特定ノードにデプロイされたサービスのみがサービスのキーを用いて登録を行います。 サービスがクラスター全体で均一にデプロイされる必要はありません。 そのため、 サービスがデプロイされたノードの認識など、 DRM はクラスター関連のサービスの「トポロジ」を理解するメカニズムとして有用です。

20.3.2. DistributedState サービス

DistributedState サービスは、 HAPartition.getDistributedState() メソッドによって HAPartition ユーザーが利用できる HAPartition サービスのレガシーコンポーネントです。 このサービスはクラスターの周囲に任意アプリケーションステートの連携管理を提供します。 このサービスは後方互換性を維持するためにサポートされていますが、 新しいアプリケーションではこのサービスを使用せず、 より高度な JBoss Cache を代わりに使用してください。
JBoss Enterprise Application Platform 5 では、 DistributedState サービスは基礎の JBoss Cache インスタンスへ委譲します。

20.3.3. HAPartition のカスタム使用

カスタムサービスも HAPartition を利用してクラスターとのやりとりに対応することができます。 通常、org.jboss.ha.framework.server.HAServiceImpl ベースクラスを拡張するのが一番簡単な方法です。 JMX の登録や通知のサポートが必要な場合は org.jboss.ha.jxm.HAServiceMBeanSupport クラスを拡張します。

第21章 クラスター化 JNDI サービス

JNDI はアプリケーションサーバーによって提供される最も重要なサービスの 1 つです。 JBoss HA-JNDI (高可用性 JNDI) サービスにより以下の機能が JNDI に提供されます。
  • ネーミング処理の透過的なフェイルオーバー。 HA-JNDI ネーミングコンテキストは特定の JBoss Enterprise Application Platform インスタンス上の HA-JNDI サービスに接続され、 サービスは失敗するか、 シャットダウンされます。 HA-JNDI クライアントは別の Enterprise Application Platform インスタンスに透過的にフェイルオーバーできます。
  • ネーミング処理の負荷分散。 HA-JNDI ネーミングコンテキストはクラスター内のすべての HA-JNDI サーバーで要求を自動的に負荷分散します。  
  • HA-JNDI サーバーの自動クライアント検出 (マルチキャストを使用)
  • クラスター全体の JNDI ツリーの統合ビュー。 クライアントはクラスター内の任意のノードで実行されている HA-JNDI サービスに接続し、 他のノードの JNDI でバインドされたオブジェクトを検索できます。 これは以下の 2 つのメカニズムによって実現されます。
    • クラスター間ルックアップ。 クライアントはルックアップを実行でき、 サーバー側 HA-JNDI サービスはクラスタ内のノードにある通常の JNDI でバインドされたものを検索できます。
    • 複製されたクラスター全体のコンテキストツリー。 HA-JNDI サービスにバインドされたオブジェクトは、 クラスター全体で複製され、 そのオブジェクトのコピーはクラスターの各ノードの VM で利用できます。
JNDI は、 他の多くのインターセプタベースのクラスタリングサービスに対する主要なコンポーネントです。 これらのサービスはそれ自体を JNDI に登録し、 クライアントがプロキシをルックアップしてそのサービスを使用できるようにします。 HA-JNDI はクライアントがこれらのプロキシをルックアップする高可用な方法を持つようにします。 ただし、 HA-JNDI の使用 (または非使用) はルックアップされるオブジェクトのクラスタリングの動作にまったく影響を及ぼしません。
  • EJB がクラスター対象として設定されていない場合は、 HA-JNDI を使用して EJB をルックアップしても、EJB にクラスタリング機能 (EJB 読み出しの負荷分散、 透過的なフェイルオーバー、 状態レプリケーション) が追加されません。
  • EJB がクラスター対象として設定された場合は、 HA-JNDI の代わりに通常の JNDI を使用して EJB をルックアップしても、 Bean プロキシのクラスタリング機能は削除されません。

21.1. 仕組み

JBoss のクライアント側の HA-JNDI ネーミングコンテキストは、 クライアント側のインターセプタのアーキテクチャが基になっています (はじめにとクイックスタートの章を参照)。 クライアントは HA-JNDI プロキシオブジェクトを取得し ( InitialContext オブジェクトより)、 プロキシよりリモートサーバーの JNDI ルックアップサービスを呼び出します。 クライアントは InitialContext オブジェクトによって使用されるネーミングプロパティを設定し、 HA-JNDI プロキシを要求します。 この詳細は 「クライアントの設定」 で取り上げています。 InitialContext に適切なネーミングプロパティが提供されていることを確認する必要がある以外は、 ネーミングコンテキストが HA-JNDI を使用していることはクライアントに対して透過的です。
サーバー側では、 HA-JNDI サービスはクラスター全体のコンテキストツリーの管理を行います。 クラスター全体のツリーはクラスター内にノードが 1 つ存在していれば常に使用することができます。 クラスター内の各ノードもノード自体のローカル JNDI コンテキストツリーを管理します。 各ノードの HA-JNDI サービスはローカル JNDI コンテキストツリーにバインドされたオブジェクトを検索でき、 他のノード上のローカルツリーにバインドされたオブジェクトを検索するためクラスター全体の RPC を作成することができます。 アプリケーションはオブジェクトをいずれかのツリーにバインドできますが、 実際はほとんどのオブジェクトがローカルの JNDI コンテキストツリーへバインドされます。このアーキテクチャーの設計原理は次の通りです。
  • すでに JNDI 実装がローカルであることを前提としていたので、アプリケーションに伴う移行関連の問題を回避し、設定ファイルを少し調整するだけでそのまますぐクラスタリングを機能するようにしたかったこと。
  • 同種のクラスターでは、 この構成によってネットワークトラフィック量が軽減され、同じタイプのオブジェクトが各ノードの同じ名前にバインドされること。
  • このような設計により、 基礎となるすべてのクラスターコードが新しい InitialContext を使用してバインディングをルックアップしたり作成するため、 HA-JNDI サービスは任意のサービスとなります。
サーバー側では、 new InitialContext() の呼び出しによって取得されたネーミングコンテキストがローカル専用のクラスタワイドでない JNDI コンテキストにバインドされます。 このため、 すべての EJB ホームなどはクラスター全体の JNDI コンテキストにはバインドされませんが、各ホームはローカルの JNDI にバインドされます。
リモートクライアントが HA-JNDI を使用してルックアップを行う時、 グローバルなクラスター全体のコンテキスト内にオブジェクトが見つからない場合 HA-JNDI はローカル JNDI コンテキスト委譲します。 詳細なルックアップルールは次の通りです。
  • クラスタ全体の JNDI ツリーにバインディングがある場合はそれを返します。
  • クラスター全体のツリーにバインディングがない場合、 ルックアップのクエリをローカルの JNDI サービスに委任して受信した応答があればそれを返信します。
  • 応答を受信しなかった場合、 HA-JNDI サービスはクラスター内の他すべてのノードに対しローカルの JNDI サービスがそのようなバインディングを持っているか問い合わせ、 受信するセットからの応答を返します。
  • バインディングを持つローカルの JNDI サービスがない場合、 最終的にはNameNotFoundException が発行されます。
実際には、オブジェクトはクラスター全体の JNDI ツリーにほとんどバインドされず、 ローカルの JNDI ツリーにバインドされます。 たとえば、 EJB がデプロイされた場合、 そのプロキシは常に HA-JNDI ではなくローカルの JNDI にバインドされます。 したがって、 HA-JNDI を使用して行われた EJB ホームルックアップは常にローカルの JNDI インスタンスに委任されます。

注記

異なる Bean (同じタイプでも異なるクラスタに参加している) が同じ JNDI 名を使用する場合、 各 JNDI サーバーは同じ名前の論理的に異なる「ターゲット」バインドを持つことになります (ノード 1 の JNDI は Bean A のバインディング、 ノード 2 の JNDI は同じ名前で Bean B のバインディングを持つ)。 必然的に、 クライアントがこの名前で HA-JNDI クエリを実行すると、このクエリはクラスターの任意の JNDI サーバーで呼び出され、 ローカルでバインドされたスタブを返します。しかし、 このスタブはクライアントが求めるスタブとは異なる可能性があります。 したがって、 常にクラスター全体で論理的に異なるバインディングに異なる名前を使用することがベストプラクティスとなります。

注記

クラスターの少数のノードでのみバインディングが使用できる場合 (例えば、クラスターにおける小さいサブセットのノードのみに Bean がデプロイされた場合)、 このバインディングを所有しない HA-JNDI サーバーをルックアップする可能性が高くなるため、 クラスターにあるすべてのノードにルックアップを転送する必要があります。 したがって、 ローカルでバインディングが使用できる場合よりもクエリにかかる時間が長くなります。そのため、 JNDI クエリの結果はできる限りクライアントでキャッシュするようにしてください。

注記

HA-JNDI を使用したい場合、 現在非 JNP JNDI 実装 (例:LDAP) をローカルの JNDI 実装として使用することはできません。 しかし、 ExternalContext MBean を用いる JNDI フェデレーションを使用すると、 非 JBoss INDI ツリーを JBoss JNDI の名前空間へバインドすることができます。 また、 クラスター全体やHA-JNDI やJNP のスクラップに 1 つの集中 JNDI サーバーを使用することもできます。

21.2. クライアントの設定

クライアントが HA-JNDI を使用するよう設定するには、 新しい InitialContext が作成された時に適切なネーミングプロパティ環境が使用できるようにします。 この方法は、 クライアントが JBoss Enterprise Application Platform 内で実行されているか別の VM で実行されているかによって異なります。

21.2.1. Enterprise Application Platform 内部で実行されているクライアントの場合

Enterprise Application Platform 内部から HA-JNDI にアクセスしたい場合、 JNDI プロパティをコンストラクターに渡して明示的に InitialContext を設定する必要があります。 次のコードは HA-JNDI にバインドされたネーミングコンテキストの作成方法について示しています。
Properties p = new Properties();  
p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");  
p.put(Context.URL_PKG_PREFIXES, "jboss.naming:org.jnp.interfaces");
// HA-JNDI is listening on the address passed to JBoss via -b  
String bindAddress = System.getProperty("jboss.bind.address", "localhost");
p.put(Context.PROVIDER_URL, bindAddress + ":1100"); // HA-JNDI address and port.  
return new InitialContext(p);
Context.PROVIDER_URL プロパティは deploy/cluster/hajndi-jboss-beans.xml ファイルに設定された HA-JNDI サービスを示しています (「JBoss の設定」 を参照)。 デフォルトでは、 このサービスは jboss.bind.address システムプロパティより命名されたインターフェースをリッスンします。 jboss.bind.address システムプロパティは、 JBoss Enterprise Application Platform 起動時に -b コマンドラインオプションへ割り当てた値に設定されます (指定がない場合は localhost)。 上記のコードはこのプロパティへのアクセス例になります。
しかし、 すべての場合で動作するわけではなく、 特に複数の JBoss Enterprise Application Platform インスタンスを同じマシン上で実行し、 同じ IP アドレスへバインドし、 異なるポートを使用するよう設定した場合は動作しません。 下記のように Context.PROVIDER_URL を指定せず、 jnp.partitionName プロパティを指定して InitialContext が VM 内の HA-JNDI を静的に見つけるようにするのが最も安全なやり方です。
Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
p.put(Context.URL_PKG_PREFIXES, "jboss.naming:org.jnp.interfaces");
// HA-JNDI is registered under the partition name passed to JBoss via -g  
String partitionName = System.getProperty("jboss.partition.name", "DefaultPartition");
p.put("jnp.partitionName", partitionName);
return new InitialContext(p);
この例は jboss.partition.name システムプロパティを使用して、 HA-JNDI サービスが動作するパーティションを特定します。 このシステムプロパティは、 JBoss Enterprise Application Platform 起動時に -g コマンドラインオプションへ割り当てた値に設定されます (指定がない場合は DefaultPartition)。
jndi.properties ファイルをデプロイメントに配置し、Enterprise Application Platform の conf/jndi.properties ファイルを編集して作業を単純化しないようにしてください。 いずれの場合でもほぼ間違いなくアプリケーションが破損し、場合によってはサーバー全体が破損します。 クライアント設定を外部化するには、 jndi.properties という名前でないプロパティファイルをデプロイし、 そのファイルの内容をロードする Properties オブジェクトをプログラムを使用して作成するのが 1 つの方法です。

21.2.1.1. EJB および WAR からのHA-JNDI リソースへのアクセス -- 環境ネーミングコンテキスト

HA-JNDI が EJB またはサーブレットである場合、 リソースのルックアップを設定する最も危害を少なくする方法は、ルックアップを実行する Bean や Web アプリケーションの環境ネーミングコンテキストへリソースをバインドすることです。 ローカルマッピングでなく HA-JNDI を使用するようバインディングを設定することができます。 JMS 接続ファクトリとキューの例は次の通りです (最も一般的なユースケースとなります)。
ejb-jar.xml の Bean 定義や war の web.xml 内で、 接続ファクトリと送信先の 2 つのリソース参照マッピングを定義する必要があります。
<resource-ref>
 <res-ref-name>jms/ConnectionFactory</res-ref-name>
 <res-type>javax.jms.QueueConnectionFactory</res-type>
 <res-auth>Container</res-auth>
</resource-ref>
 
<resource-ref>
 <res-ref-name>jms/Queue</res-ref-name>
 <res-type>javax.jms.Queue</res-type>
 <res-auth>Container</res-auth>
</resource-ref>
これらの例を使用して、 ルックアップを実行する Beanは java:comp/env/jms/ConnectionFactory をルックアップして接続ファクトリを取得し、 java:comp/env/jms/Queue をルックアップしてキューを取得できます。
JBoss 固有の配備記述子 (EJB は jboss.xml、 WAR は jboss-web.xml) の中でこれらの参照を HA-JNDI が使用する URL へマップする必要があります。
<resource-ref>
 <res-ref-name>jms/ConnectionFactory</res-ref-name>
 <jndi-name>jnp://${jboss.bind.address}:1100/ConnectionFactory</jndi-name>
</resource-ref>
 
<resource-ref>
 <res-ref-name>jms/Queue</res-ref-name>
 <jndi-name>jnp://${jboss.bind.address}:1100/queue/A</jndi-name>
 </resource-ref>
URL は、 Bean と同じノード上で稼働している HA-JNDI サーバーへの URL になります。 Bean が利用できる場合、 ローカル HA-JNDI サーバーも利用できるはずです。 ルックアップはクラスターの全ノードを自動的にクエリし、JMS リソースを持つノードを特定します。
上記で使用される ${jboss.bind.address} 構文は、 URL を判定する時に jboss.bind.address システムプロパティの値を使用するよう JBoss に伝えます。 このシステムプロパティは、 JBoss Enterprise Application Platform の起動時に -b コマンドラインオプションで割り当てた値をシステムプロパティ自体に設定します。

21.2.1.2. 単に jndi.properties ファイルに指定するのではなく、 プログラムを使用して行う理由

JBoss Enterprise Application Platform の内部ネーミング環境は、 編集してはならない conf/jndi.properties ファイルによって制御されます。
Enterprise Application Platform 内に他の jndi.properties ファイルをデプロイしないでください。 他のファイルをデプロイすると、 jndi.properties ファイルがあってはならないクラスパス上に存在してしまうことがあるため、 サーバーの内部操作を妨害する可能性があります。 例えば、 HA-JNDI に設定された jndi.properties が EJB デプロイメントに含まれる場合、 サーバーが EJB プロキシを JNDI へバインドすると、 プロキシが属するローカル JNDI ツリーではなく、レプリケートされた HA-JNDI ツリーにバインドする可能性が高いでしょう。

21.2.1.3. 正しくない HA-JNDI へバインドされたことを知る方法

jmx コンソールにて、jboss:service=JNDIView MBean 上で list 操作を実行します。結果の最後の方に「HA-JNDI Namespace」の内容が一覧表示されます。 通常、一覧には何も表示されませんが、 明示的にバインドしなかったデプロイメントが表示された場合、 不適切な jndi.properties ファイルがクラスパスにあると考えられられます。例は、Problem with removing a Node from Cluster を参照してください。

21.2.2. Enterprise Application Platform 外部で実行されているクライアントの場合

JNDI クライアントは HA-JNDI クラスターを認識しなければなりません。 JNDI サーバーの一覧 (HA-JNDI クラスター内のノードなど) を jndi.properties ファイル内の java.naming.provider.url JNDI 設定に渡すことができます。 各サーバーノードは IP アドレスと JNDI ポート番号によって識別されます。 サーバーノードはコンマで区切ります (サーバーとポートの設定方法については 「JBoss の設定」 を参照)。
java.naming.provider.url=server1:1100,server2:1100,server3:1100,server4:1100
初期化の際、JNP クライアントコードは一覧の各サーバーノードとの通信を 1 つずつ試行します。そして、通信できたサーバーがあった時点で試行を停止します。そして、そのサーバーのノードより HA-JNDI スタブをダウンロードします。

注記

JNP クライアントのルックアッププロセスには負荷分散の動作はありません。 単にプロバイダ一覧を確認してスタブを取得するために利用できる最初のサーバーを使用します。 HA-JNDI プロバイダ一覧はクラスタ内の HA-JNDI ノードのサブセットが含まれている必要があります。 HA-JNDI スタブがダウンロード可能になると、 利用可能なサーバーすべての情報がスタブによって含まれます。 サーバーのセットが含まれるようにし、 最低でも一覧のサーバーが 1 つ使用できるようにすると良いでしょう。
ダウンロードしたスマートスタブには、 現在実行されているノードの一覧と、必要な場合にネーミング要求を負荷分散し別のノードにフェイルオーバーするロジックが含まれます。 また、 サーバーに対して JNDI 呼び出しが行われる度にプロキシインターセプタのターゲット一覧が更新されます (最後の呼び出し後に一覧が変更された場合のみ)。
プロパティの文字列 java.naming.provider.url が空の場合や 表示のサーバーすべてにアクセスできない場合、 JNPクライアントはネットワーク上のマルチキャスト呼び出しより HA-JNDI サーバーをディスカバリしようとします (自動ディスカバリ)。 JNDI サーバーノード上で自動ディスカバリを設定する方法は、 「JBoss の設定」 を参照してください。 自動ディスカバリにより、 設定がなくてもクライアントは有効な HA-JNDI サーバーを取得することができる場合があります。 自動ディスカバリが動作させるには、クライアントとサーバークラスター間のネットワークセグメントを設定し、このようなマルチキャストデータグラムを伝搬するようにしなければなりません。

注記

デフォルトでは、自動ディスカバリ機能はマルチキャストグループのアドレス 230.0.0.4 と 1102 番ポートを使用します。
java.naming.provider.url プロパティだけでなく、 他のプロパティセットも指定することもできます。 次の一覧は、 新規の InitialContext を作成する時に指定できるクラスタリング関係のクライアント側プロパティになります (通常の JNDI と共に使用されるすべての標準的な非クラスタリング関連環境プロパティも使用できます)。
  • java.naming.provider.url: クラスター内の HA-JNDI プロバイダーノード群の IP アドレスとポート番号の一覧を提供します。 クライアントはプロバイダーを 1 つずつ確認し、 最初に応答するプロバイダーを使用します。
  • jnp.disableDiscovery: true が指定されると自動ディスカバリ機能が無効になります。デフォルトでは false が指定されます。
  • jnp.partitionName: 異なるクラスター (パーティション) にバインドされる複数の HA-JNDI サービスが実行されている環境でこのプロパティを使用すると、 クライアントが希望するパーティションのサーバーからの自動ディスカバリ応答のみを受け入れるようにできます。自動ディスカバリ機能を使用しない場合は (jnp.disableDiscovery が true の場合など)、このプロパティは使用されません。 デフォルトでは、 このプロパティは設定されず、クラスターパーティション名に関係なく最初に応答する HA-JNDI サーバーが自動のディスカバリ機能によって選択されます。
  • jnp.discoveryTimeout: 自動ディスカバリパケットへの応答に対するコンテキストの待ち時間を指定します。 デフォルトは 5000 ミリ秒です。
  • jnp.discoveryGroup: 自動ディスカバリに使用されるマルチキャストグループアドレスを指定します。 デフォルト値は 230.0.0.4 です。 サーバー側 HA-JNDI サービスで設定された AutoDiscoveryAddress の値を一致しなければなりません。 サーバー側の HA-JNDI サービスは、 デフォルトでは -u 起動スイッチより指定されたアドレス上でリッスンします。 そのため、 サーバー側で -u が使用される場合 (推奨通り)、 クライアント側で jnp.discoveryGroup を設定する必要があります。
  • jnp.discoveryPort: 自動ディスカバリに使用されるマルチキャストポートを指定します。 デフォルト値は 1102 です。 サーバー側 HA-JNDI サービスで設定された AutoDiscoveryPort の値と一致しなければなりません。
  • jnp.discoveryTTL: 自動ディスカバリ IP マルチキャストパケットの TTL (time-to-live) を指定します。 この値は、ネットワーク装置がマルチキャストパケットをドロップする前にマルチキャストパケットが伝搬できるネットワークホップ数を表します。 名前とは異なり、時間の単位を表すものではありません。

21.3. JBoss の設定

$JBOSS_HOME/server/all/deploy/cluster ディレクトリの hajndi-jboss-beans.xmlファイルには、HA-JNDI サービスを有効にする次の Bean が含まれています。
<bean name="HAJNDI" class="org.jboss.ha.jndi.HANamingService">    

      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX
      (name="jboss:service=HAJNDI", 
         exposedInterface=org.jboss.ha.jndi.HANamingServiceMBean.class)</annotation>  
      
      <!-- The partition used for group RPCs to find locally bound objects on other nodes -->
      <property name="HAPartition"><inject bean="HAPartition"/></property>
      
      <!-- Handler for the replicated tree -->
      <property name="distributedTreeManager">
         <bean class="org.jboss.ha.jndi.impl.jbc.JBossCacheDistributedTreeManager">
            <property name="cacheHandler"><inject bean="HAPartitionCacheHandler"/></property>
         </bean>
      </property>
      
      <property name="localNamingInstance">
         <inject bean="jboss:service=NamingBeanImpl" property="namingInstance"/>
      </property>
      
      <!-- The thread pool used to control the bootstrap and auto discovery lookups -->
      <property name="lookupPool"><inject bean="jboss.system:service=ThreadPool"/></property>
      
      <!-- Bind address of bootstrap endpoint -->
      <property name="bindAddress">${jboss.bind.address}</property>
      <!-- Port on which the HA-JNDI stub is made available -->
      <property name="port">
         <!-- Get the port from the ServiceBindingManager -->
         <value-factory bean="ServiceBindingManager" method="getIntBinding">
            <parameter>jboss:service=HAJNDI</parameter>
            <parameter>Port</parameter>
         </value-factory>
      </property>
      
      <!-- Bind address of the HA-JNDI RMI endpoint -->
      <property name="rmiBindAddress">${jboss.bind.address}</property>
      
      <!-- RmiPort to be used by the HA-JNDI service once bound. 0 = ephemeral. -->
      <property name="rmiPort">
         <!-- Get the port from the ServiceBindingManager -->
         <value-factory bean="ServiceBindingManager" method="getIntBinding">
            <parameter>jboss:service=HAJNDI</parameter>
            <parameter>RmiPort</parameter>
         </value-factory>
      </property>
      
      <!-- Accept backlog of the bootstrap socket -->
      <property name="backlog">50</property>

      <!-- A flag to disable the auto discovery via multicast -->
      <property name="discoveryDisabled">false</property>
      <!-- Set the auto-discovery bootstrap multicast bind address. If not 
      specified and a BindAddress is specified, the BindAddress will be used. -->
      <property name="autoDiscoveryBindAddress">${jboss.bind.address}</property>
      <!-- Multicast Address and group port used for auto-discovery -->
      <property name="autoDiscoveryAddress">${jboss.partition.udpGroup:230.0.0.4}</property>
      <property name="autoDiscoveryGroup">1102</property>
      <!-- The TTL (time-to-live) for autodiscovery IP multicast packets -->
      <property name="autoDiscoveryTTL">16</property>
      
      <!-- The load balancing policy for HA-JNDI -->
      <property name="loadBalancePolicy">org.jboss.ha.framework.interfaces.RoundRobin</property>

      <!-- Client socket factory to be used for client-server
           RMI invocations during JNDI queries
      <property name="clientSocketFactory">custom</property>
      -->
      <!-- Server socket factory to be used for client-server
           RMI invocations during JNDI queries
      <property name="serverSocketFactory">custom</property>
      -->
   </bean>
この Bean は、異なるプロパティに挿入された複数の他のサービスを持っていることが分かります。
  • HAPartition は、 HA-JNDI のクラスター化プロキシの管理や、 別のノードにてローカルでバインドされたオブジェクトを検索するグループ RPC の作成に使用されるコアのクラスタリングサービスを許可します。 詳細は、 「HAPartition サービス」 を参照してください。
  • distributedTreeManager は、 レプリケートされたツリーのハンドラーを許可します。 標準的なハンドラは、 JBoss Cache を使用してレプリケートされたツリーを管理します。 挿入された HAPartitionCacheHandler Bean を使用して JBoss Cache インスタンスが読み出しされます。 詳細は 「HAPartition サービス」 を参照してください。
  • localNamingInstance はローカル JNDI サービスへの参照を許可します。
  • LookupPool は、 ブートストラップや自動ディスカバリのルックアップを処理するスレッドを提供するために使用するスレッドプールを許可します。
上記の依存関係が注入されたサービスの他に、 HA-JNDI Bean に使用できる設定属性は次の通りです。
  • bindAddress は、 JNP クライアントからネーミングプロキシダウンロードリクエストをリッスンするために HA-JNDI サーバーがバインドするアドレスを指定します。 デフォルト値は jboss.bind.address システムプロパティの値になります。 jboss.bind.address システムプロパティが設定されていない場合は、 localhost がデフォルト値になります。 JBoss 起動時に -b コマンドラインスイッチが使用されると jboss.bind.address システムプロパティが設定されます。
  • port は、 JNP クライアントからネーミングプロキシダウンロード要求をリッスンするために HA-JNDI サーバーがバインドするポートを指定します。 値は conf/bootstrap/bindings.xml に設定されている ServiceBindingManager Bean より取得されます。 デフォルト値は 1100 です。
  • backlog は、 サービスが JNP クライアントからのネーミングプロキシダウンロード要求をリッスンする TCP サーバーソケットに対する受信接続指示の最大キュー長を指定します。 デフォルト値は 50 です。 
  • rmiBindAddress は、 ネーミングプロキシからの RMI 要求 (JNDI ルックアップに対してなど) をリッスンするために HA-JNDI サーバーがバインドするアドレスを指定します。 デフォルト値は jboss.bind.address システムプロパティの値になります。 jboss.bind.address システムプロパティが設定されていない場合は、 localhost がデフォルト値になります。 JBoss 起動時に -b コマンドラインスイッチが使用されると jboss.bind.address システムプロパティが設定されます。
  • rmiPort は、 ダウンロードされたスタブと通信するためにサーバーがバインドするポートを指定します。 conf/bootstrap/bindings.xml に設定された ServiceBindingManager Bean より値が取得されます。 デフォルト値は 1101 です。 設定された値がない場合、 オペレーティングシステムが自動的にポートを割り当てます。
  • discoveryDisabled は、 自動ディスカバリマルチキャストリスナの設定を無効にするブール変数フラグです。 デフォルトは false です。
  • autoDiscoveryAddress JNDI 自動ディスカバリのためにリッスンするマルチキャストアドレスを指定します。デフォルト値は、 jboss.partition.udpGroup システムプロパティの値になります。このシステムプロパティが設定されていない場合は、 230.0.0.4 がデフォルト値となります。 JBoss 起動時に -u コマンドラインスイッチが使用されると jboss.partition.udpGroup システムプロパティが設定されます。
  • autoDiscoveryGroup は、 JNDI 自動ディスカバリパケットのためにリッスンするポートを指定します。 デフォルト値は 1102 です。
  • AutoDiscoveryBindAddress は HA-JNDI が 自動ディスカバリ要求パケットをリッスンするインターフェースを設定します。 この属性が指定されておらず bindAddress が指定されている場合、 bindAddress が使用されます。
  • autoDiscoveryTTL は自動ディスクカバリ IP マルチキャストパケットの TTL (time-to-live) を指定します。 この値は、ネットワーク装置がマルチキャストパケットをドロップする前にマルチキャストパケットが伝搬できるネットワークホップ数を表します。 名前とは異なり、時間の単位を表すものではありません。
  • loadBalancePolicy は、 クライアントプロキシに含まれるべきである LoadBalancePolicyimplementation のクラス名を指定します。 詳細は、 紹介とクイックスタート章を参照してください。
  • clientSocketFactory は、 クライアントソケットの作成に使用される java.rmi.server.RMIClientSocketFactory の完全修飾クラス名を指定する任意の属性です。 デフォルトは null です。
  • serverSocketFactory は、 サーバーソケットの作成に使用される java.rmi.server.RMIServerSocketFactory の完全修飾クラス名を指定する任意の属性です。 デフォルトは null です。

21.3.1. 2 つ目の HA-JNDI サービスの追加

異なる HAPartitions を使用する複数の HA-JNDI サービスを起動することも可能です。 例えば、1 つのノードが多数の論理クラスターの一部である場合などに使用することができます。 この場合、 各サービスにも別々のポートや IP アドレスを設定するようにしてください。 例えば、 設定するサンプルのクラスターに HA-JNDI を接続してバインドするポートを変更したい場合、Bean 記述子は次のようになります (標準的なデプロイメントと変わりないプロパティは省略します)。
   <-- Cache Handler for secondary HAPartition -->
   <bean name="SecondaryHAPartitionCacheHandler"
         class="org.jboss.ha.framework.server.HAPartitionCacheHandlerImpl">
         <property name="cacheManager"><inject bean="CacheManager"/></property>
         <property name="cacheConfigName">secondary-ha-partition</property>
   </bean>
   
   <-- The secondary HAPartition -->
   <bean name="SecondaryHAPartition" class="org.jboss.ha.framework.server.ClusterPartition">     

      <depends>jboss:service=Naming</depends>
       
      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX
      (name="jboss:service=HAPartition,partition=SecondaryPartition", 
      exposedInterface=org.jboss.ha.framework.server.ClusterPartitionMBean.class, registerDirectly=true)</annotation>
       
      <property name="cacheHandler"><inject bean="SecondaryHAPartitionCacheHandler"/></property>
               
      <property name="partitionName">SecondaryPartition</property>
      
      ....      
   </bean>
   
   <bean name="MySpecialPartitionHAJNDI" class="org.jboss.ha.jndi.HANamingService">    

      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX
      (name="jboss:service=HAJNDI,partitionName=SecondaryPartition", 
         exposedInterface=org.jboss.ha.jndi.HANamingServiceMBean.class)</annotation>  
      
      <property name="HAPartition"><inject bean="SecondaryHAPartition"/></property>
      
      <property name="distributedTreeManager">
         <bean class="org.jboss.ha.jndi.impl.jbc.JBossCacheDistributedTreeManager">
            <property name="cacheHandler"><inject bean="SecondaryHAPartitionPartitionCacheHandler"/></property>
         </bean>
      </property>
      
      <property name="port">56789</property>
      
      <property name="rmiPort">56790</property>
      
      <property name="autoDiscoveryGroup">56791</property>
      
      .....
   </bean>

第22章 クラスター化されたセッション EJB

セッション EJB はリモート呼び出しサービスを提供します。 このセッションはクライアント側のインターセプターアーキテクチャーに基づいてクラスタ化されます。 クラスター化されたセッション Bean のクライアントアプリケーションは、 若干の変更を除きセッション Bean のクラスター化されていないバージョンのクライアントと同じです。 クライアント側ではコードの変更や再コンパイルは必要ありません。 それでは、 EJB 3.0 と EJB 2.x のサーバーアプリケーションそれぞれでクラスター化されたセッション Bean を設定する方法について見てみましょう。

22.1. EJB 3.0 のステートレスセッション Bean

ステートレスセッション Beanのクラスター化は、 ステートが関係しないため、 最も簡単なケースだと言えます。 呼び出しは、 クラスターの参加しているノード (この特定の Bean がデプロイされたすべてのノード) すべてへ呼び出しの負荷を分散することができます。
EJB 3.0 でステートレスセッション Bean をクラスターするには、 @Clustered アノテーションを用いて、 Bean クラスにアノテーションを付けます。 このアノテーションには、 負荷分散ポリシーと使用するパーティションの両方を上書きするオプションのパラメーターが含まれます。
public @interface Clustered
{
   String partition() default "${jboss.partition.name:DefaultPartition}";
   String loadBalancePolicy() default "LoadBalancePolicy";
}
  • partition は、 Bean が参加するクラスタの名前を指定します。 @Clustered アノテーションで、個別の Bean に対してデフォルトパーティション DefaultPartition を上書きできますが、 jboss.partition.name システムプロパティを使用するとすべての Bean に対して上書きできます。
  • loadBalancePolicy は、 クラスターのノード上の呼び出しを Bean スタブが分散する方法を示し、 org.jboss.ha.client.loadbalance.LoadBalancePolicy を実装するクラス名を定義します。 デフォルト値 LoadBalancePolicy は、セッション Bean タイプのデフォルトポリシーを示す特別なトークンです。 ステートレスセッション Bean のデフォルトポリシーは org.jboss.ha.client.loadbalance.RoundRobin です。 独自の実装を使用してデフォルト値を上書き、あるいは使用できるポリシーのリストより選択することができます。
    org.jboss.ha.client.loadbalance.RoundRobin
    無作為のターゲットから開始し、 負荷分散を最大限にするため、 常にリスト上で次に利用できるターゲットを選択しようとします。
    org.jboss.ha.client.loadbalance.RandomRobin
    以前に選択されたターゲットを考慮せずに、 無作為にターゲットを選択します。
    org.jboss.ha.client.loadbalance.aop.FirstAvailable
    ターゲットが選択されると、 同じターゲットを選択しようとします (これ以上負荷分散が行われません)。 ステートフルセッション Bean など、「スティッキーセッション」動作が望まれる場合に便利です。
    org.jboss.ha.client.loadbalance.aop.FirstAvailableIdenticalAllProxies
    FirstAvailable と似ていますが、 希望のターゲットがすべてのプロキシで共有されます。
以下は、クラスター化された EJB 3.0 のステートレスセッション bean の実装例になります。
@Stateless
@Clustered
public class MyBean implements MySessionInt
{
   public void test()
   {
      // Do something cool
   }
}
@Clustered アノテーションを使用する代わりに、 jboss.xml のセッション Bean に対してクラスタリングを有効にすることもできます。
 
<jboss>    
   <enterprise-beans>
      <session>
         <ejb-name>NonAnnotationStateful</ejb-name>
         <clustered>true</clustered>
         <cluster-config>
            <partition-name>FooPartition</partition-name>
            <load-balance-policy>org.jboss.ha.framework.interfaces.RandomRobin</load-balance-policy>
         </cluster-config>
      </session>    
   </enterprise-beans>
</jboss>

注記

<clustered>True</clustered> 要素は conf/standardjboss.xml ファイルの <configuration-name>Clustered Stateless SessionBean</configuration-name> 要素のエイリアスにすぎません。
この Bean の設定では、 Bean がクラスタリング機能のサポートを必要とすることを示す <clustered> 要素のみが必須です。 オプションの <cluster-config> 要素のデフォルト値は @Clustered アノテーションからの対応するプロパティと一致します。

22.2. EJB 3.0 でのステートフルセッション Bean

ステートフルセッション Bean のクラスター化は、JBoss がステート情報を管理する必要があるためステートレスセッション beanよりも複雑になります。すべてのステートフルセッション Bean のステートはレプリケートされ、Bean のステートが変更されるたびにクラスター全体で同期されます。

22.2.1. EJB アプリケーション設定

EJB 3.0 でステートフルセッション Bean をクラスター化するには、 EJB 3.0 のステートレスセッション Bean をクラスター化したように、 Bean 実装クラスに @Cluster アノテーションのタグを付ける必要があります。 ステートレスセッション Bean と異なり、 ステートフルセッション Bean のメソッド呼び出しは、 デフォルトで org.jboss.ha.client.loadbalance.aop.FirstAvailable を使用して負荷分散されます。 このポリシーを使用してメソッド呼び出しが無作為に選択されたノードに従います。
@org.jboss.ejb3.annotation.CacheConfig アノテーションを Bean に適応してデフォルトのキャッシング動作を上書きすることもできます。 @CacheConfig アノテーションの定義は次の通りです。
public @interface CacheConfig
{
   String name() default "";
   int maxSize() default 10000;
   long idleTimeoutSeconds() default 300;   
   boolean replicationIsPassivation() default true;   
   long removalTimeoutSeconds() default 0;
}
  • name は、 「CacheManager サービスの設定」 で説明した CacheManager サービスで登録されたキャッシュ設定の名前を指定します。 デフォルトでは、 sfsb-cache 設定が使用されます。
  • maxSize は、LRU アルゴリズムを使用して Bean の非活性化を開始する前にキャッシュできる Bean の最大数を指定します。
  • idleTimeoutSeconds はキャッシュが Bean を非活性化する前に Bean が未使用の状態でいられる最大時間を指定します (maxSize Bean がキャッシュされているかは無関係)。
  • removalTimeoutSeconds は、キャッシュが Bean を削除するまで Bean を使用しない最大時間を指定します。
  • replicationIsPassivation は、キャッシュでレプリケーションを非活性化と同等であると見なし、Bean に対して @PrePassivate と @PostActivate のコールバックを呼び出すかどうかを指定します。デフォルトでは真であり、レプリケーションには Bean のシリアル化が関係するため、シリアル化の準備とシリアル化からの回復がコールバックメソッドを実装する一般的な理由となります。
以下は、クラスター化された EJB 3.0 のステートレスセッション Bean の実装例になります。
@Stateful
@Clustered
@CacheConfig(maxSize=5000, removalTimeoutSeconds=18000)
public class MyBean implements MySessionInt
{
   private int state = 0;

   public void increment()
   {
      System.out.println("counter: " + (state++));
   }
}
ステートレス Bean と同様に、@Clustered アノテーションは省略でき、クラスタリング設定は jboss.xml に適用されます。
<jboss>    
   <enterprise-beans>
      <session>
         <ejb-name>NonAnnotationStateful</ejb-name>
         <clustered>true</clustered>
         <cache-config>
            <cache-max-size>5000</cache-max-size>
            <remove-timeout-seconds>18000</remove-timeout-seconds>
         </cache-config>
      </session>    
   </enterprise-beans>
</jboss>

22.2.2. ステートレプリケーションの最適化

レプリケーションプロセスにはコストがかかるため、 オプションで Bean クラスに org.jboss.ejb3.cache.Optimized を実装することによりレプリケーションの動作を最適化できます。
public interface Optimized
{
   boolean isModified();
}
Bean をレプリケートする前に、 Bean が Optimized メソッドを実装するかをコンテナーがチェックします。 この場合、 コンテナーがisModified() メソッドを呼び出し、 メソッドが true を返した場合のみ Bean をレプリケートします。 Bean が変更されていない場合 (またはユーザーの希望により十分な変更でないためレプリケーションが必要ない場合) は、 false を返すことができます。 この場合、 レプリケーションは発生しません。

22.2.3. CacheManager サービスの設定

JBoss Cache は EJB 3.0 のステートフルセッション bean のセッションステートレプリケーションサービスを提供します。 「JBoss Enterprise Application Platform の CacheManager サービス」 で説明されている CacheManager サービスは JBoss Cache インスタンスのファクトリでもありレジストリでもあります。 次の通り、 ステートフルセッション Bean はデフォルトで CacheManager より sfsb-cache 設定を使用します。
<bean name="StandardSFSBCacheConfig" class="org.jboss.cache.config.Configuration">

  <!--  No transaction manager lookup -->
  
  <!-- Name of cluster. Needs to be the same for all members -->
  <property name="clusterName">${jboss.partition.name:DefaultPartition}-SFSBCache</property>
  <!--
    Use a UDP (multicast) based stack. Need JGroups flow control (FC)
    because we are using asynchronous replication.
  -->
  <property name="multiplexerStack">${jboss.default.jgroups.stack:udp}</property>
  <property name="fetchInMemoryState">true</property>
  
  <property name="nodeLockingScheme">PESSIMISTIC</property>
  <property name="isolationLevel">REPEATABLE_READ</property>
  <property name="useLockStriping">false</property>
  <property name="cacheMode">REPL_ASYNC</property>
  
  <!--
    Number of milliseconds to wait until all responses for a
    synchronous call have been received. Make this longer 
    than lockAcquisitionTimeout.
  -->
  <property name="syncReplTimeout">17500</property>
  <!-- Max number of milliseconds to wait for a lock acquisition -->
  <property name="lockAcquisitionTimeout">15000</property>
  <!-- The max amount of time (in milliseconds) we wait until the
  state (ie. the contents of the cache) are retrieved from
  existing members at startup. -->
  <property name="stateRetrievalTimeout">60000</property>
  
  <!--
    SFSBs use region-based marshalling to provide for partial state
    transfer during deployment/undeployment.
  -->
  <property name="useRegionBasedMarshalling">false</property>
  <!-- Must match the value of "useRegionBasedMarshalling" -->
  <property name="inactiveOnStartup">false</property>
  
  <!-- Disable asynchronous RPC marshalling/sending -->
  <property name="serializationExecutorPoolSize">0</property>        
  <!-- We have no asynchronous notification listeners -->
  <property name="listenerAsyncPoolSize">0</property>
  
  <property name="exposeManagementStatistics">true</property>
  
  <property name="buddyReplicationConfig">
    <bean class="org.jboss.cache.config.BuddyReplicationConfig">
    
      <!--  Just set to true to turn on buddy replication -->
      <property name="enabled">false</property>
      
      <!--
        A way to specify a preferred replication group.  We try
        and pick a buddy who shares the same pool name (falling 
        back to other buddies if not available).
      -->
      <property name="buddyPoolName">default</property>
      
      <property name="buddyCommunicationTimeout">17500</property>
      
      <!-- Do not change these -->
      <property name="autoDataGravitation">false</property>
      <property name="dataGravitationRemoveOnFind">true</property>
      <property name="dataGravitationSearchBackupTrees">true</property>
               
      <property name="buddyLocatorConfig">
        <bean class="org.jboss.cache.buddyreplication.NextMemberBuddyLocatorConfig">
          <!-- The number of backup nodes we maintain -->
          <property name="numBuddies">1</property>
          <!-- Means that each node will *try* to select a buddy on 
               a different physical host. If not able to do so 
               though, it will fall back to colocated nodes. -->
          <property name="ignoreColocatedBuddies">true</property>
        </bean>
      </property>
    </bean>
  </property>
  <property name="cacheLoaderConfig">
    <bean class="org.jboss.cache.config.CacheLoaderConfig">
      <!-- Do not change these -->
      <property name="passivation">true</property>
      <property name="shared">false</property>
      
      <property name="individualCacheLoaderConfigs">
        <list>
          <bean class="org.jboss.cache.loader.FileCacheLoaderConfig">
            <!-- Where passivated sessions are stored -->
            <property name="location">${jboss.server.data.dir}${/}sfsb</property>
            <!-- Do not change these -->
            <property name="async">false</property>
            <property name="fetchPersistentState">true</property>
            <property name="purgeOnStartup">true</property>
            <property name="ignoreModifications">false</property>
            <property name="checkCharacterPortability">false</property>
          </bean>
        </list>
      </property>
    </bean>
  </property>

  <!-- EJBs use JBoss Cache eviction -->
  <property name="evictionConfig">
    <bean class="org.jboss.cache.config.EvictionConfig">
      <property name="wakeupInterval">5000</property>
      <!--  Overall default -->
      <property name="defaultEvictionRegionConfig">
        <bean class="org.jboss.cache.config.EvictionRegionConfig">
          <property name="regionName">/</property>
          <property name="evictionAlgorithmConfig">
            <bean class="org.jboss.cache.eviction.NullEvictionAlgorithmConfig"/>
          </property>
        </bean>
      </property>
      <!-- EJB3 integration code will programatically create other regions as beans are deployed -->
    </bean>
  </property>
</bean>
エビクション

デフォルトの SFSB キャッシュはエビクションをサポートするよう設定されます。 EJB3 SFSB コンテナーは JBoss Cache エビクションメカニズムを使用して SFSB 非活性化を管理します。 Bean がデプロイされた場合、 EJB コンテナーはプログラムを使用してキャッシュにエビクションリージョンを追加します (1 つの Bean タイプに対して 1 つのリージョン)。

CacheLoader

JBoss Cache CacheLoader も設定し、SFSB 非活性化を再度サポートします。Bean がキャッシュから除外されると、キャッシュローダーは永続ストアに Bean を非活性化します (この場合は $JBOSS_HOME /server/all/data/sfsb ディレクトリのファイルシステムに行います)。JBoss Cache は、様々な CacheLoader 実装に対応しており、これらの実装はあらゆる永続ストアタイプへデータを格納する方法を認識します。詳細については、JBoss Cache のドキュメントを参照してください。ただし、CacheLoaderConfiguration を変更する場合は、共有されたストア (共有されたデータベースの単一のスキーマなど) を使用しないようにしてください。クラスター内の各ノードは独自の永続ストアを持つ必要があります。そうでないと、ノードは個別でクラスター化された Bean を非活性化および活性化するため、ノードがそれぞれのデータを破損してしまいます。

バディレプリケーション

バディーレプリケーションを使用すると、クラスターのすべてのサーバーではなく、 クラスタで設定可能な数のバックアップサーバー (バディー) へステートがレプリケートされます。 バディーレプリケーションを有効にするには、 buddyReplicationConfig プロパティ Bean の次のプロパティを調整します。 

  • enabledtrue に設定します。
  • nbuddyPoolName を使用してクラスター内でノードの論理サブグループを形成します。 可能な場合、 同じバディープールのノードよりバディーが選択されます。
  • 各ノードがステートをレプリケートするバックアップノードの数に合わせ、 buddyLocatorConfig.numBuddies プロパティを調整します。

22.3. EJB 2.x のステートレスセッション Bean

EJB 2.x Bean をクラスター化するには、 jboss.xml 記述子を変更し、 <clustered> タグが含まれるようにする必要があります。
<jboss>
  <enterprise-beans>
    <session>
      <ejb-name>nextgen.StatelessSession</ejb-name>
      <jndi-name>nextgen.StatelessSession</jndi-name>
      <clustered>true</clustered>
      <cluster-config>
        <partition-name>DefaultPartition</partition-name>
        <home-load-balance-policy>org.jboss.ha.framework.interfaces.RoundRobin</home-load-balance-policy>
        <bean-load-balance-policy>org.jboss.ha.framework.interfaces.RoundRobin</bean-load-balance-policy>
      </cluster-config>
    </session>
  </enterprise-beans>
</jboss>
  • partition-name は、Bean が参加するクラスターの名前を指定します。デフォルト値は DefaultPartition です。デフォルトのパーティション名は、jboss.partition.name システムプロパティを使用してシステム全体で設定することもできます。
  • home-load-balance-policy は、 クラスターのノードへの呼び出しを分散するためにホームスタブが使用するクラスを指定します。 デフォルトでは、 プロキシは RoundRobin を用いて呼び出しの負荷を分散します。
  • bean-load-balance-policy は、クラスターのノードへの呼び出しを分散するために Bean スタブが使用するクラスを指定します。 デフォルトでは、 プロキシは RoundRobin を用いて呼び出しの負荷を分散します。

22.4. EJB 2.x のステートフルセッション Bean

ステートフルセッション Bean のクラスター化は、 JBoss がステート情報を管理する必要があるためステートレスセッション beanよりも複雑になります。 すべてのステートフルセッション Bean のステートはレプリケートされ、 Bean のステートが変更されるたびにクラスター全体で同期されます。 JBoss Enterprise Application Platform は HASessionStateService Bean を使用してクラスター化された EJB 2.x ステートフルセッション Bean の分散セッションステートを管理します。 この項では、 セッション Bean 設定と HASessionStateService Bean 設定の両方について説明します。

22.4.1. EJB アプリケーション設定

EJB アプリケーションでは、各ステートフルセッション Bean に対する jboss.xml 記述子ファイルを変更し、<clustered> タグを追加する必要があります。
<jboss>    
  <enterprise-beans>
    <session>        
      <ejb-name>nextgen.StatefulSession</ejb-name>
      <jndi-name>nextgen.StatefulSession</jndi-name>
      <clustered>True</clustered>
      <cluster-config>
        <partition-name>DefaultPartition</partition-nam>
        <home-load-balance-policy>org.jboss.ha.framework.interfaces.RoundRobin</home-load-balance-policy>
        <bean-load-balance-policy>org.jboss.ha.framework.interfaces.FirstAvailable</bean-load-balance-policy>          
        <session-state-manager-jndi-name>/HASessionState/Default</session-state-manager-jndi-name>        
      </cluster-config>
    </session>
  </enterprise-beans>
</jboss>
この Bean 設定では、Bean がクラスターで動作することを示す <clustered> タグが必須です。<cluster-config> 要素はオプションであり、そのデフォルトの属性値は上記と同じ設定で指定されます。
<session-state-manager-jndi-name> タグは、この Bean が使用する HASessionStateService サービスの JNDI 名を提供するために使用されます。
残りのタグの詳細はステートレスセッション Bean と同一となります。 クラスター化されたステートフルセッション Bean のホームインタフェースでのアクションはデフォルトでラウンドロビン方式により負荷分散されます。 クライアントに対して Bean のリモートスタブが利用できるようになると、 呼び出しはラウンドロビン方式で負荷分散されなくなり、 一覧の 1 番目のノードに固定されます。

22.4.2. ステートレプリケーションの最適化

レプリケーションプロセスにはコストがかかるため、オプションで Bean クラスに以下のシグネチャでメソッドを実装することによりレプリケーションの動作を最適化できます。
public boolean isModified();
Bean をレプリケートする前に、 Bean が このメソッドを実装するかをコンテナーがチェックします。この場合、 コンテナーがisModified() メソッドを呼び出し、 メソッドが true を返した場合のみ Bean をレプリケートします。 Bean が変更されていない場合 (またはユーザーの希望により十分な変更でないためレプリケーションが必要ない場合) は、 false を返すことができます。 この場合、 レプリケーションは発生しません。

22.4.3. The HASessionStateService サービスの設定

HASessionStateService Bean は $JBOSS_HOME/server/PROFILE/deploy/cluster/ha-legacy-jboss-beans.xmlファイルで定義されます。
 
<bean name="HASessionStateService"
      class="org.jboss.ha.hasessionstate.server.HASessionStateService">
  
  <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX
  (name="jboss:service=HASessionState", 
  exposedInterface=org.jboss.ha.hasessionstate.server.
  HASessionStateServiceMBean.class, 
  registerDirectly=true)</annotation>
  
  <!--  Partition used for group RPCs -->
  <property name="HAPartition"><inject bean="HAPartition"/></property>
  
  <!-- JNDI name under which the service is bound -->
  <property name="jndiName">/HASessionState/Default</property>
  <!-- Max delay before cleaning unreclaimed state.
       Defaults to 30*60*1000 => 30 minutes -->
  <property name="beanCleaningDelay">0</property>
   
</bean>
HASessionStateService Bean の設定属性は次の通りです。
  • HAPartition は HA-JNDI がクラスター内の通信に使用する HAPartition サービスを挿入する必須属性です。
  • JndiName は、 この HASessionStateService サービスがバインドされる JNDI 名を指定するオプションの属性です。 デフォルト値は /HAPartition/Default になります。
  • BeanCleaningDelay はオプションの属性で、 指定された時間 (ミリ秒単位) が経過した後に HASessionStateService が変更されていないステートを消去します。 Bean を所有するノードがクラッシュすると、 その兄弟ノードがこの Bean を所有することになります。 兄弟ノードのコンテナキャッシュはそれを認識しないため、 Bean の消去設定に基づいて消去することはできません。 そのため、 HASessionStateService が時々クリーンアップを行う必要があります。 デフォルト値は 30*60*1000 ミリ秒 (30 分) です。

22.4.4. クラスター再起動の処理

HA スマートクライアントアーキテクチャーについては 「クライアント側インターセプターアーキテクチャー」 で説明しました。 デフォルトの HA スマートプロキシクライアントはクラスター内に 1 つのノードがある限りフェイルルオーバーを行うことができます。 クラスターが完全にシャットダウンされた場合、プロキシは孤立しクラスター内の使用可能なノード群の情報を失うことになります。 この状態からプロキシを復帰させる方法はありません。 プロキシはノードが再起動されたら JNDI/HA-JNDI から新しい対象をルックアップする必要があります。
このような再起動の障害からの透過的に回復できるよう、RetryInterceptor をプロキシクライアント側のインターセプタースタックに追加することができます。 EJB に対してこれを有効にするには、 RetryInterceptor を含む invoker-proxy-binding を設定します。 jboss.xml 設定の例は次の通りです。
 
<jboss>
  <session>
    <ejb-name>nextgen_RetryInterceptorStatelessSession</ejb-name>
    <invoker-bindings>
      <invoker>
        <invoker-proxy-binding-name>clustered-retry-stateless-rmi-invoker</invoker-proxy-binding-name>
        <jndi-name>nextgen_RetryInterceptorStatelessSession</jndi-name>
      </invoker>
    </invoker-bindings>
    <clustered>true</clustered>
  </session>
  <invoker-proxy-binding>
    <name>clustered-retry-stateless-rmi-invoker</name>
    <invoker-mbean>jboss:service=invoker,type=jrmpha</invoker-mbean>
    <proxy-factory>org.jboss.proxy.ejb.ProxyFactoryHA</proxy-factory>
    <proxy-factory-config>
      <client-interceptors>
        <home>
          <interceptor>org.jboss.proxy.ejb.HomeInterceptor</interceptor>
          <interceptor>org.jboss.proxy.SecurityInterceptor</interceptor>
          <interceptor>org.jboss.proxy.TransactionInterceptor</interceptor>
          <interceptor>org.jboss.proxy.ejb.RetryInterceptor</interceptor>
          <interceptor>org.jboss.invocation.InvokerInterceptor</interceptor>
        </home>
        <bean>
          <interceptor>org.jboss.proxy.ejb.StatelessSessionInterceptor</interceptor>
          <interceptor>org.jboss.proxy.SecurityInterceptor</interceptor>
          <interceptor>org.jboss.proxy.TransactionInterceptor</interceptor>
          <interceptor>org.jboss.proxy.ejb.RetryInterceptor</interceptor>
          <interceptor>org.jboss.invocation.InvokerInterceptor</interceptor>
        </bean>
      </client-interceptors>
    </proxy-factory-config>
  </invoker-proxy-binding>
</jboss>

22.4.5. JNDI ルックアッププロセス

HA プロキシを回復するために、RetryInterceptor は JNDI でルックアップを行います。つまり、内部的に新しい InitialContext が作成され、JNDI ルックアップが行われます。ただし、ルックアップが成功するには、ネーミングサーバーを見つけるよう InitialContext を適切に設定する必要があります。RetryInterceptor は以下のステップを経て適切なネーミング環境プロパティを調べます。
  1. また独自の静的 retryEnv フィールドも調べます。 このフィールドは RetryInterceptor.setRetryEnv(Properties) の呼び出しを用いてクライアントコードより設定できますが、 この設定方法には 2 つの欠点があります。 1 つ目の欠点は、 JBoss 固有の呼び出しをクライアントコードに導入することによって移植性が減少することです。もう 1 つの欠点は、静的フィールドが使用されているため 1 つの JVM に対して 1 つの設定しか使用できないことです。
  2. retryEnv フィールドが null の場合は、org.jboss.naming.NamingContextFactory クラスによって ThreadLocal にバインドされた環境プロパティがチェックされます。このクラスをネーミングコンテキストファクトリとして使用するには、jndi.properties でプロパティ java.naming.factory.initial=org.jboss.naming.NamingContextFactory を適切に設定します。この利点は org.jboss.naming.NamingContextFactory を jndi.properties ファイルの設定オプションで簡単に使用できるため、java コードが影響を受けないことです。欠点はネーミングプロパティが ThreadLocal に格納されるため、InitialContext を最初に作成したスレッドに対してのみ可視の状態にあることです。
  3. 上記のいずれの方法でもネーミング環境プロパティが設定されない場合はデフォルトの InitialContext が使用されます。 ネーミングサーバーへ接続できない場合、 デフォルトでは HA-JNDI ネーミングサーバーを検索するため InitialContext がマルチキャストディスカバリへフォールバックしようとします。 HA-JNDI のマルチキャストディスカバリの詳細は、 21章クラスター化 JNDI サービス を参照してください。

22.4.6. SingleRetryInterceptor

RetryInterceptor は多くのケースで役に立ちますが、成功するまで JNDI で HA プロキシをルックアップの継続をする点が欠点です。何らかの理由で成功しない場合、この処理が永遠に続き RetryInterceptor をトリガーした EJB 呼び出しが戻らないことになります。多くのクライアントアプリケーションでは対応できません。結果として JBoss で RetryInterceptor はクラスター化された EJB のデフォルトのクライアントインターセプタースタックの一部にはなりません。
以前のリリースでは、新しい再試行インターセプター org.jboss.proxy.ejb.SingleRetryInterceptor が導入されました。このバージョンは RetryInterceptor のように動作しますが、JNDI での HA プロキシの再ルックアップを一度しか行いません。 この再ルックアップに失敗すると、 再試行インターセプタが使用されてない場合のように EJB 呼び出しに失敗します。 SingleRetryInterceptor はクラスター化された EJB のデフォルトクライアントインターセプターの一部となりました。
SingleRetryInterceptor の欠点は、サーバーを利用できないクラスターの再起動時に再試行が行われると再試行に失敗し、それ以降再試行が行われなくなることです。

第23章 クラスター化した Entity EJB

JBoss Enterprise Application Platform クラスターでは、 エンティティ Bean のインスタンスは全ノードで同期される必要があります。 エンティティ Bean がリモートサービスを提供する場合、 そのサービスメソッドも負荷分散される必要があります。

23.1. EJB 3.0 内の エンティティ Bean

EJB 3.0 では、 エンティティ Bean は主に永続データモデルとして機能し、 リモートサービスを提供しません。 そのため、 EJB 3.0 内のエンティティBean クラスター化サービスは負荷分散ではなく、 主に分散キャッシングやレプリケーションに対応します。

23.1.1. 分散型キャッシュの設定

データベースへのラウンドトリップを避ける為に、ご使用のエンティティ用のキャッシュを使用することができます。JBoss EJB 3.0 エンティティ bean は、2 次キャッシュをサポートする Hibernate によって実装されます。 2 次キャッシュは以下のような機能を提供します。
  • キャッシュが有効になっている エンティティ Bean インスタンスをエンティティマネージャーを用いてデータベースへ永続化させると、 エンティティはキャッシュの中に挿入されます。
  • エンティティ Bean インスタンスを更新し、その変更をエンティティマネージャーよりデータベースに保存すると、エンティティはキャッシュ内で更新されます。
  • エンティティ Bean インスタンスをエンティティマネージャーを用いてデータベースから削除すると、 そのエンティティはキャッシュから削除されます。
  • エンティティマネージャーを介してデータベースからキャッシュ化したエンティティを ロードする時、そのエンティティがデータベース内にまだ存在しない場合、そのエンティティは キャッシュに挿入されます。
キャッシングエンティティのリージョンと同様に、 2 次キャッシュにもキャッシングコレクション、 クエリ、 タイムスタンプ向けのリージョンが含まれています。 JBoss EJB 3.0 の実装に使用される Hibernate 設定は JBoss Cache を基礎となる 2 次キャッシュ実装として使用します。
2 次キャッシュは、 EJB3 デプロイメントの persistence.xml より設定されます。
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/persistence"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
  <persistence-unit name="tempdb" transaction-type="JTA">
    <jta-data-source>java:/DefaultDS</jta-data-source>
    <properties>
      <property name="hibernate.cache.use_second_level_cache" value="true"/>
      <property name="hibernate.cache.use_query_cache" value="true"/>
      <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.jbc2.JndiMultiplexedJBossCacheRegionFactory"/>
      <!-- region factory specific properties -->
      <property name="hibernate.cache.region.jbc2.cachefactory" value="java:CacheManager"/>
      <property name="hibernate.cache.region.jbc2.cfg.entity" value="mvcc-entity"/>
      <property name="hibernate.cache.region.jbc2.cfg.collection" value="mvcc-entity"/>
    </properties>
  </persistence-unit>
</persistence>
hibernate.cache.use_second_level_cache
エンティティとコレクションの 2 次キャッシングを有効にします。
hibernate.cache.use_query_cache
クエリの 2 次キャッシングを有効にします。
hibernate.cache.region.factory_class
リージョン固有のキャッシング動作を指示する RegionFactory 実装を定義します。 Hibernate には、共有と多重の 2 種類の JBoss Cache ベース 2 次キャッシュが同梱されています。
共有リージョンファクトリは全てのキャッシュリージョンに同じキャッシュを使用します。 これは、 以前の Hibernate バージョンのレガシー CacheProvider 実装の動作と同様です。
Hibernate には 2 つの共有リージョンファクトリ実装が同梱されています。
org.hibernate.cache.jbc2.SharedJBossCacheRegionFactory
全てのキャッシュリージョンに対し、 新たにインスタンス化された CacheManager より単一の JBoss Cache 設定を使用します。

表23.1 SharedJBossCacheRegionFactory のその他のプロパティ

プロパティ デフォルト 詳細
hibernate.cache.region.jbc2.cfg.shared treecache.xml JBoss Cache 設定が含まれるクラスパスまたはファイルシステムリソースです。
hibernate.cache.region.jbc2.cfg.jgroups.stacks org/hibernate/cache/jbc2/builder/jgroups-stacks.xml JGroups プロトコルスタック設定が含まれるクラスパスまたはファイルシステムリソースです。
org.hibernate.cache.jbc2.JndiSharedJBossCacheRegionFactory
全てのキャッシュリージョンに対し、 既存の JNDI へバインドされた既存の CacheManager より単一の JBoss Cache 設定を使用します。

表23.2 JndiSharedJBossCacheRegionFactory のその他のプロパティ

プロパティ デフォルト 詳細
hibernate.cache.region.jbc2.cfg.shared Required 共有 Cache インスタンスがバインドされる JNDI 名です。
多重リージョンファクトリは、 各キャッシュリージョンに対して最適化された設定を使用し、 個別のキャッシュインスタンスを使用します。

表23.3 多重リージョンファクトリ実装の一般的なプロパティ

プロパティ デフォルト 詳細
hibernate.cache.region.jbc2.cfg.entity optimistic-entity エンティティキャッシュリージョンに使用される JBoss Cache 設定です。 この他に、 mvcc-entity、 pessimistic-entity、 mvcc-entity-repeatable、 optimistic-entity-repeatable、p essimistic-entity-repeatable を設定することができます。
hibernate.cache.region.jbc2.cfg.collection optimistic-entity コレクションキャッシュリージョンに使用される JBoss Cache 設定です。 通常、 コレクションキャッシュリージョンはエンティティキャッシュリージョンと同じ設定を使用します。
hibernate.cache.region.jbc2.cfg.query local-query クエリキャッシュリージョンに使用される JBoss Cache 設定です。 デフォルトでは、 キャッシュされたクエリ結果はレプリケートされません。 この他に、 replicated-query を設定することができます。
hibernate.cache.region.jbc2.cfg.ts timestamps-cache タイムスタンプキャッシュリージョンに使用される JBoss Cache 設定です。 クエリキャッシングが使用される場合、 クエリキャッシュがレプリケートしなくても、 対応するタイムスタンプキャッシュはレプリケートしなければなりません。 タイムスタンプキャッシュリージョンはクエリキャッシュと同じキャッシュを共有してはいけません。
Hibernate には 2 つの共有リージョンファクトリ実装が同梱されています。
org.hibernate.cache.jbc2.MultiplexedJBossCacheRegionFactory
キャッシュリージョン毎に、 新たにインスタンス化された CacheManager より個別の JBoss Cache 設定を使用します。

表23.4 MultiplexedJBossCacheRegionFactory のその他のプロパティ

プロパティ デフォルト 詳細
hibernate.cache.region.jbc2.configs org/hibernate/cache/jbc2/builder/jbc2-configs.xml JBoss Cache 設定が含まれるクラスパスまたはファイルシステムリソースです。
hibernate.cache.region.jbc2.cfg.jgroups.stacks org/hibernate/cache/jbc2/builder/jgroups-stacks.xml JGroups プロトコルスタック設定が含まれるクラスパスまたはファイルシステムリソースです。
org.hibernate.cache.jbc2.JndiMultiplexedJBossCacheRegionFactory
キャッシュリージョン毎に、 JNDI にバインドされた CacheManager より個別の JBoss Cache 設定を使用します。 「JBoss Enterprise Application Platform の CacheManager サービス」 を参照してください。

表23.5 JndiMultiplexedJBossCacheRegionFactory のその他のプロパティ

プロパティ デフォルト 詳細
hibernate.cache.region.jbc2.cachefactory Required CacheManager インスタンスがバインドされる JNDI 名です。
これで、分散型キャッシングの EJB 3.0 エンティティ bean をサポートするための JBoss Cache を 設定したことになります。キャッシュサービスを使用するには、まだ個別の エンティティ bean を 設定する必要があります。

23.1.2. キャッシュ用の エンティティ bean の設定

次に、 キャッシュするエンティティを設定する必要があります。 上述の設定であっても、 デフォルトでは何もキャッシュしないことになっています。 キャッシュされる必要がある エンティティ bean にタグ付けするため @org.hibernate.annotations.Cache アノテーションを使用します。
@Entity 
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL) 
public class Account implements Serializable
{
   // ... ... 
}
大体の目安として、 あまり変更がなく頻繁に読み込まれるオブジェクトをキャッシュします。 適切な JBoss Cache 設定ファイル jboss-cache-manager-jboss-beans.xml など) にある各エンティティ Bean に対してキャッシュを細かく調整することができます。 例えば、 キャッシュのサイズを指定することができます。 キャッシュ内にあるオブジェクトが多すぎる場合、 キャッシュは設定通りに最も古いオブジェクトや使用頻度が最も低いオブジェクトをエビクトして新しいオブジェクトのスペースを確保することができます。 例えば、 persistence.xml で指定された region_prefix が myprefix である場合、 com.mycompany.entities.Account エンティティ bean のキャッシュリージョンのデフォルト名は /myprefix/com/mycompany/entities/Account になります。
<bean name="..." class="org.jboss.cache.config.Configuration">
   ... ...
  <property name="evictionConfig">
    <bean class="org.jboss.cache.config.EvictionConfig">
      <property name="wakeupInterval">5000</property>
      <!--  Overall default -->
      <property name="defaultEvictionRegionConfig">
        <bean class="org.jboss.cache.config.EvictionRegionConfig">
          <property name="regionName">/</property>
          <property name="evictionAlgorithmConfig">
            <bean class="org.jboss.cache.eviction.LRUAlgorithmConfig">
              <!-- Evict LRU node once we have more than this number of nodes -->
              <property name="maxNodes">10000</property>
              <!-- And, evict any node that hasn't been accessed in this many seconds -->
              <property name="timeToLiveSeconds">1000</property>
              <!-- Don't evict a node that's been accessed within this many seconds. 
                  Set this to a value greater than your max expected transaction length. -->
              <property name="minTimeToLiveSeconds">120</property>
            </bean>
          </property>
        </bean>
      </property>
      <property name="evictionRegionConfigs">
        <list>
          <bean class="org.jboss.cache.config.EvictionRegionConfig">
            <property name="regionName">/myprefix/com/mycompany/entities/Account</property>
            <property name="evictionAlgorithmConfig">
              <bean class="org.jboss.cache.eviction.LRUAlgorithmConfig">
                <property name="maxNodes">10000</property>
                <property name="timeToLiveSeconds">5000</property>
                <property name="minTimeToLiveSeconds">120</property>
              </bean>
            </property>
          </bean>
           ... ...
        </list>
      </property>
    </bean>
  </property>
</bean>
エンティティ Bean クラスに対してキャッシュリージョンを指定しないと、 上記の通り、 defaultEvictionRegionConfig を使用してそのクラスのすべてのインスタンスがキャッシュされます。 エンティティクラスの完全修飾名より自動的に作成するのではなく、 @Cache アノテーションは、 エンティティが保存されるキャッシュリージョンを指定できるようにする任意の属性「region」を公開します。
@Entity 
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL, region = "Account") 
public class Account implements Serializable
{ 
  // ... ... 
}
除外設定は以下のようになります。
<bean name="..." class="org.jboss.cache.config.Configuration">
   ... ...
  <property name="evictionConfig">
    <bean class="org.jboss.cache.config.EvictionConfig">
      <property name="wakeupInterval">5000</property>
      <!--  Overall default -->
      <property name="defaultEvictionRegionConfig">
        <bean class="org.jboss.cache.config.EvictionRegionConfig">
          <property name="regionName">/</property>
          <property name="evictionAlgorithmConfig">
            <bean class="org.jboss.cache.eviction.LRUAlgorithmConfig">
              <property name="maxNodes">5000</property>
              <property name="timeToLiveSeconds">1000</property>
              <property name="minTimeToLiveSeconds">120</property>
            </bean>
          </property>
        </bean>
      </property>
      <property name="evictionRegionConfigs">
        <list>
          <bean class="org.jboss.cache.config.EvictionRegionConfig">
            <property name="regionName">/myprefix/Account</property>
            <property name="evictionAlgorithmConfig">
              <bean class="org.jboss.cache.eviction.LRUAlgorithmConfig">
                <property name="maxNodes">10000</property>
                <property name="timeToLiveSeconds">5000</property>
                <property name="minTimeToLiveSeconds">120</property>
              </bean>
            </property>
          </bean>
           ... ...
        </list>
      </property>
    </bean>
  </property>
</bean>

23.1.3. クエリ結果のキャッシュ

EJB3 のクエリ API を使用すると、指定されたクエリの結果 (エンティティ bean の 1 次キーの集まりやスカラー値の集まりなど) を 2 次キャッシュに保存できます。 ここでは、bean に名前付きクエリのアノテーションを付ける簡単な例を説明し、Hibernate でクエリをキャッシュするための Hibernate 固有のヒントも提供します。
最初に persistence.xml で Hibernate がクエリキャッシュを有効にするよう指定する必要があります。
<property name="hibernate.cache.use_query_cache" value="true"/>
次に、エンティティに関連付けられた名前付きクエリを作成し、そのクエリの結果をキャッシュすることを Hibernate に指示します。
 
@Entity
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL, region = "Account")
@NamedQueries(
{
  @NamedQuery(
    name = "account.bybranch",
    query = "select acct from Account as acct where acct.branch = ?1",
    hints = { @QueryHint(name = "org.hibernate.cacheable", value = "true") }
  )
})
public class Account implements Serializable
{
  // ... ... 
}
@NamedQueries、 @NamedQuery、 および @QueryHint アノテーションはすべて javax.persistence パッケージに含まれます。 EJB3 クエリの使用方法とクエリをキャッシュするよう EJB3 に指示する方法の詳細については、 Hibernate と EJB3 のドキュメントを参照してください。
デフォルトでは、 Hibernate は JBoss Cache のクエリ結果を <region_prefix>/org/hibernate/cache/StandardQueryCache という名前の領域に保存します。 これに基づき、 クエリ結果に対して異なるエビクション処理を設定できます。 persistence.xml でリージョンのプレフィックスが myprefix に設定されている場合は、 以下のようなエビクション処理を作成できます。
<bean name="..." class="org.jboss.cache.config.Configuration">
    ... ...
   <property name="evictionConfig">
       <bean class="org.jboss.cache.config.EvictionConfig">
         <property name="wakeupInterval">5000</property>
         <!--  Overall default -->
         <property name="defaultEvictionRegionConfig">
            <bean class="org.jboss.cache.config.EvictionRegionConfig">
               <property name="regionName">/</property>
               <property name="evictionAlgorithmConfig">
                  <bean class="org.jboss.cache.eviction.LRUAlgorithmConfig">
                     <property name="maxNodes">5000</property>
                     <property name="timeToLiveSeconds">1000</property>
                     <property name="minTimeToLiveSeconds">120</property>
                  </bean>
               </property>
            </bean>
         </property>
         <property name="evictionRegionConfigs">
            <list>
               <bean class="org.jboss.cache.config.EvictionRegionConfig">
                  <property name="regionName">/myprefix/Account</property>
                  <property name="evictionAlgorithmConfig">
                     <bean class="org.jboss.cache.eviction.LRUAlgorithmConfig">
                        <property name="maxNodes">10000</property>
                        <property name="timeToLiveSeconds">5000</property>
                        <property name="minTimeToLiveSeconds">120</property>
                     </bean>
                  </property>
               </bean>
               <bean class="org.jboss.cache.config.EvictionRegionConfig">
                  <property name="regionName">/myprefix/org/hibernate/cache/StandardQueryCache</property>
                  <property name="evictionAlgorithmConfig">
                     <bean class="org.jboss.cache.eviction.LRUAlgorithmConfig">
                        <property name="maxNodes">100</property>
                        <property name="timeToLiveSeconds">600</property>
                        <property name="minTimeToLiveSeconds">120</property>
                     </bean>
                  </property>
               </bean>
            </list>
         </property>
      </bean>
   </property>
</bean>
上記の @NamedQuery.hints 属性はベンダー固有の @QueryHints の配列を値とします。 Hibernate は "org.hibernate.cacheRegion" クエリヒントを許可します。 この値はデフォルトの /org/hibernate/cache/StandardQueryCache の代わりに使用するキャッシュリージョンの名前です。 例は次の通りです。
@Entity
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL, region = "Account")
@NamedQueries(
{
  @NamedQuery(
    name = "account.bybranch",
    query = "select acct from Account as acct where acct.branch = ?1",
    hints = 
    {
      @QueryHint(name = "org.hibernate.cacheable", value = "true"),
      @QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")
    }
  )
})
public class Account implements Serializable
{
  // ... ... 
}
関連する除外設定:
<bean name="..." class="org.jboss.cache.config.Configuration">
    ... ...
   <property name="evictionConfig">
       <bean class="org.jboss.cache.config.EvictionConfig">
         <property name="wakeupInterval">5000</property>
         <!--  Overall default -->
         <property name="defaultEvictionRegionConfig">
            <bean class="org.jboss.cache.config.EvictionRegionConfig">
               <property name="regionName">/</property>
               <property name="evictionAlgorithmConfig">
                  <bean class="org.jboss.cache.eviction.LRUAlgorithmConfig">
                     <property name="maxNodes">5000</property>
                     <property name="timeToLiveSeconds">1000</property>
                     <property name="minTimeToLiveSeconds">120</property>
                  </bean>
               </property>
            </bean>
         </property>
         <property name="evictionRegionConfigs">
            <list>
               <bean class="org.jboss.cache.config.EvictionRegionConfig">
                  <property name="regionName">/myprefix/Account</property>
                  <property name="evictionAlgorithmConfig">
                     <bean class="org.jboss.cache.eviction.LRUAlgorithmConfig">
                        <property name="maxNodes">10000</property>
                        <property name="timeToLiveSeconds">5000</property>
                        <property name="minTimeToLiveSeconds">120</property>
                     </bean>
                  </property>
               </bean>
               <bean class="org.jboss.cache.config.EvictionRegionConfig">
                  <property name="regionName">/myprefix/Queries</property>
                  <property name="evictionAlgorithmConfig">
                     <bean class="org.jboss.cache.eviction.LRUAlgorithmConfig">
                        <property name="maxNodes">100</property>
                        <property name="timeToLiveSeconds">600</property>
                        <property name="minTimeToLiveSeconds">120</property>
                     </bean>
                  </property>
               </bean>
                ... ...
            </list>
         </property>
      </bean>
   </property>
</bean>

23.2. EJB 2.x 内の Entity Bean

最初に、2.x エンティティ Bean はクラスター化しない方がよいこと特記しておきます。クラスター化すると、クラスター化されたリモートオブジェクトに対するリモートオブジェクトとして使用するには粒度が細かすぎる要素を公開し、重大なデータ同期化に関する問題が発生する原因となります。 読み専用ノードや、 読み書き可能なノード 1 つと他の読み専用ノードをキャッシュ無効化サービスで同期化するような特殊な場合以外は、 EJB 2.x エンティティ Bean をクラスター化しないでください。
クラスター化したエンティティ bean を使用するには、 クラスター化された HA-JNDI から EJB 2.x リモート bean 参照をルックアップすること以外、 アプリケーションが行わなければならないことは特にありません。
EJB 2.x エンティティ bean をクラスター化するには、 <clustered> 要素をアプリケーションの jboss.xml 記述子ファイルに追加する必要があります。 以下に標準的な jboss.xml ファイルを示します。
<jboss>
  <enterprise-beans>
    <entity>
      <ejb-name>nextgen.EnterpriseEntity</ejb-name>
      <jndi-name>nextgen.EnterpriseEntity</jndi-name>
      <clustered>True</clustered>
      <cluster-config>
        <partition-name>DefaultPartition</partition-name>
        <home-load-balance-policy>org.jboss.ha.framework.interfaces.RoundRobin</home-load-balance-policy>
        <bean-load-balance-policy>org.jboss.ha.framework.interfaces.FirstAvailable</bean-load-balance-policy>
      </cluster-config>
    </entity>
  </enterprise-beans>
</jboss>
EJB 2.x エンティティ bean はロードバランス化したリモート起動の為にクラスター化されます。 全ての bean インスタンスは、全てのノード上で同じコンテンツを持つように同期化されます。
しかし、 クラスター化された EJB 2.x エンティティ Bean は分散型ロッキングメカニズムや、 分散型キャッシュを持ちません。 同期化させるには、 データベースレベルで行レベルロッキングを使用するか (CMP 仕様の <row-lock> 参照)、 JDBC ドライバーのトランザクション分離レベルを TRANSACTION_SERIALIZABLE に設定するしか方法はありません。 サポートされる分散型ロッキングメカニズムや分散型キャッシュがないため、 エンティティ Bean は、デフォルトでコミットオプション 「B」 を使用します。 (standardjboss.xml と コンテナー設定 Clustered CMP 2.x EntityBean、 Clustered CMP EntityBean、 Clustered BMP EntityBean を参照)。 エンティティ Bean が読み込み専用でない場合は、 コミットオプション 「A」 の使用は推奨できません 。

注記

BMP (Bean Managed Persistence: Bean 管理の永続性) を使用している場合は、ご自身で同期化を実装する必要があります。

第24章 HTTP サービス

mod_jk および mod_clusterなどの HTTP サービスのインストールや設定については、『HTTP Connectors Load Balancing Guide』にて詳細に説明しています。

第25章 JBoss Messaging のクラスタリングに関する注意

クラスタ化された環境で JBoss Messaging を使用する場合の最新情報は、 http://www.redhat.com/docs/en-US/JBoss_Enterprise_Application_Platform/ の 『JBoss Messaging User Guide』 を参照してください。

第26章 クラスター化されたデプロイメントのオプション

26.1. クラスター化シングルトンサービス

クラスター化されたシングルトンサービス (HA シングルトンとも呼ばれます) はクラスター内の複数のノードにデプロイされたサービスですが、ノードの 1 つでのみサービスを提供します。 シングルトンサービスを実行するノードは通常マスターノードと呼ばれます。
マスターノードで障害が発生する前のトポロジ

図26.1 マスターノードで障害が発生する前のトポロジ

マスターで障害が発生あるいはシャットダウンすると、 残りのノードから別のマスターが選択され、 その新しいマスターでサービスが再び起動されます。 したがって、 あるマスターが停止し、 別のマスターが引き継ぐまでの短い時間を除き、 サービスは常に 1 つのノードによって提供されます。
マスターノードで障害が発生した後のトポロジ

図26.2 マスターノードで障害が発生した後のトポロジ

26.1.1. HASingleton デプロイメントオプション

JBoss Enterprise Application Platform は、 クラスター化されたシングルトンサービのデプロイメントを容易にする複数の方法をサポートします。 この項では、 さまざまな方針について説明します。 これらすべての方法は「はじめに」で説明した HAPartition サービスの上に構築されます。 また、 HAPartition を使用してクラスター内の異なるノードが起動および停止した時に通知を行います。 これらの通知に基づいて、 クラスター内の各ノードは独自に (また一貫的に) マスターノードであるかを判断し、 サービスの提供を開始するかを決定します。

26.1.1.1. HASingletonDeployer サービス

HA シングルトンをデプロイする最も単純で最も一般的に使用されている方法は、 通常のデプロイメント (war、ear、jar やその他デプロイに通常含めるもの) を利用して、 deploy の代わりに $JBOSS_HOME/server/production/deploy-hasingleton ディレクトリにデプロイすることです。deploy-hasingleton ディレクトリは deployfarm ディレクトリに含まれないため、そのコンテンツは Enterprise Application Platform インスタンスの起動時に自動的にデプロイされません。 このディレクトリのコンテンツをデプロイするのは HASingletonDeployer bean (これ自体は deploy/deploy-hasingleton-jboss-beans.xml ファイルによってデプロイされます) という特殊なサービスです。 HASingletonDeployer サービスはそれ自体が HA シングルトンであり、マスターになった時にその提供されたサービスは deploy-hasingleton のコンテンツをデプロイし、マスターでなくなったとき (通常はサーバーのシャットダウン時) にそのサービスは deploy-hasingleton のコンテンツをアンデプロイします。
したがって、デプロイメントを deploy-hasingleton に格納することにより、デプロイメントはクラスター内のマスターノードにのみデプロイされます。マスターノードが正常にシャットダウンした場合は、シャットダウンの一部としてデプロイメントが正常にデプロイ解除されます。マスターノードで障害が発生した場合やマスターノードがシャットダウンされた場合はこのデプロイメントがマスターとして引き継いだノードにデプロイされます。
deploy-hasingleton の使用は非常に簡単ですが、以下の 2 つの欠点があります。
  • deploy-hasingleton のサービスにはホットデプロイメント機能がありません。 deploy-hasingleton にデプロイされたサービスを再デプロイするにはサーバーを再起動する必要があります。
  • マスターノードで障害が発生し、 別のノードがマスターを引き継いだ場合、 シングルトンサービスはサービスを提供する前にデプロイメントプロセス全体を経る必要があります。 サービスのデプロイメントの複雑さや実行する開始アクティビティの種類によって異なりますが、 処理にしばらく時間がかかることがあります 。処理中はサービスが提供されません。

26.1.1.2. HASingletonController を使用した POJO デプロイメント

サービスが POJO である場合 (ear、war、jar などの J2EE デプロイメントでない場合) は、 HASingletonController というサービスと共にサービスをデプロイして HA シングルトンに変えることができます。 HASingletonController は HAPartition サービスと連携してクラスターを監視し、 そのサービスのマスターノードであるかどうか確認します。 マスターノードである場合は、 サービスに対してサービスの提供を開始するメソッドが呼び出されます。 マスターノードでなくなると、 サービスに対してサービスの提供を中止するメソッドが呼び出されます。 まず、 下図を見てみましょう。
最初に HA シングルトンを作成する POJO があります。 POJO は、サービスの提供を開始する時に呼び出すことができるパブリックメソッドと、 サービスの提供を停止する時に呼び出す別のメソッドを公開する必要があります。
public interface HASingletonExampleMBean
{
   boolean isMasterNode();
}
public class HASingletonExample implements HASingletonExampleMBean
{
   private boolean isMasterNode = false; 

   public boolean isMasterNode()
   {
      return isMasterNode; 
   }

   public void startSingleton()
   { 
      isMasterNode = true;
   }

   public void stopSingleton()
   {
      isMasterNode = false; 
   }
}
上図の例では、 メソッド名が startSingletonstopSingleton になっていますが、 メソッドには任意の名前を付けることができます。
次に、制御を行うHASingletonController とサービスを共にデプロイします。通常、以下の META-INF/jboss-service.xml と共に .sar ファイルにパッケージされています。
<deployment xmlns="urn:jboss:bean-deployer:2.0">
  <!-- This bean is an example of a clustered singleton -->
  <bean name="HASingletonExample" class="org.jboss.ha.examples.HASingletonExample">
    <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX
      (name="jboss:service=HASingletonExample", 
      exposedInterface=org.jboss.ha.examples.HASingletonExampleMBean.class)</annotation>
  </bean>

  <bean name="ExampleHASingletonController" class="org.jboss.ha.singleton.HASingletonController">
    <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX
      (name="jboss:service=ExampleHASingletonController", 
      exposedInterface=org.jboss.ha.singleton.HASingletonControllerMBean.class, 
      registerDirectly=true)</annotation>
    <property name="HAPartition"><inject bean="HAPartition"/></property>
    <property name="target"><inject bean="HASingletonExample"/></property>
    <property name="targetStartMethod">startSingleton</property>
    <property name="targetStopMethod">stopSingleton</property>
  </bean>
</deployment>
クラスター化されたシングルトンサービスです。
deploy-ha-singleton と比較したこの方法の主な利点は、 上記の例を deploy または farm に格納できるため、 ホットデプロイメントやファームデプロイメントを実行できることです。 また、 このサービス例が複雑で時間がかかる起動要件を持っている場合、 create() メソッドまたは start() メソッドで実装することが可能です。 サービスがデプロイされると、 JBoss は即座に create() と start() を呼び出します。 ノードがマスターノードになるまで待機しないため、 コントローラーが startSingleton() を実装するまで待機すれば、サービスはすぐに利用できる状態になります。
上記の例にはありませんが、 HASingletonController は目的の起動メソッドや停止メソッドに対するオプションの引数をサポートします。 引数を指定するには、 起動メソッドの場合は targetStartMethodArgument プロパティを使用し、 停止メソッドの場合は TargetStopMethodArgument プロパティを使用します。 現在、 ストリング値のみがサポートされています。

26.1.1.3. バリアを使用した HASingleton デプロイメント

deploy-hasingleton のコンテンツがデプロイまたはデプロイ解除された時に (現在のノードがマスターになった時など)起動または停止する deploy または farm 内に通常デプロイされるサービスは、 バリアーサービス の依存関係のみを指定する必要があります。
<depends>jboss.ha:service=HASingletonDeployer,type=Barrier</depends>
この仕組みは、 BarrierController が HASingletonDeployer と共にデプロイされ、 そこから JMX 通知をリッスンします。 BarrierController はシステムの JMX 通知を受信するためにサブスクライブできる比較的単純な Mbean です。 また、 受け取った通知を使用して、動的に作成された Barrier という Mbean のライフサイクルを管理します。 BarrierController がデプロイされると、 Barrier はインスタンス化されてから登録され、 CREATE ステートになります。 その後、 一致する JMX 通知を受け取るとBarrierController が Barrier を起動または終了します。 したがって、 他のサービスは通常の <depends> タグを使用して Barrier Bean に依存するだけで良いのです。 これらのサービスは Barrier と並行して開始または停止します。BarrierController がアンデプロイされると、Barrier も破棄されます。
これにより deploy-hasingleton を使用した方法とは別の方法が提供され、deploy-hasingleton のコンテンツをすべてのノードに手動でコピーする必要がありますがファーミングを使用してサービスを分散できます。
その一方でバリアー依存のサービスはすべてのノードでインスタンス化および作成されます (つまり、任意の create() メソッドが呼び出されます) が、マスターノードでのみ開始されます。これは複数のノードのいずれかに deploy-hasingleton ディレクトリのコンテンツのみをデプロイ (インスタンス化/作成/開始) する deploy-hasingleton の方法とは異なります。
したがって、バリアーに依存するサービスは create() のステップ内で必要最低限の作業を行うか、まったく作業を行わないようにし、start() を使用して作業を行うようにする必要があります。

注記

Barrier は依存するサービスの起動や停止を制御しますが、 BarrierController が破棄あるいはデプロイ解除された時のみ発生するサービスの破棄については制御しません。 そのため、サービスの通常のデプロイ解除操作として Barrier を使用し、破棄しなければならないサービスを制御しようとしても (EJBContainer など)、 思い通りには動作しません。

26.1.2. マスターノードの決定

多くのクラスター化シングルトン管理方法は、 クラスターの各ノードが独自にクラスター内の変更へ反応し、 マスターノードであるかを正しく判断することに依存しています。 実際、 どのように実現されるのでしょうか。
クラスターの各メンバーに対して、 HAPartition サービスは現在のクラスターメンバーの順序化されたリストである CurrentView という属性を保持します。 ノードがクラスターに参加し、クラスターから離れると、 JGroups によってクラスターの残りの各メンバーが更新されたビューを受け取るようにします。 現在のビューは JMX コンソールに移動し、 jboss:service=DefaultPartition MBean の CurrentView 属性を確認します。 クラスターの各メンバーは同じビューを持ち、 メンバーの順番も同じです。
たとえば、ノード A から D までの 4 つのノードクラスターを持ち、現在のビューを {A, B, C, D} と表すことができるとします。通常、ビューのノードの順序はノードがクラスタに参加した順序を反映します (ただし、常にそうなるとは限らず、該当しない場合もあります)。
また、何らかの理由で B を除くクラスターにデプロイされた Foo という名前のシングルトンサービス (HASingletonController など) があるとします。 HAPartition サービスはどのサービスがどこにデプロイされているかをビューの順序で表すレジストリをクラスター全体で保持します。 したがって、クラスター内の各ノードでは、HAPartition サービスは Foo サービスに関するビューが {A, C, D} (B はなし) であることを認識します。
Foo サービスのクラスタートポロジに変更があると、 HAPartition サービスは Foo へのコールバックを呼び出し、 新しいトポロジについて通知します。 例えば、 Foo が D で起動した時に、 A、 C、 D で実行されているすべての Foo サービスが、 Foo の新しいビューが {A, C, D} であると通知するコールバックを受け取ったとします。 この場合、コールバックにより、各ノードが独自にマスターであるかを判断できる十分な情報をノードに提供します。 「HA シングルトンの選出ポリシー」 の通り、 各ノードの Foo サービスは HAPartitionHASingletonElectionPolicy を使用してマスターであるかを判断します。
A に障害が発生あるいはシャットダウンすると、 Foo の新しいビューが {C, D} であるというコールバックを C と D の Foo が受け取ります。 この時、 C がマスターになります。 A が再起動すると、 Foo の新しいビューが {C, D, A} であるというコールバックを A、C、D が受け取りますが、 C が引き続きマスターとなります。 A が前のマスターであっても、 再度マスターになるわけではありません。

26.1.2.1. HA シングルトンの選出ポリシー

HASingletonElectionPolicy オブジェクトは、 クラスタートポロジの変更後、 HA シングルトンの代わりに利用可能なノードのリストからマスターノードを選出します。
public interface HASingletonElectionPolicy
{
   ClusterNode elect(List<ClusterNode> nodes);
}
JBoss Enterprise Application Platform には 2 つの選出ポリシーが同梱されます。
HASingletonElectionPolicySimple
このポリシーはマスターノードを相対年代で選択します。 希望の年代は、 利用可能ノードリストのインデックスに相当する position プロパティより設定します。 position = 0 はデフォルトで最も古いノードを意味し、 position = 1 は 2 番目に古いノードを意味します。 position に負の数字を使用してノードの新しさを示すこともできます 。利用可能ノードのリストは環状リストであると考えてみてください。 position = -1 は最新のノードを意味し、 position = -2 は 2 番目に新しいノードを意味します。
<bean class="org.jboss.ha.singleton.HASingletonElectionPolicySimple">
  <property name="position">-1</property>
</bean>
PreferredMasterElectionPolicy
このポリシーは、 HASingletonElectionPolicySimple を拡張し、 希望のノードを設定できるようにします。 host:port または address:port と指定された preferredMaster プロパティは、 使用できる場合にマスターとなるべきノードを特定します。 希望のノードが使用できない場合、 選出ポリシーが前述の通り動作します。
<bean class="org.jboss.ha.singleton.PreferredMasterElectionPolicy">
  <property name="preferredMaster">server1:12345</property>
</bean>

26.2. ファーミングデプロイメント

アプリケーションをクラスター内にデプロイする最も簡単な方法はファーミングサービスを使用することです。 ファーミングサービスを使用すると、アプリケーション (アーカイブファイルまたは展開形式の EAR、 WAR 、 SAR など) をクラスターメンバの all/farm/ ディレクトリへデプロイすることができます。 アプリケーションは自動的に同じクラスター内の全ノードで複製されます。 ノードが後にクラスタに参加する場合、 クラスター内のファーミングデプロイされたアプリケーションがすべてプルインされ起動時にローカルにデプロイされます。 実行中のクラスター化されたサーバーノードの farm/ ディレクトリよりアプリケーションを削除すると、 アプリケーションはローカルでアンデプロイされ、 他すべてのクラスター化されたサーバーノードにある farm/ ディレクトリより削除されます (アンデプロイがトリガされます)。
JBoss Enterprise Application Platform の all 設定ではファーミングがデフォルトで有効になっているため、 自分で設定する必要はありません。必須の farm-deployment-jboss-beans.xml 設定ファイルと timestamps-jboss-beans.xml 設定ファイルは deploy/cluster ディレクトリにあります。カスタム設定でファーミングを有効にしたい場合は JBoss deploy ディレクトリ $JBOSS_HOME/server/$your_own_config/deploy/cluster にこれらのファイルをコピーするだけです。 カスタム設定ではクラスタリングが有効になっているようにしてください。
ファーミングサービスをカスタマイズする必要はほとんどありませんが、 FarmProfileRepositoryClusteringHandler Bean よりカスタマイズすることができます。 プロパティとデフォルト値は次のようになります。
<bean name="FarmProfileRepositoryClusteringHandler"
      class="org.jboss.profileservice.cluster.repository.
      DefaultRepositoryClusteringHandler">
  
  <property name="partition"><inject bean="HAPartition"/></property>
  <property name="profileDomain">default</property>
  <property name="profileServer">default</property>
  <property name="profileName">farm</property>
  <property name="immutable">false</property>
  <property name="lockTimeout">60000</property><!-- 1 minute -->
  <property name="methodCallTimeout">60000</property><!-- 1 minute -->
  <property name="synchronizationPolicy"><inject bean="FarmProfileSynchronizationPolicy"/></property>
</bean>
  • partition は必須の属性で、 クラスター内の通信でファームサービスが使用する HAPartition サービスを挿入します。
  • profile[Domain|Server|Name] は、 このハンドラーが目的とするサーバープロファイルを特定するのに使用されます。
  • immutable は、 ノードがコンテンツの変更をクラスターへプッシュすることを許可するかを示します。 true の値は、 synchronizationPolicyorg.jboss.system.server.profileservice.repository.clustered.sync. ImmutableSynchronizationPolicy に設定することに相当します。
  • lockTimeout はクラスター全体のロック取得に対して待機する時間 (ミリ秒単位) を定義します。
  • methodCallTimeout は、 リモートクラスターノード上の呼び出しに対して待機する時間 (ミリ秒単位) を定義します。
  • synchronizationPolicy は、 クラスターへの参加を試みるノードやノードの統合より、 どのようにクラスターコンテンツを追加、 再生、 更新、 削除するかを決定します。 ポリシーは「権限のある」ノード上で確認されます (クラスター上のサービスのマスターノードなど)。 再生 (Reincarnation) は、 新たに起動されたノードの farm ディレクトリに以前ファーミングサービスによって削除されたサービスが存在することで、実行されていない時に削除されると起動するノードに残存することがあります。 デフォルトの synchronizationPolicy は次のように定義されます。
    <bean name="FarmProfileSynchronizationPolicy"
          class="org.jboss.profileservice.cluster.repository.
          DefaultSynchronizationPolicy">
      <property name="allowJoinAdditions"><null/></property>
      <property name="allowJoinReincarnations"><null/></property>
      <property name="allowJoinUpdates"><null/></property>
      <property name="allowJoinRemovals"><null/></property>
      <property name="allowMergeAdditions"><null/></property>
      <property name="allowMergeReincarnations"><null/></property>
      <property name="allowMergeUpdates"><null/></property>
      <property name="allowMergeRemovals"><null/></property>
      <property name="developerMode">false</property>
      <property name="removalTrackingTime">2592000000</property><!-- 30 days -->
      <property name="timestampService"><inject bean="TimestampDiscrepancyService"/></property>
    </bean>
    
    • allow[Join|Merge][Additions|Reincarnations|Updates|Removals] は、 要求への固定応答を定義し、 結合されたノードや統合されたノードからの追加、再生、更新、削除を可能にします。
    • developerMode は、 すべての変更を許可する寛大な同期化ポリシーを有効します。 developerModeを有効にすることは、 上記の各プロパティを true に設定することに相当するため 、開発環境用の設定となります。
    • removalTrackingTime は、 再生の検知に使用するため、 ポリシーが削除されたアイテムを記憶すべき期間 (ミリ秒単位) を定義します。
    • timestampService は、 クラスターの現在および過去のメンバーに対するシステムクロックの不一致を推測し追跡します。 デフォルト実装は timestamps-jboss-beans.xml に定義されます。

第27章 JGroups サービス

JGroups は JBoss Enterprise Application Platform クラスターに対する基礎のグループ通信サポートを提供します。 クラスター化されたサービスと Groups との対話については、 「JGroups とのグループ通信」 に説明されています。 本章では、 この対話の詳細に重点を置き、設定の詳細やトラブルシューティングのヒントを中心に説明します。
本章は完全な JGroups ドキュメントではありません。 JGroups に関する詳細を知りたい場合は、 以下を参照してください。
本章の最初の項では、 多くの JGroups 設定オプションの詳細を取り上げます。 JBoss Enterprise Application Platform にはデフォルトの JGroups 設定のセットが同梱されています。 ほとんどのアプリケーションはデフォルト設定でそのまま動作します。 ネットワーク要件やパフォーマンス要件が特別なアプリケーションをデプロイする場合のみ設定を変更する必要があります。

27.1. JGroups チャネルのプロトコルスタックを設定

JGroups のフレームワークは、 クラスターでノード間のピアツーピア通信を可能にするサービスを提供します。 通信は通信チャンネル上で発生します。 チャネルはネットワーク通信プロトコルのスタックより構築され、 各チャネルはチャネル全体の動作に特定機能を追加します。 プロトコルによって提供される主な機能には、 トランスポート、 クラスターディスカバリ、 メッセージの順序付け、 無損失メッセージ配信、 失敗したピアの検知、 クラスターメンバーシップの管理サービスなどが含まれます。
図27.1「JGroups 内のプロトコルスタック」 は、 各メンバのチャネルが JGroups プロトコルのスタックで構成される概念的クラスターです。
JGroups 内のプロトコルスタック

図27.1 JGroups 内のプロトコルスタック

本項では、 チャネルへ追加する動作タイプにより 、最も頻繁に使用されるプロトコルについて取り上げます。 各プロトコルによって公開される主な設定属性についても説明しますが、 これらの属性は熟練ユーザーのみが変更すべきであるため、 プロトコルの目的を理解することに重点を置きます。
JBoss Enterprise Application Platform で使用される JGroups 設定は、 $JBOSS_HOME/server/production/deploy/cluster/jgroups-channelfactory.sar/META-INF/jgroups-channelfactory-stacks.xml ファイル内でネストされた要素として表示されます。このファイルは ChannelFactory サービスによって構文分析され、このコンテンツを使用して、正しく設定されたチャネルを必要とするクラスター化サービスへ提供します。ChannelFactory サービスの詳細は、「チャネルファクトリサービス」 を参照してください。
以下は、 jgroups-channelfactory-stacks.xml のプロトコルスタック設定例になります。
<stack name="udp-async"
           description="Same as the default 'udp' stack above, except message bundling
                        is enabled in the transport protocol (enable_bundling=true). 
                        Useful for services that make high-volume asynchronous 
                        RPCs (e.g. high volume JBoss Cache instances configured 
                        for REPL_ASYNC) where message bundling may improve performance.">
        <config>
          <UDP
             singleton_name="udp-async"
             mcast_port="${jboss.jgroups.udp_async.mcast_port:45689}"
             mcast_addr="${jboss.partition.udpGroup:228.11.11.11}"
             tos="8"
             ucast_recv_buf_size="20000000"
             ucast_send_buf_size="640000"
             mcast_recv_buf_size="25000000"
             mcast_send_buf_size="640000"
             loopback="true"
             discard_incompatible_packets="true"
             enable_bundling="true"
             max_bundle_size="64000"
             max_bundle_timeout="30"
             ip_ttl="${jgroups.udp.ip_ttl:2}"
             thread_naming_pattern="cl"
             timer.num_threads="12"
             enable_diagnostics="${jboss.jgroups.enable_diagnostics:true}"
             diagnostics_addr="${jboss.jgroups.diagnostics_addr:224.0.0.75}"
             diagnostics_port="${jboss.jgroups.diagnostics_port:7500}"

             thread_pool.enabled="true"
             thread_pool.min_threads="8"
             thread_pool.max_threads="200"
             thread_pool.keep_alive_time="5000"
             thread_pool.queue_enabled="true"
             thread_pool.queue_max_size="1000"
             thread_pool.rejection_policy="discard"
      
             oob_thread_pool.enabled="true"
             oob_thread_pool.min_threads="8"
             oob_thread_pool.max_threads="200"
             oob_thread_pool.keep_alive_time="1000"
             oob_thread_pool.queue_enabled="false"
             oob_thread_pool.rejection_policy="discard"/>
          <PING timeout="2000" num_initial_members="3"/>
          <MERGE2 max_interval="100000" min_interval="20000"/>
          <FD_SOCK/>
          <FD timeout="6000" max_tries="5" shun="true"/>
          <VERIFY_SUSPECT timeout="1500"/>
          <BARRIER/>
          <pbcast.NAKACK use_mcast_xmit="true" gc_lag="0"
                   retransmit_timeout="300,600,1200,2400,4800"
                   discard_delivered_msgs="true"/>
          <UNICAST timeout="300,600,1200,2400,3600"/>
          <pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000"
                   max_bytes="400000"/>          
          <VIEW_SYNC avg_send_interval="10000"/>
          <pbcast.GMS print_local_addr="true" join_timeout="3000"
                   shun="true"
                   view_bundling="true"
                   view_ack_collection_timeout="5000"
                   resume_task_timeout="7500"/>
          <FC max_credits="2000000" min_threshold="0.10" 
              ignore_synchronous_response="true"/>
          <FRAG2 frag_size="60000"/>
          <!-- pbcast.STREAMING_STATE_TRANSFER/ -->
          <pbcast.STATE_TRANSFER/>
          <pbcast.FLUSH timeout="0" start_flush_timeout="10000"/>
        </config>
    </stack>
<config> 要素にはすべての JGroups 設定データが含まれます。 この情報は、 概念的にソケットと似ている JGroups チャネルの設定に使用され、 クラスターのピア間の通信を管理します。 <config> 要素内部の各要素は特定の JGroups プロトコルを定義します。 各プロトコルは 1 つの機能を実行し、 これらの機能の組み合わせによってチャネル全体の特性が定義されます。 今後の項では、一般的に使用されるプロトコルやオプションについて説明し、 各プロトコルに使用できるオプションについて取り上げます。

27.1.1. 一般的な設定プロパティ

次のプロパティが以下で説明するすべての JGroups プロトコルにによって公開されます。
  • stats は、 AS の JMX コンソールや JGroups Probe ユーティリティなどのツールによって公開される操作に対するランタイム統計をプロトコルが収集するかを判断します。 収集される統計はプロトコルによって異なります。 デフォルトは true になります。

注記

JBoss Application Server 3.x および 4.x で使用された JGroups バージョンのすべてのプロトコルは down_thread 属性と up_thread 属性を公開しました。 JBoss Application Server 5 とそれ以降のバージョンに含まれる JGroups のバージョンはこれら属性を使用しません。 また、 これらの属性がプロトコルに対して設定されると、 WARN メッセージがサーバーログに書き込まれます。

27.1.2. トランスポートプロトコル

トランスポートプロトコルは、 メッセージをネットワークに送信、あるいはメッセージをネットワークから受信します。 また、 トランスポートプロトコルは使用されるスレッドプールを管理し、 受信メッセージをプロトコルスタックのより高いアドレスに送信します。 JGroups はトランスポートプロトコルとして UDPTCPTUNNEL をサポートします。

注記

UDPTCPTUNNEL プロトコルは相互に排他的です。 各 JGroups Config エレメントには 1 つのトランスポートプロトコルのみを指定できます。

27.1.2.1. UDP 設定

UDP は JGroups の推奨プロトコルです。 UDP はマルチキャスト (または特別な設定の場合は複数のユニキャスト) を使用してメッセージの送受信を行います。 クラスターサービスのトランスポートプロトコルに UDP を選択する場合は、 JGroups config 要素内の UDP サブ要素に設定する必要があります。 例は次の通りです。
          <UDP
             singleton_name="udp-async"
             mcast_port="${jboss.jgroups.udp_async.mcast_port:45689}"
             mcast_addr="${jboss.partition.udpGroup:228.11.11.11}"
             tos="8"
             ucast_recv_buf_size="20000000"
             ucast_send_buf_size="640000"
             mcast_recv_buf_size="25000000"
             mcast_send_buf_size="640000"
             loopback="true"
             discard_incompatible_packets="true"
             enable_bundling="true"
             max_bundle_size="64000"
             max_bundle_timeout="30"
             ip_ttl="${jgroups.udp.ip_ttl:2}"
             thread_naming_pattern="cl"
             timer.num_threads="12"
             enable_diagnostics="${jboss.jgroups.enable_diagnostics:true}"
             diagnostics_addr="${jboss.jgroups.diagnostics_addr:224.0.0.75}"
             diagnostics_port="${jboss.jgroups.diagnostics_port:7500}"

             thread_pool.enabled="true"
             thread_pool.min_threads="8"
             thread_pool.max_threads="200"
             thread_pool.keep_alive_time="5000"
             thread_pool.queue_enabled="true"
             thread_pool.queue_max_size="1000"
             thread_pool.rejection_policy="discard"
      
             oob_thread_pool.enabled="true"
             oob_thread_pool.min_threads="8"
             oob_thread_pool.max_threads="200"
             oob_thread_pool.keep_alive_time="1000"
             oob_thread_pool.queue_enabled="false"
             oob_thread_pool.rejection_policy="discard"/>
JGroups のトランスポート設定には、 複数の属性を使用できます。 最初に、 UDP プロトコルに使用できる属性を取り上げた後、 TCP プロトコルや TUNNEL プロトコルが使用する属性について説明します。
UDP プロトコル特有の属性は次の通りです。
  • ip_mcast は IP マルチキャスト機能を使用するかどうかを指定します。 デフォルト値は true です。 false に設定された場合は、 1 つのマルチキャストパケットではなく複数のユニキャストパケットが送信されます。 UDP プロトコルより送信されるすパケットはすべて UDP データグラムです。
  • mcast_addr はグループ (クラスターなど) との通信に対するマルチキャストアドレス (クラス D) を指定します。 JBoss AS の標準的なプロトコルスタック設定は、 システムプロパティ jboss.partition.udpGroup の値 (設定されている場合) をこの属性に使用します。 JBoss Application Server の起動時に -u コマンドラインスイッチを使用すると、 この値を設定します。 この設定属性を使用して JGroups チャネルを適切に別のチャネルより分離する方法については、 「JGroups チャネルの分離」 を参照してください。 この属性を省略すると、 デフォルト値は 228.11.11.11 になります。
  • mcast_port はグループとマルチキャスト通信するポートを指定します。 この設定属性を使用して JGroups チャネルを適切に別のチャネルより分離する方法については、 「JGroups チャネルの分離」 を参照してください。 この属性を省略すると、 デフォルト値は 45688 になります。
  • mcast_send_buf_sizemcast_recv_buf_sizeucast_send_buf_sizeucast_recv_buf_size は、 JGroups がオペレーティングシステムより要求するソケットの送受信バッファーサイズを指定します。 バッファーサイズを大きくすると、 バッファーのオーバーフローによるパケット落ちを防ぐことができます。 しかし、 ソケットバッファーサイズはオペレーティングシステムレベルで制限されるため、 希望のバッファーサイズを得るにはオペレーティングシステムレベルでの設定が必要となることがあります。 詳細は 「OS UDP の バッファー制限を設定してUDPのパフォーマンスを改善」 を参照してください。
  • bind_port はユニキャスト受信ソケットがバインドされるポートを指定します。 デフォルトは 0 で、 短命ポートを使用します。
  • port_range は、 bind_port によって特定されたポートがない場合に試行するポート数を指定します。 デフォルトは 1 で、 bind_port のみが試行されます。
  • ip_ttl は、IP マルチキャストパケットの TTL (生存期間) を指定します。TTL は、マルチキャストネットワーキングで一般的に使用される用語ですが、この値はネットワーキング装置がパケットを破棄するまでパケットがネットワークを通過する回数を表すためこの用語は実際には適切ではありません。
  • tos はユニキャストおよびマルチキャストデータグラムを送信するトラフィッククラスを指定します。
すべてのトランスポートプロトコルで共通しているため、 TCPTUNNEL で同じ意味を持つ属性は次の通りです。
  • singleton_name はトランスポートプロトコル設定に固有の名前を提供します。 アプリケーションサーバーの ChannelFactory によって使用され、 同じトランスポートプロトコルを使用する異なるチャネルによるトランスポートプロトコルインスタンスの共有をサポートします。 「JGroups 共有トランスポート」を参照してください。
  • bind_addr はメッセージの送受信を行うインターフェースを指定します。 デフォルトでは、 JGroups はシステムプロパティ jgroups.bind_addr の値を使用します。 -b コマンドラインスイッチを使用して設定することもできます。 JGroups ソケットのバインドに関する詳細は、 「その他設定の問題」 を参照してください。
  • receive_on_all_interfaces はこのノードがすべてのインターフェースでマルチキャストをリッスンするかを指定します。 デフォルト値は false です。 マルチキャストの受信については bind_addr プロパティよりも優先されます。 ただし、 マルチキャストの送信には引き続き bind_addr (設定されている場合) が使用されます。
  • send_on_all_interfaces は、 マシンに複数のネットワークインターフェースコントローラがある場合に、 このノードがすべてのネットワークインターフェースコントローラから UDP パケットを送信するかどうかを指定します。 同じマルチキャストメッセージが N 回送信されることを意味するため、 注意して使用してください。
  • receive_interfaces は、マルチキャストを受信するインターフェースの一覧を指定します。マルチキャスト受信ソケットはこれらのインターフェースすべてでリッスンします。IP アドレスまたはインターフェース名をカンマで区切ったリストになります (例: 192.168.5.1,eth1,127.0.0.1)。
  • send_interfacesは、マルチキャストを送信するインターフェースの一覧を指定します。マルチキャスト送信ソケットはこれらのインターフェースすべてでリッスンします。 IP アドレスまたはインターフェース名をカンマで区切ったリストになります (例: 192.168.5.1,eth1,127.0.0.1)。 そのため、同じマルチキャストメッセージが N 回送信されるため、注意して使用してください。
  • enable_bundling は、メッセージのバンドルを有効にするかを指定します。 true の場合、 max_bundle_size バイトが累積されるか max_bundle_time ミリ秒が経過するまで (いずれか早く発生する期間) トランスポートプロトコルが送信メッセージをキューに入れます。 次にキューに入ったメッセージを 1 つの大きなメッセージにまとめてから送信します。 このメッセージは受信側で元に戻されます。 デフォルト値は false です。
    メッセージのバンドルは、 送信元が受信先からの応答待機をブロックしない場合 (REPL_ASYNC に対して設定された JBoss Cache インスタンスなど)、 大量のメッセージ送信に使用されるチャネルに対してパフォーマンスの大幅な改善を期待できます。 送信元が応答待機をブロックする必要がある場合、 アプリケーションの待ち時間が大幅に長くなるため、 JBoss Cache インスタンスが REPL_SYNC に設定された場合など、 特定の場合でのみ推奨されます。
  • loopback は、 グループにメッセージを送信するスレッド自体が、 配信のためメッセージをスタックに戻すかを指定します (グループに送信されるメッセージは常に送信するノードにも配信されます)。 false の場合、 送信するスレッドはメッセージを持ちません。 トランスポートプロトコルがネットワークからメッセージを読み取るために待機し、 配信にメッセージ配信プールスレッドの 1 つを使用します。 デフォルトは false ですが、 ネットワークインターフェースが停止した時にチャネルがメッセージを受信できるようにするため true が推奨されます。
  • discard_incompatibe_packets は、 別バージョンの JGroups を使用するピアから送信されたパケットを破棄するか指定します。 クラスター内の各メッセージには JGroups バージョンのタグが付けられます。 discard_incompatible_packetstrue に設置されると、 別バージョンの JGroups からの受信されたメッセージは静かに破棄されます。 これ以外の場合は警告がログに記録されます。 メッセージは配信されません。 デフォルト値は false です。
  • enable_diagnostics は、 アドレス diagnostics_addr とポート diagnostics_port 上でマルチキャストソケットを開け、 JGroup の Probe ユーティリティが送信した分析要求をリッスンするかを指定します。
  • 通常の受信メッセージをスタックに運ぶため JGroups が使用するスレッドプールの動作は、 様々な thread_pool 属性が設定します。 これらの属性は、 java.util.concurrent.ThreadPoolExecutorService のインスタンスに対してコンストラクターの引数を提供します。 上記の例では、 プールの最低またはコアサイズが 8 スレッドで、 最大サイズは 200 になります。 9 つ以上のプールスレッドが作成されると、 メッセージの伝達より返されたスレッドは、 伝達する新しいメッセージが割り当てられるまで最大 5000 ミリ秒待機し、 その後終了します。 メッセージを伝達するスレッドがない場合、 ソケット外でメッセージを読み取る個別のスレッドがメッセージをキューに入れます。 キューは最大 1000 メッセージを保持することができます。 キューがいっぱいの場合、ソケット外でメッセージを読み取るスレッドはメッセージを破棄します。
  • 受信メッセージをプロトコルスタックへ運ぶために使用される java.util.concurrent.ThreadPoolExecutorService を設定するという面で、 oob_thread_pool 属性は thread_pool 属性と似ています。この場合、 OOB (帯域外、Out Of Band) メッセージと呼ばれる特別なタイプのメッセージを運ぶためにプールが使用されます。 OOB メッセージは、 NAKACK や UNICAST などのプロトコルの順番配信要件を免除されるため、 NAKACK や UNICAST が特定送信元のメッセージをキューに入れている場合でも、 OOB メッセージはスタックへ配信されます。 OOB メッセージは JGroups プロトコルによって頻繁に内部で使用され、 アプリケーションによって使用されることもあります。 例えば、 JBoss Cache が REPL_SYNC モードである場合、 2 フェーズコミットプロトコルの第 2 フェーズ にOOB メッセージを使用します。

27.1.2.2. TCP 設定

JGroups ベースのクラスターは TCP 接続でも動作します。 クラスターサイズが大きくなると、 TCP は UDP より多くのネットワークトラフィックを生成します。 TCP は基本的にはユニキャストのプロトコルです。 マルチキャストメッセージを送信するために、 JGroups は複数の TCP ユニキャストを使用します。 TCP をトランスポートプロトコルとして使用するには、 JGroups config 要素内の TCP 要素を定義してください。 TCP 要素の例は次の通りです。
<TCP singleton_name="tcp" 
        start_port="7800" end_port="7800"/>
TCP 要素固有の属性は次の通りです。
  • start_portend_port は、 サーバーがバインドする TCP ポートの範囲を定義します。 サーバーソケットは、 start_port 以降の最初に利用できるポートへバインドされます。 end_port の前に利用可能なポートが見つからない場合 (他のソケットによってポートが使用されている場合など)、 サーバーは例外をスローします。 end_port の指定がない場合や、 end_portstart_port よりも低い場合、 ポートの範囲に上限が適用されません。 start_portend_port が同じ場合、 指定されたポートが使用できないと start_port が失敗するため、 JGroups は指定されたポートの使用を強制されます。 デフォルト値は 7800 です。 0 を設定すると、 オペレーティングシステムがポートを選択します (TCCPING にノードと必要ポートをリストする必要があるため、 MPINGTCPGOSSIP のディスカバリプロトコルを使用する場合にのみ動作します)。
  • TCP の bind_portstart_port のエイリアスとして動作します。 内部に設定されると start_port を設定します。
  • recv_buf_size, send_buf_size は受信と送信のバッファーサイズを定義します。 バッファーのオーバーフローでパケットが破棄される可能性を低減するため、 受信バッファーサイズは大きめにした方がよいでしょう。
  • conn_expire_time はトラフィックが受信されていない場合、 ここに指定した時間 (ミリ秒単位) を経過すると reaper によって接続を閉じることができます。
  • reaper_interval は reaper を実行する間隔を指定します (ミリ秒単位)。 いずれの値も 0 の場合、 reap は行われません。 いずれかの値が > 0 になる場合、 reap が有効になります。デフォルトでは、reaper_interval が 0 です (つまり、reaper を実行しません)。
  • sock_conn_timeout は、ソケット作成に関する最大時間をミリ秒単位で指定します。初めて検索を実行し、ピアがハングする場合は、いつまでも待たずにタイムアウト後に他のメンバに対して ping を実行します。これにより、メンバーがまったく見つからない可能性が少なくなります。デフォルト値は 2000 です。
  • use_send_queues は各接続に別の送信キューを使用するかどうかを指定します。これにより、ピアがハングしたときに書き込みブロックが回避されます。デフォルト値は true です。
  • external_addr は、他のグループメンバにブロードキャストする外部 IP アドレス (ローカルアドレスと異なる場合) を指定します。これは、NAT (Network Address Translation) とファイアウォールの背後にあるプライベートネットワーク上のノード を使用し、そのノードに外部から見えるアドレス (バインドされるローカルアドレスとは異なります) のみを使用してルーティングできる場合に役に立ちます。したがって、ノードは、引き続きローカルアドレスにバインドできる一方で外部アドレスをブロードキャストするよう設定できます。これにより、ファイアウォール外部のノードはファイアウォール内部のノード (ただし、外部アドレスのもののみ) に引き続きルーティングできるため、TUNNEL プロトコル (つまり、中央ゴシップルーターの要件) を使用する必要がなくなります。external_addr を設定しない場合、ファイアウォール背後のノードはプライベートアドレスをそのアドレスにルーティングできない他のノードにブロードキャストします。
  • skip_suspected_members は、ユニキャストメッセージを該当すると思われるメンバに送信するかどうかを指定します。デフォルト値は true です。
  • tcp_nodelay は TCP_NODELAY を指定します。デフォルトでは TCP はメッセージに nagle を使用します。つまり、概念的に複数の小さいメッセージは大きいメッセージにまとめられます。同期クラスターメソッド呼び出しを行う場合は、メッセージバンドルを無効にするのに加えて nagle を無効にする必要があります (enable_bundling を false に設定します)。nagle を無効にするには、tcp_nodelay を true に設定します。デフォルト値は false です。

注記

UDP プロトコルの項で説明したすべてのプロトコルに共通する属性も TCP に適用されます。

27.1.2.3. TUNNEL の設定

TUNNEL プロトコルはメッセージの送信を処理するため外部ルーターを使用します。 外部ルーターは org.jgroups.stack.GossipRouter メインクラスを実行する Java プロセスです。 各ノードはこのルーターに登録する必要があります。 すべてのメッセージがこのルーターに送信されてからその目的地に転送されます。 TUNNEL の方法はファイアウォールの背後にあるノードとの通信を設定するために使用できます。 ノードはファイアウォールを通過して GossipRouter への TCP 接続を確立することができます (80番ポートの使用可)。 ファイアウォールの多くは、 ファイアウォール内部のホストへの TCP 接続を外部ホストが開始するすることを許可しないため、 ルーターによるファイアウォール背後のノードへのメッセージ送信にもこの接続が使用されます。 TUNNEL 設定は、 次のように JGroups <config> 要素内の TUNNEL 要素で定義されます。
<TUNNEL  singleton_name="tunnel"
            router_port="12001"
            router_host="192.168.5.1"/>
TUNNEL 要素内で使用できる属性は以下の通りです。
  • router_host は GossipRouter が稼働しているホストを指定します。
  • router_port は GossipRouter がリッスンしているポートを指定します。
  • reconnect_interval は、 接続が確立できない場合に TUNNELGossipRouter への接続を試行する間隔 (ミリ秒単位) を指定します。 デフォルトは 5000 です。

注記

UDP プロトコルの項で説明したすべてのプロトコルに共通する属性も TUNNEL に適用されます。

27.1.3. ディスカバリプロトコル

ノード上のチャネルが最初に接続すると、 互換性のあるチャネルを実行する他のノードやコーディネータ (新しいノードをグループへ参加させるノード) として機能しているノードを判断する必要があります。 ディスカバリプロトコルは、 クラスターのアクティブなノードを検索し、 どのノードがコーディネータであるか判断するために使用されます。そして、コーディネータの GMS と通信し、 新たに接続したノードをグループに追加するグループメンバーシッププロトコル (GMS) にその情報が提供されます (グループメンバーシッププロトコルについての詳細は「グループメンバーシップ (GMS)」 を参照してください)。
ディスカバリプロトコルは、 クラスターのスプリットを検知するために結合プロトコル (「マージ (MERGE2)」 参照) も支援します。
ディスカバリプロトコルはトランスポートプロトコルの上に位置しているため、 使用するトランスポートプロトコルに応じて異なるディスカバリプロトコルの使用を選択することができます。 また、 JGroups <config> エレメント内のサブ要素として設定することもできます。

27.1.3.1. PING

PING は PING 要求を IP マルチキャストアドレスにマルチキャストするか、ゴシップルーターに接続することによって動作する検索プロトコルです。したがって、PING は通常、UDP または TUNNEL トランスポートプロトコルの上部に位置します。各ノードはパケット {C, A} で応答します。ここで、C はコーディネータのアドレス、A は自身のアドレスを示します。ミリ秒単位のタイムアウトの経過後または num_initial_members の応答後、参加するノードは応答からコーディネータを調べ、JOIN 要求をコーディネータに送信します。誰も応答しない場合は、グループの最初のメンバと見なされます。
以下は IP マルチキャスト用の PING 設定の例です。
<PING timeout="2000"
    num_initial_members="3"/>
以下は Gossip Router に接続するための PING 設定の別の例です。
<PING gossip_host="localhost"
      gossip_port="1234"
       timeout="2000" 
      num_initial_members="3"/>
PING 要素内で使用できる属性は以下の通りです。
  • timeout はなんらかの応答を待機する最大ミリ秒数を指定します。デフォルト値は 3000 です。
  • num_initial_members は、待機する最大応答数を指定します (タイムアウトが経過していない場合)。デフォルト値は 2 です。
  • gossip_host GossipRouter が稼働しているホストを指定します。
  • gossip_port GossipRouter がリッスンしているポートを指定します。
  • gossip_refresh は GossipRouter からのリースの間隔を指定します (ミリ秒単位)。デフォルト値は 20000 です。
  • initial_hosts は、 ディスカバリで ping されるアドレスやポートをコンマで区切った一覧です (例: host1[12345],host2[23456])。 デフォルトは null で、 マルチキャストディスカバリが使用されます。 initial_hosts を指定した場合、 ウェルノウンホストの一部だけでなく可能なクラスターメンバーすべてをリストに含める必要があります。 すべてをリストしないと、 MERGE2 クラスタースプリットディスカバリが確実に動作しません。
gossip_hostgossip_port の両方が定義されると、 クラスターは初期のディスカバリに GossipRouter を使用します。 initial_hosts が指定されると、 クラスターはディスカバリにその静的アドレス一覧を ping します。 これ以外は、 クラスターはディスカバリに IP マルチキャスティングを使用します。

注記

ディスカバリフェーズが返されるのは timeout ミリ秒が経過した場合、 または num_initial_members 応答が受信された場合です。

27.1.3.2. TCPGOSSIP

TCPGOSSIP プロトコルは GossipRouter とのみ動作します。 基本的には有効な gossip_hostgossip_port の属性を持つ PING プロトコル設定と同じように動作します。 UDP および TCP 両方のトランスポートプロトコルの上で動作します。 例を示します。
<TCPGOSSIP timeout="2000"
       num_initial_members="3"
       initial_hosts="192.168.5.1[12000],192.168.0.2[12000]"/>
TCPGOSSIP 要素内で使用できる属性は以下の通りです。
  • timeout はなんらかの応答を待機する最大ミリ秒数を指定します。デフォルト値は 3000 です。
  • num_initial_members は、待機する最大応答数を指定します (タイムアウトが経過していない場合)。デフォルト値は 2 です。
  • initial_hostsGossipRouter が登録するアドレスやポートのコンマで区切りリストしたものです (例: host1[12345],host2[23456])。

27.1.3.3. TCPPING

TCPPING プロトコルは既知のメンバーのセットをとり、 ディスカバリのため ping を行います。 これは基本的には静的な設定です。 TCP の上で動作します。 次に JGroups config 要素内の TCPPING 設定要素の例を示します。
<TCPPING timeout="2000"
     num_initial_members="3"/
     initial_hosts="hosta[2300],hostb[3400],hostc[4500]"
     port_range="3">
TCPPING 要素で使用できる属性は以下の通りです。
  • timeout はなんらかの応答を待機する最大ミリ秒数を指定します。デフォルト値は 3000 です。
  • num_initial_members は、待機する最大応答数を指定します (タイムアウトが経過していない場合)。デフォルト値は 2 です。
  • initial_hosts は ping を行うアドレスのコンマ区切りリストです (例: host1[12345],host2[23456])。
  • port_range は、 初回のメンバーシップを取得する時に、 initial_hosts パラメータに指定されたポートよりプローブされる連続ポートの数を指定します。 上記の port_rangeinitial_hosts の値を例とすると、 TCPPING 層 は hosta[2300]hosta[2301]hosta[2302]hostb[3400]hostb[3401]hostb[3402]hostc[4500]hostc[4501]hostc[4502] へ接続しようとします。 この設定オプションにより、 ポートの組み合わせをすべて記述しなくても同じホストの複数のポートへ ping することができます。 TCP プロトコル設定で、 end_portstart_port より大きい場合、 TCPPING port_range がこの差異になるようにし、 許可範囲内でバインドされるポートに関係なくノードが ping されるようにすることが推奨されます。

27.1.3.4. MPING

MPING は IP マルチキャストを使用して最初のメンバーシップをディスカバリします。 ネットワーク上でのディスカバリメッセージの送受信をトランスポートプロトコルへ委譲する他とディスカバリプロトコルと違い、 MPING はソケットを開いてマルチキャストディスカバリメッセージを送受信します。 そのため、 すべてのトランスポートに使用できますが、 TCP で最も頻繁に使用されます。 通常、 TCP は可能性があるグループメンバーすべてを明示的にリストする必要がある TCPPING を必要とし、 標準のメッセージトランスポートに TCP が必要で、ディスカバリに UDP マルチキャスティングが許可される場合に使用されます。
<MPING timeout="2000"
    num_initial_members="3"
    bind_to_all_interfaces="true"
    mcast_addr="228.8.8.8"
    mcast_port="7500"
    ip_ttl="8"/>
MPING 要素で使用できる属性は以下の通りです。
  • timeout はなんらかの応答を待機する最大ミリ秒数を指定します。デフォルト値は 3000 です。
  • num_initial_members は待機する最大応答数を指定します (タイムアウトが経過しない場合)。デフォルト値は 2 です。
  • bind_addr はメッセージの送受信を行うインターフェースを指定します。 デフォルトでは、 JGroups はシステムプロパティ jgroups.bind_addr の値を使用します。 -b コマンドラインスイッチを使用して設定することもできます。 JGroups ソケットのバインドに関する詳細は、 「その他設定の問題」 を参照してください。
  • bind_to_all_interfacesbind_addr を上書きして multihome ノードにある全インターフェースを使用します。
  • mcast_addr, mcast_port, ip_ttl 属性は UDP プロトコル設定にある関連属性と同じものになります。

27.1.4. 障害検出プロトコル

障害検出プロトコルは障害が発生したノードの検出に使用されます。 障害が発生したノードが検出されると、 検証フェーズが開始されます。 このフェーズが終了してもノードがまだダウンしていると見なされた場合は、 クラスターがそのビューを更新し、 メッセージが障害が発生したノードに送信されないようにします。 ノードがクラスターの一部でなくなったことが JGroups を使用するサービスに報告されます。 障害検出プロトコルは JGroups <config> 要素内のサブ要素として設定されます。

27.1.4.1. FD

FD