開発ガイド

JBoss Enterprise Application Platform 6.1

JBoss Enterprise Application Platform 6 向け

エディッション 3

Nidhi Chaudhary

Lucas Costi

Russell Dickenson

Sande Gilda

Vikram Goyal

Eamon Logue

Darrin Mison

Scott Mumford

David Ryan

Misty Stanley-Jones

Keerat Verma

Tom Wells

概要

本書は、JBoss Enterprise Application Platform 6 とそのパッチリリースを使用する Java EE 6 の開発者向けの参考資料や例を提供します。

第1章 アプリケーションの開発

1.1. はじめに

1.1.1. JBoss Enterprise Application Platform 6 について

JBoss Enterprise Application Platform 6 は高速でセキュアな高性能ミドルウェアプラットフォームで、オープンな標準に基づいて構築され、Java Enterprise Edition 6 の仕様に準拠しています。高可用性クラスタリング、強力なメッセージング、分散キャッシングなどの技術を JBoss Application Server 7 と統合し、安定したスケーラブルな高速プラットフォームを作り上げます。
新しいモジュラー構造により、必要な時だけサービスを有効にできるため、起動速度が大幅に向上します。管理コンソールと管理コマンドラインインターフェースを使用すると、XML 設定ファイルを手作業で編集する必要がなくなるため、スクリプトを作成して作業を自動化することが可能です。さらに、API と開発フレームワークも含まれており、これらを使用して堅牢で拡張性のある、セキュアな Java EE アプリケーションを迅速に開発することができます。

1.2. 要件

1.2.1. Java Enterprise Edition 6 を理解する

1.2.1.1. EE 6 プロファイルの概要

Java Enterprise Edition 6 (EE 6) には、複数のプロファイルのサポート (つまり、API のサブセット) が含まれます。EE 6 の仕様で定義されるプロファイルは、Full ProfileWeb Profile の 2 つだけです。
EE 6 Full Profile には、EE 6 の仕様に含まれるすべての API と仕様が含まれます。EE 6 の Web Profile には、Web 開発者にとって有用な API のサブセットが含まれます。
JBoss Enterprise Application Platform 6 は、Java Enterprise Edition 6 の Full Profile および Web Profile の仕様の認定された実装です。

1.2.1.2. Java Enterprise Edition 6 Web Profile

Web Profileは、Java Enterprise Edition 6 仕様で定義されている 2 つのプロファイルのうちの1つです。Web Profile は Web アプリケーション開発向けに設計されており、Java Enterprise Edition 6 仕様で定義されている、もう1つのプロファイルは Full Profile です。詳細については、「Java Enterprise Edition 6 Full Profile」を参照してください。

Java EE 6 Web Profile の要件

  • Java Platform、Enterprise Edition 6
  • Java Web テクノロジー

    • Servlet 3.0 (JSR 315)
    • JSP 2.2 および Expression Language (EL) 1.2
    • JavaServer Faces (JSF) 2.0 (JSR 314)
    • JSP 1.2 向けの Java Standard Tag Library (JSTL)
    • Debugging Support for Other Languages 1.0 (JSR 45)
  • エンタープライズアプリケーションテクノロジー

    • Contexts and Dependency Injection (CDI) (JSR 299)
    • Dependency Injection for Java (JSR 330)
    • Enterprise JavaBeans 3.1 Lite (JSR 318)
    • Java Persistence API 2.0 (JSR 317)
    • Common Annotations for the Java Platform 1.1 (JSR 250)
    • Java Transaction API (JTA) 1.1 (JSR 907)
    • Bean Validation (JSR 303)

1.2.1.3. Java Enterprise Edition 6 Full Profile

Java Enterprise Edition 6 (EE 6) の仕様では、プロファイルのコンセプトを定義し、仕様の一部として 2 つのプロファイルを定義しています。Java Enterprise Edition 6 Web Profile ( 「Java Enterprise Edition 6 Web Profile」) でサポートされているアイテム以外に、Full Profile では以下の API がサポートされます。JBoss Enterprise Edition 6 は Full Profile をサポートします。

EE 6 Full Profile に含まれるアイテム

  • EJB 3.1 (Lite ではない) (JSR 318)
  • Java EE Connector Architecture 1.6 (JSR 322)
  • Java Message Service (JMS) API 1.1 (JSR 914)
  • JavaMail 1.4 (JSR 919)
  • Web サービステクノロジー

    • Jax-RS RESTful Web Services 1.1 (JSR 311)
    • Implementing Enterprise Web Services 1.3 (JSR 109)
    • JAX-WS Java API for XML-Based Web Services 2.2 (JSR 224)
    • Java Architecture for XML Binding (JAXB) 2.2 (JSR 222)
    • Web Services Metadata for the Java Platform (JSR 181)
    • Java APIs for XML-based RPC 1.1 (JSR 101)
    • Java APIs for XML Messaging 1.3 (JSR 67)
    • Java API for XML Registries (JAXR) 1.0 (JSR 93)
  • 管理およびセキュリティテクノロジー

    • Java Authentication Service Provider Interface for Containers 1.0 (JSR 196)
    • Java Authentication Contract for Containers 1.3 (JSR 115)
    • Java EE Application Deployment 1.2 (JSR 88)
    • J2EE Management 1.1 (JSR 77)

1.2.2. JBoss Enterprise Application Platform 6 で使用されるモジュールと新しいモジュラークラスローディングシステムについて

1.2.2.1. モジュール

モジュールは、クラスのロードと依存関係の管理に使用される、クラスの論理的なグループです。JBoss Enterprise Application Platform 6 では、静的モジュールと動的モジュールと呼ばれる 2 種類のモジュールが存在します。ただし、この 2 種類のモジュールの違いは、パッケージ化の方法のみです。すべてのモジュールは同じ機能を提供します。
静的モジュール
静的モジュールは、アプリケーションサーバーの EAP_HOME/modules/ ディレクトリに事前定義されます。各サブディレクトリは 1 つのモジュールを表し、1 つまたは複数の JAR ファイルと設定ファイル (module.xml) が含まれます。モジュールの名前は、module.xml ファイルで定義されます。アプリケーションサーバーで提供されるすべての API (Java EE API や JBoss Logging などの他の API を含む) は、静的モジュールとして提供されます。
カスタム静的モジュールの作成は、同じサードパーティーライブラリを使用する同じサーバー上に多くのアプリケーションがデプロイされる場合に役立ちます。これらのライブラリを各アプリケーションとバンドルする代わりに、JBoss 管理者はこれらのライブラリが含まれるモジュールを作成およびインストールできます。アプリケーションは、カスタム静的モジュールで明示的な依存関係を宣言できます。
動的モジュール
動的モジュールは、各 JAR または WAR デプロイメント (または、EAR 内のサブデプロイメント) に対してアプリケーションサーバーによって作成およびロードされます。動的モジュールの名前は、デプロイされたアーカイブの名前から派生されます。デプロイメントはモジュールとしてロードされるため、依存関係を設定でき、他のデプロイメントが依存関係として使用できます。
モジュールは必要なときのみロードされます。通常、明示的または暗黙的な依存関係があるアプリケーションがデプロイされるときのみ、モジュールがロードされます。

1.2.2.2. クラスロードとモジュールの概要

JBoss Enterprise Application Platform 6 は、デプロイされたアプリケーションのクラスパスを制御するために新しいモジュール形式のクラスロードシステムを使用します。このシステムでは、階層クラスローダーの従来のシステムよりも、柔軟性と制御が強化されています。開発者は、アプリケーションで利用可能なクラスに対して粒度の細かい制御を行い、アプリケーションサーバーで提供されるクラスを無視して独自のクラスを使用してデプロイメントを設定できます。
モジュール形式のクラスローダーは、すべての Java クラスをモジュールと呼ばれる論理グループに分けます。各モジュールは、独自のクラスパスに追加されたモジュールからクラスを取得するために、他のモジュールの依存関係を定義できます。デプロイされた各 JAR および WAR ファイルはモジュールとして扱われるため、開発者はモジュール設定アプリケーションに追加してアプリケーションのクラスパスの内容を制御できます。
以下に、開発者が JBoss Enterprise Application Platform 6 でアプリケーションを正しくビルドおよびデプロイするために知る必要があることを示します。

1.3. 開発環境の設定

1.3.1. JBoss Developer Studio のダウンロードとインストール

1.3.1.2. JBoss Developer Studio 5 のダウンロード

  1. https://access.redhat.com/ にアクセスします。
  2. ダウンロードJBoss Enterprise Middlewareダウンロード と選択します。
  3. ドロップボックスから JBoss Developer Studio を選択します。
  4. 適切なバージョンを選択し、ダウンロード をクリックします。

1.3.1.3. JBoss Developer Studio 5 のインストール

手順1.1 JBoss Developer Studio 5 のインストール

  1. 端末を開きます。
  2. ダウンロードした .jar ファイルが含まれるディレクトリへ移動します。
  3. 次のコマンドを実行して GUI インストーラーを開始します。
    java -jar jbdevstudio-build_version.jar
  4. [Next] をクリックしてインストールを開始します。
  5. [I accept the terms of this license agreement] を選択し、[Next] をクリックします。
  6. インストールパスを調整し、[Next] をクリックします。

    注記

    インストールパスのフォルダーが存在しない場合はメッセージが表示されます。[Ok] をクリックしてフォルダーを作成します。
  7. デフォルトの JVM が選択されます。他の JVM を選択するか、そのまま [Next] をクリックします。
  8. 使用可能なアプリケーションプラットフォームを追加し、[Next] をクリックします。
  9. インストールの詳細を確認し、[Next] をクリックします。
  10. インストールが完了したら [Next] をクリックします。
  11. JBoss Developer Studio のデスクトップショートカットを設定し、[Next] をクリックします。
  12. [Done] をクリックします。

1.3.1.4. JBoss Developer Studio の起動

手順1.2 JBoss Developer Studio を起動するコマンド

  1. 端末を開きます。
  2. インストールディレクトリへ移動します。
  3. 次のコマンドを実行して JBoss Developer Studio を起動します。
    [localhost]$ ./jbdevstudio

1.3.1.5. JBoss Enterprise Application Platform 6 サーバーの JBoss Developer Studio への追加

次の手順では、JBoss Developer Studio を初めて使用し、JBoss Enterprise Application Platform 6 サーバーを追加したことがないことを前提としています。

手順1.3 サーバーの追加

  1. [Servers]タブを開きます。[Servers]タブがない場合は次のようにパネルへ追加します。
    1. [Window][Show View][Other...] をクリックします。
    2. [Servers] フォルダーより [Server] を選択し、[OK] をクリックします。
  2. [new server wizard]リンクをクリックするか、空のサーバーパネル内で右クリックし、[New][Server] と選択します。
    新しいサーバーの追加 - 使用できるサーバーがない場合

    図1.1 新しいサーバーの追加 - 使用できるサーバーがない場合

  3. [JBoss Enterprise Middleware] を拡張し、 [JBoss Enterprise Application Platform 6.x] を選択します。その後、[Next] ボタンをクリックします。
    サーバータイプの選択

    図1.2 サーバータイプの選択

  4. [Browse] をクリックし、JBoss Enterprise Application Platform 6 のインストール場所へ移動します。そして [Next] をクリックします。
    サーバーインストールの閲覧

    図1.3 サーバーインストールの閲覧

  5. この画面でサーバーの動作を定義します。手作業でサーバーを起動するか、JBoss Developer Studio に管理を任せます。デプロイメントのリモートサーバーを定義し、そのサーバーの管理ポートを公開するかどうかを決定できます (たとえば、JMX を使用してこのサーバーに接続する必要がある場合)。この例では、サーバーがローカルサーバーであり、JBoss Developer Studio がサーバーを管理するため、何もチェックする必要がないことを前提とします。次へ (Next) をクリックします。
    新しい JBoss サーバーの挙動の定義

    図1.4 新しい JBoss サーバーの挙動の定義

  6. この画面により新しいサーバーに対して既存のプロジェクトを設定することが可能です。現時点ではプロジェクトがないため、 [Finish] をクリックします。
    新しい JBoss サーバーのリソースの変更

    図1.5 新しい JBoss サーバーのリソースの変更

結果

JBoss Enterprise Application Server 6.0 のランタイムサーバーは [Servers] タブに表示されます。

サーバーがサーバーリストに表示される

図1.6 サーバーがサーバーリストに表示される

1.4. 最初のアプリケーションの実行

1.4.1. デフォルトの Welcome Web アプリケーションの置き換え

JBoss Enterprise Application Platform 6 には、8080 番ポートでサーバーの URL を開くと表示される Welcome アプリケーションが含まれています。次の手順でこのアプリケーションを独自の Web アプリケーションに置き換えることができます。

手順1.4 デフォルトの Welcome Web アプリケーションを独自の Web アプリケーションに置き換える

  1. Welcome アプリケーションを無効にします。

    管理 CLI スクリプト EAP_HOME/bin/jboss-cli.sh を使用して次のコマンドを実行します。異なる管理対象ドメインプロファイルの変更が必要となる場合があります。スタンドアローンサーバーでは、コマンドの /profile=default 部分の削除が必要となる場合があります。
    /profile=default/subsystem=web/virtual-server=default-host:write-attribute(name=enable-welcome-root,value=false)
  2. ルートコンテキストを使用するよう Web アプリケーションを設定します。

    Web アプリケーションを設定してルートコンテキストを (/) を URL アドレスとして使用するには、META-INF/ または WEB-INF/ ディレクトリにある jboss-web.xml を変更します。<context-root> ディレクティブを次のようなディレクティブに置き換えます。
    <jboss-web>
        <context-root>/</context-root>
    </jboss-web>		
    		
    
    
  3. アプリケーションをデプロイします。

    サーバーグループか最初に変更したサーバーにアプリケーションをデプロイします。アプリケーションは http://SERVER_URL:PORT/ で使用できるようになります。

1.4.2. クイックスタートコードの例をダウンロードする

1.4.2.1. Java EE クイックスタートサンプルへのアクセス

概要

JBoss Enterprise Application Platform 6 には、ユーザーが Java EE 6 の技術を使用したアプリケーションの作成を簡単に開始できるクイックスタートのサンプルが複数含まれています。

手順1.5 クイックスタートのダウンロード

  1. Web ブラウザーを開き、URL https://access.redhat.com/jbossnetwork/restricted/listSoftware.html?product=appplatform にアクセスします。
  2. リストに「Application Platform 6 クイックスタート」があることを確認します。
  3. [ダウンロード] ボタンをクリックし、サンプルが含まれる .zip ファイルをダウンロードします。
  4. 希望のディレクトリにアーカイブを展開します。
結果

Java EE クイックスタートのサンプルがダウンロードされ、解凍されます。各クイックスタートのデプロイ方法については、jboss-eap-6.0-quickstarts/ ディレクトリーにある README.md ファイルを参照してください。

1.4.3. クイックスタートの実行

1.4.3.1. JBoss Developer Studio でのクイックスタートの実行

手順1.6 JBoss Developer Studio にクイックスタートをインポートする

各クイックスタートには、クイックスタートのプロジェクトおよび設定情報が含まれる POM (プロジェクトオブジェクトモデル) ファイルが同梱されています。この POM ファイルを使用すると、簡単にクイックスタートを JBoss Developer Studio へインポートすることができます。
  1. この作業を行っていない場合は、 「Maven 設定を使用した JBoss Enterprise Application Platform の Maven リポジトリーの設定」に記載された手順に従ってください。
  2. JBoss Developer Studio を起動します。
  3. メニューより [File][Import] と選択します。
  4. 選択リストより [Maven][Maven Projects] と選択し、[Next] を選択します。
    既存の Maven プロジェクトのインポート

    図1.7 既存の Maven プロジェクトのインポート

  5. インポートするクイックスタートのディレクトリーを参照し、OK をクリックします。[Projects] リストボックスに、選択したクイックスタートプロジェクトの pom.xml ファイルが示されます。
    Maven プロジェクトの選択

    図1.8 Maven プロジェクトの選択

  6. [Next] をクリックした後、 [Finish] をクリックします。

手順1.7 helloworld クイックスタートのビルドとデプロイ

helloworld クイックスタートは最も単純なクイックスタートの 1 つで、JBoss サーバーが適切に設定され実行されているか検証することができます。
  1. [Servers] タブを開き、パネルにアプリケーションを追加します。
    1. [Window][Show View][Other...] をクリックします。
    2. [Servers] フォルダーから [Server] を選択し[Ok] をクリックします。
  2. [Project Explorer] タブで [helloworld] を右クリックし、[Run As][Run on Server] を選択します。
  3. [JBoss EAP 6.0 Runtime Server] サーバーを選択し、[Next] をクリックします。これにより helloworld クイックスタートが JBoss サーバーにデプロイされます。
  4. helloworld が JBoss サーバーに正しくデプロイされたことを確認するには、Web ブラウザーを開いて、URL http://localhost:8080/jboss-as-helloworld でアプリケーションに接続します。

1.4.3.2. コマンドラインを使用したクイックスタートの実行

手順1.8 コマンドラインを使用したクイックスタートのビルドおよびデプロイ

コマンドラインを使用すると簡単にクイックスタートをビルドおよびデプロイすることができます。コマンドラインを使用する場合、JBoss サーバーを起動する必要がある時はユーザーが起動しなければならないため注意してください。
  1. クイックスタートのルートディレクトリにある README ファイルを確認してください。

    このファイルにはシステム要件に関する一般的な情報、Maven の設定方法、ユーザーの追加方法、クイックスタートの実行方法が含まれています。クイックスタートを始める前に必ず読むようにしてください。
    このファイルには使用可能なクイックスタートの一覧表も含まれています。この表にはクイックスタート名と使用する技術が記載され、各クイックスタートの簡単な説明と設定するために必要な経験レベルが記載されています。クイックスタートの詳細情報はクイックスタート名をクリックしてください。
    他のクイックスタートを向上したり拡張するため作成されたクイックスタートもあります。このようなクイックスタートは Prerequisites カラムに記載されています。クイックスタートに前提条件がある場合、クイックスタートを始める前にこれらをインストールする必要があります。
    任意コンポーネントのインストールや設定が必要になるクイックスタートもあります。これらのコンポーネントはクイックスタートが必要である場合のみインストールしてください。
  2. helloworld クイックスタートを実行します。

    helloworld クイックスタートは最も単純なクイックスタートの 1 つで、JBoss サーバーが適切に設定され実行されているか検証することができます。helloworld クイックスタートのルートにある README ファイルを開きます。このファイルにはクイックスタートのビルドおよびデプロイ方法や実行しているアプリケーションへのアクセス方法の詳細手順が含まれています。
  3. 別のクイックスタートを実行します。

    各クイックスタートのルートフォルダーにある README ファイルの手順に従って例を実行します。

1.4.4. クイックスタートチュートリアルの確認

1.4.4.1. helloworld クイックスタート

概要

helloworld クイックスタートでは JBoss Enterprise Application Platform 6 に単純なサーブレットをデプロイする方法を説明します。ビジネスロジックは CDI (Contexts and Dependency Injection) Bean として提供されるサービスにカプセル化されサーブレットに挿入されます。このクイックスタートは大変単純です。「Hello World」を Web ページに出力するだけです。サーバーが適切に設定され、起動されたかを最初に確認するのに適しています。

コマンドラインを使用してこのクイックスタートをビルドしデプロイする手順の詳細は helloworld クイックスタートディレクトリのルートにある README ファイルを参照してください。ここでは JBoss Developer Studio を使用してクイックスタートを実行する方法を説明します。

手順1.9 helloworld クイックスタートを JBoss Developer Studio にインポートします。

「JBoss Developer Studio でのクイックスタートの実行」に記述された手順に従ってすでにすべてのクイックスタートを JBoss Developer Studio にインポートした場合は、次のセクションに進むことができます。
  1. インポートしていない場合は、 「Maven 設定を使用した JBoss Enterprise Application Platform の Maven リポジトリーの設定」に記述された手順に従います。
  2. JBoss Developer Studio がインストールされていない場合は、 「JBoss Developer Studio 5 のインストール」に記述された手順に従います。
  3. 「JBoss Developer Studio の起動」に記述された手順に従います。
  4. メニューより [File][Import] と選択します。
  5. 選択リストより [Maven][Maven Projects] と選択し、[Next] を選択します。
    既存の Maven プロジェクトのインポート

    図1.9 既存の Maven プロジェクトのインポート

  6. QUICKSTART_HOME/quickstart/helloworld/ ディレクトリを閲覧し、[OK] をクリックします。[ Projects] リストボックスに [helloworld] クイックスタートプロジェクトから pom.xml ファイルが追加されます。
    Maven プロジェクトの選択

    図1.10 Maven プロジェクトの選択

  7. [Finish] をクリックします。

手順1.10 helloworld クイックスタートのビルドとデプロイ

  1. JBoss Enterprise Application Platform 6 用 JBoss Developer Studio がまだ設定されていない場合は、 「JBoss Enterprise Application Platform 6 サーバーの JBoss Developer Studio への追加」に記述された手順に従います。
  2. [Project Explorer] タブの [jboss-as-helloworld] を右クリックし、[Run As][Run on Server] と選択します。
    サーバー上での実行

    図1.11 サーバー上での実行

  3. [JBoss EAP 6.0 Runtime Server] サーバーを選択し、[Next] をクリックします。これにより helloworld クイックスタートが JBoss サーバーにデプロイされます。
  4. helloworld が JBoss サーバーに正しくデプロイされたことを確認するには、Web ブラウザーを開き、URL http://localhost:8080/jboss-as-helloworld を指定してアプリケーションにアクセスします。

手順1.11 ディレクトリ構造の確認

helloworld クイックスタートのコードは QUICKSTART_HOME/helloworld ディレクトリにあります。helloworld クイックスタートはサーブレットと CDI Bean によって構成されます。また、このアプリケーションの Bean を検索し、CDI をアクティベートするよう JBoss Enterprise Application Platform 6 に伝える空の beans.xml ファイルも含まれています。
  1. beans.xml はクイックスタートの src/main/webapp/ ディレクトリにある WEB-INF/ フォルダーにあります。
  2. src/main/webapp/ ディレクトリには、単純なメタリフレッシュを使用してユーザーのブラウザーを http://localhost:8080/jboss-as-helloworld/HelloWorld にあるサーブレットへリダイレクトする index.html ファイルも含まれています。
  3. この例の全設定は、例の src/main/webapp/ ディレクトリにある WEB-INF/ にあります。
  4. クイックスタートには web.xml ファイルは必要ありません。

手順1.12 コードの確認

パッケージの宣言とインポートはこれらのリストには含まれていません。完全なリストはクイックスタートのソースコードにあります。
  1. HelloWorldServlet コードの検証

    HelloWorldServlet.javasrc/main/java/org/jboss/as/quickstarts/helloworld/ ディレクトリにあります。このサーブレットが情報をブラウザーに送ります。
    27. @WebServlet("/HelloWorld")
    28. public class HelloWorldServlet extends HttpServlet {
    29. 
    30.    static String PAGE_HEADER = "<html><head /><body>";
    31.
    32.    static String PAGE_FOOTER = "</body></html>";
    33.
    34.    @Inject
    35.    HelloService helloService;
    36.
    37.    @Override
    38.    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
                                 throws ServletException, IOException {
    39.       PrintWriter writer = resp.getWriter();
    40.       writer.println(PAGE_HEADER);
    41.       writer.println("<h1>" + helloService.createHelloMessage("World") + "</h1>");
    42.       writer.println(PAGE_FOOTER);
    43.       writer.close();
    44.     }
    45. 
    46. }
    
    

    表1.1 HelloWorldServlet の詳細

    注記
    27 Java EE 6 以前はサーブレットの登録に XML ファイルが使用されました。サーブレットの登録はかなり簡易化され、@WebServlet アノテーションを追加し、サーブレットへのアクセスに使用される URL へのマッピングを提供することのみが必要となります。
    30-32 各 Web ページには適切な形式の HTML が必要になります。本クイックスタートは静的な文字列を使用して最低限のヘッダーとフッターの出力を書き出します。
    34-35 これらの行は実際のメッセージを生成する HelloService CDI Bean を挿入します。HelloService の API を変更しない限り、ビューレイヤーを変更せずに HelloService の実装を後日変更することが可能です。
    41 この行はサービスへ呼び出し、「Hello World」というメッセージを生成して HTTP 要求へ書き出します。
  2. HelloService コードの検証

    HelloService.java ファイルは src/main/java/org/jboss/as/quickstarts/helloworld/ ディレクトリにあります。このサービスは非常に単純であり、メッセージを返します。XML やアノテーションの登録は必要ありません。
     9. public class HelloService {
    10. 
    11.    String createHelloMessage(String name) {
    12.       return "Hello " + name + "!"; 
    32.    }
    33. }
    34.  
    
    

1.4.4.2. numberguess クイックスタート

概要

このクイックスタートでは単純なアプリケーションを作成し、 JBoss Enterprise Application Platform 6 にデプロイする方法を説明します。ここで作成するアプリケーションは情報を永続化しません。情報は JSF ビューを使用して表示され、ビジネスロジックは 2 つの CDI (Contexts and Dependency Injection) Bean にカプセル化されます。numberguess クイックスタートでは 1 から 100 までの数字を当てるチャンスが 10 回与えられます。数字を選択した後、その数字が正解の数字より大きいか小さいかが表示されます。

numberguess クイックスタートのコードは QUICKSTART_HOME/numberguess ディレクトリにあります。numberguess クイックスタートは WAR モジュールとしてパッケージ化された複数の Bean や設定ファイル、Facelets (JSF) ビューによって構成されます。
コマンドラインを使用してこのクイックスタートをビルドしデプロイする手順の詳細は numberguess クイックスタートディレクトリのルートにある README ファイルを参照してください。ここでは JBoss Developer Studio を使用してクイックスタートを実行する方法を説明します。

手順1.13 numberguess クイックスタートを JBoss Developer Studio にインポートします。

「JBoss Developer Studio でのクイックスタートの実行」に記述された手順に従ってすでにすべてのクイックスタートを JBoss Developer Studio にインポートした場合は、次のセクションに進むことができます。
  1. JBoss Developer Studio がインストールされていない場合は、 「JBoss Developer Studio 5 のインストール」に記述された手順に従います。
  2. 「JBoss Developer Studio の起動」に記述された手順に従います。
  3. メニューより [File][Import] と選択します。
  4. 選択リストより [Maven][Maven Projects] と選択し、[Next] を選択します。
    既存の Maven プロジェクトのインポート

    図1.12 既存の Maven プロジェクトのインポート

  5. QUICKSTART_HOME/quickstart/numberguess/ ディレクトリを閲覧し、[OK] をクリックします。 [Projects] リストボックスに [numberguess] クイックスタートプロジェクトから pom.xml ファイルが追加されます。
  6. [Finish] をクリックします。

手順1.14 numberguess クイックスタートのビルドとデプロイ

  1. JBoss Enterprise Application Platform 6 用 JBoss Developer Studio がまだ設定されていない場合は、 「JBoss Enterprise Application Platform 6 サーバーの JBoss Developer Studio への追加」に記述された手順に従います。
  2. [Project Explorer] タブの [jboss-as-numberguess] を右クリックし、[Run As][Run on Server] と選択します。
  3. [JBoss EAP 6.0 Runtime Server] サーバーを選択し、[Next] をクリックします。これにより numberguess クイックスタートが JBoss サーバーにデプロイされます。
  4. numberguess が JBoss サーバーに正しくデプロイされたことを確認するには、Web ブラウザを開き、URL http://localhost:8080/jboss-as-numberguess を指定してアプリケーションにアクセスします。

手順1.15 設定ファイルの確認

この例の設定ファイルはすべてクイックスタートの src/main/webapp/ ディレクトリにある WEB-INF/ ディレクトリに格納されています。
  1. faces-config ファイルの確認

    本クイックスタートは faces-config.xml ファイル名の JSF 2.0 バージョンを使用します。Facelets の標準的なバージョンが JSF 2.0 のデフォルトのビューハンドラーであるため、特に必要なものはありません。ここでは JBoss Enterprise Application Platform 6 は Java EE の領域を越えます。この設定ファイルが含まれると JSF が自動的に設定されます。そのため、設定はルート要素のみで構成されます。
    03. <faces-config version="2.0"
    04.    xmlns="http://java.sun.com/xml/ns/javaee"
    05.    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    06.    xsi:schemaLocation="
    07.       http://java.sun.com/xml/ns/javaee>
    08.       http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">
    09.      
    10. </faces-config>
    
    
  2. beans.xml ファイルの確認

    アプリケーションの Bean を検索し、CDI を有効にするよう JBoss Enterprise Application Platform に伝える空の beans.xml ファイルも存在します。
  3. web.xml ファイルはありません

    クイックスタートには web.xml ファイルは必要ありません。

手順1.16 JSF コードの確認

JSF はソースファイルに .xhtml ファイル拡張子を使用しますが、レンダリングされたビューには .jsf 拡張子を使用します。
  • home.xhtml コードの確認

    home.xhtml ファイルは src/main/webapp/ ディレクトリにあります。
    03. <html xmlns="http://www.w3.org/1999/xhtml"
    04.    xmlns:ui="http://java.sun.com/jsf/facelets"
    05.    xmlns:h="http://java.sun.com/jsf/html"
    06.    xmlns:f="http://java.sun.com/jsf/core">
    07.
    08. <head>
    09. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    10. <title>Numberguess</title>
    11. </head>
    12.
    13. <body>
    14.    <div id="content">
    15.       <h1>Guess a number...</h1>
    16.       <h:form id="numberGuess">
    17.
    18.          <!-- Feedback for the user on their guess -->
    19.          <div style="color: red">
    20.             <h:messages id="messages" globalOnly="false" />
    21.             <h:outputText id="Higher" value="Higher!"
    22.                rendered="#{game.number gt game.guess and game.guess ne 0}" />
    23.             <h:outputText id="Lower" value="Lower!"
    24.                rendered="#{game.number lt game.guess and game.guess ne 0}" />
    25.          </div>
    26.
    27.          <!-- Instructions for the user -->
    28.          <div>
    29.             I'm thinking of a number between <span
    30.                id="numberGuess:smallest">#{game.smallest}</span> and <span
    31.                id="numberGuess:biggest">#{game.biggest}</span>. You have
    32.             #{game.remainingGuesses} guesses remaining.
    33.          </div>
    34.
    35.          <!-- Input box for the users guess, plus a button to submit, and reset -->
    36.          <!-- These are bound using EL to our CDI beans -->
    37.          <div>
    38.             Your guess:
    39.             <h:inputText id="inputGuess" value="#{game.guess}"
    40.                required="true" size="3"
    41.                disabled="#{game.number eq game.guess}"
    42.                validator="#{game.validateNumberRange}" />
    43.             <h:commandButton id="guessButton" value="Guess"
    44.                action="#{game.check}"
    45.                disabled="#{game.number eq game.guess}" />
    46.          </div>
    47.          <div>
    48.             <h:commandButton id="restartButton" value="Reset"
    49.                action="#{game.reset}" immediate="true" />
    50.          </div>
    51.       </h:form>
    52.
    53.    </div>
    54.
    55.    <br style="clear: both" />
    56.
    57. </body>
    58. </html>
    
    

    表1.2 JSF の詳細

    注記
    20-24 ユーザーに送信できるメッセージ、「Higher」(より大きい) と「Lower」(より小さい) になります。
    29-32 ユーザーが数を選択するごとに数字の範囲が狭まります。有効な数の範囲が分かるようにこの文章は変更されます。
    38-42 このフィールドは値式を使用して Bean プロパティーにバインドされます。
    42 ユーザーが誤って範囲外の数字を入力しないようバリデーターのバインディングが使用されます。バリデーターがない場合は、ユーザーが範囲外の数字を使用することがあります。
    43-45 ユーザーの選択した数字をサーバーに送る方法があるはずです。ここでは Bean 上のアクションメソッドをバインドします。

手順1.17 クラスファイルの確認

numberguess クイックスタートのソースファイルはすべて src/main/java/org/jboss/as/quickstarts/numberguess/ ディレクトリにあります。パッケージの宣言とインポートはリストには含まれていません。完全なリストはクイックスタートのソースコードにあります。
  1. Random.java 限定子コードの検証

    型に基づき挿入の対象となる 2 つの Bean 間の曖昧さを取り除くために修飾子が使用されます。修飾子の詳細については、 「修飾子を使用して不明な挿入を解決」を参照してください。
    @Random 限定子は乱数の挿入に使用されます。
    21. @Target({ TYPE, METHOD, PARAMETER, FIELD })
    22. @Retention(RUNTIME)
    23. @Documented
    24. @Qualifier
    25. public @interface Random {
    26.
    27. }
    
    
  2. MaxNumber.java 限定子コードの検証

    @MaxNumberqualifier は最大許可数の挿入に使用されます。
    21. @Target({ TYPE, METHOD, PARAMETER, FIELD })
    22. @Retention(RUNTIME)
    23. @Documented
    24. @Qualifier
    25. public @interface MaxNumber {
    26.
    27. }
    
    
  3. ジェネレーターコードの検証

    Generator クラスは producer メソッドより乱数を作成する役割があります。また、producer メソッドより最大可能数も公開します。このクラスはアプリケーションスコープ指定であるため、毎回異なる乱数になることはありません。
    28. @ApplicationScoped
    29. public class Generator implements Serializable {
    30.    private static final long serialVersionUID = -7213673465118041882L;
    31.
    32.    private java.util.Random random = new java.util.Random(System.currentTimeMillis());
    33.
    34.    private int maxNumber = 100;
    35.
    36.    java.util.Random getRandom() {
    37.       return random;
    38.    }
    39.
    40.    @Produces
    41.    @Random
    42.    int next() {
    43.       // a number between 1 and 100
    44.       return getRandom().nextInt(maxNumber - 1) + 1;
    45.    }
    46.
    47.    @Produces
    48.    @MaxNumber
    49.    int getMaxNumber() {
    50.       return maxNumber;
    51.    }
    52. }
    
    
  4. ゲームコードの検証

    セッションスコープ指定クラス Game はアプリケーションのプライマリエントリーポイントです。ゲームの設定や再設定、ユーザーが選択する数字のキャプチャーや検証、FacesMessage によるユーザーへのフィードバック提供を行う役割があります。コンストラクト後の lifecycle メソッドを使用し、@Random Instance<Integer> Bean より乱数を読み出してゲームを初期化します。
    このクラスの @Named アノテーションを見てください。このアノテーションは式言語 (EL) より Bean を JSF ビューにアクセスできるようにしたい場合のみ必要です。この場合 #{game} が EL になります。
    035. @Named
    036. @SessionScoped
    037. public class Game implements Serializable {
    038.
    039.    private static final long serialVersionUID = 991300443278089016L;
    040.
    041.    /**
    042.     * The number that the user needs to guess
    043.     */
    044.    private int number;
    045.
    046.    /**
    047.     * The users latest guess
    048.     */
    049.    private int guess;
    050.
    051.    /**
    052.     * The smallest number guessed so far (so we can track the valid guess range).
    053.     */
    054.    private int smallest;
    055.
    056.    /**
    057.     * The largest number guessed so far
    058.     */
    059.    private int biggest;
    060.
    061.    /**
    062.     * The number of guesses remaining
    063.     */
    064.    private int remainingGuesses;
    065.
    066.    /**
    067.     * The maximum number we should ask them to guess
    068.     */
    069.    @Inject
    070.    @MaxNumber
    071.    private int maxNumber;
    072.
    073.    /**
    074.     * The random number to guess
    075.     */
    076.    @Inject
    077.    @Random
    078.    Instance<Integer> randomNumber;
    079.
    080.    public Game() {
    081.    }
    082.
    083.    public int getNumber() {
    084.       return number;
    085.    }
    086.
    087.    public int getGuess() {
    088.       return guess;
    089.    }
    090.
    091.    public void setGuess(int guess) {
    092.       this.guess = guess;
    093.    }
    094.
    095.    public int getSmallest() {
    096.       return smallest;
    097.    }
    098.
    099.    public int getBiggest() {
    100.       return biggest;
    101.    }
    102.
    103.    public int getRemainingGuesses() {
    104.       return remainingGuesses;
    105.    }
    106.
    107.    /**
    108.     * Check whether the current guess is correct, and update the biggest/smallest guesses as needed.
    109.     * Give feedback to the user if they are correct.
    110.     */
    111.    public void check() {
    112.       if (guess > number) {
    113.          biggest = guess - 1;
    114.       } else if (guess < number) {
    115.          smallest = guess + 1;
    116.       } else if (guess == number) {
    117.          FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Correct!"));
    118.       }
    119.       remainingGuesses--;
    120.    }
    121.
    122.    /**
    123.     * Reset the game, by putting all values back to their defaults, and getting a new random number.
    124.     * We also call this method when the user starts playing for the first time using
    125.     * {@linkplain PostConstruct @PostConstruct} to set the initial values.
    126.     */
    127.    @PostConstruct
    128.    public void reset() {
    129.       this.smallest = 0;
    130.       this.guess = 0;
    131.       this.remainingGuesses = 10;
    132.       this.biggest = maxNumber;
    133.       this.number = randomNumber.get();
    134.    }
    135.
    136.    /**
    137.     * A JSF validation method which checks whether the guess is valid. It might not be valid because
    138.     * there are no guesses left, or because the guess is not in range.
    139.     *
    140.     */
    141.    public void validateNumberRange(FacesContext context, UIComponent toValidate, Object value) {
    142.       if (remainingGuesses <= 0) {
    143.          FacesMessage message = new FacesMessage("No guesses left!");
    144.          context.addMessage(toValidate.getClientId(context), message);
    145.          ((UIInput) toValidate).setValid(false);
    146.          return;
    147.       }
    148.       int input = (Integer) value;
    149.
    150.       if (input < smallest || input > biggest) {
    151.          ((UIInput) toValidate).setValid(false);
    152.
    153.          FacesMessage message = new FacesMessage("Invalid guess");
    154.          context.addMessage(toValidate.getClientId(context), message);
    155.       }
    156.    }
    157. }
    
    

第2章 Maven ガイド

2.1. Maven について

2.1.1. Maven リポジトリについて

Apache Maven は、ソフトウェアプロジェクトの作成、管理、構築を行う Java アプリケーションの開発で使用される分散型ビルド自動化ツールです。Maven は Project Object Model (POM) と呼ばれる標準の設定ファイルを利用して、プロジェクトの定義や構築プロセスの管理を行います。POM はモジュールやコンポーネントの依存関係、ビルドの順番、結果となるプロジェクトパッケージングのターゲットを記述し、XML ファイルを使用して出力します。こうすることで、プロジェクトが正しく統一された状態で構築されるようにします。
Maven は、リポジトリを使いアーカイブを行います。Maven リポジトリには Java ライブラリ、プラグイン、その他のアーティファクトが格納されています。デフォルトのパブリックリポジトリは Maven 2 Central Repository ですが、複数の開発チームの間で共通のアーティファクトを共有する目的で、社内のプライベートおよび内部リポジトリとすることが可能です。また、サードパーティのリポジトリもあります。JBoss Enterprise Application Platform 6 には、Java EE 開発者が通常 JBoss Enterprise Application Platform 6 でアプリケーションを構築する際に利用する要件の多くが含まれています。このようなリポジトリを使うようプロジェクトを設定するには、 「 JBoss Enterprise Application Platform の Maven リポジトリの設定」 を参照してください。
リポジトリはリモートにもローカルにもすることができます。リモートのリポジトリには、HTTP サーバーのリポジトリにはhttp://、ファイルサーバーのリポジトリにはfile:// という風に共通のプロトコルを使いアクセスします。ローカルのリポジトリは、リモートリポジトリからのアーティファクトをダウンロードしキャッシュ化したものです。
Maven に関する詳細情報は、Welcome to Apache Maven を参照してください。
また、Maven リポジトリの情報は Apache Maven Project - Introduction to Repositories を確認してください。
さらに、Maven POM ファイルの詳細情報は Apache Maven Project POM Reference および 「Maven POM ファイルについて」 から確認いただけます。

2.1.2. Maven POM ファイルについて

プロジェクトオブジェクトモデル (POM) ファイルはプロジェクトをビルドするために Maven で使用する設定ファイルです。POM ファイルは XML のファイルであり、プロジェクトの情報やビルド方法を含みます。これには、ソース、テスト、およびターゲットのディレクトリーの場所、プロジェクトの依存関係、プラグインリポジトリー、実行できるゴールが含まれます。また、バージョン、説明、開発者、メーリングリスト、ライセンスなどのプロジェクトに関する追加情報も含まれます。pom.xml ファイルでは一部の設定オプションを設定する必要があり、他のすべてのオプションはデフォルト値に設定されます。詳細については、 「Maven POM ファイルの最低要件」を参照してください。
pom.xml ファイルのスキーマは http://maven.apache.org/maven-v4_0_0.xsd にあります。
POM ファイルの詳細は Apache Maven Project POM Reference を参照してください。

2.1.3. Maven POM ファイルの最低要件

最低要件

pom.xml ファイルの最低要件は次の通りです。

  • プロジェクトルート
  • modelVersion
  • groupId - プロジェクトのグループの ID
  • artifactId - アーティファクト (プロジェクト) の ID
  • version - 指定グループ下のアーティファクトのバージョン
サンプル pom.xml ファイル

基本的な pom.xml ファイルは次のようになります。

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.jboss.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1</version>
</project> 

2.1.4. Maven 設定ファイルについて

Maven の settings.xml ファイルには Maven に関するユーザー固有の設定情報が含まれています。開発者の ID、プロキシ情報、ローカルリポジトリの場所など、 pom.xml ファイルで配布されてはならないユーザー固有の設定が含まれています。
settings.xml が存在する場所は 2 つあります。
Maven インストール
設定ファイルは M2_HOME/conf/ ディレクトリにあります。これらの設定は global 設定と呼ばれます。デフォルトの Maven 設定ファイルはコピー可能なテンプレートで、これを基にユーザー設定ファイルを設定することが可能です。
ユーザーのインストール
設定ファイルは USER_HOME/.m2/ ディレクトリにあります。 Maven とユーザーの settings.xml ファイルが存在する場合、内容はマージされます。重複する内容がある場合、ユーザーの settings.xml ファイルが優先されます。
Maven settings.xml ファイルの例は以下のとおりです。
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" 
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">  
  <profiles>
    <!-- Configure the JBoss EAP Maven repository -->
    <profile>
      <id>jboss-eap-maven-repository</id>
      <repositories>
        <repository>
          <id>jboss-eap</id>
          <url>file:///path/to/repo/jboss-eap-6.0-maven-repository</url>
          <releases>
            <enabled>true</enabled>
          </releases>
          <snapshots>
            <enabled>false</enabled>
          </snapshots>
        </repository>
      </repositories>
      <pluginRepositories>
        <pluginRepository>
          <id>jboss-eap-maven-plugin-repository</id>
          <url>file:///path/to/repo/jboss-eap-6.0-maven-repository</url>
          <releases>
            <enabled>true</enabled>
          </releases>
          <snapshots>
            <enabled>false</enabled>
          </snapshots>
        </pluginRepository>
      </pluginRepositories>
    </profile>
  </profiles>
  <activeProfiles>
    <!-- Optionally, make the repository active by default -->
    <activeProfile>jboss-eap-maven-repository</activeProfile>
  </activeProfiles>
</settings>

settings.xml ファイルのスキーマは http://maven.apache.org/xsd/settings-1.0.0.xsd にあります。

2.2. Maven と JBoss Maven レポジトリのインストール

2.2.1. Maven のダウンロードとインストール

  1. Apache Maven Project - Download Maven へアクセスし、ご使用のオペレーティングシステムに対する最新のディストリビューションをダウンロードします。
  2. ご使用のオペレーシングシステムに対して Apache Maven をダウンロードしインストールする方法については Maven のドキュメントを参照してください。

2.2.2. JBoss Enterprise Application Platform 6 の Maven リポジトリのインストール

リポジトリをインストールする方法には、ローカルファイルシステム上のインストール、Apache Web サーバー上のインストール、Maven リポジトリマネージャーを使用したインストールの 3 つの方法があります。

2.2.3. JBoss Enterprise Application Platform 6 の Maven リポジトリのローカルインストール

概要

リポジトリをインストールする方法には、ローカルファイルシステム上のインストール、Apache Web サーバー上のインストール、Maven リポジトリマネージャーを使用したインストールの 3 つの方法があります。この例では、ローカルのファイルシステムへ JBoss Enterprise Application Platform 6 の Maven リポジトリをダウンロードする手順を取り上げます。このオプションは設定が簡単で、ローカルマシンですぐ使用することが可能になります。開発環境で Maven の知識を深めることができますが、チームによる実稼働環境での使用は推奨されません。

手順2.1 JBoss Enterprise Application Platform 6 Maven リポジトリーをダウンロードしてローカルファイルシステムにインストールする

  1. JBoss Enterprise Application Platform 6 の Maven リポジトリ ZIP アーカイブのダウンロード

    Web ブラウザーを開き、URL https://access.redhat.com/jbossnetwork/restricted/listSoftware.html?product=appplatform にアクセスします。
  2. リストに「Application Platform 6 Maven リポジトリ」があることを確認します。
  3. [ダウンロード] ボタンをクリックし、リポジトリが含まれる .zip ファイルをダウンロードします。
  4. ローカルファイルシステム上の同じディレクトリにあるファイルを希望のディレクトリへ解凍します。
結果

これにより、jboss-eap-6.1.0.maven-repository という名前の Maven リポジトリーディレクトリーが作成されます。

重要

古いローカルリポジトリーを引き続き使用する場合は、そのリポジトリーを Maven settings.xml 設定ファイルで個別に設定する必要があります。各ローカルリポジトリーは、独自の <repository> タグ内で設定する必要があります。

重要

新しい Maven リポジトリをダウンロードする時、新しい Maven リポジトリを使用する前に、.m2/ ディレクトリにあるキャッシュされた repository/ サブディレクトリを削除してください。

2.2.4. Apache httpd を使用するため JBoss Enterprise Application Platform 6 の Maven リポジトリをインストールする

リポジトリをインストールする方法には、ローカルファイルシステム上のインストール、Apache Web サーバー上のインストール、Maven リポジトリマネージャーを使用したインストールの 3 つの方法があります。この例では、Apache httpd を使用するため JBoss Enterprise Application Platform 6 の Maven リポジトリをダウンロードする手順を取り上げます。Web サーバーにアクセスできる開発者は Maven リポジトリにもアクセスできるため、このオプションは マルチユーザーの開発環境や、チームにまたがる開発環境向けのオプションになります。
要件

Apache httpd を設定する必要があります。手順は Apache HTTP Server Project を参照してください。

手順2.2 JBoss Enterprise Application Platform 6 の Maven リポジトリ ZIP アーカイブのダウンロード

  1. Web ブラウザーを開き、URL https://access.redhat.com/jbossnetwork/restricted/listSoftware.html?product=appplatform にアクセスします。
  2. リストに「Application Platform 6 Maven リポジトリ」があることを確認します。
  3. [ダウンロード] ボタンをクリックし、リポジトリが含まれる .zip ファイルをダウンロードします。
  4. Apache サーバー上で Web にアクセス可能なディレクトリにファイルを展開します。
  5. Apache を設定し、作成されたディレクトリの読み取りアクセスとディレクトリの閲覧を許可します。
結果

マルチユーザー環境が Apache httpd 上で Maven リポジトリにアクセスできるようになります。

注記

以前のバージョンのリポジトリーからアップグレードする場合は、競合を発生させずに JBoss Enterprise Application Platform 6.1.0 Maven リポジトリーアーティファクトを既存の JBoss 製品 Maven リポジトリー (JBoss Enterprise Application Platform 6.0.1 など) に単純に抽出できることに注意してください。リポジトリーアーカイブの抽出後は、このリポジトリーの既存の Maven 設定でアーティファクトを使用できます。

2.2.5. Nexus Maven リポジトリマネージャーを使用して JBoss Enterprise Application Platform 6 の Maven リポジトリをインストールする

リポジトリをインストールする方法には、ローカルファイルシステム上のインストール、Apache Web サーバー上のインストール、Maven リポジトリマネージャーを使用したインストールの 3 つの方法があります。Nexus Maven リポジトリマネージャーを使用すると、JBoss リポジトリを既存のリポジトリと共にホストできるため、ライセンスを所有し、既にリポジトリマネージャーを使用している場合はこの方法が最適です。Maven リポジトリマネージャーの詳細は 「Maven リポジトリマネージャーについて」 を参照してください。
この例では Sonatype Nexus Maven リポジトリマネージャーを使用して JBoss Enterprise Application Platform 6 の Maven リポジトリをインストールする手順を取り上げます。 完全な手順は Sonatype Nexus: Manage Artifacts を参照してください。

手順2.3 JBoss Enterprise Application Platform 6 の Maven リポジトリ ZIP アーカイブのダウンロード

  1. Web ブラウザーを開き、URL https://access.redhat.com/jbossnetwork/restricted/listSoftware.html?product=appplatform にアクセスします。
  2. リストに「Application Platform 6 Maven リポジトリ」があることを確認します。
  3. [ダウンロード] ボタンをクリックし、リポジトリが含まれる .zip ファイルをダウンロードします。
  4. 希望のディレクトリにファイルを展開します。

手順2.4 Nexus Maven リポジトリマネージャーを使用して JBoss Enterprise Application Platform 6 の Maven リポジトリを追加する

  1. 管理者として Nexus にログインします。
  2. リポジトリマネージャーの左側の [Views][Repositories] メニューより [Repositories] セクションを選択します。
  3. [Add...] ドロップダウンメニューをクリックし、[Hosted Repository] を選択します。
  4. 新しいリポジトリに名前と ID をつけます。
  5. フィールド [Override Local Storage] の場所に、展開されたリポジトリへのディスク上のパスを入力します。
  6. リポジトリグループでアーティファクトを使用できるようにする場合は次の手順に従い設定を継続します。必要がない場合は継続しないでください。
  7. リポジトリグループを選択します。
  8. [Configure] タブをクリックします。
  9. [Available Repositories] リストにある新しい JBoss Maven リポジトリを左側の [Ordered Group Repositories] へドラッグします。

    注記

    このリストの順番により Maven アーティファクトの検索優先度が決定されます。
結果

Nexus Maven リポジトリマネージャーを使用してリポジトリが設定されます。

2.2.6. Maven リポジトリマネージャーについて

リポジトリマネージャーは、 Maven リポジトリーを容易に管理できるようにするツールです。リポジトリーマネージャーには、次のような利点があります。
  • お客様の組織と Maven リポジトリーとの間のプロキシを設定する機能を提供します。これには、デプロイメントの高速化や効率化、Maven によるダウンロード対象を制御するレベルの向上など、さまざまな利点があります。
  • 独自に生成したアーティファクトのデプロイ先を提供し、組織全体にわたる異なる開発チーム間におけるコラボレーションを可能にします。
Maven リポジトリーマネージャーの詳細については、「Apache Maven Project - The List of Repository Managers (Apache Maven プロジェクト - リポジトリーマネージャーのリスト)」を参照してください。

一般的に使用される Maven リポジトリマネージャー

Sonatype Nexus
Nexus に関する詳しい情報は Sonatype Nexus: Manage Artifacts を参照してください。
Artifactory
Artifactory に関する詳しい情報は Artifactory Open Source を参照してください。
Apache Archiva
Apache Archiva に関する詳しい情報は Apache Archiva: The Build Artifact Repository Manager を参照してください。

2.3. Maven レポジトリの設定

2.3.1. JBoss Enterprise Application Platform の Maven リポジトリの設定

概要

プロジェクトで Maven により JBoss Enterprise Application Platform Maven リポジトリーを使用するには 2 つの方法があります。

  • リポジトリーをMaven グローバルまたはユーザー設定で設定します。
  • リポジトリーをプロジェクトの POM ファイルで設定します。

手順2.5 JBoss Enterprise Application Platform の Maven リポジトリを使用するよう Maven を設定する

  1. Maven の設定を使用して Maven リポジトリを設定する

    これは推奨される方法です。リポジトリマネージャーや共有サーバーを用いたリポジトリを使用して Maven を設定すると、プロジェクトの制御や管理が向上します。また、代替のミラーを使用してプロジェクトファイルを変更せずにリポジトリマネージャーへの特定リポジトリのルックアップ要求をすべてリダイレクトすることが可能になります。ミラーに関する詳細については、http://maven.apache.org/guides/mini/guide-mirror-settings.html を参照してください。
    プロジェクトの POM ファイルにリポジトリ設定が含まれていない場合、この設定方法はすべての Maven プロジェクトに対して適用されます。
  2. プロジェクトの POM を使用して Maven リポジトリを設定する

    通常、この方法は推奨されません。プロジェクトの POM ファイルにリポジトリーを設定する場合は慎重に計画します。ビルドに時間がかかり、想定外のリポジトリーからアーティファクトが抽出されることがあることに注意してください。

    注記

    通常レポジトリーマネージャーが使用されるエンタープライズ環境では、Maven は、このマネージャーを使用してすべてのプロジェクトに対してすべてのアーティファクトを問い合わせる必要があります。Maven は、宣言されたすべてのリポジトリーを使用して不明なアーティファクトを見つけます。探しているものが見つからない場合は、中央リポジトリー (組み込みの親 POM で定義されます) での検索を試行します。この中央の場所をオーバーライドするには、central で定義を追加してデフォルトの中央リポジトリーがリポジトリーマネージャーになるようにします。これは、確立されたプロジェクトには適切ですが、クリーンな、または「新しい」プロジェクトの場合は、周期的な依存関係が作成されるため、問題が発生します。
    このような設定では、推移的に含まれた POM も問題になります。Maven は、これらの外部リポジトリーで不明なアーティファクトを問い合わせる必要があります。これにより、ビルドに時間がかかるだけでなく、アーティファクトの抽出元を制御できなくなり、多くの場合、ビルドが破壊されます。
    この設定方法は、設定されたプロジェクトのグローバルおよびユーザーの Maven 設定を上書きします。

2.3.2. Maven 設定を使用した JBoss Enterprise Application Platform の Maven リポジトリーの設定

プロジェクトにおいて Maven で JBoss Enterprise Application Platform Maven リポジトリーを使用するには 2 つの方法があります。
  • Maven 設定を変更できます。
  • プロジェクトの POM ファイルを設定できます。
このタスクでは、Maven で Maven グローバル設定またはユーザー設定を使用してすべてのプロジェクトで JBoss Enterprise Application Platform Maven リポジトリーを使用する方法を示します。これは推奨される方法です。

注記

リポジトリーの URL は、リポジトリーが存在する場所 (ファイルシステムまたはWeb サーバー) によって異なります。 リポジトリーのインストール方法については、JBoss Enterprise Application Platform 6 用 『開発ガイド (Development Guide)』 (https://access.redhat.com/site/documentation/JBoss_Enterprise_Application_Platform/) の 『Maven ガイド (Maven Guide)』 を参照してください。各インストールオプションの例は以下のとおりです。
ファイルシステム
file:///path/to/repo/jboss-eap-6.0.0-maven-repository
Apache Web サーバー
http://intranet.acme.com/jboss-eap-6.0.0-maven-repository/
Nexus リポジトリマネージャー
https://intranet.acme.com/nexus/content/repositories/jboss-eap-6.0.0-maven-repository
インストール設定またはユーザーインストール設定を使用して Maven で JBoss Enterprise Application Platform リポジトリーを使用するよう設定できます。設定の場所や動作の詳細については、JBoss Enterprise Application Platform 6 用 『開発ガイド (Development Guide)』 (https://access.redhat.com/site/documentation/JBoss_Enterprise_Application_Platform/) の章「『Maven ガイド (Maven Guide)』」を参照してください。
ローカルのユーザーシステムで JBoss Enterprise Application Platform のリポジトリを使用する場合は、次の手順に従ってください。

手順2.6 設定

  1. 選択した設定タイプの settings.xml を開きます。
    • グローバル設定

      global 設定を設定する場合は M2_HOME/conf/settings.xml ファイルを開きます。
    • ユーザー設定

      ユーザー固有の設定を設定する場合、USER_HOME/.m2/settings.xml ファイルが存在しない時は M2_HOME/conf/ ディレクトリの settings.xml ファイルを USER_HOME/.m2/ ディレクトリにコピーします。
  2. 以下の XML を settings.xml ファイルの <profiles> 要素にコピーします。<url> を実際のリポジトリーの場所に変更します。
    
    <profile>
      <id>jboss-eap-repository</id>
      <repositories>
        <repository>
          <id>jboss-eap-repository</id>
          <name>JBoss EAP Maven Repository</name>
          <url>file:///path/to/repo/jboss-eap-6.0.0-maven-repository</url>
          <layout>default</layout>
          <releases>
            <enabled>true</enabled>
            <updatePolicy>never</updatePolicy>
          </releases>
          <snapshots>
            <enabled>false</enabled>
            <updatePolicy>never</updatePolicy>
          </snapshots>
        </repository>
      </repositories>
      <pluginRepositories>
        <pluginRepository>
          <id>jboss-eap-repository-group</id>
          <name>JBoss EAP Maven Repository</name>
          <url>
          file:///path/to/repo/jboss-eap-6.0.0-maven-repository
          </url>
          <layout>default</layout>
          <releases>
            <enabled>true</enabled>
            <updatePolicy>never</updatePolicy>
          </releases>
          <snapshots>
            <enabled>false</enabled>
            <updatePolicy>never</updatePolicy>
          </snapshots>
        </pluginRepository>
      </pluginRepositories>
    </profile>
    
    
    次の XML を settings.xml ファイルの <activeProfiles> 要素へコピーします。
    
    <activeProfile>jboss-eap-repository</activeProfile>
    
    
    
  3. JBoss Developer Studio の稼働中に settings.xml ファイルを変更する時は、ユーザー設定をリフレッシュする必要があります。メニューより [Window][Preferences] と選択します。 [Preferences] ウインドウで [Maven] を開き、[User Settings] を選択します。[Update Settings] ボタンをクリックし、 JBoss Developer Studio で Maven のユーザー設定をリフレッシュします。
    Maven ユーザー設定の更新

    図2.1 Maven ユーザー設定の更新

重要

Maven リポジトリーに古いアーティファクトが含まれる場合は、プロジェクトをビルドまたはデプロイしたときに以下のいずれかの Maven エラーメッセージが表示されることがあります。
  • Missing artifact ARTIFACT_NAME
  • [ERROR] Failed to execute goal on project PROJECT_NAME; Could not resolve dependencies for PROJECT_NAME
この問題を解決するには、最新の Maven アーティファクトをダウンロードするためにローカルリポジトリーのキャッシュバージョンを削除します。キャッシュバージョンは ~/.m2/repository/ サブディレクトリー (Linux の場合) または %SystemDrive%\Users\USERNAME\.m2\repository\ サブディレクトリー (Windows の場合) に存在します。
結果

JBoss Enterprise Application Platform のリポジトリが設定されます。

2.3.3. プロジェクト POM を用いた JBoss Enterprise Application Platform の Maven リポジトリの設定

プロジェクトにおいて Maven で JBoss Enterprise Application Platform Maven リポジトリーを使用するには 2 つの方法があります。
  • Maven 設定を変更できます。
  • プロジェクトの POM ファイルを設定できます。
このタスクでは、リポジトリー情報をプロジェクトの pom.xml に追加して、JBoss Enterprise Application Platform の Maven リポジトリーを使用するよう特定のプロジェクトを設定する方法について説明します。この設定方法は、グローバル設定とユーザー設定よりも優先されます。
通常、この設定方法は推奨されません。プロジェクトの POM ファイルにリポジトリーを設定する場合は慎重に計画します。ビルドに時間がかかり、想定外のリポジトリーからアーティファクトが抽出されることがあることに注意してください。

注記

通常レポジトリーマネージャーが使用されるエンタープライズ環境では、Maven は、このマネージャーを使用してすべてのプロジェクトのすべてのアーティファクトを問い合わせる必要があります。Maven は、宣言されたすべてのリポジトリーを使用して不明なアーティファクトを見つけます。探しているものが見つからない場合は、中央リポジトリー (組み込みの親 POM で定義されます) での検索を試行します。この中央の場所を上書きオーバーライドするには、central で定義を追加してデフォルトの中央リポジトリーがリポジトリーマネージャーになるようにします。これは、確立されたプロジェクトには適切ですが、クリーンな、または「新しい」プロジェクトの場合は、周期的な依存関係が作成されるため、問題が発生します。
このような設定では、推移的に含まれた POM も問題になります。Maven は、これらの外部リポジトリーで不明なアーティファクトを問い合わせる必要があります。これにより、ビルドに時間がかかるだけでなく、アーティファクトの抽出元を制御できなくなり、多くの場合、ビルドが破壊されます。

注記

リポジトリーの URL はリポジトリの場所 (ファイルシステムまたは Web サーバー) によって異なります。リポジトリーのインストール方法については、 「JBoss Enterprise Application Platform 6 の Maven リポジトリのインストール」を参照してください。各インストールオプションの例は次のとおりです。
ファイルシステム
file:///path/to/repo/jboss-eap-6.0.0-maven-repository
Apache Web サーバー
http://intranet.acme.com/jboss-eap-6.0.0-maven-repository/
Nexus リポジトリマネージャー
https://intranet.acme.com/nexus/content/repositories/jboss-eap-6.0.0-maven-repository
  1. テキストエディターでプロジェクトの pom.xml ファイルを開きます。
  2. 次のリポジトリ設定を追加します。既にファイルに <repositories> 設定が存在する場合は <repository> 要素を追加します。必ず <url> をリポジトリが実存する場所に変更するようにしてください。
    <repositories>
       <repository>
          <id>jboss-eap-repository-group</id>
          <name>JBoss EAP Maven Repository</name>
          <url>file:///path/to/repo/jboss-eap-6.0.0-maven-repository/</url>
          <layout>default</layout>
          <releases>
             <enabled>true</enabled>
             <updatePolicy>never</updatePolicy>
          </releases>
          <snapshots>
             <enabled>true</enabled>
             <updatePolicy>never</updatePolicy>
          </snapshots>
       </repository>
    </repositories>
    
    
  3. 次のプラグインリポジトリ設定を追加します。既にファイルに <pluginRepositories> 設定が存在する場合は <pluginRepository> 要素を追加します。
    <pluginRepositories>
       <pluginRepository>
          <id>jboss-eap-repository-group</id>
          <name>JBoss EAP Maven Repository</name>
          <url>file:///path/to/repo/jboss-eap-6.0.0-maven-repository/</url>
          <releases>
             <enabled>true</enabled>
          </releases>
          <snapshots>
             <enabled>true</enabled>
          </snapshots>
       </pluginRepository>
    </pluginRepositories>
    
    

第3章 クラスローディングとモジュール

3.1. はじめに

3.1.1. クラスロードとモジュールの概要

JBoss Enterprise Application Platform 6 は、デプロイされたアプリケーションのクラスパスを制御するために新しいモジュール形式のクラスロードシステムを使用します。このシステムでは、階層クラスローダーの従来のシステムよりも、柔軟性と制御が強化されています。開発者は、アプリケーションで利用可能なクラスに対して粒度の細かい制御を行い、アプリケーションサーバーで提供されるクラスを無視して独自のクラスを使用してデプロイメントを設定できます。
モジュール形式のクラスローダーは、すべての Java クラスをモジュールと呼ばれる論理グループに分けます。各モジュールは、独自のクラスパスに追加されたモジュールからクラスを取得するために、他のモジュールの依存関係を定義できます。デプロイされた各 JAR および WAR ファイルはモジュールとして扱われるため、開発者はモジュール設定アプリケーションに追加してアプリケーションのクラスパスの内容を制御できます。
以下に、開発者が JBoss Enterprise Application Platform 6 でアプリケーションを正しくビルドおよびデプロイするために知る必要があることを示します。

3.1.2. クラスローディング

クラスローディングとは、Java クラスやリソースを Java ランタイム環境にロードするメカニズムのことです。

3.1.3. モジュール

モジュールは、クラスのロードと依存関係の管理に使用される、クラスの論理的なグループです。JBoss Enterprise Application Platform 6 では、静的モジュールと動的モジュールと呼ばれる 2 種類のモジュールが存在します。ただし、この 2 種類のモジュールの違いは、パッケージ化の方法のみです。すべてのモジュールは同じ機能を提供します。
静的モジュール
静的モジュールは、アプリケーションサーバーの EAP_HOME/modules/ ディレクトリに事前定義されます。各サブディレクトリは 1 つのモジュールを表し、1 つまたは複数の JAR ファイルと設定ファイル (module.xml) が含まれます。モジュールの名前は、module.xml ファイルで定義されます。アプリケーションサーバーで提供されるすべての API (Java EE API や JBoss Logging などの他の API を含む) は、静的モジュールとして提供されます。
カスタム静的モジュールの作成は、同じサードパーティーライブラリを使用する同じサーバー上に多くのアプリケーションがデプロイされる場合に役立ちます。これらのライブラリを各アプリケーションとバンドルする代わりに、JBoss 管理者はこれらのライブラリが含まれるモジュールを作成およびインストールできます。アプリケーションは、カスタム静的モジュールで明示的な依存関係を宣言できます。
動的モジュール
動的モジュールは、各 JAR または WAR デプロイメント (または、EAR 内のサブデプロイメント) に対してアプリケーションサーバーによって作成およびロードされます。動的モジュールの名前は、デプロイされたアーカイブの名前から派生されます。デプロイメントはモジュールとしてロードされるため、依存関係を設定でき、他のデプロイメントが依存関係として使用できます。
モジュールは必要なときのみロードされます。通常、明示的または暗黙的な依存関係があるアプリケーションがデプロイされるときのみ、モジュールがロードされます。

3.1.4. モジュールの依存関係

モジュール依存関係とは、あるモジュールが機能するには別のモジュールのクラスを必要とする宣言のことです。モジュールはいくつでも他のモジュールの依存関係を宣言することができます。アプリケーションサーバーがモジュールをロードする時、モジュールクラスローダーがモジュールの依存関係を解析し、各依存関係のクラスをクラスパスに追加します。指定の依存関係が見つからない場合、モジュールはロードできません。
デプロイされたアプリケーション (JAR および WAR) は動的モジュールとしてロードされ、依存関係を用いて JBoss Enterprise Application Platform 6 によって提供される API へアクセスします。
依存関係には明示的と暗黙的の 2 つのタイプがあります。
明示的な依存関係は開発者によって設定に宣言されます。静的モジュールは依存関係を modules.xml ファイルに宣言することができます。動的モジュールはデプロイメントの MANIFEST.MF または jboss-deployment-structure.xml 記述子に依存関係を宣言することができます。
暗示的な依存関係は、任意の依存関係として指定することができます。任意の依存関係をロードできなくても、モジュールのロードに失敗する原因にはなりません。しかし、依存関係が後で使用できるようになっても、モジュールのクラスパスには追加されません。モジュールがロードされる時に依存関係が使用できなければなりません。
暗黙的な依存関係は、特定の条件やメタデータがデプロイメントで見つかった場合に自動的に追加されます。JBoss Enterprise Application Platform に含まれる Java EE 6 API は、デプロイメントで暗黙的な依存関係が検出された時に追加されるモジュールの一例になります。
デプロイメントを設定して特定の暗黙的な依存関係を除外することも可能です。この設定は jboss-deployment-structure.xml デプロイメント記述子ファイルで行います。これは、アプリケーションサーバーが暗黙的な依存関係として追加しようとする特定バージョンのライブラリを、アプリケーションがバンドルする場合に一般的に行われます。
モジュールのクラスパスには独自のクラスとその直接の依存関係のみが含まれます。モジュールは 1 つの依存関係の依存関係クラスにはアクセスできませんが、暗示的な依存関係のエクスポートを指定できます。エクスポートされた依存関係は、エクスポートするモジュールに依存するモジュールへ提供されます。

例3.1 モジュールの依存関係

モジュール A はモジュール B に依存し、モジュール B はモジュール C に依存します。モジュール A はモジュール B のクラスにアクセスでき、モジュール B はモジュール C のクラスにアクセスできます。以下の場合を除き、モジュール A はモジュール C のクラスにはアクセスできません。
  • モジュール A がモジュール C への明示的な依存関係を宣言する場合。
  • または、モジュール B がモジュール B の依存関係をモジュール C でエクスポートする場合。

3.1.5. デプロイメントでのクラスローディング

JBoss Enterprise Application Platform では、クラスローディングのためにデプロイメントはすべてモジュールとして処理されます。このようなデプロイメントは動的モジュールと呼ばれます。クラスローディングの動作はデプロイメントのタイプによって異なります。
WAR デプロイメント
WAR デプロイメントは 1 つのモジュールとして考慮されます。WEB-INF/lib ディレクトリのクラスは WEB-INF/classes ディレクトリにあるクラスと同じように処理されます。war にパッケージされているクラスはすべて、同じクラスローダーでロードされます。
EAR デプロイメント
EAR デプロイメントは複数のモジュールで構成されます。これらのモジュールは以下のルールに従って定義されます。
  1. EAR の lib/ ディレクトリは親モジュールと呼ばれる1つのモジュールです。
  2. また、EAR 内の各 WAR デプロイメントは1つのモジュールです。
  3. 同様に、EAR 内の EJB JAR デプロイメントも 1 つのモジュールとなっています。
サブデプロイメントモジュール (EAR 内の WAR、JAR デプロイメント) は、自動的に親モジュールに依存しますが、サブデプロイメント同士が自動的に依存するわけではありません。これは、サブデプロイメントの分離 (subdeployment isolation) と呼ばれ、デプロイメントごとまたはアプリケーションサーバー全体で無効にすることができます。
サブデプロイメントモジュール間の明示的な依存関係については、他のモジュールと同じ方法で追加することが可能です。

3.1.6. クラスローディングの優先順位

JBoss Enterprise Application Platform 6 のモジュラークラスローダーは優先順位の仕組みを利用してクラスローディングの競合が発生しないようにします。
デプロイメント時に、パッケージとクラスの完全リストがデプロイメント毎そして依存性毎に作成されます。この一覧は、クラスローディングの優先順位のルールに従い順番に並べられています。ランタイムにクラスをロードすると、クラスローダーはこの一覧を検索し最初に一致したものをロードします。こうすることで、デプロイメントクラスパスにある同じクラスやパッケージの複数のコピーが競合しないようにします。
クラスローダーは上から順に(降順) クラスをロードします。
  1. 暗黙的な依存性
    Java EE API などの、JBoss Enterprise Application Platform 6 が自動的に追加する依存性です。こちらの依存性は、一般的な機能や JBoss Enterprise Application Platform 6 が対応する API が含まれているため、優先順位が最も高くなっています。
    各暗黙的依存性に関する完全な詳細情報は 「暗黙的なモジュール依存関係」 を参照してください。
  2. 明示的な依存性
    アプリケーション設定にて手動で追加される依存性です。これらの依存性は、アプリケーションの MANIFEST.MF ファイルや、新しくオプションで追加された JBoss の配備記述子 jboss-deployment-structure.xml ファイルを使い追加可能です。
    明示的な依存性の追加方法については、「デプロイメントへの明示的なモジュール依存関係の追加」 を参照してください。
  3. ローカルリソース
    デプロイメント内にパッケージ化されるクラスファイル (例:WAR ファイルの WEB-INF/classes あるいは WEB-INF/lib から)
  4. デプロイメント間の依存性
    これらは、EAR デプロイメントにある他のデプロイメントの依存関係です。これには、EAR のlib ディレクトリーにあるクラス、あるいは他の EJB jar に定義されているクラスが含まれます。

3.1.7. 動的モジュールの名前付け

すべてのモジュールは JBoss Enterprise Application Platform 6 によってモジュールとしてロードされ、以下の慣例に従って名前が付けられます。
  1. WAR および JAR ファイルのデプロイメントは次の形式で名前が付けられます。
     deployment.DEPLOYMENT_NAME 
    例えば、inventory.war のモジュール名は deployment.inventory.war となり、store.jar のモジュール名は deployment.store.jar となります。
  2. エンタープライズアーカイブ内のサブデプロイメントは次の形式で名前が付けられます。
     deployment.EAR_NAME.SUBDEPLOYMENT_NAME 
    たとえば、エンタープライズアーカイブ accounts.ear 内にある reports.war のサブデプロイメントのモジュール名は deployment.accounts.ear.reports.war になります。

3.1.8. jboss-deployment-structure.xml

jboss-deployment-structure.xml は JBoss Enterprise Application Platform 6 の新しいオプションデプロイメント記述子です。このデプロイメント記述子を使用すると、デプロイメントのクラスローディングを制御できます。
このデプロイメント記述子の XML スキーマは、EAP_HOME/docs/schema/jboss-deployment-structure-1_2.xsd にあります。

3.2. デプロイメントへの明示的なモジュール依存関係の追加

このタスクでは、アプリケーションへ明示的な依存関係を追加する方法を説明します。明示的なモジュール依存関係をアプリケーションに追加すると、これらのモジュールのクラスをアプリケーションのクラスパスに追加することができます。
一部の依存関係は JBoss Enterprise Application Platform 6 によって自動的にデプロイメントへ追加されます。詳細は 「暗黙的なモジュール依存関係」 を参照してください。

要件

  1. モジュール依存関係を追加するソフトウェアプロジェクトが存在する必要があります。
  2. 依存関係として追加するモジュールの名前を覚えておく必要があります。JBoss Enterprise Application Platform に含まれる静的モジュールのリストは 「含まれるモジュール」 を参照してください。モジュールが他のデプロイメントである場合は 「動的モジュールの名前付け」 を参照してモジュール名を判断してください。
依存関係を設定する方法は 2 つあります。
  1. デプロイメントの MANIFEST.MF ファイルにエントリーを追加します。
  2. jboss-deployment-structure.xml デプロイメント記述子にエントリーを追加します。

手順3.1 MANIFEST.MF へ依存関係の設定を追加する

Maven プロジェクトを設定して MANIFEST.MF ファイルに必要な依存関係エントリを作成することができます。「Maven を使用した MANIFEST.MF エントリーの生成」 を参照してください。
  1. MANIFEST.MF ファイルの追加

    プロジェクトに MANIFEST.MF ファイルがない場合、MANIFEST.MF というファイルを作成します。Web アプリケーション (WAR) では、このファイルを META-INF ディレクトリーに追加します。EJB アーカイブ (JAR) では、META-INF ディレクトリーに追加します。
  2. 依存関係エントリの追加

    依存関係モジュール名をコンマで区切り、依存関係エントリーを MANIFEST.MF ファイルへ追加します。
    Dependencies: org.javassist, org.apache.velocity
  3. 任意: 依存関係を任意にする

    依存関係エントリーのモジュール名に optional を付けると、依存関係を任意にすることができます。
    Dependencies: org.javassist optional, org.apache.velocity
  4. 任意: 依存関係のエクスポート

    依存関係エントリーのモジュール名に export を付けると、依存関係をエクスポートすることができます。
    Dependencies: org.javassist, org.apache.velocity export

手順3.2 jboss-deployment-structure.xml への依存関係設定の追加

  1. jboss-deployment-structure.xml の追加

    アプリケーションに jboss-deployment-structure.xml ファイルが存在しない場合は、jboss-deployment-structure.xml という新しいファイルを作成し、プロジェクトに追加します。このファイルは <jboss-deployment-structure> がルート要素の XML ファイルです。
    <jboss-deployment-structure> 
    
    </jboss-deployment-structure>
    
    Web アプリケーション (WAR) では、このファイルを WEB-INF に追加します。EJB アーカイブ (JAR) では、META-INF ディレクトリに追加します。
  2. 依存関係セクションの追加

    <deployment> 要素をドキュメントルート内に作成し、その中に <dependencies> 要素を作成します。
  3. モジュール要素の追加

    依存関係ノード内に各モジュール依存関係に対するモジュール要素を追加します。name 属性をモジュールの名前に設定します。
    <module name="org.javassist" />
    
  4. 任意: 依存関係を任意にする

    値が TRUE のモジュールエントリーに optional 属性を追加すると依存関係を任意にすることができます。この属性のデフォルト値は FALSE です。
    <module name="org.javassist" optional="TRUE" />
    
  5. 任意: 依存関係のエクスポート

    値が TRUE のモジュールエントリーに export 属性を追加すると依存関係をエクスポートできます。この属性のデフォルト値は FALSE です。
    <module name="org.javassist" export="TRUE" />
    

例3.2 2 つの依存関係を持つ jboss-deployment-structure.xml

<jboss-deployment-structure>

   <deployment>

      <dependencies>
         <module name="org.javassist" />
         <module name="org.apache.velocity" export="TRUE" />
      </dependencies>

   </deployment>

</jboss-deployment-structure>
JBoss Enterprise Application Platform 6 はデプロイされた時に、指定されたモジュールからアプリケーションのクラスパスへクラスを追加します。

3.3. Maven を使用した MANIFEST.MF エントリーの生成

Maven JAR、EJB、WAR パッケージングプラグインのいずれかを使用する Maven プロジェクトは Dependencies エントリーを持つ MANIFEST.MF ファイルを生成することができます。この処理により、依存関係の一覧は自動的に生成されず、pom.xml に指定された詳細が含まれる MANIFEST.MF ファイルのみが作成されます。

要件

  1. 作業用の Maven プロジェクトが既に存在している必要があります。
  2. Maven プロジェクトが JAR、EJB、WAR プラグイン ( maven-jar-pluginmaven-ejb-pluginmaven-war-plugin) のいずれかを使用しなければなりません。
  3. プロジェクトのモジュール依存関係の名前を知っていなければなりません。JBoss Enterprise Application Platform 6 に含まれる静的モジュールの一覧は 「含まれるモジュール」 を参照してください。モジュールが別のデプロイメントにある場合は 「動的モジュールの名前付け」 を参照してモジュール名を判断してください。

手順3.3 モジュール依存関係が含まれる MANIFEST.MF ファイルの生成

  1. 設定の追加

    プロジェクトの pom.xml ファイルにあるパッケージングプラグイン設定に次の設定を追加します。
    <configuration>
       <archive>
          <manifestEntries>
             <Dependencies></Dependencies>
          </manifestEntries>
       </archive>
    </configuration>
    
  2. 依存関係の一覧表示

    モジュール依存関係の一覧を <Dependencies> 要素に追加します。MANIFEST.MF に依存関係を追加する時と同じ形式を使用します。この形式に関する詳細は 「デプロイメントへの明示的なモジュール依存関係の追加」 を参照してください。
    <Dependencies>org.javassist, org.apache.velocity</Dependencies>
    
  3. プロジェクトの構築

    Maven アセンブリゴールを用いたプロジェクトの構築
    [Localhost ]$ mvn assembly:assembly
アセンブリゴールを使用してプロジェクトを構築すると、指定のモジュール依存関係を持つ MANIFEST.MF ファイルが最終アーカイブに含まれます。

例3.3 pom.xml の設定されたモジュール依存関係

この例は WAR プラグインの例になりますが、JAR や EJB プラグイン (maven-jar-plugin や maven-ejb-plugin) でも動作します。
<plugins>
   <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-war-plugin</artifactId>
      <configuration>
         <archive>
            <manifestEntries>
               <Dependencies>org.javassist, org.apache.velocity</Dependencies>
            </manifestEntries>
         </archive>
      </configuration>
   </plugin>
</plugins>

3.4. モジュールが暗黙的にロードされないようにする

このタスクでは、モジュール依存関係のリストを除外するようアプリケーションを設定する方法を説明します。
デプロイ可能なアプリケーションを設定して暗黙的な依存関係がロードされないようにすることが可能です。これは、アプリケーションサーバーより提供される暗黙的な依存関係とは異なるバージョンのライブラリやフレームワークがアプリケーションに含まれる場合に一般的に行われます。

要件

  1. モジュール依存関係を除外するソフトウェアプロジェクトが存在する必要があります。
  2. 除外するモジュール名を知っている必要があります。暗黙的な依存関係のリストや状態については 「暗黙的なモジュール依存関係」 を参照してください。

手順3.4 jboss-deployment-structure.xml への依存関係除外設定の追加

  1. アプリケーションに jboss-deployment-structure.xml ファイルが存在しない場合は、jboss-deployment-structure.xml という新しいファイルを作成し、プロジェクトに追加しあす。このファイルは <jboss-deployment-structure> がルート要素の XML ファイルです。
    <jboss-deployment-structure>
    
    </jboss-deployment-structure>
    
    Web アプリケーション (WAR) では、このファイルを WEB-INF に追加します。EJB アーカイブ (JAR) では、META-INF ディレクトリに追加します。
  2. <deployment> 要素をドキュメントルート内に作成し、その中に <exclusions> 要素を作成します。
    <deployment>
       <exclusions>
       
       </exclusions>
    </deployment>
    
  3. exclusions 要素内で、除外される各モジュールに対して <module> 要素を追加します。 name 属性をモジュールの名前に設定します。
    <module name="org.javassist" />
    

例3.4 2 つのモジュールの除外

<jboss-deployment-structure>
   <deployment>
      <exclusions>
         <module name="org.javassist" />
         <module name="org.dom4j" />
      </exclusions>
   </deployment>
</jboss-deployment-structure>

3.5. サブシステムをデプロイメントから除外する

概要

ここではサブシステムをデプロイメントより除外するために必要な手順について説明します。jboss-deployment-structure.xml 設定ファイルを編集します。サブシステムの除外はサブシステムの削除と同じ影響がありますが、1 つのデプロイメントのみに適用されます。

手順3.5 サブシステムの除外

  1. テキストエディターで jboss-deployment-structure.xml ファイルを開きます。
  2. 次の XML を <deployment> タグの中に追加します。
    <exclude-subsystems>
      <subsystem name="SUBSYSTEM_NAME" />
    </exclude-subsystems>
    
  3. jboss-deployment-structure.xml ファイルを保存します。
結果

サブシステムが除外されます。サブシステムのデプロイメントユニットプロセッサがデプロイメント上で実行されないようになります。

例3.5 jboss-deployment-structure.xml ファイルの例

<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
  <ear-subdeployments-isolated>true</ear-subdeployments-isolated>
  <deployment>
    <exclude-subsystems>
      <subsystem name="resteasy" />
    </exclude-subsystems>
    <exclusions>
      <module name="org.javassist" />
    </exclusions>
    <dependencies>
      <module name="deployment.javassist.proxy" />
      <module name="deployment.myjavassist" />
      <module name="myservicemodule" services="import"/>
    </dependencies>
    <resources>
      <resource-root path="my-library.jar" />
    </resources>
  </deployment>
  <sub-deployment name="myapp.war">
    <dependencies>
      <module name="deployment.myear.ear.myejbjar.jar" />
    </dependencies>
    <local-last value="true" />
  </sub-deployment>
  <module name="deployment.myjavassist" >
    <resources>
     <resource-root path="javassist.jar" >
       <filter>
         <exclude path="javassist/util/proxy" />
       </filter>
     </resource-root>
    </resources>
  </module>
  <module name="deployment.javassist.proxy" >
    <dependencies>
      <module name="org.javassist" >
        <imports>
          <include path="javassist/util/proxy" />
          <exclude path="/**" />
        </imports>
      </module>
    </dependencies>
  </module>
</jboss-deployment-structure>

3.6. クラスローディングとサブデプロイメント

3.6.1. エンタープライズアーカイブのモジュールおよびクラスロード

エンタープライズアーカイブ (EAR) は、JAR または WAR デプロイメントのように、単一モジュールとしてロードされません。これらは、複数の一意のモジュールとしてロードされます。
以下のルールによって、EAR に存在するモジュールが決定されます。
  • 各 WAR および EJB JAR サブデプロイメントはモジュールです。
  • EAR アーカイブのルートにある lib/ ディレクトリの内容はモジュールです。これは、親モジュールと呼ばれます。
これらのモジュールの動作は、以下の追加の暗黙的な依存関係がある他のモジュールと同じです。
  • WAR サブデプロイメントでは、親モジュールとすべての EJB JAR サブデプロイメントに暗黙的な依存関係が存在します。
  • EJB JAR サブデプロイメントでは、親モジュールと他のすべての EJB JAR サブデプロイメントに暗黙的な依存関係が存在します。

重要

サブデプロイメントでは、WAR サブデプロイメントに暗黙的な依存関係が存在しません。他のモジュールと同様に、サブデプロイメントは、別のサブデプロイメントの明示的な依存関係で設定できます。
JBoss Enterprise Application Platform 6 ではサブデプロイメントクラスローダーの隔離がデフォルトで無効になるため、上記の暗黙的な依存関係が発生します。
サブデプロイメントクラスローダーの分離は、厳密な互換性が必要な場合に有効にできます。これは、単一の EAR デプロイメントまたはすべての EAR デプロイメントに対して有効にできます。Java EE 6 の仕様では、依存関係が各サブデプロイメントの MANIFEST.MF ファイルのClass-Path エントリーとして明示的に宣言されない限り、移植可能なアプリケーションがお互いにアクセスできるサブデプロイメントに依存しないことが推奨されます。

3.6.2. サブデプロイメントクラスローダーの分離

エンタープライズアーカイブ (EAR) の各サブデプロイメントは独自のクラスローダーを持つ動的モジュールです。デフォルトでは、サブデプロイメントは他のサブデプロイメントのリソースにアクセスできます。
サブデプロイメントが他のサブデプロイメントのリソースにアクセスすべきでない場合 (厳格なサブデプロイメントの分離が必要な場合)は、この挙動を有効にできます。

3.6.3. EAR 内のサブデプロイメントクラスローダーの分離を無効化する

このタスクでは、EAR の特別なデプロイメント記述子を使用して EAR デプロイメントのサブデプロイメントクラスローダーの分離を無効にする方法を説明します。アプリケーションサーバーを変更する必要はなく、他のデプロイメントも影響を受けません。

重要

サブデプロイメントクラスローダーの分離が無効であっても、WAR を依存関係として追加することはできません。
  1. デプロイメント記述子ファイルの追加

    jboss-deployment-structure.xml デプロイメント記述子ファイルが存在しない場合は EAR の META-INF ディレクトリへ追加し、次の内容を追加します。
    <jboss-deployment-structure>
    
    </jboss-deployment-structure>
    
  2. <ear-subdeployments-isolated> 要素の追加

    <ear-subdeployments-isolated> 要素が存在しない場合は jboss-deployment-structure.xml ファイルへ追加し、内容が false となるようにします。
    <ear-subdeployments-isolated>false</ear-subdeployments-isolated>
    
結果

この EAR デプロイメントに対してサブデプロイメントクラスローダーの分離が無効になります。そのため、EAR のサブデプロイメントは WAR ではないサブデプロイメントごとに自動的な依存関係を持ちます。

3.7. 参考資料

3.7.1. 暗黙的なモジュール依存関係

以下の表には、依存関係としてデプロイメントに自動的に追加されるモジュールと、依存関係をトリガーする条件が記載されています。

表3.1 暗黙的なモジュール依存関係

サブシステム 常に追加されるモジュール 条件付きで追加されるモジュール 条件
コアサーバー
  • javax.api
  • sun.jdk
  • org.jboss.logging
  • org.apache.log4j
  • org.apache.commons.logging
  • org.slf4j
  • org.jboss.logging.jul-to-slf4j-stub
-
-
EE サブシステム
  • javaee.api
-
-
EJB3 サブシステム
-
  • javaee.api
Java EE 6 の仕様で指定されているように、デプロイメント内の有効な場所で ejb-jar.xml が存在するか、アノテーションベースの EJB が存在すること (例:@Stateless@Stateful@MessageDriven など)
JAX-RS (Resteasy) サブシステム
  • javax.xml.bind.api
  • org.jboss.resteasy.resteasy-atom-provider
  • org.jboss.resteasy.resteasy-cdi
  • org.jboss.resteasy.resteasy-jaxrs
  • org.jboss.resteasy.resteasy-jaxb-provider
  • org.jboss.resteasy.resteasy-jackson-provider
  • org.jboss.resteasy.resteasy-jsapi
  • org.jboss.resteasy.resteasy-multipart-provider
  • org.jboss.resteasy.async-http-servlet-30
デプロイメント内に JAX-RS のアノテーションが存在すること
JCA サブシステム
  • javax.resource.api
  • javax.jms.api
  • javax.validation.api
  • org.jboss.logging
  • org.jboss.ironjacamar.api
  • org.jboss.ironjacamar.impl
  • org.hibernate.validator
デプロイメントがリソースアダプター (RAR) デプロイメントの場合
JPA (Hibernate) サブシステム
  • javax.persistence.api
  • javaee.api
  • org.jboss.as.jpa
  • org.hibernate
  • org.javassist
@PersistenceUnit または @PersistenceContext アノテーションが存在するか、デプロイメント記述子に<persistence-unit-ref> または <persistence-context-ref> が存在すること
SAR サブシステム
-
  • org.jboss.logging
  • org.jboss.modules
デプロイメントが SAR アーカイブであること
セキュリティサブシステム
  • org.picketbox
-
-
Web サブシステム
-
  • javaee.api
  • com.sun.jsf-impl
  • org.hibernate.validator
  • org.jboss.as.web
  • org.jboss.logging
デプロイメントは WAR アーカイブです。利用されている場合は、JavaServer Faces(JSF) のみが追加されます。
Web サービスサブシステム
  • org.jboss.ws.api
  • org.jboss.ws.spi
-
-
Weld (CDI) サブシステム
-
  • javax.persistence.api
  • javaee.api
  • org.javassist
  • org.jboss.interceptor
  • org.jboss.as.weld
  • org.jboss.logging
  • org.jboss.weld.core
  • org.jboss.weld.api
  • org.jboss.weld.spi
beans.xml ファイルがデプロイメント内で検出された場合

3.7.2. 含まれるモジュール

  • asm.asm
  • ch.qos.cal10n
  • com.google.guava
  • com.h2database.h2
  • com.sun.jsf-impl
  • com.sun.jsf-impl
  • com.sun.xml.bind
  • com.sun.xml.messaging.saaj
  • gnu.getopt
  • javaee.api
  • javax.activation.api
  • javax.annotation.api
  • javax.api
  • javax.ejb.api
  • javax.el.api
  • javax.enterprise.api
  • javax.enterprise.deploy.api
  • javax.faces.api
  • javax.faces.api
  • javax.inject.api
  • javax.interceptor.api
  • javax.jms.api
  • javax.jws.api
  • javax.mail.api
  • javax.management.j2ee.api
  • javax.persistence.api
  • javax.resource.api
  • javax.rmi.api
  • javax.security.auth.message.api
  • javax.security.jacc.api
  • javax.servlet.api
  • javax.servlet.jsp.api
  • javax.servlet.jstl.api
  • javax.transaction.api
  • javax.validation.api
  • javax.ws.rs.api
  • javax.wsdl4j.api
  • javax.xml.bind.api
  • javax.xml.jaxp-provider
  • javax.xml.registry.api
  • javax.xml.rpc.api
  • javax.xml.soap.api
  • javax.xml.stream.api
  • javax.xml.ws.api
  • jline
  • net.sourceforge.cssparser
  • net.sourceforge.htmlunit
  • net.sourceforge.nekohtml
  • nu.xom
  • org.antlr
  • org.apache.ant
  • org.apache.commons.beanutils
  • org.apache.commons.cli
  • org.apache.commons.codec
  • org.apache.commons.collections
  • org.apache.commons.io
  • org.apache.commons.lang
  • org.apache.commons.logging
  • org.apache.commons.pool
  • org.apache.cxf
  • org.apache.httpcomponents
  • org.apache.james.mime4j
  • org.apache.log4j
  • org.apache.neethi
  • org.apache.santuario.xmlsec
  • org.apache.velocity
  • org.apache.ws.scout
  • org.apache.ws.security
  • org.apache.ws.xmlschema
  • org.apache.xalan
  • org.apache.xerces
  • org.apache.xml-resolver
  • org.codehaus.jackson.jackson-core-asl
  • org.codehaus.jackson.jackson-jaxrs
  • org.codehaus.jackson.jackson-mapper-asl
  • org.codehaus.jackson.jackson-xc
  • org.codehaus.woodstox
  • org.dom4j
  • org.hibernate
  • org.hibernate.envers
  • org.hibernate.infinispan
  • org.hibernate.validator
  • org.hornetq
  • org.hornetq.ra
  • org.infinispan
  • org.infinispan.cachestore.jdbc
  • org.infinispan.cachestore.remote
  • org.infinispan.client.hotrod
  • org.jacorb
  • org.javassist
  • org.jaxen
  • org.jboss.as.aggregate
  • org.jboss.as.appclient
  • org.jboss.as.cli
  • org.jboss.as.clustering.api
  • org.jboss.as.clustering.common
  • org.jboss.as.clustering.ejb3.infinispan
  • org.jboss.as.clustering.impl
  • org.jboss.as.clustering.infinispan
  • org.jboss.as.clustering.jgroups
  • org.jboss.as.clustering.service
  • org.jboss.as.clustering.singleton
  • org.jboss.as.clustering.web.infinispan
  • org.jboss.as.clustering.web.spi
  • org.jboss.as.cmp
  • org.jboss.as.connector
  • org.jboss.as.console
  • org.jboss.as.controller
  • org.jboss.as.controller-client
  • org.jboss.as.deployment-repository
  • org.jboss.as.deployment-scanner
  • org.jboss.as.domain-add-user
  • org.jboss.as.domain-http-error-context
  • org.jboss.as.domain-http-interface
  • org.jboss.as.domain-management
  • org.jboss.as.ee
  • org.jboss.as.ee.deployment
  • org.jboss.as.ejb3
  • org.jboss.as.embedded
  • org.jboss.as.host-controller
  • org.jboss.as.jacorb
  • org.jboss.as.jaxr
  • org.jboss.as.jaxrs
  • org.jboss.as.jdr
  • org.jboss.as.jmx
  • org.jboss.as.jpa
  • org.jboss.as.jpa.hibernate
  • org.jboss.as.jpa.hibernate
  • org.jboss.as.jpa.hibernate.infinispan
  • org.jboss.as.jpa.openjpa
  • org.jboss.as.jpa.spi
  • org.jboss.as.jpa.util
  • org.jboss.as.jsr77
  • org.jboss.as.logging
  • org.jboss.as.mail
  • org.jboss.as.management-client-content
  • org.jboss.as.messaging
  • org.jboss.as.modcluster
  • org.jboss.as.naming
  • org.jboss.as.network
  • org.jboss.as.osgi
  • org.jboss.as.platform-mbean
  • org.jboss.as.pojo
  • org.jboss.as.process-controller
  • org.jboss.as.protocol
  • org.jboss.as.remoting
  • org.jboss.as.sar
  • org.jboss.as.security
  • org.jboss.as.server
  • org.jboss.as.standalone
  • org.jboss.as.threads
  • org.jboss.as.transactions
  • org.jboss.as.web
  • org.jboss.as.webservices
  • org.jboss.as.webservices.server.integration
  • org.jboss.as.webservices.server.jaxrpc-integration
  • org.jboss.as.weld
  • org.jboss.as.xts
  • org.jboss.classfilewriter
  • org.jboss.com.sun.httpserver
  • org.jboss.common-core
  • org.jboss.dmr
  • org.jboss.ejb-client
  • org.jboss.ejb3
  • org.jboss.iiop-client
  • org.jboss.integration.ext-content
  • org.jboss.interceptor
  • org.jboss.interceptor.spi
  • org.jboss.invocation
  • org.jboss.ironjacamar.api
  • org.jboss.ironjacamar.impl
  • org.jboss.ironjacamar.jdbcadapters
  • org.jboss.jandex
  • org.jboss.jaxbintros
  • org.jboss.jboss-transaction-spi
  • org.jboss.jsfunit.core
  • org.jboss.jts
  • org.jboss.jts.integration
  • org.jboss.logging
  • org.jboss.logmanager
  • org.jboss.logmanager.log4j
  • org.jboss.marshalling
  • org.jboss.marshalling.river
  • org.jboss.metadata
  • org.jboss.modules
  • org.jboss.msc
  • org.jboss.netty
  • org.jboss.osgi.deployment
  • org.jboss.osgi.framework
  • org.jboss.osgi.resolver
  • org.jboss.osgi.spi
  • org.jboss.osgi.vfs
  • org.jboss.remoting3
  • org.jboss.resteasy.resteasy-atom-provider
  • org.jboss.resteasy.resteasy-cdi
  • org.jboss.resteasy.resteasy-jackson-provider
  • org.jboss.resteasy.resteasy-jaxb-provider
  • org.jboss.resteasy.resteasy-jaxrs
  • org.jboss.resteasy.resteasy-jsapi
  • org.jboss.resteasy.resteasy-multipart-provider
  • org.jboss.sasl
  • org.jboss.security.negotiation
  • org.jboss.security.xacml
  • org.jboss.shrinkwrap.core
  • org.jboss.staxmapper
  • org.jboss.stdio
  • org.jboss.threads
  • org.jboss.vfs
  • org.jboss.weld.api
  • org.jboss.weld.core
  • org.jboss.weld.spi
  • org.jboss.ws.api
  • org.jboss.ws.common
  • org.jboss.ws.cxf.jbossws-cxf-client
  • org.jboss.ws.cxf.jbossws-cxf-factories
  • org.jboss.ws.cxf.jbossws-cxf-server
  • org.jboss.ws.cxf.jbossws-cxf-transports-httpserver
  • org.jboss.ws.jaxws-client
  • org.jboss.ws.jaxws-jboss-httpserver-httpspi
  • org.jboss.ws.native.jbossws-native-core
  • org.jboss.ws.native.jbossws-native-factories
  • org.jboss.ws.native.jbossws-native-services
  • org.jboss.ws.saaj-impl
  • org.jboss.ws.spi
  • org.jboss.ws.tools.common
  • org.jboss.ws.tools.wsconsume
  • org.jboss.ws.tools.wsprovide
  • org.jboss.xb
  • org.jboss.xnio
  • org.jboss.xnio.nio
  • org.jboss.xts
  • org.jdom
  • org.jgroups
  • org.joda.time
  • org.junit
  • org.omg.api
  • org.osgi.core
  • org.picketbox
  • org.picketlink
  • org.python.jython.standalone
  • org.scannotation.scannotation
  • org.slf4j
  • org.slf4j.ext
  • org.slf4j.impl
  • org.slf4j.jcl-over-slf4j
  • org.w3c.css.sac
  • sun.jdk

3.7.3. JBoss デプロイメント構造のデプロイメント記述子のリファレンス

このデプロイメント記述子を使用して実行できる主なタスクは次の通りです。
  • 明示的なモジュール依存関係を定義する。
  • 特定の暗黙的な依存関係がローディングされないようにする。
  • デプロイメントのリソースより追加モジュールを定義する。
  • EAR デプロイメントのサブデプロイメント分離の挙動を変更する。
  • EAR のモジュールに追加のリソースルートを追加する。

第4章 グローバル値

4.1. バルブについて

バルブは、アプリケーションのパイプラインを処理するリクエストに挿入される Java クラスです。バルブはサーブレットフィルターの前にパイプラインへ挿入されます。バルブはリクエストを渡す前に変更を加えることができ、認証またはリクエストのキャンセルなどの他の処理を実行できます。通常、バルブはアプリケーションとパッケージ化されます。
6.1.0 およびそれ以降のバージョンはグローバルバルブをサポートします。

4.2. グローバルバルブについて

グローバルバルブは、デプロイされたすべてのアプリケーションのパイプラインを処理するリクエストに挿入されるバルブです。バルブは JBoss Enterprise Application Platform 6 の静的モジュールとしてパッケージ化およびインストールされ、グローバルバルブとなります。グローバルバルブは Web サブシステムで設定されます。
6.1.0 およびそれ以降のバージョンのみがグローバルバルブをサポートします。

4.3. オーセンティケーターバルブについて

オーセンティケーターバルブは、リクエストの証明情報を認証するバルブです。オーセンティケーターバルブは org.apache.catalina.authenticator.AuthenticatorBase のサブクラスで、authenticate() メソッドを上書きします。
このバルブを使用して追加の認証スキームを実装できます。

4.4. Web アプリケーションがバルブを使用するよう設定する

グローバルバルブとしてインストールされないバルブは、アプリケーションに含め、jboss-web.xml デプロイメント記述子で設定する必要があります。

重要

グローバルバルブとしてインストールされたバルブは、デプロイされたすべてのアプリケーションに自動的に適用されます。

要件

  • バルブを作成し、アプリケーションのクラスパスに含める必要があります。これは、バルブをアプリケーションの WAR ファイルにまたは依存関係として追加されたモジュールに含めることにより、実現できます。このようなモジュールの例には、サーバーにインストールされた静的モジュールや EAR アーカイブの lib/ ディレクトリーにある JAR ファイル (WAR が EAR でデプロイされる場合) があります。
  • アプリケーションは jboss-web.xml デプロイメント記述子を含む必要があります。

手順4.1 ローカルバルブのためにアプリケーションを設定する

  1. バルブ要素を追加する

    name と class-name の属性を使用してバルブ要素をアプリケーションの jboss-web.xml ファイルに追加します。name は、バルブの一意の ID であり、class-name はバルブクラスの名前です。
    <valve name="VALVENAME" class-name="VALVECLASSNAME">
       
    </valve>
    
  2. 特定のパラメーター

    バルブでパラメーターを設定できる場合は、各パラメーターのバルブ要素に param 子要素を追加してそれぞれに対して名前と値を指定します。
    <param name="PARAMNAME" value = "VALUE" />
    
アプリケーションがデプロイされた場合、バルブは、指定された設定でアプリケーションに対して有効になります。

例4.1 jboss-web.xml バルブ設定

<valve name="clientlimiter" class-name="org.jboss.samplevalves.restrictedUserAgentsValve">
    <param name="restricteduseragents"  value = "^.*MS Web Services Client Protocol.*$" />
</valve>

4.5. Web アプリケーションがオーセンティケーターバルブを使用するよう設定する

アプリケーションがオーセンティケーターバルブを使用するよう設定するには、バルブをインストールおよび設定し (アプリケーションに対してローカル、またはグローバルバルブとして)、アプリケーションの web.xml デプロイメント記述子を設定する必要があります。最も単純なケースでは、web.xml 設定は BASIC 認証を使用した場合と同じです。ただし、of login-configauth-method 子要素は、設定を実行するバルブの名前に設定されます。

要件

  • 認証バルブがすでに作成されている必要があります。
  • 認証バルブがグローバルバルブの場合、認証バルブはすでにインストールおよび設定されている必要があります。また、設定された名前を知っている必要があります。
  • アプリケーションが使用するセキュリティーレルムのレルム名を知っている必要があります。
使用するバルブまたはセキュリティーレルム名を知らない場合は、サーバー管理者に問い合わせてください。

手順4.2 アプリケーションがオーセンティケーターバルブを使用するよう設定する

  1. バルブを設定する

    ローカルバルブを使用する場合は、jboss-web.xml デプロイメント記述子で設定する必要があります。「Web アプリケーションがバルブを使用するよう設定する」を参照してください。
    グローバルバルブを使用する場合、これは不必要です。
  2. セキュリティー設定を web.xml に追加する

    security-constraint、login-config、security-role などの標準的な要素を使用して、セキュリティー設定をアプリケーションの web.xml ファイルに追加します。login-config 要素で、auth-method の値をオーセンティケーターバルブの名前に設定します。また、realm-name 要素を、アプリケーションが使用している JBoss セキュリティーレルムの名前に設定する必要があります。
    <login-config>
       <auth-method>VALVE_NAME</auth-method>
       <realm-name>REALM_NAME</realm-name>
    </login-config>
    
アプリケーションがデプロイされた場合、要求の認証は設定された認証バルブにより処理されます。

4.6. カスタムバルブを作成する

バルブは、アプリケーションのサーブレットフィルターの前にアプリケーション用要求処理パイブラインに挿入される Java クラスです。これは、要求を変更または他の動作を実行するために使用できます。このタスクは、バルブを実装するのに必要な基本的な手順を示しています。

手順4.3 カスタムバルブを作成する

  1. バルブクラスを作成する

    org.apache.catalina.valves.ValveBase のサブクラスを作成します。
    package org.jboss.samplevalves;
    
    import org.apache.catalina.valves.ValveBase;
    import org.apache.catalina.connector.Request;
    import org.apache.catalina.connector.Response;
    
    public class restrictedUserAgentsValve extends ValveBase {
    
    }
    
  2. 呼び出しメソッドを実装する

    invoke() メソッドは、このバルブがパイプラインで実行されるときに呼び出されます。要求オブジェクトと応答オブジェクトはパラメーターとして渡されます。ここで、要求と応答の処理と変更を行います。
    public void invoke(Request request, Response response)
    {
    
    }
    
  3. 次のパイプラインステップを呼び出す

    呼び出しメソッドが最後に実行する必要があることはパイプラインの次のステップを呼び出し、変更された要求オブジェクトと応答オブジェクトを渡すことです。これは、getNext().invoke() メソッドを使用して行われます。
    getNext().invoke(request, response);
    
  4. オプション: パラメーターを指定する

    バルブを設定可能にする必要がある場合は、パラメーターを追加してこれを有効にします。これは、インスタンス変数と各パラメーターに対するセッターを追加して行います。
    private String restrictedUserAgents = null;
    
    public void setRestricteduseragents(String mystring) 
    {
       this.restrictedUserAgents = mystring;
    }
    

例4.2 単純なカスタムバルブ

package org.jboss.samplevalves;

import java.io.IOException;
import java.util.regex.Pattern;

import javax.servlet.ServletException;
import org.apache.catalina.valves.ValveBase;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;

public class restrictedUserAgentsValve extends ValveBase 
{
    private String restrictedUserAgents = null;

    public void setRestricteduseragents(String mystring) 
    {
        this.restrictedUserAgents = mystring;
    }

    public void invoke(Request request, Response response) throws IOException, ServletException 
    {
      String agent = request.getHeader("User-Agent");
      System.out.println("user-agent: " + agent + " : " + restrictedUserAgents);
      if (Pattern.matches(restrictedUserAgents, agent)) 
      {
         System.out.println("user-agent: " + agent + " matches: " + restrictedUserAgents);
         response.addHeader("Connection", "close");
      }
      getNext().invoke(request, response);
    }
}

第5章 開発者向けのロギング

5.1. はじめに

5.1.1. ロギングについて

ロギングとはアプリケーションから活動に関する記録 (ログ) を受け取り、メッセージ群を記録することです。
ログメッセージは、アプリケーションをデバッグする開発者や実稼働環境のアプリケーションを維持するシステム管理者に対して重要な情報を提供します。
最新の Java のロギングフレームワークの多くには、正確な時間やメッセージの起源など他の詳細も含まれています。

5.1.2. JBoss LogManager でサポートされるアプリケーションロギングフレームワーク

JBoss LogManager は次のロギングフレームワークをサポートします。

5.1.3. ログレベルについて

ログレベルとは、ログメッセージの性質と重大度を示す列挙値の順序付けされたセットです。 特定のログメッセージのレベルは、そのメッセージを送信するために選択したロギングフレームワークの適切なメソッドを使用して開発者が指定します。
JBoss Enterprise Application Platform 6 はサポートされるアプリケーションロギングフレームワークによって使用されるすべてのログレベルをサポートします。最も一般的に使用される 6 つのログレベルは、ログレベルの低い順に TRACEDEBUGINFOWARNERROR および FATAL となります。
ログレベルはログカテゴリとログハンドラーによって使用され、それらが担当するメッセージを限定します。各ログレベルには、他のログレベルに対して相対的な順番を示す数値が割り当てられています。ログカテゴリーとハンドラーにはログレベルが割り当てられ、そのレベル以上のログメッセージのみを処理します。たとえば、WARN レベルのログハンドラーは、WARNERROR、および FATAL のレベルのメッセージのみを記録します。

5.1.4. サポートされているログレベル

表5.1 サポートされているログレベル

ログレベル 説明
FINEST 300
-
FINER 400
-
TRACE 400
アプリケーションの実行状態に関する詳細情報を提供するメッセージに使用します。通常、TRACE のログメッセージはアプリケーションのデバッグ時のみにキャプチャーされます。
DEBUG 500
アプリケーションの個別の要求またはアクティビティの進捗状況を表示するメッセージに使用します。DEBUG のログメッセージは通常アプリケーションのデバッグ時のみにキャプチャーされます。
FINE 500
-
CONFIG 700
-
INFO 800
アプリケーションの全体的な進捗状況を示すメッセージに使用します。多くの場合、アプリケーションの起動、シャットダウン、およびその他の主要なライフサイクルイベントに使用されます。
WARN 900
エラーではないが、理想的とは見なされない状況を示すために使用されます。将来的にエラーをもたらす可能性のある状況を示します。
WARNING 900
-
ERROR 1000
発生したエラーの中で、現在のアクティビティや要求の完了を妨げる可能性があるが、アプリケーション実行の妨げにはならないエラーを表示するために使用されます。
SEVERE 1000
-
FATAL 1100
クリティカルなサービス障害やアプリケーションのシャットダウンをもたらしたり、JBoss Enterprise Application Platform 6 のシャットダウンを引き起こす可能性があるイベントを表示するのに使用します。

5.1.5. デフォルトのログファイルの場所

これらは、デフォルトのロギング設定に対して作成されたログファイルです。デフォルトの設定では、周期的なログハンドラーを使用してサーバーログファイルが書き込まれます。

表5.2 スタンドアローンサーバー用デフォルトログファイル

ログファイル 説明
EAP_HOME/standalone/log/boot.log
サーバールートログ。サーバーの起動に関連するログメッセージが含まれます。
EAP_HOME/standalone/log/server.log
サーバーログ。サーバー起動後のすべてのログメッセージが含まれます。

表5.3 管理対象ドメイン用デフォルトログファイル

ログファイル 説明
EAP_HOME/domain/log/host-controller/boot.log
ホストコントローラーブートログ。ホストコントローラーの起動に関連するログメッセージが含まれます。
EAP_HOME/domain/log/process-controller/boot.log
プロセスコントローラーブートログ。プロセスコントローラーの起動に関連するログメッセージが含まれます。
EAP_HOME/domain/servers/SERVERNAME/log/boot.log
指定されたサーバーのサーバーブートログ。指定されたサーバーの起動に関連するログメッセージが含まれます。
EAP_HOME/domain/servers/SERVERNAME/log/server.log
指定されたサーバーのサーバーログ。指定されたサーバー起動後のすべてのログメッセージが含まれます。

5.2. JBoss ロギングフレームワークを用いたロギング

5.2.1. JBoss Logging について

JBoss ロギングは JBoss Enterprise Application Platform 6 に含まれるアプリケーションロギングフレームワークです。
JBoss ロギングはアプリケーションにロギングを追加する簡単な方法を提供します。フレームワークを使用するアプリケーションにコードを追加し、定義された形式でログメッセージを送信します。アプリケーションサーバーにアプリケーションがデプロイされると、これらのメッセージがサーバーによってキャプチャーされ、サーバーの設定通りファイルに表示されたり書き込まれたりします。

5.2.2. JBoss ロギングの機能

  • 革新的かつ使いやすい「型指定された」ロガーを提供します。
  • 国際化および現地化を完全サポートします。翻訳者はプロパティーファイルのメッセージバンドルを使用します。開発者はインターフェースやアノテーションを使用できます。
  • 実稼働向けにはビルド時に型指定されたロガーを生成し、開発向けにはランタイムで型指定されたロガーを生成するツール。

5.2.3. JBoss ロギングを使用してアプリケーションにロギングを追加

アプリケーションからのメッセージをログに記録するために、Logger オブジェクト (org.jboss.logging.Logger) を作成し、そのオブジェクトの適切なメソッドを呼び出します。このタスクは、アプリケーションにこのオブジェクトのサポートを追加するために必要な手順を示しています。

要件

このタスクを行う前に、 次の条件を満たす必要があります。
  • ビルドシステムとして Maven を使用している場合は、JBoss Maven リポジトリーを含めるようプロジェクトが設定されている必要があります。「Maven 設定を使用した JBoss Enterprise Application Platform の Maven リポジトリーの設定」を参照してください。
  • JBoss ロギング JAR ファイルがアプリケーションのビルドパスに指定されている必要があります。これを行う方法は、アプリケーションをビルドするのに JBoss Developer Studio を使用するか、Maven を使用するかによって異なります。
    • JBoss Developer Studio を使用してビルドする場合、これを行うには JBoss Developer Studio メニューから [Project] -> [Properties] を選択し、[Targeted Runtimes] を選択して、JBoss Enterprise Application Platform 6 のランタイムがチェックされていることを確認します。
    • Maven を使用してビルドする場合、これを行うには、次の依存性設定をプロジェクトの pom.xml ファイルに追加します。
      <dependency>
         <groupId>org.jboss.logging</groupId>
         <artifactId>jboss-logging</artifactId>
         <version>3.1.2.GA-redhat-1</version>
         <scope>provided</scope>
      </dependency>
      
    JAR は、JBoss Enterprise Application Platform 6 がデプロイされたアプリケーションに提供するため、ビルドされたアプリケーションに含める必要はありません。
プロジェクトが正しくセットアップされたら、ロギングを追加する各クラスに対して次の手順を実行する必要があります。
  1. インポートの追加

    使用する JBoss Logging クラスネームスペースに対して import ステートメントを追加します。少なくとも、import org.jboss.logging.Logger をインポートする必要があります。
    import org.jboss.logging.Logger;
    
  2. Logger オブジェクトの作成

    org.jboss.logging.Logger のインスタンスを作成し、静的メソッド Logger.getLogger(Class) を呼び出して初期化します。各クラスに対してこれを単一インスタンス変数として作成することが推奨されます。
    private static final Logger LOGGER = Logger.getLogger(HelloWorld.class);
    
  3. ロギングメッセージの追加

    Logger オブジェクトのメソッドへの呼び出しを、ログメッセージを送信するコードに追加します。Logger オブジェクトには、さまざまなタイプのメッセージに対するさまざまなパラメーターを持つさまざまなメソッドが含まれます。最も使用しやすいものは次のとおりです。
    debug(Object message)
    info(Object message)
    error(Object message)
    trace(Object message)
    fatal(Object message)
    これらのメッセージは、対応するログレベルと message パラメーターを文字列として持つログメッセージを送信します。
    LOGGER.error("Configuration file not found.");
    
    JBoss Logging メソッドの完全なリストについては、JBoss Enterprise Application Platform 6 API ドキュメンテーションの org.jboss.logging パッケージを参照してください。

例5.1 プロパティーファイルを開くときに JBoss ロギングを使用

次の例は、プロパティーファイルからアプリケーションのカスタマイズされた設定をロードするクラスのコードの一部を示しています。指定されたファイルが見つからない場合は、エラーレベルログメッセージが記録されます。
import org.jboss.logging.Logger;
public class LocalSystemConfig
{
   private static final Logger LOGGER = Logger.getLogger(LocalSystemConfig.class);

   public Properties openCustomProperties(String configname) throws CustomConfigFileNotFoundException
   {
      Properties props = new Properties();
      try 
      {
         LOGGER.info("Loading custom configuration from "+configname);
         props.load(new FileInputStream(configname));
      }
      catch(IOException e) //catch exception in case properties file does not exist
      {
         LOGGER.error("Custom configuration file ("+configname+") not found. Using defaults.");
         throw new CustomConfigFileNotFoundException(configname);
      }
      
      return props;
   }

5.3. ロギングプロファイル

5.3.1. ロギングプロファイルについて

重要

ロギングプロファイルは 6.1.0 およびそれ以降のバージョンでのみ使用可能です。
ロギングプロファイルは、デプロイされたアプリケーションに割り当てられる独立したロギング設定のセットです。ロギングプロファイルはハンドラー、カテゴリーおよびルートロガーを通常のロギングサブシステム同様に定義できますが、他のプロファイルやメインのロギングサブシステムを参照できません。ロギングプロファイルは設定を容易にするためロギングサブシステムに似ています。
ログインプロファイルを使用すると、管理者は他のロギング設定に影響を与えることなく 1 つ以上のアプリケーションに固有するロギング設定を作成することができます。各プロファイルはサーバー設定に定義されるため、影響するアプリケーションを再デプロイする必要はなく、ロギング設定を変更できます。
各ロギングプロファイルに含めることができる設定は次のとおりです。
  • 一意の名前 (必須)。
  • ログハンドラーの数 (いくつでも)。
  • ログカテゴリーの数 (いくつでも)。
  • ルートロガー (1 つまで)。
アプリケーションは logging-profile 属性を使用して MANIFEST.MF ファイルで使用するロギングプロファイルを指定できます。

重要

ロギングプロファイルは管理コンソールを使用して設定できません。

5.3.2. アプリケーションにおけるロギングプロファイルの指定

アプリケーションは使用するロギングプロファイルを MANIFEST.MF ファイルに指定します。

前提条件

  1. サーバー上に設定されたロギングプロファイルの名前を認識している必要があります。使用するプロファイルの名前についてはサーバー管理者に問い合わせてください。

手順5.1 ロギングプロファイル設定をアプリケーションへ追加

  • MANIFEST.MF の編集

    アプリケーションに MANIFEST.MF ファイルがない場合は、以下の内容が含まれるファイルを作成します。NAME は必要なプロファイル名に置き換えてください。
    Manifest-Version: 1.0
          Logging-Profile: NAME
    
    アプリケーションに MANIFEST.MF ファイルがある場合は、以下の行を追加し、NAME を必要なプロファイル名に置き換えます。
    Logging-Profile: NAME
    

注記

Maven および maven-war-plugin を使用している場合、MANIFEST.MF ファイルを src/main/resources/META-INF/ に置き、次の設定を pom.xml ファイルに追加できます。
<plugin>
      <artifactId>maven-war-plugin</artifactId>
      <configuration>
        <archive>
          <manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>  
        </archive>
      </configuration>
   </plugin>
アプリケーションがデプロイされると、ログメッセージに対して指定されたロギングプロファイルの設定を使用します。

第6章 国際化と現地語化

6.1. はじめに

6.1.1. 国際化について

国際化とは、技術的な変更を行わずに異なる言語や地域に対してソフトウェアを適合させるソフトウェア設計のプロセスのことです。

6.1.2. 多言語化について

多言語化とは、特定の地域や言語に対してロケール固有のコンポーネントやテキストの翻訳を追加することで、国際化されたソフトウェアを適合させるプロセスのことです。

6.2. JBoss ロギングツール

6.2.1. 概要

6.2.1.1. JBoss ロギングツールの国際化および現地語化

JBoss ロギングツールは、ログメッセージや例外メッセージ、汎用文字列などの国際化や現地語化のサポートを提供する Java API です。JBoss ロギングツールは翻訳のメカニズムを提供するだけでなく、各ログメッセージに対して一意な識別子のサポートも提供します。
国際化されたメッセージや例外は、org.jboss.logging アノテーションが付けられたインターフェース内でメソッド定義として作成されます。JBoss ロギングがコンパイル時にインターフェースを実装するため、インターフェースを実装する必要はありません。定義すると、これらのメソッドを使用してコードでメッセージをログに記録したり、例外オブジェクトを取得することが可能です。
JBoss ロギングツールによって作成される国際化されたロギングインターフェースや例外インターフェースは、特定の言語や地域に対する翻訳が含まれる各バンドルのプロパティーファイルを作成して現地語化されます。JBoss ロギングツールはトランスレーターが編集できる各バンドル対してテンプレートプロパティーファイルを生成できます。
JBoss ロギングツールは、プロジェクトの対象翻訳プロパティーファイルごとに各バンドルの実装を作成します。必要なのはバンドルに定義されているメソッドを使用することのみで、JBoss ロギングツールは現在の地域設定に対して正しい実装が呼び出されるようにします。
メッセージ ID とプロジェクトコードは各ログメッセージの前に付けられる固有の識別子です。この識別子をドキュメントに使用すると、ログメッセージの情報を簡単に検索することができます。適切なドキュメントでは、メッセージが書かれた言語に関係なく、ログメッセージの意味を識別子より判断することが可能です。

6.2.1.2. JBoss ロギングツールのクイックスタート

JBoss ロギングツールのクイックスタート logging-tools には JBoss ロギングツールの機能を実証する単純な Maven プロジェクトが含まれています。このクイックスタートは本書のコード例で幅広く使用されています。
このクイックスタートを参照すると、本書で説明されている全機能を完全実証することができます。

6.2.1.3. メッセージロガー

メッセージロガーは国際化されたログメッセージを定義するために使用されるインターフェースです。メッセージロガーには @org.jboss.logging.MessageLogger アノテーションが付けられます。

6.2.1.4. メッセージバンドル

メッセージバンドルは、汎用の翻訳可能なメッセージや国際化されたメッセージが含まれる例外オブジェクトの定義に使用できるインターフェースです。メッセージバンドルはログメッセージの作成には使用されません。
メッセージバンドルインターフェースには @org.jboss.logging.MessageBundle アノテーションが付けられます。

6.2.1.5. 国際化されたログメッセージ

国際化されたログメッセージは、メッセージロガーのメソッドで定義を行い作成されるログメッセージです。メソッドには @LogMessage@Message アノテーションを付ける必要があり、@Message の値属性を使用してログメッセージを指定しなければなりません。国際化されたログメッセージはプロパティーファイルに翻訳を提供するとローカライズされます。
JBoss ロギングツールはコンパイル時に各翻訳に必要なロギングクラスを生成し、ランタイム時に現ロケールに対して適切なメソッドを呼び出します。

6.2.1.6. 国際化された例外

国際化された例外はメッセージバンドルで定義されたメソッドから返された例外オブジェクトです。Java Exception オブジェクトを返すメッセージバンドルメソッドにアノテーションを付けてデフォルトの例外メッセージを定義することができます。現在のロケールに一致するプロパティーファイルに翻訳があると、デフォルトメッセージは翻訳に置き換えられます。国際化された例外にもプロジェクトコードとメッセージ ID が割り当てられています。

6.2.1.7. 国際化されたメッセージ

国際化されたメッセージはメッセージバンドルに定義されるメソッドから返された文字列です。Java String オブジェクトを返すメッセージバンドルメソッドにアノテーションを付け、その文字列のデフォルトの内容 (メッセージ) を定義することができます。現在のロケールに一致するプロパティーファイルに翻訳があると、デフォルトメッセージは翻訳に置き換えられます。

6.2.1.8. 翻訳プロパティーファイル

翻訳プロパティーファイルは、1 つのロケール、国、バリアントに対する 1 つのインターフェースからのメッセージ翻訳が含まれる Java プロパティーファイルです。翻訳プロパティーファイルは、メッセージを返すクラスを生成するため JBoss ロギングツールによって使用されます。

6.2.1.9. JBoss ロギングツールのプロジェクトコード

プロジェクトコードはメッセージのグループを識別する文字列のことです。プロジェクトコードは各ログメッセージの最初に表示され、メッセージ ID の前に付けられます。プロジェクトコードは @MessageLogger アノテーションの projectCode 属性で定義されます。

6.2.1.10. JBoss ロギングツールのメッセージ ID

メッセージ ID は数字で、プロジェクトコードと組み合わせてログメッセージを一意に識別します。メッセージ IDは各ログメッセージの最初に表示され、メッセージのプロジェクトコードの後に付けられます。メッセージ ID は @Message アノテーションの id 属性で定義されます。

6.2.2. 国際化されたロガー、メッセージ、例外の作成

6.2.2.1. 国際化されたログメッセージの作成

このタスクでは、JBoss ロギングツールを使用して MessageLogger インターフェースを作成することにより、国際化されたログメッセージを作成する方法を示します。すべてのオプション機能またはログメッセージの国際化については取り上げません。
完全な例は logging-tools クイックスタートを参照してください。

前提条件

  1. Maven プロジェクトがすでに存在している必要があります。「JBoss ロギングツールの Maven 設定」を参照してください。
  2. JBoss ロギングツールに必要な Maven 設定がプロジェクトにある必要があります。

手順6.1 国際化されたログメッセージバンドルの作成

  1. メッセージロガーインターフェースの作成

    ログメッセージの定義が含まれるように Java インターフェースをプロジェクトに追加します。定義されるログメッセージに対し、インターフェースにその内容を表す名前を付けます。
    ログメッセージインターフェースの要件は次の通りです。
    • @org.jboss.logging.MessageLogger アノテーションが付けられていなければなりません。
    • org.jboss.logging.BasicLogger を拡張しなければなりません。
    • このインターフェースを実装する型付きロガーのフィールドをインターフェースが定義する必要があります。org.jboss.logging.LoggergetMessageLogger() メソッドで定義します。
    package com.company.accounts.loggers;
    
    import org.jboss.logging.BasicLogger;
    import org.jboss.logging.Logger;
    import org.jboss.logging.MessageLogger;
    
    @MessageLogger(projectCode="")
    interface AccountsLogger extends BasicLogger
    {
       AccountsLogger LOGGER = Logger.getMessageLogger(
             AccountsLogger.class,
             AccountsLogger.class.getPackage().getName() );
    }
    
  2. メソッド定義の追加

    各ログメッセージのインターフェースにメソッド定義を追加します。ログメッセージに対する各メソッドにその内容を表す名前を付けます。
    各メソッドの要件は次の通りです。
    • メソッドは void を返さなければなりません。
    • @org.jboss.logging.LogMessage アノテーションが付いていなければなりません。
    • @org.jboss.logging.Message アノテーションが付いていなければなりません。
    • @org.jboss.logging.Message の値属性にはデフォルトのログインメッセージが含まれます。翻訳がない場合にこのメッセージが使用されます。
    @LogMessage
    @Message(value = "Customer query failed, Database not available.")
    void customerQueryFailDBClosed();
    
    デフォルトのログレベルは INFO です。
  3. メソッドの呼び出し

    メッセージがロギングされなければならない場所にコードのインターフェースメソッドへの呼び出しを追加します。プロジェクトがコンパイルされる時にアノテーションプロセッサーがインターフェースの実装を作成するため、インターフェースの実装を作成する必要はありません。
    AccountsLogger.LOGGER.customerQueryFailDBClosed();
    
    カスタムのロガーは BasicLogger よりサブクラス化されるため、BasicLogger のロギングメソッド (debug()error() など) を使用することもできます。国際化されていないメッセージをログに記録するため他のロガーを作成する必要はありません。
    AccountsLogger.LOGGER.error("Invalid query syntax.");
    
結果: 現地語化できる 1 つ以上の国際化されたロガーをプロジェクトがサポートするようになります。

6.2.2.2. 国際化されたメッセージの作成と使用

このタスクでは、国際化されたメッセージの作成方法と使用方法を示します。すべてのオプション機能またはメッセージの国際化プロセスについては取り上げません。
完全な例は logging-tools クイックスタートを参照してください。

要件

  1. JBoss Enterprise Application Platform 6 のリポジトリを使用する作業用の Maven プロジェクトが存在しなければなりません。「Maven 設定を使用した JBoss Enterprise Application Platform の Maven リポジトリーの設定」 を参照してください。
  2. JBoss ロギングツールの必要な Maven 設定が追加されている必要があります。「JBoss ロギングツールの Maven 設定」 を参照してください。

手順6.2 国際化されたメッセージの作成と使用

  1. 例外のインターフェースの作成

    JBoss ロギングツールはインターフェースで国際化されたメッセージを定義します。定義されるメッセージに対し、インターフェースにその内容を表す名前を付けます。
    インターフェースの要件は次の通りです。
    • パブリックとして宣言される必要があります。
    • @org.jboss.logging.MessageBundle アノテーションが付けられていなければなりません。
    • インターフェースと同じ型のメッセージバンドルであるフィールドをインターフェースが定義する必要があります。
    @MessageBundle(projectCode="")
    public interface GreetingMessageBundle 
    {
       GreetingMessageBundle MESSAGES = Messages.getBundle(GreetingMessageBundle.class);
    }
    
  2. メソッド定義の追加

    各メッセージのインターフェースにメソッド定義を追加します。メッセージに対する各メソッドにその内容を表す名前を付けます。
    各メソッドの要件は次の通りです。
    • String のオブジェクトを返す必要があります。
    • @org.jboss.logging.Message アノテーションが付いていなければなりません。
    • デフォルトメッセージに @org.jboss.logging.Message の値属性が設定されていなければなりません。翻訳がない場合にこのメッセージが使用されます。
    @Message(value = "Hello world.")
       String helloworldString();
    
  3. 呼び出しメソッド

    メッセージを取得する必要がある場所でアプリケーションのインターフェースメソッドを呼び出します。
    System.console.out.println(helloworldString());
    
結果: 現地語化できる国際化されたメッセージをプロジェクトがサポートするようになります。

6.2.2.3. 国際化された例外の作成

このタスクでは、国際化された例外の作成方法と使用方法を示します。すべてのオプション機能またはこれらの例外の国際化プロセスについては取り上げません。
完全な例は logging-tools クイックスタートを参照してください。
このタスクでは、 JBoss Developer Studio または Maven に構築されたソフトウェアプロジェクトが既に存在し、このプロジェクトに国際化された例外を追加することを前提としています。

手順6.3 国際化された例外の作成と使用

  1. JBoss ロギングツール設定の追加

    JBoss ロギングツールをサポートするために必要なプロジェクト設定を追加します。「JBoss ロギングツールの Maven 設定」を参照してください。
  2. 例外のインターフェースの作成

    JBoss ロギングツールはインターフェースで国際化された例外を定義します。定義される例外に対し、インターフェースにその内容を表す名前を付けます。
    インターフェースの要件は次の通りです。
    • public として宣言される必要があります。
    • @org.jboss.logging.MessageBundle アノテーションが付けられていなければなりません。
    • インターフェースと同じ型のメッセージバンドルであるフィールドをインターフェースが定義する必要があります。
    @MessageBundle(projectCode="")
    public interface ExceptionBundle 
    {
       ExceptionBundle EXCEPTIONS = Messages.getBundle(ExceptionBundle.class);
    }
    
    
  3. メソッド定義の追加

    各例外のインターフェースにメソッド定義を追加します。例外に対する各メソッドにその内容を表す名前を付けます。
    各メソッドの要件は次の通りです。
    • Exception のオブジェクトまたは Exception のサブタイプを返す必要があります。
    • @org.jboss.logging.Message アノテーションが付いていなければなりません。
    • デフォルトの例外メッセージに @org.jboss.logging.Message の値属性が設定されていなければなりません。翻訳がない場合にこのメッセージが使用されます。
    • メッセージ文字列の他にパラメータを必要とするコンストラクターが返された例外にある場合、@Param アノテーションを使用してこれらのパラメーターをメソッド定義に提供しなければなりません。パラメーターはコンストラクターと同じ型で同じ順番でなければなりません。
    @Message(value = "The config file could not be opened.")
    IOException configFileAccessError();
    
    @Message(id = 13230, value = "Date string '%s' was invalid.")
    ParseException dateWasInvalid(String dateString, @Param int errorOffset);
    
  4. 呼び出しメソッド

    例外を取得する必要がある場所でコードのインターフェースメソッドを呼び出します。メソッドは例外をスローしませんが、スローできる例外オブジェクトを返します。
    try 
    {
       propsInFile=new File(configname);
       props.load(new FileInputStream(propsInFile));
    }
    catch(IOException ioex) //in case props file does not exist
    {
       throw ExceptionBundle.EXCEPTIONS.configFileAccessError(); 
    }
    
結果: 現地語化できる国際化された例外をプロジェクトがサポートするようになります。

6.2.3. 国際化されたロガー、メッセージ、例外の現地語化

6.2.3.1. Maven で新しい翻訳プロパティーファイルを生成する

Maven で構築されたプロジェクトは、各メッセージロガーに対する空の翻訳プロパティーファイルと含まれるメッセージバンドルを生成できます。これらのファイルは新しい翻訳ファイルとして使用することができます。
新しい翻訳プロパティーファイルを生成するため Maven プロジェクトを設定する手順は次の通りです。
完全な例は logging-tools クイックスタートを参照してください。

前提条件

  1. 作業用の Maven プロジェクトが既に存在している必要があります。
  2. JBoss ロギングツールに対してプロジェクトが設定されていなければなりません。
  3. 国際化されたログメッセージや例外を定義する 1 つ以上のインターフェースがプロジェクトに含まれていなければなりません。

手順6.4 Maven で新しい翻訳プロパティーファイルを生成する

  1. Maven 設定の追加

    -AgenereatedTranslationFilePath コンパイラー引数を Maven コンパイラープラグイン設定に追加し、新しいファイルが作成されるパスを割り当てます。
    <plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-compiler-plugin</artifactId>
       <version>2.3.2</version>
       <configuration> 
          <source>1.6</source>
          <target>1.6</target>             
          <compilerArgument>
          -AgeneratedTranslationFilesPath=${project.basedir}/target/generated-translation-files
          </compilerArgument>
          <showDeprecation>true</showDeprecation>
       </configuration>
    </plugin>
    
    上記の設定は Maven プロジェクトの target/generated-translation-files ディレクトリに新しいファイルを作成します。
  2. プロジェクトの構築

    Maven を使用したプロジェクトの構築
    [Localhost]$ mvn compile
@MessageBundle または @MessageLogger アノテーションが付けられたインターフェースごとに 1 つのプロパティーファイルが作成されます。各インターフェースが宣言される Java パッケージに対応するサブディレクトリに新しいファイルが作成されます。
各ファイルは、InterfaceName.i18n_locale_COUNTRY_VARIANT.properties という構文を使用して名前が付けられます。InterfaceName はこのファイルが生成されたインターフェースの名前になります。
新しい翻訳の基盤としてこれらのファイルをプロジェクトへコピーすることができます。

6.2.3.2. 国際化されたロガーや例外、メッセージの翻訳

JBoss ロギングツールを使用してインターフェースに定義されたロギングメッセージや例外メッセージの翻訳をプロパティーファイルに提供することが可能です。
次の手順は翻訳プロパティーファイルの作成方法と使用方法を表しています。この手順では、国際化された例外やログメッセージに対して 1 つ以上のインターフェースが定義されているプロジェクトが存在することを前提にしています。
完全な例は logging-tools クイックスタートを参照してください。

要件

  1. 作業用の Maven プロジェクトが既に存在している必要があります。
  2. JBoss ロギングツールに対してプロジェクトが設定されていなければなりません。
  3. 国際化されたログメッセージや例外を定義する 1 つ以上のインターフェースがプロジェクトに含まれていなければなりません。
  4. テンプレート翻訳プロパティーファイルを生成するようプロジェクトが設定されている必要があります。

手順6.5 国際化されたロガーや例外、メッセージの翻訳

  1. テンプレートプロパティーファイルの生成

    mvn compile コマンドを実行し、テンプレート翻訳プロパティーファイルを作成します。
  2. プロジェクトへのテンプレートファイルの追加

    翻訳したいインターフェースのテンプレートを、テンプレートが作成されたディレクトリからプロジェクトの src/main/resources ディレクトリへコピーします。プロパティーファイルは翻訳するインターフェースと同じパッケージに存在しなければなりません。
  3. コピーしたテンプレートファイルの名前変更

    GreeterLogger.i18n_fr_FR.properties のように、含まれる翻訳に応じてテンプレートファイルのコピーの名前を変更します。
  4. テンプレートの内容の翻訳

    新しい翻訳プロパティーファイルを編集し、適切な翻訳が含まれるようにします。
    # Level: Logger.Level.INFO
    # Message: Hello message sent.
    logHelloMessageSent=Bonjour message envoyé.
    
    実行された各バンドルの各翻訳に対して手順の 2、3、4 を繰り返します。
結果: 1 つ以上のメッセージバンドルやロガーバンドルに対する翻訳がプロジェクトに含まれるようになります。プロジェクトを構築すると、提供された翻訳が含まれるログメッセージに適切なクラスが生成されます。JBoss ロギングツールは、アプリケーションサーバーの現在のロケールに合わせて適切なクラスを自動的に使用するため、明示的にメソッドを呼び出したり、特定言語に対してパラメーターを提供したりする必要はありません。
生成されたクラスのソースコードは target/generated-sources/annotations/ で確認できます。

6.2.4. 国際化されたログメッセージのカスタマイズ

6.2.4.1. ログメッセージへのメッセージ IDとプロジェクトコードの追加

このタスクではメッセージ ID とプロジェクトコードを国際化されたログメッセージへ追加する方法を説明します。ログメッセージがログで表示されるようにするには、プロジェクトコードとメッセージ ID の両方が必要となります。メッセージにプロジェクトコードとメッセージ ID の両方がない場合、どちらも表示されません。
完全な例は logging-tools クイックスタートを参照してください。

要件

  1. 国際化されたログメッセージを持つプロジェクトが存在する必要があります。「国際化されたログメッセージの作成」を参照してください。
  2. 使用するプロジェクトコードを認識する必要があります。プロジェクトコードを 1 つ使用することも、各インターフェースに異なるコードを定義することも可能です。

手順6.6 メッセージ ID とプロジェクトコードをログメッセージに追加する

  1. インターフェースのプロジェクトコードを指定します。

    カスタムのロガーインターフェースに付けられる @MessageLogger アノテーションの projectCode 属性を使用してプロジェクトコードを指定します。インターフェースに定義されるすべてのメッセージがこのプロジェクトコードを使用します。
    @MessageLogger(projectCode="ACCNTS")
    interface AccountsLogger extends BasicLogger
    {
    
    }
    
  2. メッセージ ID の指定

    メッセージを定義するメソッドに付けられる @Message アノテーションの id 属性を使用して各メッセージに対してメッセージ ID を指定します。
    @LogMessage
    @Message(id=43, value = "Customer query failed, Database not available.")  void customerQueryFailDBClosed();
    
メッセージ ID とプロジェクトコードの両方が関連付けられたログメッセージは、メッセージ IDとプロジェクトコードをログに記録されたメッセージの前に付けます。
10:55:50,638 INFO  [com.company.accounts.ejb] (MSC service thread 1-4) ACCNTS000043: Customer query failed, Database not available.

6.2.4.2. メッセージのログレベル設定

JBoss ロギングツールのインターフェースによって定義されるメッセージのログレベルのデフォルトは INFO です。ロギングメソッドに付けられた @LogMessage アノテーションの level 属性を用いて異なるログレベルを指定することが可能です。

手順6.7 メッセージのログレベルの指定

  1. level 属性の指定

    ログメッセージメソッド定義の @LogMessage アノテーションに level 属性を追加します。
  2. ログレベルの割り当て

    このメッセージに対するログレベルの値を level 属性に割り当てます。level に有効な値は org.jboss.logging.Logger.Level に定義される 6 つの列挙定数である DEBUGERRORFATALINFOTRACEWARN になります。
    Import org.jboss.logging.Logger.Level;
    
    @LogMessage(level=Level.ERROR)
    @Message(value = "Customer query failed, Database not available.")
    void customerQueryFailDBClosed();
    
    
上記の例のロギングメソッドを呼び出すと、 ERROR レベルのログメッセージが作成されます。
10:55:50,638 ERROR  [com.company.app.Main] (MSC service thread 1-4) 
 Customer query failed, Database not available.

6.2.4.3. パラメーターによるログメッセージのカスタマイズ

カスタムのログインメソッドはパラメーターを定義できます。これらのパラメーターを使用してログメッセージに表示される追加情報を渡すことが可能です。ログメッセージでパラメーターが表示される場所は、明示的なインデクシングか通常のインデクシングを使用してメッセージ自体に指定されます。

手順6.8 パラメーターによるログメッセージのカスタマイズ

  1. メソッド定義へパラメーターを追加する

    すべての型のパラメーターをメソッド定義に追加することができます。型に関係なくパラメーターの String 表現がメッセージに表示されます。
  2. ログメッセージへパラメーター参照を追加する

    参照は明示的なインデックスか通常のインデックスを使用できます。
    • 通常のインデックスを使用するには、各パラメーターを表示したいメッセージ文字列に %s 文字を挿入します。%s の最初のインスタンスにより最初のパラメーターが挿入され、2 番目のインスタンスにより 2 番目のパラメーターが挿入されます。
    • 明示的なインデックスを使用するには、文字 %{#} をメッセージに挿入します。# は表示したいパラメーターの数に置き換えます。

重要

明示的なインデックスを使用すると、メッセージのパラメーター参照の順番がメソッドで定義される順番とは異なるようになります。これは、異なるパラメーターの順番が必要な翻訳メッセージで重要になります。
指定されたメッセージでは、パラメーターの数とパラメーターへの参照の数が同じでなければなりません。同じでないとコードがコンパイルしません。@Cause アノテーションが付けられたパラメーターはパラメーターの数には含まれません。

例6.1 通常のインデックスを使用したメッセージパラメーター

@LogMessage(level=Logger.Level.DEBUG)
@Message(id=2, value="Customer query failed, customerid:%s, user:%s")
void customerLookupFailed(Long customerid, String username);

例6.2 明示的なインデックスを使用したメッセージパラメーター

@LogMessage(level=Logger.Level.DEBUG)
@Message(id=2, value="Customer query failed, customerid:%{1}, user:%{2}")
void customerLookupFailed(Long customerid, String username);

6.2.4.4. ログメッセージの原因として例外を指定する

JBoss ログインツールでは、カスタムログインメソッドのパラメーターの 1 つをメッセージの原因として定義することができます。定義するには、このパラメーターを Throwable 型とするか、サブクラスのいずれかに @Cause アノテーションを付ける必要があります。このパラメーターは、他のパラメーターのようにログメッセージで参照することはできず、ログメッセージの後に表示されます。
次の手順は、@Cause パラメーターを使用して「原因となる」例外を示し、ロギングメソッドを更新する方法を表しています。この機能に追加したい国際化されたロギングメッセージが既に作成されていることを前提とします。

手順6.9 ログメッセージの原因として例外を指定する

  1. パラメーターの追加

    Throwable 型のパラメーターまたはサブクラスをメソッドに追加します。
    @Message(id=404, value="Loading configuration failed. Config file:%s")
    void loadConfigFailed(Exception ex, File file);
    
  2. アノテーションの追加

    パラメーターに @Cause アノテーションを追加します。
    import org.jboss.logging.Cause
    
    @Message(value = "Loading configuration failed. Config file: %s")
    void loadConfigFailed(@Cause Exception ex, File file);
    
    
  3. メソッドの呼び出し

    コードでメソッドが呼び出されると、正しい型のオブジェクトが渡され、ログメッセージの後に表示されます。
    try 
    {
       confFile=new File(filename);
       props.load(new FileInputStream(confFile));
    }
    catch(Exception ex) //in case properties file cannot be read
    {
         ConfigLogger.LOGGER.loadConfigFailed(ex, filename);
    }
    
    
    コードが FileNotFoundException 型の例外をスローした場合、上記コード例の出力は次のようになります。
    10:50:14,675 INFO [com.company.app.Main] (MSC service thread 1-3) Loading configuration failed. Config file: customised.properties
    java.io.FileNotFoundException: customised.properties (No such file or directory)
       at java.io.FileInputStream.open(Native Method)
       at java.io.FileInputStream.<init>(FileInputStream.java:120)
       at com.company.app.demo.Main.openCustomProperties(Main.java:70)
       at com.company.app.Main.go(Main.java:53)
       at com.company.app.Main.main(Main.java:43)
    

6.2.5. 国際化された例外のカスタマイズ

6.2.5.1. メッセージ ID とプロジェクトコードを例外メッセージに追加する

以下の手順は、JBoss ロギングツールを使用して作成された国際化済み例外メッセージにメッセージ ID とプロジェクトコードを追加するために必要な作業を示します。
メッセージ ID とプロジェクトコードは国際化された例外によって表示された各メッセージの前に付けられる固有の識別子です。これらの識別コードによってアプリケーションに対する全例外メッセージの参照を作成できるため、理解できない言語で書かれた例外メッセージの意味をルックアップすることが可能です。

要件

  1. 国際化された例外を持つプロジェクトが存在する必要があります。「国際化された例外の作成」を参照してください。
  2. 使用するプロジェクトコードを認識する必要があります。プロジェクトコードを 1 つ使用することも、各インターフェースに異なるコードを定義することも可能です。

手順6.10 メッセージ ID とプロジェクトコードを例外メッセージに追加する

  1. プロジェクトコードの指定

    例外バンドルインターフェースに付けられる @MessageBundle アノテーションの projectCode 属性を使用してプロジェクトコードを指定します。インターフェースに定義されるすべてのメッセージがこのプロジェクトコードを使用します。
    @MessageBundle(projectCode="ACCTS")
    interface ExceptionBundle
    {
       ExceptionBundle EXCEPTIONS = Messages.getBundle(ExceptionBundle.class);
    }
    
  2. メッセージ ID の指定

    例外を定義するメソッドに付けられる @Message アノテーションの id 属性を使用して各例外に対してメッセージ ID を指定します。
    @Message(id=143, value = "The config file could not be opened.")
    IOException configFileAccessError();
    

重要

プロジェクトコードとメッセージ ID を両方持つメッセージでは、メッセージの前にプロジェクトコードとメッセージ ID が表示されます。プロジェクトコードとメッセージ ID の両方がない場合は、どちらも表示されません。

例6.3 国際化された例外の作成

この例外バンドルインターフェースは、プロジェクトコード ACCTS と ID が 143 の例外メソッドを 1 つ持っています。
@MessageBundle(projectCode="ACCTS")
interface ExceptionBundle
{
    ExceptionBundle EXCEPTIONS = Messages.getBundle(ExceptionBundle.class);

    @Message(id=143, value = "The config file could not be opened.")
    IOException configFileAccessError();
}
次のコードを使用して例外オブジェクトを取得したりスローしたりすることが可能です。
throw ExceptionBundle.EXCEPTIONS.configFileAccessError();
これにより、次のような例外メッセージが表示されます。
Exception in thread "main" java.io.IOException: ACCTS000143: The config file could not be opened.
at com.company.accounts.Main.openCustomProperties(Main.java:78)
at com.company.accounts.Main.go(Main.java:53)
at com.company.accounts.Main.main(Main.java:43)

6.2.5.2. パラメーターによる例外メッセージのカスタマイズ

例外を定義する例外バンドルメソッドは、パラメーターを指定して例外メッセージに表示される追加情報を渡すことが可能です。例外メッセージでパラメーターが表示される場所は、明示的なインデクシングか通常のインデクシングを使用してメッセージ自体に指定されます。
以下の手順では、メソッドパラメーターを使用してメソッド例外をカスタマイズするために必要な作業について説明します。

手順6.11 パラメーターによる例外メッセージのカスタマイズ

  1. メソッド定義へパラメーターを追加する

    すべての型のパラメーターをメソッド定義に追加することができます。型に関係なくパラメーターの String 表現がメッセージに表示されます。
  2. 例外メッセージへパラメーター参照を追加する

    参照は明示的なインデックスか通常のインデックスを使用できます。
    • 通常のインデックスを使用するには、各パラメーターを表示したいメッセージ文字列に %s 文字を挿入します。%s の最初のインスタンスにより最初のパラメーターが挿入され、2 番目のインスタンスにより 2 番目のパラメーターが挿入されます。
    • 明示的なインデックスを使用するには、文字 %{#} をメッセージに挿入します。# は表示したいパラメーターの数に置き換えます。
    明示的なインデックスを使用すると、メッセージのパラメーター参照の順番がメソッドで定義される順番とは異なるようになります。これは、異なるパラメーターの順番が必要な翻訳メッセージで重要になります。

重要

指定されたメッセージでは、パラメーターの数とパラメーターへの参照の数が同じでなければなりません。同じでないとコードがコンパイルしません。@Cause アノテーションが付けられたパラメーターはパラメーターの数には含まれません。

例6.4 通常のインデックスを使用

@Message(id=143, value = "The config file %s could not be opened.")
IOException configFileAccessError(File config);

例6.5 明示的なインデックスを使用

@Message(id=143, value = "The config file %{1} could not be opened.")
IOException configFileAccessError(File config);

6.2.5.3. 別の例外の原因として 1 つの例外を指定する

例外バンドルメソッドより返された例外に対し、他の例外を基盤の原因として指定することができます。指定するには、パラメーターをメソッドに追加し、パラメーターに @Cause アノテーションを付けます。このパラメーターを使用して原因となる例外を渡します。このパラメーターを例外メッセージで参照することはできません。
次の手順は、@Cause パラメーターを使用して原因となる例外を示し、例外バンドルよりメソッドを更新する方法を表しています。この機能に追加したい国際化された例外バンドルが既に作成されていることを前提とします。

手順6.12 別の例外の原因として 1 つの例外を指定する

  1. パラメーターの追加

    Throwable 型のパラメーターまたはサブクラスをメソッドに追加します。
    @Message(id=328, value = "Error calculating: %s.")
    ArithmeticException calculationError(Throwable cause, String msg);
    
  2. アノテーションの追加

    パラメーターに @Cause アノテーションを追加します。
    import org.jboss.logging.Cause
    
    @Message(id=328, value = "Error calculating: %s.")
    ArithmeticException calculationError(@Cause Throwable cause, String msg);
    
  3. メソッドの呼び出し

    例外オブジェクトを取得するためインターフェースメソッドを呼び出します。キャッチした例外を原因として使用し、キャッチブロックより新しい例外をスローするのが最も一般的なユースケースになります。
    try 
    {
       ...
    }
    catch(Exception ex)
    {
       throw ExceptionBundle.EXCEPTIONS.calculationError(
                                        ex, "calculating payment due per day");
    }
    

例6.6 別の例外の原因として 1 つの例外を指定する

この例外バンドルは、ArithmeticException 型の例外を返す単一のメソッドを定義します。
@MessageBundle(projectCode = "TPS")
interface CalcExceptionBundle 
{
	CalcExceptionBundle EXCEPTIONS = Messages.getBundle(CalcExceptionBundle.class);

    @Message(id=328, value = "Error calculating: %s.")
    ArithmeticException calcError(@Cause Throwable cause, String value);

}
このコードスニペットは、整数のゼロ除算を実行しようとすると例外をスローする演算を行います。最初の例外を原因として使用して例外がキャッチされ、新しい例外が作成されます。
int totalDue = 5;
int daysToPay = 0;
int amountPerDay;

try
{
   amountPerDay = totalDue/daysToPay;
}
catch (Exception ex)
{
   throw CalcExceptionBundle.EXCEPTIONS.calcError(ex, "payments per day");
}
例外メッセージは次のようになります。
Exception in thread "main" java.lang.ArithmeticException: TPS000328: Error calculating: payments per day.
	at com.company.accounts.Main.go(Main.java:58)
	at com.company.accounts.Main.main(Main.java:43)
Caused by: java.lang.ArithmeticException: / by zero
	at com.company.accounts.Main.go(Main.java:54)
	... 1 more

6.2.6. 参考資料

6.2.6.1. JBoss ロギングツールの Maven 設定

国際化に JBoss ロギングツールを使用する Maven プロジェクトを構築するには、pom.xml ファイルのプロジェクトの設定を次のように変更する必要があります。
完全な pom.xml ファイルの例については、logging-tools クイックスタートを参照してください。
  1. プロジェクトに対して JBoss Maven リポジトリが有効になっている必要があります。「Maven 設定を使用した JBoss Enterprise Application Platform の Maven リポジトリーの設定」 を参照してください。
  2. jboss-loggingjboss-logging-processor の Maven 依存関係を追加する必要があります。これらの依存関係は両方 JBoss Enterprise Application Platform 6 で使用可能であるため、各依存関係の scope 要素を次のように provided に設定できます。
    <dependency>
       <groupId>org.jboss.logging</groupId>
       <artifactId>jboss-logging-processor</artifactId>
       <version>1.0.0.Final</version>
       <scope>provided</scope>
    </dependency>
    
    <dependency>
       <groupId>org.jboss.logging</groupId>
       <artifactId>jboss-logging</artifactId>
       <version>3.1.0.GA</version>
       <scope>provided</scope>
    </dependency>
    
  3. maven-compiler-plugin のバージョンは 2.2 以上である必要があり、1.6 のターゲットソースおよび生成されたソースに対して設定する必要があります。
    <plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-compiler-plugin</artifactId>
       <version>2.3.2</version>
       <configuration>
          <source>1.6</source>
          <target>1.6</target>
       </configuration>
    </plugin>
    

6.2.6.2. 翻訳プロパティーファイルの形式

JBoss ロギングツールでのメッセージの翻訳に使用されるプロパティーファイルは標準的な Java プロパティーファイルです。このファイルの形式は、http://docs.oracle.com/javase/6/docs/api/java/util/Properties.htmljava.util.Properties クラスのドキュメントに記載されている単純な行指向の key=value ペア形式です。
ファイル名の形式は次のようになります。
InterfaceName.i18n_locale_COUNTRY_VARIANT.properties 
  • InterfaceName は翻訳が適用されるインターフェースの名前です。
  • localeCOUNTRY、および VARIANT は翻訳が適用される地域設定を識別します。
  • locale は ISO-639 言語コードを使用して言語を指定し、 COUNTRY は ISO-3166 国名コードを使用して国を指定します。COUNTRY は任意です。
  • VARIANT は特定のオペレーティングシステムやブラウザーのみに適用される翻訳を識別するために使用される任意の識別子です。
翻訳ファイルに含まれるプロパティーは翻訳されたインターフェースからのメソッド名です。プロパティに割り当てられた値が翻訳になります。メソッドがオーバロードされると、ドットと名前へのパラメーター数が付加されます。翻訳のメソッドは異なるパラメーター数が提供される場合のみオーバーロードされます。

例6.7 翻訳プロパティーファイルの例

ファイル名: GreeterService.i18n_fr_FR_POSIX.properties
# Level: Logger.Level.INFO
# Message: Hello message sent.
logHelloMessageSent=Bonjour message envoyé.

6.2.6.3. JBoss ロギングツールのアノテーションに関する参考資料

JBoss ロギングでは、ログメッセージや文字列、例外の国際化や現地語化に使用する以下のアノテーションが定義されています。

表6.1 JBoss ロギングツールのアノテーション

アノテーション ターゲット 説明 属性
@MessageBundle インターフェース
インターフェースをメッセージバンドルとして定義します。
projectCode
@MessageLogger インターフェース
インターフェースをメッセージロガーとして定義します。
projectCode
@Message メソッド
メッセージバンドルとメッセージロガーで使用できます。メッセージロガーでは、多言語化されたロガーとしてメソッドを定義します。メッセージバンドルでは、多言語化された文字列または例外オブジェクトを返すメソッドとして定義します。
valueid
@LogMessage メソッド
メッセージロガーのメソッドをロギングメソッドとして定義します。
level (デフォルトは INFO)
@Cause パラメーター
ログメッセージまたは他の例外が発生したときに例外を渡すパラメーターとして定義します。
-
@Param パラメーター
例外のコンストラクターへ渡されるパラメーターとして定義します。
-

第7章 Enterprise JavaBeans

7.1. はじめに

7.1.1. Enterprise JavaBeans の概要

Enterprise JavaBeans (EJB) 3.1 は、Enterprise Bean と呼ばれるサーバーサイドコンポーネントを使用してセキュアでポータブルな分散 Java EE アプリケーションを開発するための API です。Enterprise Bean は、再利用を促進する分離された方法でアプリケーションのビジネスロジックを実装します。Enterprise JavaBeans 3.1 は、Java EE 仕様 JSR-318 としてドキュメント化されています。
JBoss Enterprise Application Platform 6 では、Enterprise JavaBeans 3.1 仕様を使用してビルドされたアプリケーションが完全にサポートされます。EJB コンテナは JBoss EJB3 コミュニティープロジェクト (http://www.jboss.org/ejb3) を使用して実装されます。

7.1.2. EJB 3.1 機能セット

以下の機能が EJB 3.1 でサポートされています。
  • セッション Bean
  • メッセージ駆動型 Bean
  • ノーインターフェースビュー (No-interface view)
  • ローカルインターフェース
  • リモートインターフェース
  • JAX-WS web サービス
  • JAX-RS web サービス
  • タイマーサービス
  • 非同期呼び出し
  • インターセプター
  • RMI/IIOP 相互運用性
  • トランザクションサポート
  • セキュリティ
  • 埋め込み API
以下の機能は EJB 3.1 で対応していますが、「プルーニング」用として提案されています。そのため、これらの機能は Java EE 7 ではオプションとなる可能性があります。
  • エンティティー Bean (コンテナおよび Bean 管理の永続性)
  • EJB 2.1 エンティティー Bean のクライアントビュー
  • EJB クエリ言語 (EJB QL)
  • JAX-RPC ベースの Web サービス (エンドポイントおよびクライアントビュー)

7.1.3. EJB 3.1 Lite

EJB Lite は EJB 3.1 仕様のサブセットであり、Java EE 6 Web プロファイルの一部として完全な EJB 3.1 仕様の単純なバージョンを提供します。
EJB Lite により、エンタープライズを使用すると、エンタープライズ Bean を使用した Web アプリケーションでのビジネスロジックの実装が簡略化されます。
  1. Web アプリケーションに適切な機能のみをサポートします。
  2. EJB を同じ WAR ファイルで Web アプリケーションとしてデプロイできます。

7.1.4. EJB 3.1 Lite の機能

EJB Lite には、次の機能があります。
  • ステートレス、ステートフル、およびシングルトンセッション Bean
  • ローカルビジネスインターフェースおよび「インターフェースなし」Bean
  • インターセプター
  • コンテナ管理および Bean 管理トランザクション
  • 宣言およびプログラミング可能なセキュリティ
  • 埋め込み API
EJB 3.1 の次の機能は含まれていません。
  • リモートインターフェース
  • RMI と IIOP の相互運用性
  • JAX-WS Web サービスエンドポイント
  • EJB タイマーサービス
  • 非同期セッション Bean 呼び出し
  • メッセージ駆動 Bean

7.1.5. エンタープライズ Bean

Enterprise JavaBeans (EJB) 3.1 仕様、JSR-318 に定義されているように、エンタープライズ Bean はサーバー側のアプリケーションコンポーネントのことです。エンタープライズ Bean は疎結合方式でアプリケーションのビジネスロジックを実装し再利用ができるように設計されています。
エンタープライズ Bean は Java クラスとして記述され、適切な EJB アノテーションが付けられます。アプリケーションサーバーに独自のアーカイブ (JAR ファイル) でデプロイするか、 Java EE アプリケーションの一部としてデプロイすることが可能です。アプリケーションサーバーは各エンタープライズ Bean のライフサイクルを管理し、セキュリティーやトランザクション、同時処理制御などのサービスを提供します。
エンタープライズ Bean はビジネスインターフェースをいくつでも定義することができます。ビジネスインターフェースは、クライアントが使用できる Bean のメソッドに対して優れた制御機能を提供し、リモート JVM で実行されているクライアントへのアクセスも許可します。
エンタープライズ Bean には、セッション Bean、メッセージ駆動型 Bean、およびエンティティー Bean の 3 種類があります。

重要

エンティティー Bean は EJB 3.1 で廃止されました。Red Hat は代わりに JPA エンティティーの使用を推奨します。Red Hat はレガシーシステムで後方互換性に対応する場合のみエンティティー Bean の使用を推奨します。

7.1.6. エンタープライズ Bean の記述について

エンタープライズ Bean はサーバー側のコンポーネントで、特定のアプリケーションクライアントから分離された状態でビジネスロジックをカプセル化するためのものです。エンタープライズ Bean 内にビジネスロジックを実装すると、これらの Bean を複数のアプリケーションで再使用することができます。
エンタープライズ Bean はアノテーション付けされた Java クラスとして記述されます。特定の EJB インターフェースを実装する必要や、エンタープライズ Bean として考慮される EJB スーパークラスからサブクラス化される必要はありません。
EJB 3.1 エンタープライズ Bean は Java アーカイブ (JAR) ファイルにパッケージ化されデプロイされます。エンタープライズ Bean の JAR ファイルは、アプリケーションサーバーへデプロイしたり、エンタープライズアーカイブ (EAR) ファイルに含まれるようにしてアプリケーションと共にデプロイすることが可能です。また、Bean が EJB 3.1 Lite 仕様に準拠する場合は、エンタープライズ Bean を Web アプリケーションと共に WAR ファイルにデプロイすることも可能です。

7.1.7. セッション Bean ビジネスインターフェース

7.1.7.1. エンタープライズ Bean のビジネスインターフェース

EJB ビジネスインターフェースは Bean 開発者によって書かれた Java インターフェースで、クライアントが使用できるセッション Bean のパブリックメソッドの宣言を提供します。セッション Bean は ゼロ (「インターフェースのない」Bean) を含む、あらゆる数のインターフェースを実装することが可能です。
ビジネスインターフェースをローカルインターフェースまたはリモートインターフェースとして宣言することができますが、両方を宣言することはできません。

7.1.7.2. EJB ローカルビジネスインターフェース

EJB ローカルビジネスインターフェースは、Bean とクライアントは同じ JVM にある場合に利用可能なメソッドを宣言します。セッション Bean がローカルのビジネスインターフェースを実装する場合、そのインターフェースで宣言されたメソッドのみがクライアントで利用できます。

7.1.7.3. EJB リモートビジネスインターフェース

EJB リモートビジネスインターフェースは、リモートクライアントで利用可能なメソッドを宣言します。リモートインターフェースを実装するセッション Bean へのリモートアクセスは、自動的に EJB コンテナにより提供されます。
リモートクライアントとは別の JVM で実行するクライアントのことで、別のアプリケーションサーバーにデプロイされている Web アプリケーション、サービス、エンタープライズ Bean、デスクトップなどが含まれます。
ローカルクライアントは、リモートのビジネスインターフェースが公開するメソッドへアクセス可能です。これは、リモートクライアントと同じメソッドを使い実行され、リモートリクエストを出した時に付随する通常のオーバーヘッドがすべて発生します。

7.1.7.4. EJB のインタフェース以外の Bean

ビジネスインターフェースを実装しないセッション Bean はインターフェース以外の Bean と呼ばれます。インターフェース以外の Bean の公開メソッドはすべてローカルのクライアントにアクセスできます。
ビジネスインターフェースを実装するセッション Bean は、"non-interface" ビューを表示するために記述可能です。

7.2. エンタープライズ Bean プロジェクトの作成

7.2.1. JBoss Developer Studio を使用した EJB アーカイブプロジェクトの作成

このタスクでは、JBoss Developer Studio に Enterprise JavaBeans (EJB) プロジェクトを作成する方法を説明します。

要件

  • JBoss Enterprise Application Platform 6 のサーバーとサーバーランタイムが設定されている必要があります。

手順7.1 JBoss Developer Studio での EJB プロジェクトの作成

  1. 新規プロジェクトの作成

    新規 EJB プロジェクト ウィザードを開くために、ファイル (File) メニューで 新規 (New) を選択し、次に EJB プロジェクト (EJB Project) を選択します。
    New EJB Project ウィザード

    図7.1 New EJB Project ウィザード

  2. 詳細の指定

    次の詳細を入力します。
    • プロジェクト名
      JBoss Developer Studio で表示されるプロジェクト名ですが、デプロイされた JAR ファイルのデフォルトのファイル名にもなります。
    • プロジェクトの場所
      プロジェクトのファイルが保存されるディレクトリです。現在のワークスペースのディレクトリがデフォルトになります。
    • ターゲットランタイム
      プロジェクトに使用されるサーバーランタイムです。デプロイするサーバーによって使用される JBoss Enterprise Application Platform 6 のランタイムと同様に設定される必要があります。
    • EJB モジュールバージョン。エンタープライズ Bean が準拠する EJB 仕様のバージョンになります。Red Hat は 3.1 の使用を推奨します。
    • これでプロジェクトのサポート対象機能を調整できるようになります。選択したランタイムにデフォルト設定を使用します。
    [Next] をクリックして作業を継続します。
  3. Java 構築設定

    この画面では、Java ソースファイルが格納されるディレクトリや構築された出力が置かれるディレクトリをカスタマイズすることが可能です。
    この設定は変更せずに [Next] をクリックします。
  4. EJB モジュール設定

    デプロイメント記述子が必要な場合は [Generate ejb-jar.xml deployment descriptor] チェックボックスにチェックマークを付けます。EJB 3.1 ではデプロイメント記述子は任意で、必要な場合は後で追加することが可能です。
    [Finish] をクリックするとプロジェクトが作成され、Project Explorer に表示されます。
    Project Explorer の新規作成された EJB プロジェクト

    図7.2 Project Explorer の新規作成された EJB プロジェクト

  5. デプロイメントに対して構築アーティファクトをサーバーに追加する

    サーバータブにて、構築アーティファクトをデプロイしたいサーバーを右クリックし、 [Add and Remove] ダイアログを開きます。[Add and Remove] を選択します。
    [Available] カラムよりデプロイするリソースを選択し、 [Add] ボタンをクリックします。リソースが [Configured] カラムに移動します。[Finish] をクリックしてダイアログを閉じます。
    ダイアログの追加と削除

    図7.3 ダイアログの追加と削除

結果

ビルドし、指定のサーバーにデプロイできる EJB プロジェクトが JBoss Developer Studio で作成されます。

プロジェクトにエンタープライズ Bean が追加されないと、JBoss Developer Studio は「An EJB module must contain one or more enterprise beans」という警告を表示します。プロジェクトにエンタープライズ Bean が 1 つ以上追加されるとこの警告は表示されないようになります。

7.2.2. Maven における EJB アーカイブプロジェクトの作成

Maven を使用して JAR ファイルにパッケージ化された 1 つ以上のエンタープライズ Bean が含まれるプロジェクトを作成する方法を説明します。

前提条件

  • Maven が既にインストールされている必要があります。
  • Maven の基本的な使用法を理解している必要があります。

手順7.2 Maven における EJB アーカイブプロジェクトの作成

  1. Maven プロジェクトの作成

    Maven のアーキタイプシステムと ejb-javaee6 アーキタイプを使用して EJB プロジェクトを作成することができます。作成するには、以下のパラメーターを用いて mvn コマンドを実行します。
     mvn archetype:generate -DarchetypeGroupId=org.codehaus.mojo.archetypes -DarchetypeArtifactId=ejb-javaee6 
    プロジェクトの groupIdartifactIdversionpackage を指定するよう要求されます。
    [localhost]$ mvn archetype:generate -DarchetypeGroupId=org.codehaus.mojo.archetypes -DarchetypeArtifactId=ejb-javaee6
    [INFO] Scanning for projects...
    [INFO]                                                                         
    [INFO] ------------------------------------------------------------------------
    [INFO] Building Maven Stub Project (No POM) 1
    [INFO] ------------------------------------------------------------------------
    [INFO] 
    [INFO] >>> maven-archetype-plugin:2.0:generate (default-cli) @ standalone-pom >>>
    [INFO] 
    [INFO] <<< maven-archetype-plugin:2.0:generate (default-cli) @ standalone-pom <<<
    [INFO] 
    [INFO] --- maven-archetype-plugin:2.0:generate (default-cli) @ standalone-pom ---
    [INFO] Generating project in Interactive mode
    [INFO] Archetype [org.codehaus.mojo.archetypes:ejb-javaee6:1.5] found in catalog remote
    Define value for property 'groupId': : com.shinysparkly
    Define value for property 'artifactId': : payment-arrangments
    Define value for property 'version':  1.0-SNAPSHOT: : 
    Define value for property 'package':  com.shinysparkly: : 
    Confirm properties configuration:
    groupId: com.company
    artifactId: payment-arrangments
    version: 1.0-SNAPSHOT
    package: com.company.collections
    Y: : 
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 32.440s
    [INFO] Finished at: Mon Oct 31 10:11:12 EST 2011
    [INFO] Final Memory: 7M/81M
    [INFO] ------------------------------------------------------------------------
    [localhost]$
    
  2. エンタープライズ Bean の追加

    エンタープライズ Bean を作成し、Bean のパッケージの適切なサブディレクトリにある src/main/java ディレクトリ下のプロジェクトに追加します。
  3. プロジェクトの構築

    プロジェクトを構築するには、 pom.xml ファイルと同じディレクトリで mvn package コマンドを実行します。このコマンドを実行すると、Java クラスがコンパイルされ、JAR ファイルがパッケージ化されます。ビルドされた JAR ファイルには artifactId-version.jar という名前が付けられ、target/ ディレクトリに置かれます。
結果: JAR ファイルをビルドしパッケージ化する Maven プロジェクトが作成されます。アプリケーションサーバーへデプロイすることができるエンタープライズ Bean と JAR ファイルがこのプロジェクトに含まれるようにすることが可能です。

7.2.3. EJB プロジェクトが含まれる EAR プロジェクトの作成

EJB プロジェクトが含まれる新しいエンタープライズアーカイブ (EAR) プロジェクトを JBoss Developer Studio で作成する方法を説明します。

要件

手順7.3 EJB プロジェクトが含まれる EAR プロジェクトの作成

  1. 新しい EAR アプリケーションプロジェクトウィザードを開く

    [File] メニューより [New][Project] の順に選択すると、[New Project] ウィザードが表示されます。[Java EE/Enterprise Application Project] を選択し、[Next] をクリックします。
    新しい EAR アプリケーションウィザード

    図7.4 新しい EAR アプリケーションウィザード

  2. 詳細の入力

    次の詳細を入力します。
    • プロジェクト名
      JBoss Developer Studio で表示されるプロジェクト名ですが、デプロイされた EAR ファイルのデフォルトのファイル名にもなります。
    • プロジェクトの場所
      プロジェクトのファイルが保存されるディレクトリです。現在のワークスペースのディレクトリがデフォルトになります。
    • ターゲットランタイム
      プロジェクトに使用されるサーバーランタイムです。デプロイするサーバーによって使用される JBoss Enterprise Application Platform 6 のランタイムと同様に設定される必要があります。
    • EAR バージョン
      プロジェクトが準拠する Java Enterprise Edition 仕様のバージョンになります。Red Hat は 6 の使用を推奨します。
    • これでプロジェクトのサポート対象機能を調整できるようになります。選択したランタイムにデフォルト設定を使用します。
    [Next] クリックして作業を継続します。
  3. 新しい EJB モジュールの追加

    新しいモジュールはウィザードの Enterprise Application ページより追加することができます。次の手順に従って新しい EJB プロジェクトをモジュールとして追加します。
    1. 新しい EJB モジュールの追加

      [New Module] をクリックし、 [Create Default Modules] チェックボックスのチェックを外します。[Enterprise Java Bean] を選択し、[Next] をクリックすると [New EJB Project] ウィザードが表示されます。
    2. EJB プロジェクトの作成

      New EJB Project ウィザードは、新しいスタンドアローン EJB プロジェクトを作成するために使用するウィザードと同じで、「JBoss Developer Studio を使用した EJB アーカイブプロジェクトの作成」 に説明されています。
      プロジェクト作成のために最低限必要な情報は次の通りです。
      • プロジェクト名
      • ターゲットランタイム
      • EJB モジュールのバージョン
      • 設定
      ウィザードの他の手順はすべて任意の手順となります。[Finish] をクリックして EJB プロジェクトの作成を完了します。
    新規作成された EJB プロジェクトは Java EE モジュールの依存関係に一覧表示され、チェックボックスにチェックが付けられます。
  4. 任意の作業: application.xml デプロイメント記述子の追加

    必要な場合は [Generate application.xml deployment descriptor] チェックボックスにチェックを付けます。
  5. Finish のクリック

    EJB プロジェクトと EAR プロジェクトの 2 つの新しいプロジェクトが表示されます。
  6. デプロイメントに対して構築アーティファクトをサーバーに追加する

    [Servers] タブにて、構築アーティファクトをデプロイしたいサーバーを右クリックし、 [Add and Remove] ダイアログを開きます。[Add and Remove] を選択します。
    [Available] カラムよりデプロイする EAR リソースを選択し、 [Add] ボタンをクリックします。リソースが [Configured] カラムに移動します。[Finish] をクリックしてダイアログを閉じます。
    ダイアログの追加と削除

    図7.5 ダイアログの追加と削除

結果

メンバーの EJB プロジェクトを持つ Enterprise Application プロジェクトが作成されます。この Enterprise Application プロジェクトはビルドされ、EJB サブデプロイメントが含まれる単一の EAR デプロイメントとして指定のサーバーにデプロイされます。

7.2.4. EJB プロジェクトへのデプロイメント記述子の追加

EJB デプロイメント記述子がない状態で作成された EJB プロジェクトに EJB デプロイメント記述子を追加することができます。次の手順に従って追加します。

前提条件

  • EJB デプロイメント記述子を追加したい EJB プロジェクトが JBoss Developer Studio に存在している必要があります。

手順7.4 EJB プロジェクトにデプロイメント記述子を追加する

  1. プロジェクトを開く

    JBoss Developer Studio でプロジェクトを開きます。
  2. デプロイメント記述子の追加

    プロジェクトビューの Deployment Descriptor フォルダーを右クリックし、[Generate Deployment Descriptor Stub] を選択します。
    デプロイメント記述子の追加

    図7.6 デプロイメント記述子の追加

新しいファイル ejb-jar.xmlejbModule/META-INF/ に作成されます。

7.3. セッション Bean

7.3.1. セッション Bean

セッション Bean は、関連の業務プロセスやタスクのセットをカプセル化し、要求したクラスにインジェクトするエンタープライズ Bean です。セッション Bean には、ステートレス、ステートフル、シングルトンの 3 種類があります。

7.3.2. ステートレスセッション Bean

ステートレスセッション Bean は最もシンプルですが、幅広く利用されているセッション Bean です。クライアントアプリケーションへのビジネスメソッドを提供しますが、メソッド呼び出し間のステートは保持しません。各メソッドは、セッション Bean 内で共有ステートに依存しない完全タスクです。ステートがないため、アプリケーションサーバーは各メソッド呼び出しが同じインスタンスで実行されているか確認する必要がありません。結果、ステートレス Bean の効率と拡張性は非常に高くなります。

7.3.3. ステートフルセッション Bean

ステートフルセッション Bean はエンタープライズ Bean でビジネスメソッドをクライアントアプリケーションに渡し、クライアントとの会話の状態を維持します。複数のステップ (メソッド呼び出し) を踏んで実行する必要のあるタスクにこれらの Bean を利用してください。それぞれのステップでは、1つ前のステップの状態を維持します。アプリケーションサーバーは、各クライアントがメソッド呼び出しごとに同じステートフルセッション Bean のインスタンスを受け取るようにします。

7.3.4. シングルトンセッション Bean

シングルトンセッション Bean はアプリケーションごとに 1 回インスタンス化されるセッション Bean で、1 つのシングルトン Bean に対するクライアント要求はすべて同じインスタンスへ送信されます。シングルトン Bean はシングルトンデザインパターンの実装であり、Erich Gamma、Richard Helm、Ralph Johnson、John Vlissides によって執筆され、1994 年に Addison-Wesley より出版された 『 Design Patterns: Elements of Reusable Object-Oriented Software』 で説明されています。
シングルトン Bean はセッション Bean の型で最も小さいメモリーフットプリントを提供しますが、スレッドセーフである必要があります。EJB 3.1 はコンテナ管理の並行性 (Container-Managed Concurrency、CMC) を提供し、開発者がスレッドセーフのシングルトン Bean を簡単に実装できるようにします。CMC の柔軟性が足りない場合は、従来のマルチスレッドコード (Bean 管理の並行性、BMC)を使用してシングルトン Bean を書くことも可能です。

7.3.5. JBoss Developer Studio のプロジェクトにセッション Bean を追加する

JBoss Developer Studio にはエンタープライズ Bean クラスを即座に作成できる複数のウィザードがあります。以下は、JBoss Developer Studio のウィザードを使用してプロジェクトにセッション Bean を追加する手順になります。

前提条件

  • 1 つ以上のセッション Bean を追加したい EJB または動的 Web プロジェクトが JBoss Developer Studio に存在する必要があります。

手順7.5 JBoss Developer Studio のプロジェクトにセッション Bean を追加する

  1. プロジェクトを開く

    JBoss Developer Studio でプロジェクトを開きます。
  2. [Create EJB 3.x Session Bean] ウィザードを開く

    [Create EJB 3.x Session Bean] ウィザードを開くために、[File] メニューへ移動し、[New] を選択してから [Session Bean (EJB 3.x)] を選択します。
    [Create EJB 3.x Session Bean] ウィザード

    図7.7 [Create EJB 3.x Session Bean] ウィザード

  3. クラス情報の指定

    次の詳細を入力します。
    • プロジェクト
      正しいプロジェクトが選択されているか検証します。
    • ソースホルダー
      Java ソースファイルが作成されるフォルダーになります。通常、変更する必要はありません。
    • パッケージ
      クラスが属するパッケージを指定します。
    • クラス名
      セッション Bean になるクラスの名前を指定します。
    • スーパークラス
      セッション Bean クラスはスーパークラスより継承することができます。セッションにスーパークラスがあるかどうかをここに指定します。
    • ステートタイプ
      セッション Bean のステートタイプ (ステートレス、ステートフル、シングルトン) を指定します。
    • ビジネスインターフェース
      デフォルトでは No-interface ボックスにチェックマークが付けられているため、インターフェースは作成されません。定義したいインターフェースのボックスにチェックマークを付け、必要な場合は名前を調整します。
      Web アーカイブ (WAR) のエンタープライズ Bean は EJB 3.1 Lite のみをサポートするため、リモートビジネスインターフェースは含まれません。
    [Next] をクリックします。
  4. セッション Bean の特定情報

    ここに追加情報を入力してセッション Bean を更にカスタマイズすることが可能です。ここで情報を変更する必要はありません。
    変更できる項目は次の通りです。
    • Bean 名。
    • マッピングされた名前。
    • トランザクションタイプ (コンテナ管理または Bean 管理)。
    • Bean が実装しなければならない追加のインターフェースを入力できます。
    • 必要な場合は、EJB 2.x のホームインターフェースやコンポーネントインターフェースを指定することもできます。
  5. 完了

    [Finish] をクリックすると、新しいセッション Bean が作成され、プロジェクトに追加されます。指定された場合、新しいビジネスインターフェースのファイルも作成されます。
結果: 新しいセッション Bean がプロジェクトに追加されます。
JBoss Developer Studio の新しいセッション Bean

図7.8 JBoss Developer Studio の新しいセッション Bean

7.4. メッセージ駆動型 Bean

7.4.1. メッセージ駆動型 Bean

メッセージ駆動型 Bean (MDB) は、アプリケーション開発にイベント駆動モデルを提供します。MDB のメソッドはクライアントコードに挿入されるか、クライアントコードから呼び出されますが、Java Messaging Service (JMS) サーバーなどのメッセージングサービスからメッセージを受け取ることによってトリガーされます。Java EE 6 仕様では JMS がサポートされている必要がありますが、他のメッセージングシステムをサポートすることもできます。

7.4.2. リソースアダプター

リソースアダプターは、 Java Connector Architecture (JCA) 仕様を使用して Java EE アプリケーションとエンタープライズ情報システム (EIS) との間の通信を提供するデプロイ可能な Java EE コンポーネントです。通常、リソースアダプターは EIS のベンダーによって提供されるため、ベンダーの製品と Java EE アプリケーションとの統合は容易になります。
エンタープライズ情報システムは、組織内における他のあらゆるソフトウェアシステムのことです。例としては、エンタープライズリソースプランニング (ERP) システム、データベースシステム、電子メールサーバー、商用メッセージングシステムなどが挙げられます。
リソースアダプターは、JBoss Enterprise Application Platform 6 にデプロイできる Resource Adapter Archive (RAR) ファイルでパッケージ化されます。また、RAR ファイルは、Enterprise Archive (EAR) デプロイメントにも含まれていることがあります。

7.4.3. JBoss Developer Studio に JMS ベースのメッセージ駆動型 Bean を作成する

JBoss Developer Studio のプロジェクトに JMS ベースのメッセージ駆動型 Bean を追加する手順は次の通りです。この手順では、アノテーションを使用する EJB 3.x メッセージ駆動型 Bean を作成します。

前提条件

  1. JBoss Developer Studio で既存のプロジェクトが開かれていなければなりません。
  2. Bean がリッスンする JMS 宛先の名前とタイプを認識している必要があります。
  3. Bean がデプロイされる JBoss Enterprise Application Platform の設定で Java メッセージングサービス (JMS) のサポートが有効になっている必要があります。

手順7.6 JBoss Developer Studio に JMS ベースのメッセージ駆動型 Bean を追加する

  1. [Create EJB 3.x Message-Driven Bean] ウィザードを開く

    [File][New][Other] と移動します。[EJB/Message-Driven Bean (EJB 3.x)] を選択し、 [Next] ボタンをクリックします。
    Create EJB 3.x Message-Driven Bean ウィザード

    図7.9 Create EJB 3.x Message-Driven Bean ウィザード

  2. クラスファイルの宛先詳細の指定

    Bean クラスに対して指定する詳細のセットは、プロジェクト、Java クラス、メッセージの宛先の 3 つがあります。
    プロジェクト
    • [Workspace] に複数のプロジェクトが存在する場合は、[Project] メニューで正しいプロジェクトが選択されるようにしてください。
    • 新しい Bean のソースファイルが作成されるフォルダーは、選択されたディレクトリ下の ejbModule に作成されます。特定の要件がある場合のみこのフォルダーを変更します。
    Java クラス
    • 必須のフィールドは [Java package][class name] になります。
    • アプリケーションのビジネスロジックがスーパークラスを必要とする場合を除き、[Superclass] を入力する必要はありません。
    メッセージの宛先
    JMS ベースのメッセージ駆動型 Bean に提供しなければならない詳細は次の通りです。
    • [Destination name]。Bean が応答するメッセージに含まれるキューまたはトピック名です。
    • デフォルトでは [JMS] チェックボックスが選択されます。これは変更しないでください。
    • [Destination type] を必要に応じて [Queue] または [Topic] に設定します。
    [Next] ボタンをクリックします。
  3. メッセージ駆動型 Bean に固有の情報の入力

    以下のデフォルト値はコンテナ管理トランザクションを使用する JMS ベースのメッセージ駆動型 Bean に適するデフォルト値となります。
    • Bean が Bean 管理トランザクションを使用する場合はトランザクションタイプを Bean に変更します。
    • クラス名とは異なる Bean 名が必要な場合は Bean 名を変更します。
    • JMS メッセージリスナーインターフェースが表示されるはずです。インターフェースがアプリケーションのビジネスロジックに固有する場合を除き、インターフェースを追加したり削除したりする必要はありません。
    • メソッドスタブ作成のチェックボックスはそのまま選択された状態にしてきます。
    [Finish] ボタンをクリックします。
結果: デフォルトのコンストラクターのスタブメソッドと onMessage() メソッドによってメッセージ駆動型 Bean が作成されます。JBoss Developer Studio のエディターウィンドウが対応するファイルによって開かれます。

7.5. セッション Bean の呼び出し

7.5.1. JNDI を使用したリモートでのセッション Bean の呼び出し

このタスクは、JNDI を使用してセッション Bean の呼び出すリモートクライアントへサポートを追加する方法を説明します。Maven を使用してプロジェクトがビルドされていることが前提となります。
ejb-remote クイックスタートには、この機能のデモを行う Maven プロジェクトが含まれています。このクイックスタートには、デプロイするセッション Bean のプロジェクトとリモートクライアントのプロジェクトの両方が含まれています。下記のコード例はリモートクライアントのプロジェクトから引用されています。
このタスクでは、セッション Bean に認証の必要がないことが前提となっています。

要件

始める前に、次の前提条件を満たしている必要があります。
  • Maven プロジェクトが作成され、使用できる状態です。
  • JBoss Enterprise Application Platform 6 の Maven リポジトリが既に追加されています。
  • 呼び出しするセッション Bean が既にデプロイされています。
  • デプロイされたセッション Bean がリモートビジネスインターフェースを実装します。
  • セッション Bean のリモートビジネスインターフェースは Maven 依存関係として使用できます。リモートビジネスインターフェースが JAR ファイルとしてのみ使用できる場合は、JAR をアーティファクトとして Maven リポジトリに追加することが推奨されます。手順については、http://maven.apache.org/plugins/maven-install-plugin/usage.html にある Maven ドキュメントの install:install-file ゴールを参照してください。
  • セッション Bean をホストするサーバーのホスト名と JNDI ポートを覚えておく必要があります。
リモートクライアントよりセッション Bean を呼び出すには、最初にプロジェクトを適切に設定する必要があります。

手順7.7 セッション Bean のリモート呼び出しに対する Maven プロジェクト設定を追加する

  1. 必要なプロジェクト依存関係の追加

    必要な依存関係が含まれるようにするため、プロジェクトの pom.xml を更新する必要があります。
  2. jboss-ejb-client.properties ファイルの追加

    JBoss EJB クライアント API は、JNDI サービスの接続情報が含まれる jboss-ejb-client.properties という名前のプロジェクトのルートにファイルがあることを想定します。このファイルを以下の内容と共にプロジェクトの src/main/resources/ ディレクトリーに追加します。
    remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
    
    remote.connections=default
    
    remote.connection.default.host=localhost
    remote.connection.default.port = 4447
    remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
    
    
    ホスト名とポートを変更してサーバーと一致するようにします。4447 がデフォルトのポート番号です。 安全な接続の場合、SSL_ENABLED 行を true に設定し、 SSL_STARTTLS 行をアンコメントします。コンテナ内のリモーティングインターフェースは同じポートを使用して安全な接続と安全でない接続をサポートします。
  3. リモートビジネスインターフェースの依存関係の追加

    セッション Bean のリモートビジネスインターフェースに対する pom.xml に Maven の依存関係を追加します。
    <dependency>
       <groupId>org.jboss.as.quickstarts</groupId>
       <artifactId>jboss-as-ejb-remote-server-side</artifactId>
       <type>ejb-client</type>
       <version>${project.version}</version>
    </dependency>
    
これでプロジェクトが適切に設定されたため、コードを追加してセッション Bean へアクセスしたり呼び出しすることができるようになりました。

手順7.8 JNDI を使用して Bean プロキシを取得し、Bean のメソッドを呼び出す

  1. チェック例外の処理

    次のコードに使用されるメソッドの 2 つ (InitialContext() および lookup()) は、タイプ javax.naming.NamingException のチェック済み例外を持っています。これらのメソッド呼び出しは NamingException をキャッチする try/catch ブロックか、NamingException のスローが宣言されたメソッドに存在する必要があります。ejb-remote クイックスタートでは、2 番目の方法を使用します。
  2. JNDI コンテキストの作成

    JNDI コンテキストオブジェクトはサーバーよりリソースを要求するメカニズムを提供します。次のコードを使用して JNDI コンテキストを作成します。
    final Hashtable jndiProperties = new Hashtable();
    jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
    final Context context = new InitialContext(jndiProperties);
    
    JNDI サービスの接続プロパティーは jboss-ejb-client.properties ファイルより読み取られます。
  3. JNDI コンテキストの lookup() メソッドを使用した Bean プロキシの取得

    Bean プロキシの lookup() メソッドを呼び出し、必要なセッション Bean の JNDI 名 へ渡します。これにより、呼び出したいメソッドが含まれるリモートビジネスインターフェースのタイプへキャストされなければならないオブジェクトが返されます。
    
    final RemoteCalculator statelessRemoteCalculator = (RemoteCalculator) context.lookup(
        "ejb:/jboss-as-ejb-remote-server-side/CalculatorBean!" + 
        RemoteCalculator.class.getName());
    
    
    セッション Bean の JNDI 名は特別な構文によって定義されます。
  4. 呼び出しメソッド

    プロキシ Bean オブジェクトを取得したため、リモートビジネスインターフェースに含まれるすべてのメソッドを呼び出しすることができます。
    int a = 204;
    int b = 340;
    System.out.println("Adding " + a + " and " + b + " via the remote stateless calculator deployed on the server");
    int sum = statelessRemoteCalculator.add(a, b);
    System.out.println("Remote calculator returned sum = " + sum);
    
    メソッド呼び出し要求が実行されるサーバー上で、プロキシ Bean がメソッド呼び出し要求をセッション Bean へ渡します。結果はプロキシ Bean へ返され、プロキシ Bean によって結果が呼び出し側へ返されます。プロキシ Bean とリモートセッション Bean 間の通信は呼び出し側に透過的です。
これで、Maven プロジェクトを設定してリモートサーバー上で呼び出しを行うセッション Bean をサポートし、JNDI を使用してサーバーより読み出したプロキシ Bean を使用してセッション Bean メソッドを呼び出すコードを作成できるようになりました。

7.5.2. EJB クライアントコンテキストについて

JBoss Enterprise Application Platform 6 には、リモート EJB 呼び出しを管理する EJB クライアント API が導入されました。JBoss EJB クライアント API は、1 つまたは複数のスレッドで同時に関連付けたり、使用したりできる EJBClientContext を使用します。つまり、EJBClientContext には任意の数の EJB レシーバーを含めることができます。EJB レシーバーは、EJB 呼び出しを処理できるサーバーとの通信方法を知っているコンポーネントです。一般的に、EJB リモートアプリケーションは以下のように分類できます。
  • リモートクライアント。スタンドアロン Java アプリケーションとして実行されます。
  • リモートクライアント。別の JBoss Enterprise Application Platform インスタンス内で実行されます。
EJB クライアント API の観点から、リモートクライアントのタイプに応じて、1 つの JVM 内には複数の EJBClientContext が存在することがあります。
スタンドアロンアプリケーションは通常、任意の数の EJB レシーバーにより支援されることがある単一の EJBClientContext を持ちますが、これは必須ではありません。スタンドアロンアプリケーションが複数の EJBClientContext を持つ場合、EJB クライアントコンテキストセレクターは適切なコンテキストを返します。
別の JBoss Enterprise Application Platform インスタンス内で実行されるリモートクライアントの場合、デプロイされた各アプリケーションは、対応する EJB クライアントコンテキストを持ちます。このアプリケーションが別の EJB を呼び出すと、適切な EJB レシーバーを見つけるために、対応する EJB クライアントコンテキストが使用され、呼び出しが処理されます。

7.5.3. 単一 EJB コンテキストを使用する場合の留意事項

概要

スタンドアロンリモートクライアントで単一 EJB クライアントコンテキストを使用する場合は、アプリケーション要件を考慮する必要があります。異なるタイプのリモートクライアントの詳細については、「EJB クライアントコンテキストについて」 を参照してください。

単一 EJB クライアントコンテキストを持つリモートスタンドアロンの一般的なプロセス

一般的に、リモートスタンドアロンクライアントは任意の数の EJB レシーバーにより支援された唯一の EJB クライアントコンテキストを持っています。以下に、スタンドアロンリモートクライアントアプリケーションの例を示します。

public class MyApplication {
    public static void main(String args[]) {
        final javax.naming.Context ctxOne = new javax.naming.InitialContext();
        final MyBeanInterface beanOne = ctxOne.lookup("ejb:app/module/distinct/bean!interface");
        beanOne.doSomething();
        ...
    }
}

リモートクライアント JNDI ルックアップは、通常 jboss-ejb-client.properties ファイルにより支援され、このファイルは EJB クライアントコンテキストと EJB レシーバーをセットアップするために使用されます。また、この設定には、セキュリティークレデンシャルが含まれ、このセキュリティークレデンシャルは JBoss Enterprise Application Platform サーバーに接続する EJB レシーバーを作成するために使用されます。上記のコードが呼び出された場合、EJB クライアント API は EJB クライアントコンテキストを探します。この EJB クライアントコンテキストは EJB 呼び出し要求を受け取り処理する EJB レシーバーを選択するために使用されます。この場合は、EJB クライアントコンテキストが 1 つしかないため、Bean を呼び出すためにそのコンテキストが上記のコードにより使用されます。JNDI をリモートで使用してセッション Bean を呼び出す手順の詳細については、「JNDI を使用したリモートでのセッション Bean の呼び出し」 を参照してください。
リモートスタンドアロンクライアントは異なるクレデンシャルを必要とする

ユーザーアプリケーションが Bean を複数回呼び出す場合に、異なるセキュリティークレデンシャルを使用して JBoss Enterprise Application Platform サーバーに接続したいことがあります。以下に、同じ Bean を 2 回呼び出すスタンドアロンリモートクライアントアプリケーションの例を示します。

public class MyApplication {
    public static void main(String args[]) {
        // Use the "foo" security credential connect to the server and invoke this bean instance
        final javax.naming.Context ctxOne = new javax.naming.InitialContext();
        final MyBeanInterface beanOne = ctxOne.lookup("ejb:app/module/distinct/bean!interface");
        beanOne.doSomething();
        ...
 
        // Use the "bar" security credential to connect to the server and invoke this bean instance
        final javax.naming.Context ctxTwo = new javax.naming.InitialContext();
        final MyBeanInterface beanTwo = ctxTwo.lookup("ejb:app/module/distinct/bean!interface");
        beanTwo.doSomething();
        ...
    }
}

この場合、アプリケーションは同じサーバーインスタンスに接続してそのサーバーにホストされた EJB を呼び出し、サーバーに接続する際に 2 つの異なるクレデンシャルを使用します。クライアントアプリケーションは単一の EJB クライアントコンテキストを持ち、各サーバーインスタンスに対して EJB レシーバーを 1 つしか持つことができないため、上記のコードはクレデンシャルを 1 つだけ使用してサーバーに接続し、コードはアプリケーションの期待どおりに実行されません。
解決法

スコープ EJB クライアントコンテキストを使用するとこの問題を解決できます。スコープ EJB クライアントコンテキストにより、EJB クライアントコンテキストと、関連する JNDI コンテキスト (一般的に EJB 呼び出しに使用されます) を細かく制御できるようになります。スコープ EJB クライアントコンテキストの詳細については、「スコープ EJB クライアントコンテキストの使用」「スコープ EJB クライアントコンテキストを使用した EJB の設定」 を参照してください。

7.5.4. スコープ EJB クライアントコンテキストの使用

概要

JBoss Enterprise Application Platform 6 の初期バージョンで EJB を呼び出すには、通常 JNDI コンテキストを作成し、PROVIDER_URL (ターゲットサーバーを示します) に渡します。JNDI コンテキストを使用してルックアップされた EJB プロキシに対して行われたすべての呼び出しは最終的にそのサーバーに対して行われます。スコープ EJB クライアントコンテキストにより、ユーザーアプリケーションは特定の呼び出しに使用される EJB レシーバーを制御できます。

リモートスタンドアロンクライアントでスコープ EJB クライアントコンテキストを使用する

スコープ EJB クライアントコンテキストが導入される前に、コンテキストは通常クライアントアプリケーションにスコープ指定されていました。スコープクライアントコンテキストにより、EJB クライアントコンテキストを JNDI コンテキストでスコープ指定できるようになりました。以下に、スコープ EJB クライアントコンテキストを使用して同じ Bean を 2 回呼び出すスタンドアロンリモートクライアントアプリケーションの例を示します。

public class MyApplication { 
    public static void main(String args[]) {
 
        // Use the "foo" security credential connect to the server and invoke this bean instance
        final Properties ejbClientContextPropsOne = getPropsForEJBClientContextOne():
        final javax.naming.Context ctxOne = new javax.naming.InitialContext(ejbClientContextPropsOne);
        final MyBeanInterface beanOne = ctxOne.lookup("ejb:app/module/distinct/bean!interface");
        beanOne.doSomething();
        ...
 
        // Use the "bar" security credential to connect to the server and invoke this bean instance
        final Properties ejbClientContextPropsTwo = getPropsForEJBClientContextTwo():
        final javax.naming.Context ctxTwo = new javax.naming.InitialContext(ejbClientContextPropsTwo);
        final MyBeanInterface beanTwo = ctxTwo.lookup("ejb:app/module/distinct/bean!interface");
        beanTwo.doSomething();
        ...
    }
}

スコープ EJB クライアントコンテキストを使用するには、EJB クライアントプロパティーをプログラミングで設定し、コンテキスト作成でプロパティーを渡します。プロパティーは、標準的な jboss-ejb-client.properties ファイルで使用されるのと同じプロパティーセットです。EJB クライアントコンテキストを JNDI コンテキストにスコープ指定するには、org.jboss.ejb.client.scoped.context プロパティーを指定し、その値を true に設定する必要があります。このプロパティーは、EJB クライアント API に、EJB クライアントコンテキスト (EJB レシーバーにより支援される) を作成する必要があることと、作成されたコンテキストが作成元の JNDI コンテキストに対してのみスコープ指定されるか、可視状態であることを通知します。この JNDI コンテキストを使用してルックアップされた、または呼び出されたすべての EJB プロキシは、この JNDI コンテキストに関連付けられた EJB クライアントコンテキストのみを認識します。EJB をルックアップし、呼び出すためにアプリケーションにより使用される他の JNDI コンテキストは、他のスコープ EJB クライアントコンテキストについて認識しません。
org.jboss.ejb.client.scoped.context プロパティーを渡さず、EJB クライアントコンテキストにスコープ指定されない JNDI コンテキストはデフォルトの動作を使用します。デフォルトの動作では、一般的にアプリケーション全体に割り当てられた既存の EJB クライアントコンテキストを使用します。
スコープ EJB クライアントコンテキストは、JBoss Enterprise Application Platform の以前のバージョンの JNP ベース JNDI 呼び出しに関連する柔軟性をユーザーアプリケーションに提供します。スコープ EJB クライアントコンテキストにより、ユーザーアプリケーションはどの JNDI コンテキストがどのサーバーと通信するかや、JNDI コンテキストがどのようにサーバーと接続するかを細かく制御できるようになります。

7.5.5. スコープ EJB クライアントコンテキストを使用した EJB の設定

概要

EJB は、マップベースのスコープコンテキストを使用して設定できます。これは、プログラムで、jboss-ejb-client.properties にある標準的なプロパティーを使用して Properties マップに値を入力し、org.jboss.ejb.client.scoped.context プロパティーに true を指定して、InitialContext のプロパティーを渡すことにより実現されます。

スコープコンテキストを使用する利点は、EJB を直接参照したり、JBoss クラスをインポートしたりせずにアクセスを設定できることです。また、マルチスレッド環境で実行時にホストを設定および負荷分散することが可能になります。

手順7.9 マップベースのスコープコンテキストを使用した EJB の設定

  1. プロパティーの設定

    EJB クライアントプロパティーをプログラムで設定し、標準的な jboss-ejb-client.properties ファイルで使用されたのと同じプロパティーセットを指定します。スコープコンテキストを有効にするには、org.jboss.ejb.client.scoped.context プロパティーを指定し、その値を true に設定する必要があります。以下は、プロパティーをプログラムで設定する例です。
    // Configure  EJB Client properties for the InitialContext
    Properties ejbClientContextProps = new Properties();
    ejbClientContextProps.put(“remote.connections”,”name1”);
    ejbClientContextProps.put(“remote.connection.name1.host”,”localhost”);
    ejbClientContextProps.put(“remote.connection.name1.port”,”4447”);
    // Property to enable scoped EJB client context which will be tied to the JNDI context
    ejbClientContextProps.put("org.jboss.ejb.client.scoped.context", “true”);
    
  2. コンテキスト作成でプロパティーを渡す

    // Create the context using the configured properties
    InitialContext ic = new InitialContext(ejbClientContextProps);
    MySLSB bean = ic.lookup("ejb:myapp/ejb//MySLSBBean!" + MySLSB.class.getName());
    
その他の情報

  • ルックアップ EJB プロキシーにより生成されたコンテキストは、このスコープコンテキストによりバインドされ、重要な接続パラメーターのみを使用します。これにより、さまざまなコンテキストを作成してクライアントアプリケーション内のデータにアクセスしたり、さまざまなログインを使用してサーバーに独立してアクセスしたりできます。
  • クライアントでは、スコープ InitialContext とスコーププロキシーの両方がスレッドに渡され、各スレッドが該当するコンテキストで動作することが可能になります。また、プロキシーを同時に使用できる複数のスレッドにプロキシーを渡すことができます。
  • スコープコンテキスト EJB プロキシーは、リモートコールでシリアライズされ、サーバーでデシリアライズされます。デシリアライズされるとき、スコープコンテキスト情報が削除され、デフォルト状態に戻ります。デシリアライズされたプロキシーがリモートサーバーで使用される場合は、作成時に使用されたスコープコンテキストを持たなくなるため、EJBCLIENT000025 エラーが発生したり、EJB 名を使用して間違った対象を呼び出したりすることがあります。

7.5.6. EJB クライアントプロパティー

概要

以下の表は、プログラムまたは jboss-ejb-client.properties ファイルで設定できるプロパティーを示しています。

EJB クライアントグローバルプロパティー

以下の表は、同じスコープ内のライブラリー全体で有効なプロパティーを示しています。

表7.1 グローバルプロパティー

プロパティー名 説明
endpoint.name
クライアントエンドポイントの名前。設定されない場合、デフォルト値は client-endpoint です。
スレッド名にはこのプロパティーが含まれるため、異なるエンドポイント設定を区別するのに役に立つことがあります。
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED
すべての接続に対して SSL プロトコルが有効であるかどうかを指定するブール値。
deployment.node.selector
org.jboss.ejb.client.DeploymentNodeSelector の実装の完全修飾名。
これは、EJB の呼び出しを負荷分散するために使用されます。
invocation.timeout
EJB ハンドシェイクまたはメソッド呼び出し要求/応答サイクルのタイムアウト。この値はミリ秒単位です。
実行にタイムアウト時間よりも長い時間がかかった場合は、任意のメソッドの呼び出しで java.util.concurrent.TimeoutException がスローされます。実行が完了し、サーバーは中断されません。
reconnect.tasks.timeout
バックグラウンド再接続タスクのタイムアウト。この値はミリ秒単位です。
複数の接続がダウンしている場合は、次のクライアント EJB 呼び出しで、適切なノードを見つけるために再接続が必要かどうかを決定するアルゴリズムが使用されます。
org.jboss.ejb.client.scoped.context
スコープ EJB クライアントコンテキストを有効にするかどうかを指定するブール値。デフォルトは、false です。
true に設定された場合、EJB クライアントは JNDI コンテキストに割り当てられたスコープコンテキストを使用します。その他の場合、EJB クライアントコンテキストは JVM でグローバルセレクターを使用して、リモート EJB およびホストを呼び出すために使用されるプロパティーを決定します。
EJB クライアント接続プロパティー

接続プロパティーは、プレフィックス remote.connection.CONNECTION_NAME で始まります。CONNECTION_NAME は、接続を一意に識別するためにのみ使用されるローカル ID です。

表7.2 接続プロパティー

プロパティー名 説明
remote.connections
アクティブな connection-names のカンマ区切りのリスト。各接続はこの名前を使用して設定されます。
remote.connection.CONNECTION_NAME.host
接続のホスト名または IP。
remote.connection.CONNECTION_NAME.port
接続のポート。デフォルト値は 4447 です。
remote.connection.CONNECTION_NAME.username
接続セキュリティーを認証するために使用されるユーザー名。
remote.connection.CONNECTION_NAME.password
ユーザーを認証するために使用されるパスワード
remote.connection.CONNECTION_NAME.connect.timeout
初期接続のタイムアウト時間。この時間が経過すると、再接続タスクにより、接続を確立できるかどうかが定期的に確認されます。値はミリ秒単位です。
remote.connection.CONNECTION_NAME.callback.handler.class
CallbackHandler クラスの完全修飾名。これは、接続を確立するために使用され、接続がオープンである限り変更できません。
remote.connection.CONNECTION_NAME.
channel.options.org.jboss.remoting3.RemotingOptions.MAX_OUTBOUND_MESSAGES
アウトバウンド要求の最大数を指定する整数値。デフォルト値は 80 です。
すべての呼び出しを処理するために、サーバーに対してクライアント (JVM) からの接続が 1 つだけあります。
remote.connection.CONNECTION_NAME.
connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS
正常に接続するためにクライアントがクレデンシャルを提供する必要があるかどうかを決定するブール値。デフォルト値は true です。
true に設定された場合、クライアントはクレデンシャルを提供する必要があります。false に設定された場合は、リモートコネクターがセキュリティーレルムを要求しない限り、呼び出しが許可されます。
remote.connection.CONNECTION_NAME.
connect.options.org.xnio.Options.SASL_DISALLOWED_MECHANISMS
接続作成中に認証に使用される特定の SASL メカニズムを無効にします。
JBOSS_LOCAL_USER の場合は、サイレント認証メカニズム (クライアントとサーバーが同じマシンにあるときに使用されます) が無効になります。
remote.connection.CONNECTION_NAME.
connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT
認証中のプレーンテキストメッセージの使用を有効または無効にするブール値。JAAS を使用する場合は、プレーンテキストパスワードを許可するために false に設定する必要があります。
remote.connection.CONNECTION_NAME.
connect.options.org.xnio.Options.SSL_ENABLED
この接続に対して SSL プロトコルが有効であるかどうかを指定するブール値。
remote.connection.CONNECTION_NAME.
connect.options.org.jboss.remoting3.RemotingOptions.HEARTBEAT_INTERVAL
自動的なクローズ (ファイアウォールの場合など) を回避するためにクライアントとサーバー間でハートビートを送信する間隔。値はミリ秒単位です。
EJB クライアントクラスタープロパティー

初期接続でクラスター環境に接続する場合は、クラスターのトポロジーが自動的に非同期で受信されます。これらのプロパティーは、受信された各メンバーに接続するために使用されます。各プロパティーは、プレフィックス remote.cluster.CLUSTER_NAME で始まります。CLUSTER_NAME は、関連するサーバーの Infinispan サブシステム設定を参照します。

表7.3 クラスタープロパティ

プロパティー名 説明
remote.cluster.CLUSTER_NAME.
clusternode.selector
org.jboss.ejb.client.ClusterNodeSelector の実装の完全修飾名。
このクラス (org.jboss.ejb.clientDeploymentNodeSelector ではない) は、クラスター環境で EJB 呼び出しを負荷分散するために使用されます。クラスターが完全にダウンしている場合、呼び出しは No ejb receiver available で失敗します。
remote.cluster.CLUSTER_NAME.
channel.options.org.jboss.remoting3.RemotingOptions.MAX_OUTBOUND_MESSAGES
クラスター全体に対して実行できるアウトバウンド要求の最大数を指定する整数値。
remote.cluster.CLUSTER_NAME.
node.NODE_NAME. channel.options.org.jboss.remoting3.RemotingOptions.MAX_OUTBOUND_MESSAGES
この特定のクラスターノードに対して実行できるアウトバウンド要求の最大数を指定する整数値。

7.6. クラスター化された Enterprise JavaBeans

7.6.1. クラスター化された Enterprise JavaBean (EJB) について

高可用性が必要となる場合は、EJB コンポーネントをクラスター化することができます。EJB コンポーネントは HTTP コンポーネントとは異なるプロトコルを使用するため、異なる方法でクラスター化されます。EJB 2 および 3 のステートフル Bean とステートレス Bean をクラスター化できます。
シングルトンについては、「HA シングルトンの実装」を参照してください。

注記

EJB 2 エンティティー Bean は、クラスター化できません。この制限を変更する予定はありません。

7.7. 参考資料

7.7.1. EJB JNDI の名前に関する参考資料

セッション Bean の JNDI ルックアップ名の構文は次の通りです。
 ejb:<appName>/<moduleName>/<distinctName>/<beanName>!<viewClassName>?stateful 
<appName>
セッション Bean の JAR ファイルがエンタープライズアーカイブ (EAR) 内にデプロイされた場合、EAR の名前になります。デフォルトでは、ファイル名から .ear サフィックスを除いたものが EAR の名前になります。また、アプリケーション名を application.xml ファイルで上書きすることも可能です。セッション Bean が EAR にデプロイされていない場合は空白のままにしておきます。
<moduleName>
モジュール名はセッション Bean がデプロイされた JAR ファイルの名前になります。デフォルトでは、ファイル名から .jar サフィックスを除いたものが JAR ファイルの名前になります。また、モジュール名を JAR の ejb-jar.xml ファイルで上書きすることも可能です。
<distinctName>
JBoss Enterprise Application Platform 6 では、各デプロイメントが任意の個別名を指定することができます。デプロイメントの個別名がない場合は空白のままにしておきます。
<beanName>
Bean 名は呼び出されるセッション Bean のクラス名です。
<viewClassName>
ビュークラス名はリモートインターフェースの完全修飾クラス名です。インターフェースのパッケージ名が含まれます。
?stateful
JNDI 名がステートフルセッション Bean を参照する時に ?stateful サフィックスが必要となります。他の Bean タイプでは含まれていません。

7.7.2. EJB 参照の解決

本項では、JBoss が @EJB@Resource を実装する方法について説明します。XML は常にアノテーションを上書きしますが、同じルールが適用されることに注意してください。

@EJB アノテーションのルール

  • @EJB アノテーションは mappedName() 属性を持っています。仕様はこのベンダー固有のメタデータを無視しますが、 JBoss は参照しているEJBのグローバル JNDI 名としてmappedName() を認識します。mappedName() を指定した場合、他の属性はすべて無視され、このグローバル JNDI 名がバインディングに使用されます。
  • 以下のように属性を定義せずに @EJB を指定するとします。
    @EJB 
    ProcessPayment myEjbref;
    この場合、次のルールが適用されます。
    • 参照する Bean の EJB jar が、@EJB 挿入に使用されるインターフェースを持つ EJB に対して検索されます。同じビジネスインターフェースをパブリッシュする EJB が複数ある場合、例外がスローされます。インターフェースを持つ Bean が 1 つのみである場合はその Bean が使用されます。
    • そのインターフェースをパブリッシュする EJB に対する EAR を検索します。複製がある場合は例外がスローされます。それ以外の場合は、一致する Bean が返されます。
    • JBoss ランタイムでそのインターフェースの EJB に対してグローバルに検索が行われます。ここでも複製があると例外がスローされます。
  • @EJB.beanName()<ejb-link> に対応します。beanName() が定義されている場合、属性が定義されていない @EJB として同じアルゴリズムが使用されますが、検索で beanName() がキーとして使用されます。ejb-link の # 構文を使用する場合、このルールの例外となります。# 構文は、参照する EJB が存在する EAR の jar への相対パスを指定できるようにします。詳細については EJB 3.1 仕様を参照してください。

7.7.3. リモート EJB クライアントのプロジェクト依存関係

リモートクライアントからのセッション Bean の呼び出しが含まれる Maven プロジェクトには JBoss Enterprise Application Platform 6 の Maven リポジトリより次の依存関係が必要となります。

表7.4 リモート EJB クライアントに対する Maven の依存関係

GroupID ArtifactID
org.jboss.spec jboss-javaee-6.0
org.jboss.as jboss-as-ejb-client-bom
org.jboss.spec.javax.transaction jboss-transaction-api_1.1_spec
org.jboss.spec.javax.ejb jboss-ejb-api_3.1_spec
org.jboss jboss-ejb-client
org.jboss.xnio xnio-api
org.jboss.xnio xnio-nio
org.jboss.remoting3 jboss-remoting
org.jboss.sasl jboss-sasl
org.jboss.marshalling jboss-marshalling-river
jboss-javaee-6.0jboss-as-ejb-client-bom を除き、これらの依存関係を pom.xml ファイルの <dependencies> セクションに追加する必要があります。
jboss-javaee-6.0jboss-as-ejb-client-bom の依存関係は、スコープが importpom.xml<dependencyManagement> セクションに追加する必要があります。

注記

artifactID のバージョンは変更される可能性があります。該当バージョンについては、Maven リポジトリーを参照してください。
<dependencyManagement>
   <dependencies>
      <dependency>
         <groupId>org.jboss.spec</groupId>
         <artifactId>jboss-javaee-6.0</artifactId>
         <version>3.0.0.Final-redhat-1</version>
         <type>pom</type>
         <scope>import</scope>
      </dependency>

      <dependency>
         <groupId>org.jboss.as</groupId>
         <artifactId>jboss-as-ejb-client-bom</artifactId>
         <version>7.1.1.Final-redhat-1</version>
         <type>pom</type>
         <scope>import</scope>
      </dependency>
   </dependencies>
</dependencyManagement>
リモートセッション Bean の呼び出しに対する依存関係設定の例は remote-ejb/client/pom.xml を参照してください。

7.7.4. jboss-ejb3.xml デプロイメント記述子に関する参考文書

jboss-ejb3.xml は EJB JAR または WAR アーカイブで使用できるカスタムのデプロイメント記述子です。EJB JAR アーカイブでは META-INF/ ディレクトリ、WAR アーカイブでは WEB-INF/ ディレクトリにある必要があります。
形式は ejb-jar.xml に似ていて、同じ名前空間を一部使用し、他の名前空間を一部提供します。jboss-ejb3.xml の内容は ejb-jar.xml の内容と結合されますが、jboss-ejb3.xml の項目の方が優先されます。
本文書では jboss-ejb3.xml によって使用される非標準の名前空間のみ取り上げます。標準的な名前空間については http://java.sun.com/xml/ns/javaee/ のドキュメントを参照してください。
ルート名前空間は http://www.jboss.com/xml/ns/javaee です。

アセンブリ記述子の名前空間

次の名前空間はすべて <assembly-descriptor> 要素で使用されます。これらの名前空間の設定を 1 つの Bean に適用したり、 \*ejb-name として使用してデプロイメントのすべての Bean に対して適用するために使用されます。
クラスタリング名前空間: urn:clustering:1.0
xmlns:c="urn:clustering:1.0"
これにより、EJB がクラスター化されているとマーク付けすることができます。これは @org.jboss.ejb3.annotation.Clustered に相当するデプロイメント記述子です。
<c:clustering>
   <ejb-name>DDBasedClusteredSFSB</ejb-name>
   <c:clustered>true</c:clustered>
</c:clustering>
セキュリティー名前空間 (urn:security)
xmlns:s="urn:security"
これにより、EJB のセキュリティードメインと run-as プリンシパルを設定できます。
<s:security>
  <ejb-name>*</ejb-name>
  <s:security-domain>myDomain</s:security-domain>
  <s:run-as-principal>myPrincipal</s:run-as-principal>
</s:security>
リソースアダプター名前空間: urn:resource-adapter-binding
xmlns:r="urn:resource-adapter-binding"
これにより、メッセージ駆動 Bean にリソースアダプターを設定できます。
<r:resource-adapter-binding>
  <ejb-name>*</ejb-name>
  <r:resource-adapter-name>myResourceAdaptor</r:resource-adapter-name>
</r:resource-adapter-binding>
IIOP 名前空間: urn:iiop
xmlns:u="urn:iiop"
IIOP 名前空間には IIOP が設定されます。
プール名前空間: urn:ejb-pool:1.0
xmlns:p="urn:ejb-pool:1.0"
これにより、含まれるステートレスセッション Bean やメッセージ駆動 Bean によって使用されるプールを選択できます。プールはサーバー設定で定義されます。
<p:pool>
   <ejb-name>*</ejb-name>
   <p:bean-instance-pool-ref>my-pool</p:bean-instance-pool-ref>
</p:pool>
キャッシュ名前空間: urn:ejb-cache:1.0
xmlns:c="urn:ejb-cache:1.0"
これにより、含まれるステートフルセッション Bean によって使用されるキャッシュを選択できます。キャッシュはサーバー設定で定義されます。
<c:cache>
   <ejb-name>*</ejb-name>
   <c:cache-ref>my-cache</c:cache-ref>
</c:cache>

例7.1 jboss-ejb3.xml ファイルの例

<?xml version="1.1" encoding="UTF-8"?>
   <jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee"
                  xmlns="http://java.sun.com/xml/ns/javaee"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xmlns:c="urn:clustering:1.0"
                  xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd"
                  version="3.1"
                  impl-version="2.0">
      <enterprise-beans>
         <message-driven>
            <ejb-name>ReplyingMDB</ejb-name>
            <ejb-class>org.jboss.as.test.integration.ejb.mdb.messagedestination.ReplyingMDB</ejb-class>
            <activation-config>
               <activation-config-property>
                  <activation-config-property-name>destination</activation-config-property-name>
                  <activation-config-property-value>java:jboss/mdbtest/messageDestinationQueue
                  </activation-config-property-value>
               </activation-config-property>
            </activation-config>
         </message-driven>
      </enterprise-beans>
      <assembly-descriptor>
         <c:clustering>
            <ejb-name>DDBasedClusteredSFSB</ejb-name>
            <c:clustered>true</c:clustered>
         </c:clustering>
      </assembly-descriptor>
   </jboss:ejb-jar>

第8章 Web アプリケーションのクラスター化

8.1. セッションレプリケーション

8.1.1. HTTP セッションレプリケーションについて

セッションレプリケーションにより、分散可能なアプリケーションのクライアントセッションがクラスター内のノードのフェイルオーバーなどで中断されないようにします。クラスター内の各ノードは実行中のセッションの情報を共有するため、もともと関連していたノードが消えた場合も作業を引き継ぐことができます。
セッションレプリケーションは、mod_cluster、mod_jk、mod_proxy、ISAPI、NSAPI クラスターにより高可用性を確保する仕組みのことです。

8.1.2. Web セッションキャッシュについて

Web セッションキャッシュは、standalone-ha.xml プロファイルを含むいずれかの HA プロファイル、管理対象ドメインプロファイル ha または full-ha を使用するときに設定できます。最も一般的に設定される要素は、キャッシュモードと分散キャッシュのキャッシュオーナーの数です。
キャッシュモード

キャッシュモードは、REPL (デフォルト値) または DIST のいずれかになります。

REPL
REPL モードでは、クラスターの他のノードそれぞれにキャッシュ全体がレプリケートされます。これは、最も安全なオプションですが、オーバーヘッドが増加します。
DIST
DIST モードは、以前の実装で提供されたバディモードに似ています。このモードでは、owners パラメーターで指定された数のノードにキャッシュを分散することによりオーバーヘッドが削減されます。オーナーのこの数のデフォルト値は 2 です。
オーナー

owners パラメーターは、セッションのレプリケートされたコピーを保持するクラスターノード数を制御します。デフォルト値は、2 です。

8.1.3. Web セッションキャッシュの設定

Web セッションキャッシュのデフォルト値は REPL です。DIST モードを使用する場合は、管理 CLI で次の 2 つのコマンドを実行します。異なるプロファイルを使用する場合は、コマンドでプロファイル名を変更します。スタンドアロンサーバーを使用する場合は、コマンドの /profile=ha 部分を削除します。

手順8.1 Web セッションキャッシュの設定

  1. デフォルトキャッシュモードを DIST に変更します。

    /profile=ha/subsystem=infinispan/cache-container=web/:write-attribute(name=default-cache,value=dist)
    
  2. 分散キャッシュのオーナー数を設定します。

    以下のコマンドでは、5 オーナーが設定されます。デフォルト値は 2 です。
    /profile=ha/subsystem=infinispan/cache-container=web/distributed-cache=dist/:write-attribute(name=owners,value=5)
    
  3. デフォルトキャッシュモードを REPL に戻します。

    /profile=ha/subsystem=infinispan/cache-container=web/:write-attribute(name=default-cache,value=repl)
    
  4. サーバーの再起動

    Web キャッシュモードの変更後は、サーバーを再起動する必要があります。
結果

サーバーでセッションレプリケーションが設定されます。独自のアプリケーションでセッションレプリケーションを使用するには、「アプリケーションにおけるセッションレプリケーションの有効化」を参照してください。

8.1.4. アプリケーションにおけるセッションレプリケーションの有効化

概要

JBoss Enterprise Application Platform の高可用性 (HA) 機能を利用するには、アプリケーションが配布可能になるよう設定する必要があります。ここでは配布可能にする手順を説明した後、使用可能な高度な設定オプションの一部について解説します。

手順8.2 アプリケーションを配布可能にする

  1. 要件: アプリケーションが配布可能であることを示します。

    アプリケーションが配布可能とマークされていないとセッションが配布されません。アプリケーションの web.xml 記述子ファイルの <web-app> タグ内に <distributable /> 要素を追加します。例は次の通りです。

    例8.1 配布可能なアプリケーションの最低限の設定

    <?xml version="1.0"?>
    <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">
              
          <distributable/>
        
    </web-app>
    				
    
    
  2. 希望する場合はデフォルトのレプリケーション動作を変更します。

    セッションレプリケーションに影響する値を変更したい場合は、<jboss-web> 要素の子要素である <replication-config> 要素内で値を上書きします。デフォルトを上書きしたい場合のみ指定の要素が含まれるようにします。以下の例に、全デフォルト設定の一覧と、最も一般的に変更されるオプションを説明する表を示します。

    例8.2 デフォルトの <replication-config>

    <!DOCTYPE jboss-web PUBLIC
        "-//JBoss//DTD Web Application 5.0//EN"
        "http://www.jboss.org/j2ee/dtd/jboss-web_5_0.dtd">
    
    <jboss-web>
       
       <replication-config>
          <cache-name>custom-session-cache</cache-name>
          <replication-trigger>SET</replication-trigger>
          <replication-granularity>ATTRIBUTE</replication-granularity>
          <use-jk>false</use-jk>
          <max-unreplicated-interval>30</max-unreplicated-interval>
          <snapshot-mode>INSTANT</snapshot-mode>
          <snapshot-interval>1000</snapshot-interval>
          <session-notification-policy>com.example.CustomSessionNotificationPolicy</session-notification-policy>
      </replication-config>
    
    </jboss-web>
    				
    
    

表8.1 セッションレプリケーションの一般的なオプション

オプション
説明
<replication-trigger>
クラスター全体でセッションデータのレプリケーションが引き起こされるのはどのような状態であるか制御します。セッション属性として保存された可変オブジェクトがセッションからアクセスされた後、メソッド setAttribute() が直接呼び出されない限り、オブジェクトが変更されレプリケーションが必要であるかをコンテナは明確に認識できないため、このオプションは必須となります。

<replication-trigger> の有効な値

SET_AND_GET
最も安全で、最もパフォーマンスが悪いオプションになります。コンテンツへのアクセスのみが行われ、変更されなくても常にセッションデーターがレプリケートされます。この設定はレガシー機能に対応する目的でのみ保持されています。同じ動作のパフォーマンスを向上させるには、この設定を使用する代わりに、<max_unreplicated_interval> を 0 に設定します。
SET_AND_NON_PRIMITIVE_GET
デフォルト値です。非プリミティブ型のオブジェクトがアクセスされた時のみセッションデータがレプリケートされます。オブジェクトは IntegerLongString などの良く知られた Java データ型ではありません。
SET
このオプションは、データのレプリケーションが必要な時にセッション上でアプリケーションが setAttribute を明示的に呼び出すことを前提としています。これにより、不必要なレプリケーションの発生を防ぎ、全体的なパフォーマンスも改善されますが、本質的に安全ではありません。
設定に関係なく、setAttribute() を呼び出すと常にセッションレプリケーションが引き起こされます。
<replication-granularity>
レプリケートされるデータの細かさを決定します。デフォルトは SESSION ですが、ATTRIBUTE を設定すると、ほとんどの属性は変更されずにセッションのパフォーマンスを向上することができます。
以下は変更する必要がほとんどないオプションになります。

表8.2 セッションレプリケーションの変更が稀なオプション

オプション
説明
<useJK>
mod_clustermod_jkmod_proxy などのロードバランサーの使用を前提とするか指定します。デフォルトは false です。 true に設定すると、各要求に関連付けられているセッション ID がコンテナによって確認され、フェイルオーバーが発生するとセッション ID の jvmRoute の部分が置き換えられます。
<max-unreplicated-interval>
セッションのタイムスタンプのレプリケーションがトリガーされるまで、セッション後に待機する最大間隔 (秒単位) になります。変更がないと判断された場合でも適用されます。これにより、各セッションのタイムスタンプがクラスターノードによって認識されるようにし、フェイルオーバー中にレプリケートされなかったセッションが誤って期限切れにならないようにします。また、フェイルオーバー中に HttpSession.getLastAccessedTime() への呼び出しに正しい値を使用できるようにします。
デフォルトでは値は指定されません。値が指定されないと、コンテナの jvmRoute 設定が JK フェイルオーバーが使用されているかを判断します。 0 を設定すると、セッションがアクセスされるたびにタイムスタンプがレプリケートされます。-1 を設定すると、要求中の他のアクティビティがレプリケーションをトリガーした場合のみタイムスタンプがレプリケートされます。 HttpSession.getMaxInactiveInterval() よりも大きい正の値を設定すると設定ミスとして扱われ、0 に変換されます。
<snapshot-mode>
セッションが他のノードへレプリケートされるタイミングを指定します。デフォルトは INSTANT で、INTERVAL を使用することも可能です。
INSTANT モードでは要求処理スレッドが使用され、変更は要求の最後にレプリケートされます。<snapshot-interval> オプションは無視されます。
INTERVAL モードでは、バックグラウンドタスクは <snapshot-interval> によって指定される間隔で実行され、変更されたセッションがレプリケートされます。
<snapshot-interval>
INTERVAL<snapshot-mode> の値として使用された時に、変更されたセッションがレプリケートされる間隔 (ミリ秒単位) になります。
<session-notification-policy>
インターフェース ClusteredSessionNotificationPolicy の実装の完全修飾クラス名です。登録された HttpSessionListenerHttpSessionAttributeListenerHttpSessionBindingListener へサーブレット仕様の通知が送信されたかどうかを管理します。

8.2. HttpSession の非活性化および活性化

8.2.1. HTTP セッションパッシベーションおよびアクティベーション

パッシベーションとは、比較的利用されていないセッションをメモリーから削除し、永続ストレージへ保存することでメモリの使用量を制御するプロセスのことです。
アクティベーションとは、パッシベートされたデータを永続ストレージから読み出し、メモリに戻すことを言います。
パッシベーションは HTTP セッションのライフタイムで 3 回発生します。
  • コンテナが新規セッションの作成を要求する時に現在アクティブなセッションの数が設定上限を越えている場合、サーバーはセッションの一部をパッシベートして新規セッションを作成できるようにします。
  • 設定された間隔で、定期的にバックグラウンドタスクがセッションをパッシベートすべきかチェックします。
  • ある Web アプリケーションがデプロイされ、他のサーバーでアクティブなセッションのバックアップコピーが、新たにデプロイする Web アプリケーションのセッションマネージャーによって取得された場合、セッションはパッシベートされることがあります。
以下の条件を満たすとセッションはパッシベートされます。
  • セッションが設定した最大アイドル時間の間利用されていない。
  • アクティブなセッションの数が設定上限を越えず、セッションがアイドル時間の設定下限を超えていない。
セッションは常に LRU (Least Recently Used) アルゴリズムを使ってパッシベートされます。

8.2.2. アプリケーションにおける HttpSession パッシベーションの設定

概要

HttpSession パッシベーションはアプリケーションの WEB_INF/jboss-web.xml ファイルまたは META_INF/jboss-web.xml ファイルで設定されます。

例8.3 jboss-web.xml ファイルの例

<!DOCTYPE jboss-web PUBLIC
    "-//JBoss//DTD Web Application 5.0//EN"
    "http://www.jboss.org/j2ee/dtd/jboss-web_5_0.dtd">

<jboss-web version="6.0"
           xmlns="http://www.jboss.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-web_6_0.xsd">

   <max-active-sessions>20</max-active-sessions>
   <passivation-config>
      <use-session-passivation>true</use-session-passivation>
      <passivation-min-idle-time>60</passivation-min-idle-time>
      <passivation-max-idle-time>600</passivation-max-idle-time>
   </passivation-config>


</jboss-web>

パッシベーション設定要素

<max-active-sessions>
許可されるアクティブセッションの最大数です。パッシベーションが有効になっている場合、セッションマネージャーによって管理されるセッション数がこの値を越えると、設定された <passivation-min-idle-time> を基に過剰なセッションがパッシベートされます。それでもアクティブセッションの数が制限を越える場合は、新しいセッションの作成に失敗します。デフォルト値は-1 で、アクティブセッションの最大数は制限されません。
<passivation-config>
この要素は、子要素などの残りのパッシベーション設定パラメーターを保持します。

<passivation-config> 子要素

<use-session-passivation>
セッションパッシベーションを使用するかどうか。デフォルト値は false です。
<passivation-min-idle-time>
アクティブなセッションの数を減らし max-active-sessions によって定義された値に従うため、コンテナがパッシベーションの実行を考慮する前にセッションが非アクティブでなければならない最小期間。デフォルト値は -1 で、<passivation-max-idle-time> が経過する前のセッションのパッシベートを無効にします。<max-active-sessions> が設定されている場合、-1 や大きな値は推奨されません。
<passivation-max-idle-time>
メモリーを節約するため、コンテナがパッシベーションを実行しようとする前にセッションが非アクティブにならなければならない最大期間。アクティブセッションの数が <max-active-sessions> を越えるかどうかに関係なく、このようなセッションのパッシベーションは実行されます。この値は web.xml<session-timeout> 設定よりも小さい値とする必要があります。デフォルト値は -1 で、非アクティブとなる最大期間を基にしたパッシベーションを無効にします。

注記

メモリーのセッション合計数にはこのノードでアクセスされていない他のクラスターノードからレプリケートされたセッションが含まれています。これを考慮して <max-active-sessions> を設定してください。また、他のノードからレプリケートされるセッションの数は、REPL または DIST キャッシュモードが有効であるかどうかによっても異なります。REPL キャッシュモードでは、各セッションは各ノードにレプリケートされます。DIST キャッシュモードでは、各セッションは、owner パラメーターによって指定された数のノードにのみレプリケートされます。セッションキャッシュモードの設定については、「Web セッションキャッシュについて」および「Web セッションキャッシュの設定」を参照してください。
たとえば、各ノードが 100 人のユーザーからの要求を処理する 8 つのノードを持つクラスターについて考えてみましょう。REPL キャッシュモードでは、各ノードはメモリーに 800 のセッションを保存します。DIST キャッシュモードが有効であり、デフォルトの owners 設定が 2 である場合、各ノードはメモリーに 200 のセッションを保存します。

8.4. HA シングルトンの実装

概要

JBoss Enterprise Application Platform 5 では、HA シングルトンアーカイブは他のデプロイメントとは別に deploy-hasingleton/ ディレクトリーにデプロイされていました。これは自動デプロイメントが発生しないようにするためで、また確実に HASingletonDeployer サービスがデプロイメントを制御し、クラスターのマスターノードのみにアーカイブがデプロイされるようにするための処置でした。ホットデプロイメント機能がなかったため、再デプロイメントにはサーバーの再起動が必要でした。また、マスターノードに障害が発生し、他のノードがマスターとして引き継ぐ必要がある場合、シングルトンサービスはサービスを提供するためデプロイメントプロセス全体を実行する必要がありました。

JBoss Enterprise Application Platform 6 ではこれが変更になりました。SingletonService を使用してクラスターの各ノードに目的のサービスがインストールされますが、サービスは一度に 1 つのノード上でのみ起動されます。これにより、デプロイメントの要件が簡素化され、ノード間でシングルトンマスターサービスを移動するために必要な時間が最小限になります。

手順8.3 HA シングルトンサービスの実装

  1. HA シングルトンサービスアプリケーションを作成します。

    シングルトンサービスとしてデプロイされる SingletonService デコレーターでラッピングされたサービスの簡単な例は次のとおりです。
    1. シングルトンサービスを作成します。

      以下のリストは、シングルトンサービスの例です。
      package com.mycompany.hasingleton.service.ejb;
      
      import java.util.concurrent.atomic.AtomicBoolean;
      import java.util.logging.Logger;
      
      import org.jboss.as.server.ServerEnvironment;
      import org.jboss.msc.inject.Injector;
      import org.jboss.msc.service.Service;
      import org.jboss.msc.service.ServiceName;
      import org.jboss.msc.service.StartContext;
      import org.jboss.msc.service.StartException;
      import org.jboss.msc.service.StopContext;
      import org.jboss.msc.value.InjectedValue;
      
      /**
       * @author <a href="mailto:wfink@redhat.com">Wolf-Dieter Fink</a>
       */
      public class EnvironmentService implements Service<String> {
          private static final Logger LOGGER = Logger.getLogger(EnvironmentService.class.getCanonicalName());
          public static final ServiceName SINGLETON_SERVICE_NAME = ServiceName.JBOSS.append("quickstart", "ha", "singleton");
          /**
           * A flag whether the service is started.
           */
          private final AtomicBoolean started = new AtomicBoolean(false);
      
          private String nodeName;
      
          private final InjectedValue<ServerEnvironment> env = new InjectedValue<ServerEnvironment>();
      
          public Injector<ServerEnvironment> getEnvInjector() {
              return this.env;
          }
      
          /**
           * @return the name of the server node
           */
          public String getValue() throws IllegalStateException, IllegalArgumentException {
              if (!started.get()) {
                  throw new IllegalStateException("The service '" + this.getClass().getName() + "' is not ready!");
              }
              return this.nodeName;
          }
      
          public void start(StartContext arg0) throws StartException {
              if (!started.compareAndSet(false, true)) {
                  throw new StartException("The service is still started!");
              }
              LOGGER.info("Start service '" + this.getClass().getName() + "'");
              this.nodeName = this.env.getValue().getNodeName();
          }
      
          public void stop(StopContext arg0) {
              if (!started.compareAndSet(true, false)) {
                  LOGGER.warning("The service '" + this.getClass().getName() + "' is not active!");
              } else {
                  LOGGER.info("Stop service '" + this.getClass().getName() + "'");
              }
          }
      }
      
      
    2. サーバー起動時にサービスを SingletonService として起動するためにシングルトン EJB を作成します。

      以下のリストは、サーバー起動時に SingletonService を起動するシングルトン EJB の例です。
      package com.mycompany.hasingleton.service.ejb;
      
      import java.util.Collection;
      import java.util.EnumSet;
      
      import javax.annotation.PostConstruct;
      import javax.annotation.PreDestroy;
      import javax.ejb.Singleton;
      import javax.ejb.Startup;
      
      import org.jboss.as.clustering.singleton.SingletonService;
      import org.jboss.as.server.CurrentServiceContainer;
      import org.jboss.as.server.ServerEnvironment;
      import org.jboss.as.server.ServerEnvironmentService;
      import org.jboss.msc.service.AbstractServiceListener;
      import org.jboss.msc.service.ServiceController;
      import org.jboss.msc.service.ServiceController.Transition;
      import org.jboss.msc.service.ServiceListener;
      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;
      
      
      /**
       * A Singleton EJB to create the SingletonService during startup.
       * 
       * @author <a href="mailto:wfink@redhat.com">Wolf-Dieter Fink</a>
       */
      @Singleton
      @Startup
      public class StartupSingleton {
        private static final Logger LOGGER = LoggerFactory.getLogger(StartupSingleton.class);
      
        /**
         * Create the Service and wait until it is started.<br/>
         * Will log a message if the service will not start in 10sec. 
         */
        @PostConstruct
        protected void startup() {
          LOGGER.info("StartupSingleton will be initialized!");
      
          EnvironmentService service = new EnvironmentService();
          SingletonService<String> singleton = new SingletonService<String>(service, EnvironmentService.SINGLETON_SERVICE_NAME);
          // if there is a node where the Singleton should deployed the election policy might set,
          // otherwise the JGroups coordinator will start it
          //singleton.setElectionPolicy(new PreferredSingletonElectionPolicy(new NamePreference("node2/cluster"), new SimpleSingletonElectionPolicy()));
          ServiceController<String> controller = singleton.build(CurrentServiceContainer.getServiceContainer())
              .addDependency(ServerEnvironmentService.SERVICE_NAME, ServerEnvironment.class, service.getEnvInjector())
              .install();
      
          controller.setMode(ServiceController.Mode.ACTIVE);
          try {
            wait(controller, EnumSet.of(ServiceController.State.DOWN, ServiceController.State.STARTING), ServiceController.State.UP);
            LOGGER.info("StartupSingleton has started the Service");
          } catch (IllegalStateException e) {
            LOGGER.warn("Singleton Service {} not started, are you sure to start in a cluster (HA) environment?",EnvironmentService.SINGLETON_SERVICE_NAME);
          }
        }
      
        /**
         * Remove the service during undeploy or shutdown
         */
        @PreDestroy
        protected void destroy() {
          LOGGER.info("StartupSingleton will be removed!");
          ServiceController<?> controller = CurrentServiceContainer.getServiceContainer().getRequiredService(EnvironmentService.SINGLETON_SERVICE_NAME);
          controller.setMode(ServiceController.Mode.REMOVE);
          try {
            wait(controller, EnumSet.of(ServiceController.State.UP, ServiceController.State.STOPPING, ServiceController.State.DOWN), ServiceController.State.REMOVED);
          } catch (IllegalStateException e) {
            LOGGER.warn("Singleton Service {} has not be stopped correctly!",EnvironmentService.SINGLETON_SERVICE_NAME);
          }
        }
      
        private static <T> void wait(ServiceController<T> controller, Collection<ServiceController.State> expectedStates, ServiceController.State targetState) {
          if (controller.getState() != targetState) {
            ServiceListener<T> listener = new NotifyingServiceListener<T>();
            controller.addListener(listener);
            try {
              synchronized (controller) {
                int maxRetry = 2;
                while (expectedStates.contains(controller.getState()) && maxRetry > 0) {
                  LOGGER.info("Service controller state is {}, waiting for transition to {}", new Object[] {controller.getState(), targetState});
                  controller.wait(5000);
                  maxRetry--;
                }
              }
            } catch (InterruptedException e) {
              LOGGER.warn("Wait on startup is interrupted!");
              Thread.currentThread().interrupt();
            }
            controller.removeListener(listener);
            ServiceController.State state = controller.getState();
            LOGGER.info("Service controller state is now {}",state);
            if (state != targetState) {
              throw new IllegalStateException(String.format("Failed to wait for state to transition to %s.  Current state is %s", targetState, state), controller.getStartException());
            }
          }
        }
      
        private static class NotifyingServiceListener<T> extends AbstractServiceListener<T> {
          @Override
          public void transition(ServiceController<? extends T> controller, Transition transition) {
            synchronized (controller) {
              controller.notify();
            }
          }
        }
      }
      
      
    3. クライアントよりサービスへアクセスするためステートレスセッション Bean を作成します。

      以下は、クライアントからサービスにアクセスするステートレスセッション Bean の例です。
      package com.mycompany.hasingleton.service.ejb;
      
      import javax.ejb.Stateless;
      
      import org.jboss.as.server.CurrentServiceContainer;
      import org.jboss.msc.service.ServiceController;
      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;
      
      /**
       * A simple SLSB to access the internal SingletonService.
       * 
       * @author <a href="mailto:wfink@redhat.com">Wolf-Dieter Fink</a>
       */
      @Stateless
      public class ServiceAccessBean implements ServiceAccess {
          private static final Logger LOGGER = LoggerFactory.getLogger(ServiceAccessBean.class);
      
          public String getNodeNameOfService() {
              LOGGER.info("getNodeNameOfService() is called()");
              ServiceController<?> service = CurrentServiceContainer.getServiceContainer().getService(
                      EnvironmentService.SINGLETON_SERVICE_NAME);
              LOGGER.debug("SERVICE {}", service);
              if (service != null) {
                  return (String) service.getValue();
              } else {
                  throw new IllegalStateException("Service '" + EnvironmentService.SINGLETON_SERVICE_NAME + "' not found!");
              }
          }
      }
      
      
    4. SingletonService のビジネスロジックインターフェースを作成します。

      以下は、SingletonService に対するビジネスロジックインターフェースの例です。
      package com.mycompany.hasingleton.service.ejb;
      
      import javax.ejb.Remote;
      
      /**
       * Business interface to access the SingletonService via this EJB
       * 
       * @author <a href="mailto:wfink@redhat.com">Wolf-Dieter Fink</a>
       */
      @Remote
      public interface ServiceAccess {
          public abstract String getNodeNameOfService();
      } 
      
      
      
  2. クラスタリングが有効な状態で各 Jboss Enterprise Application Platform 6 インスタンスを起動します。

    クラスターを有効化する方法は、サーバーがスタンドアロンであるか管理ドメインで実行されているかによって異なります。
    1. 管理対象ドメインで実行されているサーバーに対してクラスタリングを有効にします。

      管理 CLI を使用してクラスタリングを有効にするか、設定ファイルを手動で編集できます。
      • 管理 CLI を使用してクラスタリングを有効にします。

        1. ドメインコントローラーを起動します。

        2. 使用しているオペレーティングシステムのコマンドプロンプトを開きます。

        3. ドメインコントローラーの IP アドレスまたは DNS 名を渡して管理 CLI に接続します。

          この例では、ドメインコントローラーの IP アドレスが 192.168.0.14 であることを前提とします。
          • Linux の場合は、コマンドラインで以下を入力します。
            $ EAP_HOME/bin/jboss-cli.sh --connect --controller=192.168.0.14
            $ Connected to domain controller at 192.168.0.14
            
          • Windows の場合は、コマンドラインで以下を入力します。
            C:\>EAP_HOME\bin\jboss-cli.bat --connect --controller=192.168.0.14
            C:\> Connected to domain controller at 192.168.0.14
            
        4. main-server サーバーグループを追加します。

          [domain@192.168.0.14:9999 /] /server-group=main-server-group:add(profile="ha",socket-binding-group="ha-sockets") 
          {
              "outcome" => "success",
              "result" => undefined,
              "server-groups" => undefined
          }
          
        5. server-one という名前のサーバーを作成し、main-server サーバーグループに追加します。

          [domain@192.168.0.14:9999 /]  /host=station14Host2/server-config=server-one:add(group=main-server-group,auto-start=false)
          {
              "outcome" => "success",
              "result" => undefined
          }
          
        6. main-server サーバーグループに対して JVM を設定します。

          [domain@192.168.0.14:9999 /] /server-group=main-server-group/jvm=default:add(heap-size=64m,max-heap-size=512m)
          {
              "outcome" => "success",
              "result" => undefined,
              "server-groups" => undefined
          }
          
        7. server-two という名前のサーバーを作成し、別のサーバーグループに置き、ポートオフセットを 100 に設定します。

          [domain@192.168.0.14:9999 /]  /host=station14Host2/server-config=server-two:add(group=distinct2,socket-binding-port-offset=100)
          {
              "outcome" => "success",
              "result" => undefined
          }
          
      • サーバー設定ファイルを手動で編集してクラスタリングを有効にします。

        1. JBoss Enterprise Application Platform サーバーを停止します。

          重要

          変更がサーバーの再起動後にも維持されるようにするには、サーバー設定ファイルの編集前にサーバーを停止する必要があります。
        2. domain.xml 設定ファイルを開いて編集します。

          ha プロファイルと ha-sockets ソケットバインディンググループを使用するサーバーグループを指定します。例は次のとおりです。
          <server-groups>
            <server-group name="main-server-group" profile="ha">
              <jvm name="default">
                <heap size="64m" max-size="512m"/>
              </jvm>
              <socket-binding-group ref="ha-sockets"/>
            </server-group>
          </server-groups>
          
          
        3. host.xml 設定ファイルを開いて編集します。

          以下のようにファイルを変更します。
          <servers>
            <server name="server-one" group="main-server-group" auto-start="false"/>
            <server name="server-two" group="distinct2">
              <socket-bindings port-offset="100"/>
            </server>
          <servers>
          
          
        4. サーバーを起動します。

          • Linux の場合は、EAP_HOME/bin/domain.sh と入力します。
          • Microsoft Windows の場合は、EAP_HOME\bin\domain.bat と入力します。
    2. スタンドアロンサーバーに対してクラスタリングを有効にします。

      スタンドアロンサーバーに対してクラスタリングを有効にするには、次のようにノード名と standalone-ha.xml 設定ファイルを使用してサーバーを起動します。
      • Linux の場合は、EAP_HOME/bin/standalone.sh --server-config=standalone-ha.xml -Djboss.node.name=UNIQUE_NODE_NAME と入力します。
      • Microsoft Windows の場合は、EAP_HOME\bin\standalone.bat --server-config=standalone-ha.xml -Djboss.node.name=UNIQUE_NODE_NAME と入力します。

    注記

    1 つのマシン上で複数のサーバーが実行されている時にポートの競合が発生しないようにするため、別のインターフェースでバインドするように各サーバーインスタンスに対して standalone-ha.xml ファイルを設定します。または、コマンドラインで -Djboss.socket.binding.port-offset=100 のような引数を使用し、ポートオフセットを持つ後続のサーバーインスタンスを開始して対応することも可能です 。
  3. アプリケーションをサーバーにデプロイします。

    Maven を使用してアプリケーションをデプロイする場合は、次の Maven コマンドを使用してデフォルトのポートで稼働しているサーバーへデプロイします。
    mvn clean install jboss-as:deploy
    追加のサーバーをデプロイするには、サーバー名とポート番号をコマンドラインに渡します。
    mvn clean package jboss-as:deploy -Ddeploy.hostname=localhost -Ddeploy.port=10099

第9章 CDI

9.1. CDI の概要

9.1.2. Contexts and Dependency Injection (CDI) について

Contexts and Dependency Injection (CDI) は、EJB 3.0 コンポーネントを Java Server Faces (JSF) 管理対象 Bean として使用できるよう設計された仕様であり、2 つのコンポーネントモデルを統合し、Java を使用した Web ベースのアプリケーション向けプログラミングモデルを大幅に簡略化します。先行する引用符は JSR-299 仕様から除外されました (http://www.jcp.org/en/jsr/detail?id=299 を参照)。
JBoss Enterprise Application Platform には、JSR-299 の参照実装である Weld が含まれます。タイプセーフ依存関係挿入の詳細については、「タイプセーフ依存関係挿入について」 を参照してください。

9.1.3. CDI の利点

  • CDI を使用すると、多くのコードをアノテーションに置き換えることにより、コードベースが単純化および削減されます。
  • CDI は柔軟であり、CDI を使用すると、挿入およびイベントを無効または有効にしたり、代替の Bean を使用したり、非 CDI オブジェクトを簡単に挿入したりできます。
  • CDI で古いコードを使用することは簡単です。これを行うには beans.xmlMETA-INF/ または WEB-INF/ ディレクトリーに配置します。このファイルは空白である場合があります。
  • CDI を使用すると、パッケージ化とデプロイメントが簡略化され、デプロイメントに追加する必要がある XML の量が減少します。
  • CDI により、コンテキストを使用したライフサイクル管理が提供されます。挿入を要求、セッション、会話、またはカスタムコンテキストに割り当てることができます。
  • また、CDI により、文字列ベースの挿入よりも安全かつ簡単にデバッグを行える、タイプセーフな依存関係挿入が提供されます。
  • CDI はインターセプターと Bean を切り離します。
  • CDI では、複雑なイベント通知も提供されます。

9.1.4. タイプセーフ依存関係挿入について

JSR-299 および CDI 以前は、Java で依存関係を挿入するには文字列を使う方法しかありませんでした。この方法では間違いが起きやすいため、CDI によりタイプセーフな形で依存関係を挿入する機能が導入されました。
CDI の詳細については、「Contexts and Dependency Injection (CDI) について」 を参照してください。

9.1.5. Weld、Seam 2、 および JavaServer Faces 間の関係

Seam 2 の目的は、Enterprise Java Bean (EJB) と JavaServer Faces (JSF) 管理対象 Bean を統合することでした。
JavaServer Faces (JSF) は、JSR-314 を実装します。これは、サーバーサイドユーザーインターフェースを構築するための API です。JBoss Web Framework Kit には、JavaServer Faces と AJAX の実装であるRichFaces が含まれます。
Weld は、JSR-299 で定義されているContexts and Dependency Injection (CDI) の参照実装です。Weld は、Seam 2 と他の依存関係挿入フレームワークの影響を受けています。Weld は、JBoss Enterprise Application Platform に含まれます。

9.2. CDI の使用

9.2.1. 最初の手順

9.2.1.1. CDI の有効化

概要

Contexts and Dependency Injection (CDI) は、JBoss Enterprise Application Platform の中核的なテクノロジーの 1 つであり、デフォルトで有効になります。何らかの理由で無効になっている場合は、以下の手順に従って有効にする必要があります。

手順9.1 JBoss Enterprise Application Platform での CDI の有効化

  1. 設定ファイルで、CDI サブシステムの詳細がコメントアウトされているかどうかを確認します。

    サブシステムは、domain.xml または standalone.xml 設定ファイルの該当するセクションをコメントアウトするか、該当するセクション全体を削除することにより、無効にできます。
    EAP_HOME/domain/configuration/domain.xml または EAP_HOME/standalone/configuration/standalone.xml で CDI サブシステムを検索するには、これらのファイルで文字列 <extension module="org.jboss.as.weld"/> を検索します。検索候補が存在する場合、検索候補は <extensions> セクション内部に存在します。
  2. ファイルを編集する前に、JBoss Enterprise Application Platform を停止します。

    JBoss Enterprise Application Platform により実行中に設定ファイルが変更されるため、設定ファイルを直接編集する前にサーバーを停止する必要があります。
  3. CDI サブシステムを復元するよう設定ファイルを編集します。

    CDI サブシステムがコメントアウトされている場合は、コメントを削除します。
    CDI サブシステムが完全に削除されたら、次の行を、</extensions> タグのすぐ上にある新しい行に追加することにより、CDI サブシステムを復元します。
    <extension module="org.jboss.as.weld"/>
  4. JBoss Enterprise Application Platform を再起動します。

    更新された設定で JBoss Enterprise Application Platform を起動します。
結果

JBoss Enterprise Application Platform は、CDI サブシステムが有効になった状態で起動します。

9.2.2. CDI を使用したアプリケーションの開発

9.2.2.1. CDI を使用したアプリケーションの開発

はじめに

Contexts and Dependency Injection (CDI) を使用すると、アプリケーションの開発、コードの再利用、デプロイメント時または実行時のコードの調整、およびユニットテストを非常に柔軟に実行できます。JBoss Enterprise Application Platform には、CDI の参照実装である Weld が含まれます。これらのタスクは、エンタープライズアプリケーションで CDI を使用する方法を示しています。

9.2.2.2. 既存のコードでの CDI の使用

パラメーターがないコンストラクターを持つほぼすべての具象 Java クラスまたはアノテーション @Inject が指定されたコンストラクターは Bean です。Bean の挿入を開始する前に必要な唯一のものは、アーカイブの META-INF/ または WEB-INF/ ディレクトリーにある beans.xml という名前のファイルです。このファイルは空白の場合があります。

手順9.2 CDI アプリケーションでのレガシー Bean の使用

  1. Bean をアーカイブにパッケージ化します。

    Bean を JAR または WAR アーカイブにパッケージ化します。
  2. beans.xml ファイルをアーカイブに含めます。

    beans.xml ファイルを JAR アーカイブの META-INF/ ディレクトリーまたは WAR アーカイブの WEB-INF/ ディレクトリーに配置します。このファイルは空白の場合があります。
結果

これらの Bean を CDI で使用できます。コンテナは、Bean のインスタンスを作成および破棄し、指定されたコンテキストに関連付け、他の Bean に挿入し、EL 式で使用して、修飾子アノテーションで特殊化し、インターセプターとデコレーターをこれらに追加できます (既存のコードを変更しません)。状況によっては、いくつかのアノテーションを追加する必要がある場合があります。

9.2.2.3. スキャンプロセスからの Bean の除外

概要

Weld の機能の 1 つである JBoss Enterprise Application Platform の CDI 実装は、スキャンからアーカイブのクラスを除外する機能であり、コンテナライフサイクルイベントを発生させ、Bean としてデプロイされます。これは、JSR-299 仕様の一部ではありません。

例9.1 Bean からのパッケージの除外

以下の例では、複数の <weld:exclude> タグが使用されています。
  1. 最初のタグでは、すべての Swing クラスが除外されます。
  2. 2 番目のタグでは、Google Web Toolkit がインストールされていない場合に Google Web Toolkit クラスが除外されます。
  3. 3 番目のタグでは、文字列 Blether (通常の式を使用) で終了するクラスが除外されます (システムプロパティー verbosity low に設定されている場合)。
  4. 4 番目のタグでは、Java Server Faces (JSF) クラスが除外されます (Wicket クラスが存在し、viewlayer システムプロパティーが設定されてない場合)。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xmlns:weld="http://jboss.org/schema/weld/beans" 
       xsi:schemaLocation="
          http://java.sun.com/xml/ns/javaee http://docs.jboss.org/cdi/beans_1_0.xsd
          http://jboss.org/schema/weld/beans http://jboss.org/schema/weld/beans_1_1.xsd">
    
    <weld:scan>
      
        <!-- Don't deploy the classes for the swing app! -->
        <weld:exclude name="com.acme.swing.**" />
      
        <!-- Don't include GWT support if GWT is not installed -->
        <weld:exclude name="com.acme.gwt.**">
            <weld:if-class-available name="!com.google.GWT"/>
        </weld:exclude>
        
        <!--
            Exclude classes which end in Blether if the system property verbosity is set to low
            i.e.
              java ... -Dverbosity=low            
        -->        
        <weld:exclude pattern="^(.*)Blether$">
            <weld:if-system-property name="verbosity" value="low"/>
        </weld:exclude>
        
       <!--
             Don't include JSF support if Wicket classes are present, and the viewlayer system
             property is not set
        -->
        <weld:exclude name="com.acme.jsf.**">
            <weld:if-class-available name="org.apache.wicket.Wicket"/>
            <weld:if-system-property name="!viewlayer"/>
        </weld:exclude>
    </weld:scan>
</beans>

Weld 固有の設定オプションの正式な仕様は http://jboss.org/schema/weld/beans_1_1.xsd で参照できます。

9.2.2.4. 挿入を使用して実装を拡張

概要

挿入を使用して、既存のコードの機能を追加または変更できます。この例は、既存のクラスに翻訳機能を追加する方法を示しています。翻訳機能は想像上の機能であり、例での実装方法は擬似コードであり、説明を目的としています。

この例では、メソッド buildPhrase を持つ Welcome クラスがすでにあることを前提とします。buildPhrase メソッドは、都市の名前を引数として取得し、"Welcome to Boston." などのフレーズを出力します。ここでの目標は、このような挨拶を別の言語に翻訳できる Welcome クラスのバージョンを作成することです。

例9.2 Translator Bean を Welcome クラスに挿入する

以下の擬似コードは、想像上の Translator オブジェクトを Welcome クラスに挿入します。Translator オブジェクトは、文をある言語から別の言語に翻訳できる EJB ステートレス Bean または別のタイプの Bean になります。この例では、挨拶全体を翻訳するために Translator が使用されます。元の Welcome クラスは実際にはまったく変更されません。Translator は、buildPhrase メソッドが実装される前に挿入されます。
以下のコード例は、サンプル Translating Welcome クラスです。
public class TranslatingWelcome extends Welcome {

    @Inject Translator translator;

    public String buildPhrase(String city) {
        return translator.translate("Welcome to " + city + "!");
    }
    ...
}

9.2.3. あいまいな依存関係または満たされていない依存関係

9.2.3.1. 依存性があいまいな場合、あるいは満たされていない場合

コンテナが 1 つの Bean への注入を解決できない場合、依存性があいまいとなります。
コンテナがいずれの Bean に対しても注入の解決をできない場合、依存性が満たされなくなります。
コンテナは以下の手順を踏み、依存性の解決をはかります。
  1. インジェクションポイントの Bean 型を実装する全 Bean にある修飾子アノテーションを解決します。
  2. 無効となっている Bean をフィルタリングします。無効な Bean とは、明示的に有効化されていない @Alternative Bean のことです。
依存性があいまいな場合、あるいは満たされない場合は、コンテナはデプロイメントを中断し例外を送出します。
あいまいな依存性を修正する方法は、 「修飾子を使用して不明な挿入を解決」 を参照してください。

9.2.3.2. 修飾子について

修飾子は、Bean を Bean タイプに割り当てるアノテーションです。修飾子を使用すると、挿入する Bean を適切に指定できます。修飾子はリテンションとターゲットを持ちます。これらは、以下の例のように定義されます。

例9.3 @Synchronous 修飾子と @Asynchronous 修飾子を定義する

@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface Synchronous {}
@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface Asynchronous {}

例9.4 1@Synchronous 修飾子と @Asynchronous 修飾子を使用する

@Synchronous
public class SynchronousPaymentProcessor implements PaymentProcessor {

   public void process(Payment payment) { ... }

}
@Asynchronous
public class AsynchronousPaymentProcessor implements PaymentProcessor {

   public void process(Payment payment) { ... }
}

9.2.3.3. 修飾子を使用して不明な挿入を解決

概要

このタスクは、不明な挿入を示し、修飾子を使用して不明な挿入を削除します。不明な挿入の詳細については、「依存性があいまいな場合、あるいは満たされていない場合」 を参照してください。

例9.5 不明な挿入

Welcome の 2 つの実装があり、1 つは翻訳を行い、もう 1 つは翻訳を行いません。このような場合は、以下の挿入が不明であり、翻訳を行う Welcome を使用するよう指定する必要があります。
public class Greeter {
  private Welcome welcome;

  @Inject
  void init(Welcome welcome) {
    this.welcome = welcome;
  }
  ...
}

手順9.3 修飾子を使用して不明な挿入を解決する

  1. @Translating という修飾子アノテーションを作成します。

    @Qualifier
    @Retention(RUNTIME)
    @Target({TYPE,METHOD,FIELD,PARAMETERS})
    public @interface Translating{}
    
  2. 翻訳を行う Welcome@Translating アノテーションでアノテートします。

    @Translating
    public class TranslatingWelcome extends Welcome {
        @Inject Translator translator;
        public String buildPhrase(String city) {
            return translator.translate("Welcome to " + city + "!");
        }
        ...
    }
    
  3. 挿入の、翻訳を行う Welcome を要求します。

    ファクトリーメソッドパターンの場合と同様に、修飾された実装を明示的に要求する必要があります。不明な点は、挿入時に解決されます。
    public class Greeter {
      private Welcome welcome;
      @Inject
      void init(@Translating Welcome welcome) {
        this.welcome = welcome;
      } 
      public void welcomeVisitors() {
        System.out.println(welcome.buildPhrase("San Francisco"));
      }
    }
    
結果

TranslatingWelcome が使用されます。不明な点はありません。

9.2.4. 管理 Bean

9.2.4.1. 管理対象 Beans について

管理 Bean (MBean) は、依存関係の挿入を利用して作成した JavaBean です。各MBean はJava 仮想マシン (JVM) で実行されるリソースを表します。
Java EE 6 はこの定義に基づいて拡張されます。Bean は Java クラスにより実装され、Bean クラスとして参照されます。管理対象 bean は最上位の Java クラスです。
管理対象 Bean の詳細については、JSR-255 仕様 (http://jcp.org/en/jsr/detail?id=255) を参照してください。CDI の詳細については、「Contexts and Dependency Injection (CDI) について」 を参照してください。

9.2.4.2. Bean であるクラスのタイプ

管理対象 Bean は Java クラスです。管理対象 Bean の基本的なライフサイクルやセマンティクスは、管理対象 Bean の仕様で定義されています。Bean クラス @ManagedBean をアノテートすることで明示的に管理対象 Bean を宣言できますが、CDI ではその必要はありません。この仕様によると、CDI コンテナでは、以下の条件を満たすクラスはすべて管理対象 Bean として扱われます。
  • 非静的な内部クラスではないこと。
  • 具象クラス、あるいは @Decorator でアノテートされていること。
  • EJB コンポーネントを定義するアノテーションでアノテートされていないこと、あるいは ejb-jar.xml で EJB Bean クラスとして宣言されていること。
  • インターフェース javax.enterprise.inject.spi.Extension が実装されていないこと。
  • パラメーターのないコンストラクターか、@Inject でアノテートされたコンストラクターがあること。
管理対象 Bean の Bean 型で無制限のものには、直接的あるいは間接的に実装する Bean クラス、全スーパークラス、および全インターフェースが含まれます。
管理対象 Bean にパブリックフィールドがある場合、デフォルトの @Dependent スコープがなければなりません。

9.2.4.3. CDI を使用してオブジェクトを Bean に挿入する

デプロイメントアーカイブに META-INF/beans.xml または WEB-INF/beans.xml ファイルが含まれる場合、CDI を使用してデプロイメントの各オブジェクト挿入することが可能です。
この手順では、オブジェクトに他のオブジェクトを挿入する主な方法を紹介します。
  1. @Inject アノテーションを用いてオブジェクトを Bean の一部に挿入します。

    Bean 内でクラスのインスタンスを取得するには、フィールドに @Inject アノテーションを付けます。

    例9.6 TranslateControllerTextTranslator インスタンスを挿入する

    public class TranslateController {
    
       @Inject TextTranslator textTranslator;
       ...
    
  2. 挿入したオブジェクトのメソッドを使用する

    挿入したオブジェクトのメソッドを直接使用することが可能です。TextTranslator にメソッド translate があることを前提とします。

    例9.7 挿入したオブジェクトのメソッドを使用する

    // in TranslateController class
    
    public void translate() {
    
       translation = textTranslator.translate(inputText); 
    
    }
    
  3. Bean のコンストラクターで挿入を使用する

    ファクトリーやサービスロケーターを使用して作成する代わりに、Bean のコンストラクターへオブジェクトを挿入することができます。

    例9.8 Bean のコンストラクターで挿入を使用する

    public class TextTranslator {
    
       private SentenceParser sentenceParser;
    
       private Translator sentenceTranslator;
    
        
    
       @Inject
    
       TextTranslator(SentenceParser sentenceParser, Translator sentenceTranslator) {
    
          this.sentenceParser = sentenceParser;
    
          this.sentenceTranslator = sentenceTranslator;
    
       }
    
       // Methods of the TextTranslator class
       ...
    }
    
  4. Instance(<T>) インターフェースを使用し、プログラムを用いてインスタンスを取得します。

    Bean 型でパラメーター化されると、Instance インターフェースは TextTranslator のインスタンスを返すことができます。

    例9.9 プログラムを用いてインスタンスを取得する

    @Inject Instance<TextTranslator> textTranslatorInstance;
    
    ...
    
    public void translate() {
    
       textTranslatorInstance.get().translate(inputText);
    
    }
    
結果

オブジェクトを Bean に挿入すると、Bean は全オブジェクトのメソッドとプロパティーを使用できるようになります。Bean のコンストラクターに挿入すると、挿入が既に存在するインスタンスを参照する場合以外は、Bean のコンストラクターが呼び出されると挿入されたオブジェクトのインスタンスが作成されます。例えば、セッションのライフタイムの間にセッションスコープ付けされた Bean を挿入しても、新しいインスタンスは作成されません。

9.2.5. コンテキスト、スコープ、依存関係

9.2.5.1. コンテキストおよびスコープ

CDI の観点から、コンテキストは特定のスコープに関連付けられた Bean のインスタンスを保持するストレージ領域です。
スコープは Bean とコンテキスト間のリンクです。スコープとコンテキストの組み合わせは特定のライフサイクルを持つことがあります。事前定義された複数のスコープが存在し、独自のスコープを作成できます。事前定義されたスコープの例は @RequestScoped@SessionScoped、および @ConversationScope です。

9.2.5.2. 利用可能なコンテキスト

表9.1 利用可能なコンテキスト

コンテキスト 説明
@Dependent Bean は、参照を保持する Bean のライフサイクルにバインドされます。
@ApplicationScoped アプリケーションのライフサイクルにバインドされます。
@RequestScoped 要求のライフサイクルにバインドされます。
@SessionScoped セッションのライフサイクルにバインドされます。
@ConversationScoped 会話のライフサイクルにバインドされます。会話スコープは、要求の長さとセッションの間であり、アプリケーションによって制御されます。
カスタムスコープ 上記のコンテキストでニーズが満たされない場合は、カスタムスコープを定義できます。

9.2.6. Bean ライフサイクル

9.2.6.1. Bean のライフサイクルの管理

概要

このタスクは、要求の残存期間の間 Bean を保存する方法を示しています。他の複数のスコープが存在し、独自のスコープを定義できます。

挿入された Bean のデフォルトのスコープは @Dependent です。つまり、Bean のライフサイクルは、参照を保持する Bean のライフサイクルに依存します。詳細については、「コンテキストおよびスコープ」 を参照してください。

手順9.4 Bean ライフサイクルを管理する

  1. 必要なスコープに対応するスコープで Bean をアノテートします。

    @RequestScoped
    @Named("greeter")
    public class GreeterBean {
      private Welcome welcome;
      private String city; // getter & setter not shown
      @Inject   void init(Welcome welcome) {
        this.welcome = welcome;
      }
      public void welcomeVisitors() {
        System.out.println(welcome.buildPhrase(city));
      }
    }
    
  2. Bean が JSF ビューで使用される場合、Bean はステートを保持します。

    <h:form>
      <h:inputText value="#{greeter.city}"/>
      <h:commandButton value="Welcome visitors" action="#{greeter.welcomeVisitors}"/>
    </h:form>
    
結果

Bean は、指定するスコープに関連するコンテキストに保存され、スコープが適用される限り存続します。

9.2.6.2. プロデューサーメソッドの使用

概要

このタスクは、挿入用の Bean ではないさまざまなオブジェクトを生成するプロデューサーメソッドを使用する方法を示しています。

例9.10 代替の代わりにプロデューサーメソッドを使用してデプロイメント後のポリモーフィズムを可能にします。

例の @Preferred アノテーションは、修飾子アノテーションです。修飾子の詳細については、「修飾子について」を参照してください。
@SessionScoped
public class Preferences implements Serializable {
   private PaymentStrategyType paymentStrategy;
   ...
   @Produces @Preferred 
   public PaymentStrategy getPaymentStrategy() {
       switch (paymentStrategy) {
           case CREDIT_CARD: return new CreditCardPaymentStrategy();
           case CHECK: return new CheckPaymentStrategy();
           default: return null;
       } 
   }
}
以下の挿入ポイントは、プロデューサーメソッドと同じタイプおよび修飾子アノテーションを持つため、通常の CDI 挿入ルールを使用してプロデューサーメソッドに解決されます。プロデューサーメソッドは、この挿入ポイントを処理するインスタンスを取得するためにコンテナにより呼び出されます。
@Inject @Preferred PaymentStrategy paymentStrategy;

例9.11 プロデューサーメソッドへのスコープの割り当て

プロデューサーメソッドのデフォルトのスコープは @Dependent です。スコープを Bean に割り当てた場合、スコープは適切なコンテキストにバインドされます。この例のプロデューサーメソッドは、1 つのセッションあたり一度だけ呼び出されます。
@Produces @Preferred @SessionScoped
public PaymentStrategy getPaymentStrategy() {
   ...
}

例9.12 プロデューサーメソッド内部での挿入の使用

アプリケーションにより直接インスタンス化されたオブジェクトは、依存関係挿入を利用できず、インターセプターを持ちません。ただし、プロデューサーメソッドへの依存関係挿入を使用して Bean インスタンスを取得できます。
@Produces @Preferred @SessionScoped
public PaymentStrategy getPaymentStrategy(CreditCardPaymentStrategy ccps,
                                          CheckPaymentStrategy cps ) {
   switch (paymentStrategy) {
      case CREDIT_CARD: return ccps;
      case CHEQUE: return cps;
      default: return null;
   } 
}

要求スコープ Bean をセッションスコーププロデューサー挿入する場合は、プロデューサーメソッドにより、現在の要求スコープインスタンスがセッションスコープにプロモートされます。これは、適切な動作ではないため、プロデューサーメソッドをこのように使用する場合は注意してください。

注記

プロデューサーメソッドのスコープは、プロデューサーメソッドを宣言する Bean から継承されません。
結果

プロデューサーメソッドを使用して、非 Bean オブジェクトを挿入し、コードを動的に変更できます。

9.2.7. 名前付き Bean と代替の Bean

9.2.7.1. 名前付き Bean について

Bean には、@Named アノテーションを使用して名前が付けられます。Bean を命名することにより、Bean を Java Server Faces (JSF) で直接使用できるようになります。
@Named アノテーションは、Bean 名であるオプションパラメーターを取ります。このパラメーターが省略された場合は、小文字の Bean 名が名前として使用されます。

9.2.7.2. 名前付き Bean の使用

  1. @Named アノテーションを使用して名前を Bean に割り当てます。

    @Named("greeter")
    public class GreeterBean {
      private Welcome welcome;
    
      @Inject
      void init (Welcome welcome) {
        this.welcome = welcome;
      }
    
      public void welcomeVisitors() {
        System.out.println(welcome.buildPhrase("San Francisco"));
      }
    }
    
    Bean 名自体はオプションです。省略された場合、クラス名に基づいて Bean に名前が付けられます (最初の文字は小文字になります)。上記の例では、デフォルトの名前は greeterBean になります。
  2. JSF ビューで名前付き Bean を使用します。

    <h:form>
      <h:commandButton value="Welcome visitors" action="#{greeter.welcomeVisitors}"/>
    </h:form>
    
結果

名前付き Bean が、JSF ビューでアクションとしてコントロールに割り当てられ、コーディングが最小化されます。

9.2.7.3. 代替の Bean について

他には、実装が特定のクライアントモジュールまたはデプロイメントシナリオに固有である Bean があります。

例9.13 代替の定義

この代替により、@Synchronous PaymentProcessor と @Asynchronous PaymentProcessor の両方の模擬実装が定義されます。
@Alternative @Synchronous @Asynchronous

public class MockPaymentProcessor implements PaymentProcessor {

   public void process(Payment payment) { ... }

}
デフォルトでは、@Alternative Bean が無効になります。これらは、beans.xml ファイルを編集することにより、特定の Bean アーカイブに対して有効になります。

9.2.7.4. 代替で挿入をオーバーライド

概要

代替の Bean を使用すると、既存の Bean をオーバーライドできます。これらは、同じ役割を満たすクラスをプラグインする方法として考えることができますが、動作が異なります。これらはデフォルトで無効になります。このタスクは、代替を指定し、有効にする方法を示しています。

手順9.5 挿入をオーバーライドする

このタスクでは、プロジェクトに TranslatingWelcome クラスがすでにあることを前提としています。ただし、これを "mock" TranslatingWelcome クラスでオーバーライドするとします。これは、実際の Translator Bean を使用できないテストデプロイメントのケースに該当します。
  1. 代替を定義します。

    @Alternative
    @Translating 
    public class MockTranslatingWelcome extends Welcome {
      public String buildPhrase(string city) {
        return "Bienvenue à " + city + "!");
      }
    }
    
  2. 代替を置換します。

    置換実装をアクティベートするために、完全修飾クラス名を META-INF/beans.xml または WEB-INF/beans.xmlファイルに追加します。
    <beans>
      <alternatives>
        <class>com.acme.MockTranslatingWelcome</class>
      </alternatives>
    </beans>
    
結果

元の実装の代わりに代替実装が使用されます。

9.2.8. ステレオタイプ

9.2.8.1. ステレオタイプについて

多くのシステムでは、アーキテクチャーパターンを使用して再帰 Bean ロールのセットを生成します。ステレオタイプを使用すると、このようなロールを指定し、中心的な場所で、このロールを持つ Bean に対する共通メタデータを宣言できます。
ステレオタイプにより、以下のいずれかの組み合わせがカプセル化されます。
  • デフォルトスコープ
  • インターセプターバインディングのセット
また、ステレオタイプにより、以下の 2 つのいずれかのシナリオを指定できます。
  • ステレオタイプを持つすべての Bean にデフォルトの Bean EL 名がある
  • ステレオタイプを持つすべての Bean が代替である
Bean では、ステレオタイプをゼロ個、1 個、または複数宣言できます。ステレオタイプアノテーションは、Bean クラスまたはプロデューサーメソッドあるいはフィールドに適用できます。
ステレオタイプは、他の複数のアノテーションをパッケージ化するアノテーションであり、@Stereotype でアノテートされます。
ステレオタイプからスコープを継承するクラスは、そのステレオタイプをオーバーライドし、Bean で直接スコープを指定できます。
また、ステレオタイプが @Named アノテーションを持つ場合、配置された Bean はデフォルトの Bean 名を持ちます。この Bean は、@Named アノテーションが Bean で直接指定された場合に、この名前をオーバーライドできます。名前付き Bean の詳細については、「名前付き Bean について」 を参照してください。

9.2.8.2. ステレオタイプの使用

概要

ステレオタイプがない場合は、アノテーションをクラスタリングできます。このタスクは、ステレオタイプを使用して煩雑さとコードを減らす方法を示しています。ステレオタイプの詳細については、「ステレオタイプについて」 を参照してください。

例9.14 アノテーションの煩雑さ

@Secure
@Transactional
@RequestScoped
@Named
public class AccountManager {
  public boolean transfer(Account a, Account b) {
    ...
  }
}

手順9.6 ステレオタイプを定義および使用する

  1. ステレオタイプを定義します。

    @Secure
    @Transactional
    @RequestScoped
    @Named
    @Stereotype
    @Retention(RUNTIME)
    @Target(TYPE)
    public @interface BusinessComponent {
     ...
    }
    
  2. ステレオタイプを使用します。

    @BusinessComponent
    public class AccountManager {
      public boolean transfer(Account a, Account b) {
        ...
      }
    }
    
結果

ステレオタイプにより、コードが削減され、単純化されます。

9.2.9. オブザーバーメソッド

9.2.9.1. オブサーバーメソッドについて

オブザーバーメソッドは、イベント発生時に通知を受け取ります。
CDI は、イベントが発生したトランザクションの完了前または完了後フェーズ中にイベント通知を受け取るトランザクションオブザーバーメソッドを提供します。

9.2.9.2. イベントの発生と確認

例9.15 イベントの発生

以下のコードは、メソッドで挿入および使用されるイベントを示しています。
public class AccountManager {
  @Inject Event<Withdrawal> event;
  
  public boolean transfer(Account a, Account b) {
    ...
    event.fire(new Withdrawal(a));
  }
}

例9.16 修飾子を使用したイベントの発生

修飾子を使用して、より具体的にイベント挿入をアノテートできます。修飾子の詳細については、「修飾子について」 を参照してください。
public class AccountManager {
  @Inject @Suspicious Event <Withdrawal> event;
  
  public boolean transfer(Account a, Account b) {
    ...
    event.fire(new Withdrawal(a));
  }
}

例9.17 イベントの確認

イベントを確認するには、@Observes アノテーションを使用します。
public class AccountObserver {
  void checkTran(@Observes Withdrawal w) {
    ...
  }
}

例9.18 修飾されたイベントの確認

修飾子を使用して特定の種類のイベントだけを確認できます。修飾子の詳細については、「修飾子について」 を参照してください。
public class AccountObserver {
  void checkTran(@Observes @Suspicious Withdrawal w) {
    ...
  }
}

9.2.10. インターセプター

9.2.10.1. インターセプターについて

インターセプターは、JavaBeans 仕様の一部として定義されます (http://jcp.org/aboutJava/communityprocess/final/jsr318/ を参照)。インターセプターを使用すると、Bean のメソッドを直接変更せずに Bean のビジネスメソッドに機能を追加できます。インターセプターは、Bean のビジネスメソッドの前に実行されます。
CDI により、インターセプターと Bean をバインドするアノテーションを利用できるため、この機能が強化されます。

インターセプションポイント

ビジネスメソッドのインターセプション
ビジネスメソッドのインターセプターは、Bean のクライアントによる Bean のメソッド呼び出しに適用されます。
ライフサイクルコールバックのインターセプション
ライフサイクルのコールバックインターセプションは、コンテナによるライフサイクルコールバックの呼び出しに適用されます。
タイムアウトメソッドのインターセプション
タイムアウトメソッドのインターセプターは、コンテナによる EJB タイムアウトメソッドの呼び出しに適用されます。

9.2.10.2. CDI とのインターセプターの使用

例9.19 CDI なしのインターセプター

CDI がない場合、インターセプターには 2 つの問題があります。
  • Bean は、インターセプター実装を直接指定する必要があります。
  • アプリケーションの各 Bean は、インターセプターの完全なセットを適切な順序で指定する必要があります。この場合、アプリケーション全体でインターセプターを追加または削除するには時間がかかり、エラーが発生する傾向があります。
@Interceptors({
  SecurityInterceptor.class,
  TransactionInterceptor.class,
  LoggingInterceptor.class
})
@Stateful public class BusinessComponent {
  ...
}

手順9.7 CDI とのインターセプターの使用

  1. インターセプターバインディングタイプを定義します。

    @InterceptorBinding
    @Retention(RUNTIME)
    @Target({TYPE, METHOD})
    public @interface Secure {}
    
  2. インターセプター実装をマークします。

    @Secure
    @Interceptor
    public class SecurityInterceptor {
      @AroundInvoke
      public Object aroundInvoke(InvocationContext ctx) throws Exception {
        // enforce security ...
        return ctx.proceed();
        }
    }
    
  3. ビジネスコードでインターセプターを使用します。

    @Secure
    public class AccountManager {
      public boolean transfer(Account a, Account b) {
        ...
      }
    }
    
  4. インターセプターを META-INF/beans.xml または WEB-INF/beans.xml に追加することにより、インターセプターをデプロイメントで有効にします。

    <beans>
      <interceptors>
        <class>com.acme.SecurityInterceptor</class>
        <class>com.acme.TransactionInterceptor</class>
      </interceptors>
    </beans>
    
    インターセプターは、リストされた順序で適用されます。
結果

CDI により、インターセプターコードが単純化され、ビジネスコードへの適用が簡単になります。

9.2.11. デコレーターについて

デコレーターは、特定の Java インターフェースからの呼び出しをインターセプトし、そのインターフェースに割り当てられたすべてのセマンティクスを認識します。デコレーターは、何らかの業務をモデル化するのに役に立ちますが、インターセプターの一般性を持ちません。デコレーターは Bean または抽象クラスであり、デコレートするタイプを実装し、@Decorator でアノテートされます。

例9.20 デコレーターの例

@Decorator

public abstract class LargeTransactionDecorator

      implements Account {

   @Inject @Delegate @Any Account account;

   @PersistenceContext EntityManager em;

   public void withdraw(BigDecimal amount) {

      ...

   }
    
   public void deposit(BigDecimal amount);

      ...

   }

}

9.2.12. 移植可能な拡張機能について

CDI は、フレームワーク、拡張機能、および他のテクノロジーとの統合の基礎となることを目的としています。したがって、CDI は、移植可能な CDI の拡張機能の開発者が使用する SPI のセットを公開します。拡張機能は、以下の種類の機能を提供できます。
  • ビジネスプロセス管理エンジンとの統合
  • Spring、Seam、GWT、Wicket などのサードパーティーフレームワークとの統合
  • CDI プログラミングモデルに基づく新しいテクノロジー
JSR-299 仕様に基づいて、移植可能な拡張機能は次の方法でコンテナと統合できます。
  • 独自の Bean、インターセプター、およびデコレーターをコンテナに提供します。
  • 依存関係挿入サービスを使用して独自のオブジェクトに依存関係を挿入します。
  • カスタムスコープのコンテキスト実装を提供します。
  • アノテーションベースのメタデータを他のソースからのメタデータで拡大またはオーバーライドします。

9.2.13. Bean プロキシ

9.2.13.1. Bean プロキシ

プロキシは Bean のサブクラスでランタイム時に生成されます。プロキシは Bean の作成時に挿入され、依存 Bean のライフサイクルはプロキシに関係しているため、依存するスコープ付き Bean をプロキシから挿入することができます。また、プロキシは依存関係の挿入の代わりとして使用され、2 つの問題を解決します。

プロキシを利用することで解決される依存関係挿入の問題

  • パフォーマンス - プロキシは依存関係の挿入よりも速度が早いため、高パフォーマンスを必要とする Bean に利用することができます。
  • スレッドセーフ - 複数のスレッドが同時に Bean にアクセスしている場合でも、プロキシは適切な Bean インスタンスにリクエストを転送します。依存関係の挿入はスレッドの安全性を保証しません。

プロキシ化できないクラス型

  • プリミティブ型あるいはアレイ型
  • final のクラスあるいは final メソッドを持つクラス
  • プライベートではないデフォルトのコンストラクターを持つクラス

9.2.13.2. 挿入でプロキシを使用する

概要

各 Bean のライフサイクルが異なる場合に挿入にプロキシが使用されます。プロキシはランタイム時に作成された Bean のサブクラスで、Bean クラスのプライベートメソッド以外のメソッドをすべて上書きします。プロキシは実際の Bean インスタンスへ呼び出しを転送します。

この例では、PaymentProcessor インスタンスは直接 Shop へ挿入されません。その代わりにプロキシが挿入され、processPayment() メソッドが呼び出されるとプロキシが現在の PaymentProcessor Bean インスタンスをルックアップし、processPayment() メソッドを呼び出します。

例9.21 プロキシの挿入

@ConversationScoped
class PaymentProcessor
{
  public void processPayment(int amount)
  {
    System.out.println("I'm taking $" + amount);
  }
}
 
@ApplicationScoped
public class Shop
{
 
  @Inject
  PaymentProcessor paymentProcessor; 
 
  public void buyStuff()
  {
    paymentProcessor.processPayment(100);
  }
}

プロキシ化できるクラス型などプロキシに関する詳細情報は 「Bean プロキシ」 を参照してください。

第10章 Java トランザクション API (JTA)

10.1. 概要

10.1.1. Java トランザクション API (JTA) の概要

はじめに

これらのトピックは、 Java トランザクション API (JTA) の基礎的な内容について取り上げます。

10.2. トランザクションの概念

10.2.1. トランザクションについて

トランザクションは 2 つ以上のアクションで構成されており、アクションすべてが成功または失敗する必要があります。成功した場合はコミット、失敗した場合はロールバックが結果的に実行されます。ロールバックでは、トランザクションがコミットを試行する前に、各メンバーのステートが元の状態に戻ります。
適切に設計されたトランザクションは一般的に ACID (原子性、一貫性、独立性、永続性) を基準とします。

10.2.2. トランザクションの ACID プロパティーについて

ACID は 原子性 (Atomicity)、一貫性 (Consistency)、独立性 (Isolation)、永続性 (Durability) の略語です。この単語は通常データベースやトランザクション操作において使用されます。

ACID の定義

原子性 (Atomicity)
トランザクションの原子性を保つには、トランザクション内の全メンバーが同じ決定をする必要があります。つまり、全メンバーがコミットまたはロールバックを行う必要があります。原子性が保たれない場合の結果をヒューリスティックな結果と言います。
一貫性 (Consistency)
一貫性とは、データベーススキーマの観点から、データベースに書き込まれたデータが有効なデータであることを保証するという意味です。データベースあるいは他のデータソースは常に一貫した状態でなければなりません。一貫性のない状態の例には、操作が中断される前にデータの半分が書き込みされてしまったフィールドなどがあります。すべてのデータが書き込まれた場合や、書き込みが完了しなかった時に書き込みがロールバックされた場合に、一貫した状態となります。
独立性 (Isolation)
独立性とは、トランザクションのスコープ外のプロセスがデータを変更できないように、トランザクションで操作されたデータが変更前にロックされる必要があることを意味します。
永続性 (Durability)
永続性とは、トランザクションのメンバーにコミットの指示を出してから外部で問題が発生した場合、問題が解決されると全メンバーがトランザクションのコミットを継続できるという意味です。ここで言う問題とは、ハードウェア、ソフトウェア、ネットワークなどのシステムが関係する問題のことです。

10.2.3. トラザクションコーディネーターあるいはトランザクションマネージャーについて

JBoss Enterprise Application Platform のトランザクションでは、トランザクションコーディネータートランザクションマネージャーの用語はほとんど同じことを意味します。トランザクションコーディネーターという用語は通常、分散トランザクションで利用されます。
JTA トランザクションでは、トランザクションマネージャーは JBoss Enterprise Application Platform 内で実行され、2相コミットのプロトコルでトランザクションの参加者と通信します。
トランザクションマネージャーはトランザクションの参加者に対して、別のトランザクションの参加者の結果に従い、データをコミットするか、ロールバックするか指示を出します。こうすることで、確実にトランザクションが ACID 基準に準拠するようにします。
JTS トランザクションでは、トランザクションコーディネーターは別サーバーにある各種トランザクションマネージャー同士のやり取りを管理します。

10.2.4. トランザクションの参加者を表示します。

トランザクションの参加者とはトランザクション内のプロセスのことで、ステートをコミットあるいはロールバックする機能を持ちます。データベースや他のアプリケーションなどがその一例です。トランザクションの各参加者は、他のすべての参加者がステートのコミットに合意した場合にのみステートをコミットします。その他の場合は、各参加者はロールバックを実行します。

10.2.5. Java Transactions API (JTA) について

Java Transactions API (JTA) は、Java Enterprise Edition アプリケーションでトランザクションを利用する際の仕様で、JSR-907 に定義されています。
JTA トランザクションは複数のアプリケーションサーバーにまたがって分散されず、ネストすることはできません。
JTA トランザクションは EJB コンテナーで制御されます。アノテーションは、お使いのコード内でトランザクションを作成および制御する 1 つの方法です。

10.2.6. Java Transaction Service (JTS) について

Java トランザクションサービス (JTS) は、トランザクションの参加者が複数の Java Enterprise Edition コンテナ (アプリケーションサーバー) に存在する場合に Java Transaction API (JTA) トランザクションをサポートするメカニズムです。ローカル JTA トランザクションの場合と同様に、各コンテナはトランザクションマネージャー (TM) と呼ばれるプロセスを実行します。TM は、Common Object Request Broker Architecture (CORBA) と呼ばれる通信標準を使用して Object Request Broker (ORB) と呼ばれるプロセスでお互いと通信します。
アプリケーションの観点から、JTS トランザクションは JTA トランザクションと同様に動作します。違いは、トランザクションの参加者とデータソースが別のコンテナに存在することです。

注記

JBoss Enterprise Application Platform に含まれる JTS の実装は、分散 JTA トランザクションをサポートします。分散 JTA トランザクションと完全準拠 JTS トランザクションの違いは外部のサードパーティー ORB との相互運用性です。この機能は、JBoss Enterprise Application Platform 6 ではサポートされません。サポートされる設定では、複数の JBoss Enterprise Application Platform コンテナでのみトランザクションが分散されます。

10.2.7. XA データソースおよび XA トランザクションについて

XA データソースとは XA のグローバルトランザクションに参加できるデータソースのことです。
XA トランザクションとは、複数のリソースにまたがることができるトランザクションのことです。これには、コーディネートを行うトランザクションマネージャーが関係します。このトランザクションマネージャーは、すべてが 1 つのグローバルトランザクションに関与する 1 つ以上のデータベースまたはその他のトランザクションリソースを持ちます。

10.2.8. XA リカバリーについて

Java トランザクション API (JTA) は複数の X/Open XA リソース にまたがる分散トランザクションを許可します。XA は Extended Architecture (拡張アーキテクチャー) の略で、複数のバックエンドデータストアを使用するトランザクションを定義するため X/Open Group によって開発されました。XA 標準には、グローバル トランザクションマネージャー (TM) とローカルリソースマネージャーとの間のインターフェースに関する説明があります。XA は、トランザクションの原子性を保持しながらアプリケーションサーバー、データベース、キャッシュ、メッセージキューなどの複数のリソースが同じトランザクションに参加できるようにします。原子性とは、参加者の 1 つが変更のコミットに失敗した場合に他の参加者がトランザクションをアボートし、トランザクションが発生する前の状態に戻すことを言います。
XA リカバリーは、トランザクションの参加者がクラッシュしたり使用できなくなったりしても、トランザクションの影響を受けたすべてのリソースが確実に更新またはロールバックされるようにするプロセスのことです。JBoss Enterprise Application Platform 6 の範囲内では、XA データソースや JMS メッセージキュー、JCA リソースアダプターなどの XA リソースやサブシステムに対して、トランザクションサブシステムが XA リカバリーのメカニズムを提供します。
XA リカバリーはユーザーの介入がなくても発生します。XA リカバリーに失敗すると、エラーがログ出力に記録されます。サポートが必要な場合は Red Hat グローバルサポートサービスまでご連絡ください。

10.2.9. 2 相コミットプロトコルについて

2 相コミット (2PC) とはデータベーストランザクションでの通常のパターンのことです。
フェーズ 1

最初のフェーズでは、トランザクションをコミットできるか、あるいはロールバックする必要があるかをトランザクションの参加者がトランザクションコーディネーターに通知します。

フェーズ 2

2 番目のフェーズでは、トランザクションコーディネーターが全体のトランザクションをコミットするか、ロールバックするか決定します。参加者が 1 つでもコミットできない場合、トランザクションはロールバックしなければなりません。参加者がすべてコミットできる場合はトランザクションはコミットすることができます。コーディネーターは何を行うかをトランザクションに指示し、トランザクションは何を行ったかコーディネーターに通知します。この時点で、トランザクションが完了します。

10.2.10. トランザクションタイムアウトについて

原子性を確保し、トランザクションを ACID 標準に準拠させるため、トランザクションの一部が長期間実行される場合があります。トランザクションの参加者は、コミット時にデータソースの一部をロックする必要があります。また、トランザクションマネージャーは各トランザクション参加者からの応答を待ってからすべての参加者にコミットあるいはロールバックの指示を出す必要があります。ハードウェアあるいはネットワークの障害のため、リソースが永久にロックされることがあります。
トランザクションのタイムアウトをトランザクションと関連付け、ライフサイクルを制御することができます。タイムアウトのしきい値がトランザクションのコミットあるいはロールバック前に渡された場合、タイムアウトにより、自動的にトランザクションがロールバックされます。
トランザクションサブシステム全体に対しデフォルトのタイムアウト値を設定できます。または、デフォルトのタイムアウト値を無効にし、トランザクションごとにタイムアウトを指定できます。

10.2.11. 分散トランザクションについて

分散トランザクションあるいは分散 Java Transaction API (JTA) トランザクションは、複数の Enterprise Application Platform サーバー上に参加者が存在するトランザクションです。 分散トランザクションと Java Transaction Service (JTS) トランザクションとの違いは、JTS の仕様では異なるベンダーのアプリケーションサーバーにまたがってトランザクションが分散可能でなければならない点です。JBoss Enterprise Application Platform は分散 JTA トランザクションに対応しています。

10.2.12. ORB 移植性 API について

Object Request Broker (ORB) とは、複数のアプリケーションサーバーにわたって分散されるトランザクションの参加者、コーディネーター、リソース、その他のサービスにメッセージを送受信するプロセスのことです。ORB は標準的なインターフェース記述言語 (IDL) を使用してメッセージを通信し解釈します。Common Object Request Broker Architecture (CORBA) は JBoss Enterprise Application Platform の ORB によって使用される IDL です。
ORB を使用する主なタイプのサービスは、Java トランザクションサービス (JTS) プロトコルを使用する分散 Java トランザクションのシステムです。レガシーシステムなどの他のシステムは、通信にリモートエンタープライズ JavaBeans や JAX-WS または JAX-RS Web サービスなどのメカニズムを使用せずに、 ORB を使用することがあります。
ORB 移植性 API は ORB とやりとりするメカニズムを提供します。この API は ORB への参照を取得するメソッドや、ORB からの受信接続をリッスンするモードにアプリケーションを置くメソッドを提供します。API のメソッドの一部はすべての ORB によってサポートされていません。このような場合、例外がスローされます。
API は 2 つの異なるクラスによって構成されます。

ORB 移植性 API のクラス

  • com.arjuna.orbportability.orb
  • com.arjuna.orbportability.oa
ORB 移植性 API に含まれるメソッドやプロパティーの詳細は、Red Hat カスタマーポータルで JBoss Enterprise Application Platform 6 の Javadocs バンドルを参照してください。

10.2.13. ネストされたトランザクションについて

ネストされたトランザクションは、一部の参加者がトランザクションでもあるトランザクションです。

ネストされたトランザクションの利点

障害の分離
サブトランザクションがロールバックされた場合に、使用しているオブジェクトが失敗したため、エンクローズトランザクションはロールバックする必要がありません。
モジュール性
新しいトランザクションが開始されるときにトランザクションがすでに呼び出しに関連付けられている場合は、新しいトランザクションがそのトランザクション内にネストされます。したがって、オブジェクトでトランザクションが必要なことがわかっている場合は、オブジェクト内でトランザクションを開始できます。オブジェクトのメソッドがクライアントトランザクションなしで呼び出された場合は、オブジェクトのトランザクションは最上位レベルです。それ以外の場合、これらのトランザクションはクライアントのトランザクションのスコープ内でネストされます。同様に、クライアントはオブジェクトがトランザクション対応であるかどうかを知る必要がありません。クライアントは、独自のトランザクションを開始できます。
ネストされたトランザクションは、Java トランザクション API (JTA) の一部ではなく Java トランザクションサービス (JTS) API の一部としてのみサポートされます。(非分散) JTA トランザクションをネストしようとすると、例外が発生します。

10.3. トランザクションの最適化

10.3.1. トランザクション最適化の概要

はじめに

JBoss Enterprise Application Platform のトランザクションサブシステムには複数の最適化機能が含まれており、お使いのアプリケーションでご活用いただけます。

10.3.2. 1相コミット (1PC) の LRCO 最適化について

トランザクションでは、一般的に 2 相コミットプロトコル (2PC) が使用されることが多いですが、両フェーズに対応する必要がなかったり、対応できない場合もあります。そのような場合、1 相コミット (1PC) プロトコルを使用することができます。XA 未対応のデータソースがトランザクションに参加する必要がある場合などがこの一例になります。
このような状況では、最終リソースコミット最適化 (LRCO: Last Resource Commit Optimization) という最適化が適用されます。1 相リソースは、トランザクションの準備フェーズで最後に処理され、コミットが試行されます。コミットに成功すると、トランザクションログが書き込まれ、残りのリソースが 2PC に移動します。最終リソースがコミットに失敗すると、トランザクションはロールバックされます。
このプロトコルにより、トランザクションの多くが通常に完了できますが、特殊なエラーによりトランザクションの結果に一貫性がなくなってしまう場合もあります。そのため、この方法は最終手段としてお使いください。
ローカルの TX データソースが1つのみトランザクションで使用されると、LRCO が自動的に適用されます。

10.3.3. 推定中止 (presumed-abort) 最適化について

トランザクションをロールバックする場合、この情報をローカルで記録し、参加している参加者すべてに通知します。この通知は形式的なもので、トランザクションの結果には何ら影響を与えません。全参加者に通知がいくと、このトランザクションに関する情報を削除することができます。
トランザクションのステートに対する後続の要求が発生すると、利用可能な情報がなくなります。このような場合、要求側はトランザクションが中断され、ロールバックされたと推測します。推定中止 (presumed-abort) の最適化とは、トランザクションがコミットの実行を決定するまでは参加者に関する情報を永続化する必要がないことを意味します。これは、トランザクションがコミットの実行を決定する時点以前に発生した障害はトランザクションの中止であると推定されるためです。

10.3.4. 読み取り専用の最適化について

参加者が準備するよう要求されると、トランザクション中に変更したデータがないことをコーディネーターに伝えることができます。参加者が最終的にどうなってもトランザクションに影響を与えることはないため、このような参加者にトランザクションの結果について通知する必要はありません。読み取り専用の参加者はコミットプロトコルの第二フェーズから省略可能です。

10.4. トランザクションの結果

10.4.1. トランザクションの結果について

可能なトランザクションの結果は次の 3 つになります。
ロールバック
トランザクションの参加者のいずれかがコミットできなかったり、トランザクションコーディネーターが参加者にコミットを指示できない場合、トランザクションがロールバックされます。詳細は 「トランザクションロールバックについて」 を参照してください。
コミット
トランザクションの参加者すべてがコミットできる場合、トランザクションコーディネーターはコミットの実行を指示します。詳細は 「トランザクションのコミットについて」 を参照してください。
ヒューリスティックな結果
トランザクションの参加者の一部がコミットし、他の参加者がロールバックした場合をヒューリスティックな結果と呼びます。ヒューリスティックな結果が発生すると、人的な介入が必要になります。詳細は 「ヒューリスティックな結果について」 を参照してください。

10.4.2. トランザクションのコミットについて

トランザクションの参加者がコミットすると、新規のステートが永続化されます。新規のステートはトランザクションで作業を行った参加者により作成されます。トランザクションのメンバーがデータベースに記録を書き込む時などが最も一般的な例になります。
コミット後、トランザクションの情報はトランザクションコーディネーターから削除され、新たに書き込まれたステートが永続ステートとなります。

10.4.3. トランザクションロールバックについて

トランザクションの参加者はトランザクションの開始前に、ステートを反映するためステートをリストアし、ロールバックを行います。ロールバック後のステートはトランザクション開始前のステートと同じになります。

10.4.4. ヒューリスティックな結果について

ヒューリスティックな結果あるいは原子的でない結果とは、トランザクションに異常があることで、トランザクションの参加者の一部はステートをコミットし、その他の参加者はロールバックした場合を言います。ヒューリスティックな結果が発生すると、ステートの一貫性が保たれなくなります。
通常、ヒューリスティックな結果は、2 相コミット (2PC) プロトコルの 2 番目のフェーズで発生します。基盤のハードウェアや基盤サーバーの通信サブシステムの障害が原因となる場合が多くあります。
ヒューリスティックな結果には 4 種類あります。
ヒューリスティックロールバック
参加者の一部あるいはすべてが一方的にトランザクションをロールバックしたため、コミット操作に失敗します。
ヒューリスティックコミット
参加者のすべてが一方的にコミットしたため、ロールバック操作に失敗します。例えば、コーディネーターが正常にトランザクションを準備したにも関わらず、ログ更新の失敗などコーディネーター側で障害が発生したためロールバックの実行を決定した場合などに発生します。暫定的に参加者がコミットの実行を決定する場合があります。
ヒューリスティック混合
一部の参加者がコミットし、その他の参加者はロールバックした状態です。
ヒューリスティックハザード
更新の一部の結果が不明な状態です。既知の更新結果はすべてコミットまたはロールバックします。
ヒューリスティックな結果が起こると、システムの整合性が保たれなくなり、通常、解決に人的介入が必要になります。ヒューリスティックな結果に依存するようなコードは記述しないようにしてください。

10.4.5. JBoss Transactions エラーと例外

UserTransaction クラスのメソッドがスローする例外に関する詳細は、http://download.oracle.com/javaee/1.3/api/javax/transaction/UserTransaction.html の 『UserTransaction API』 の仕様を参照してください。

10.5. JTA トランザクションの概要

10.5.1. Java Transactions API (JTA) について

Java Transactions API (JTA) は、Java Enterprise Edition アプリケーションでトランザクションを利用する際の仕様で、JSR-907 に定義されています。
JTA トランザクションは複数のアプリケーションサーバーにまたがって分散されず、ネストすることはできません。
JTA トランザクションは EJB コンテナーで制御されます。アノテーションは、お使いのコード内でトランザクションを作成および制御する 1 つの方法です。

10.5.2. JTA トランザクションのライフサイクル

リソースがトランザクションへの参加を要求すると、一連のイベントが開始されます。トランザクションマネージャーは、アプリケーションサーバー内のプロセスで、トランザクションを管理します。トランザクションの参加者は、トランザクションに参加するオブジェクトです。また、リソースとは、データソースや JMS 接続ファクトリ、その他の JCA 接続のことです。
  1. アプリケーションが新しいトランザクションを開始する

    トランザクションを開始するには、お使いのアプリケーションが JNDI から(または、EJB の場合はアノテーションから) UserTransaction クラスのインスタンスを取得します。UserTransaction インターフェースには、トップレベルのトランザクションを開始、コミット、ロールバックするメソッドが含まれています。新規作成されたトランザクションは、そのトランザクションを呼び出すスレッドと自動的に関連付けされます。ネストされたトランザクションは JTA ではサポートされないため、すべてのトランザクションがトップレベルのトランザクションとなります。
    UserTransaction.begin() を呼び出すと、新規トランザクションが開始されます。この時点移行に使ったリソースはすべて、このトランザクションと関連付けられます。1つ以上のリソースが登録された場合、このトランザクションは XA トランザクションになり、コミット時に 2 相コミットプロトコルに参加します。
  2. アプリケーションがステートを変更する

    次に、トランザクションが作業を実行しステートを変更します。
  3. アプリケーションがコミットまたはロールバックを決定する

    お使いのアプリケーションがステータスの変更を終了すると、コミットするか、ロールバックするか決定し、適切なメソッドを呼び出します。UserTransaction.commit() または UserTransaction.rollback() を呼び出します。1 つ以上のリソースを登録している場合は、ここで 2 相コミットプロトコル (2PC) が起こります。「2 相コミットプロトコルについて」
  4. トランザクションマネージャーが記録からトランザクションを削除する

    コミットあるいはロールバックが完了すると、トランザクションマネージャーは記録を消去し、トランザクションに関する情報を削除します。
障害回復

障害回復は自動的に行われます。リソース、トランザクションの参加者、アプリケーションサーバーが使用できなくなった場合、この問題が解決した時にトランザクションマネージャーがリカバリー処理を行います。

10.6. トランザクションサブシステムの設定

10.6.1. トランザクション設定の概要

はじめに

次の手順は、JBoss Enterprise Application Platform のトランザクションサブシステムを設定する方法を示しています。

10.6.2. トランザクションデータソースの設定

10.6.2.1. JTA トランザクションを使用するようにデータソースを設定

概要

ここでは、データソースで Java Transactions API (JTA) を有効にする方法を説明します。

要件

このタスクを行う前に、 次の条件を満たす必要があります。

  • お使いのデータベースまたはその他のリソースが JTA をサポートしている必要があります。不明な場合は、データソースまたはリソースの文書を参照してください。
  • データベースを作成する必要があります。「管理インターフェースによる非 XA データソースの作成」 を参照してください。
  • JBoss Enterprise Application Platform を停止します。
  • テキストエディターで設定ファイルを直接編集できる権限を持たなければなりません。

手順10.1 JTA トランザクションを使用するようデータソースを設定する

  1. テキストエディターで設定ファイルを開きます。

    JBoss Enterprise Application Platform を管理対象ドメインまたはスタンドアロンサーバーで実行するかによって、設定ファイルの場所は異なります。
    • 管理対象ドメイン

      管理対象ドメインのデフォルトの設定ファイルは、Red Hat Enterprise Linux の場合は EAP_HOME/domain/configuration/domain.xml にあります。Microsoft Windows サーバーの場合は EAP_HOME\domain\configuration\domain.xml にあります。
    • スタンドアロンサーバー

      スタンドアロンサーバーのデフォルトの設定ファイルは、Red Hat Enterprise Linux の場合は EAP_HOME/standalone/configuration/standalone.xml にあります。Microsoft Windows サーバーの場合は EAP_HOME\standalone\configuration\standalone.xml にあります。
  2. お使いのデータソースに対応する <datasource> タグを探します。

    データソースの jndi-name 属性には作成時に指定した属性が設定されます。例えば、 ExampleDS データソースは次のようになります。
    <datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="H2DS" enabled="true" jta="true" use-java-context="true" use-ccm="true">
  3. jta 属性を true に設定します。

    上記のように、jta="true"<datasource> タグの内容に追加します。
  4. 設定ファイルを保存します。

    設定ファイルを保存しテキストエディターを終了します。
  5. JBoss Enterprise Application Platform を起動します。

    JBoss Enterprise Application Platform 6 サーバーを再起動します。
結果

JBoss Enterprise Application Platform が起動し、データソースが JTA トランザクションを使用するように設定されます。

10.6.2.2. XA Datasource の設定

要件

XA Datasource を追加するには、管理コンソールにログインする必要があります。詳細は 「管理コンソールへログイン」 を参照してください。

  1. 新しいデータソースの追加

    新しいデータソースを JBoss Enterprise Application Platform に追加します。「管理インターフェースによる非 XA データソースの作成」 の手順に従いますが、上部の XA Datasource タブをクリックしてください。
  2. 必要に応じて他のプロパティーを設定します。

    データソースパラメーターの一覧は 「データソースのパラメーター」 にあります。
結果

XA Datasource が設定され、使用する準備ができます。

10.6.2.3. 管理コンソールへログイン

要件

  • JBoss Enterprise Application Platform 6 が稼働している必要があります。

手順10.2 管理コンソールへログイン

  1. 管理コンソールのスタートページに移動

    Web ブラウザーで管理コンソールに移動します。デフォルトの場所は http://localhost:9990/console/ です。ポート 9990 は管理コンソールのソケットバインディングとして事前定義されています。
  2. 管理コンソールへログイン

    以前作成したアカウントのユーザー名とパスワードを入力し、管理コンソールのログイン画面でログインします。
    管理コンソールのログイン画面。

    図10.1 管理コンソールのログイン画面

結果

ログインすると、管理コンソールの最初のページが表示されます。
管理対象ドメイン
スタンドアロンサーバー

10.6.2.4. 管理インターフェースによる非 XA データソースの作成

概要

ここでは、管理コンソールまたは管理 CLI のいずれかを使用して非 XA データソースを作成する手順について取り上げます。

要件

  • JBoss Enterprise Application Platform 6 サーバーが稼働している必要があります。

注記

バージョン 10.2 以前の Oracle データソースでは非トランザクション接続とトランザクション接続が混在するとエラーが発生したため、<no-tx-separate-pools/> パラメーターが必要でした。一部のアプリケーションでは、このパラメーターが必要ではなくなりました。

手順10.3 管理 CLI または管理コンソールのいずれかを使用したデータソースの作成

    • 管理 CLI

      1. CLI ツールを起動し、サーバーに接続します。
      2. 以下のコマンドを実行して非 XA データソースを作成し、適切に変数を設定します。
        data-source add --name=DATASOURCE_NAME --jndi-name=JNDI_NAME --driver-name=DRIVER_NAME  --connection-url=CONNECTION_URL
      3. データソースを有効にします。
        data-source enable --name=DATASOURCE_NAME
    • 管理コンソール

      1. 管理コンソールへログインします。
      2. 管理コンソールの [Datasources] パネルに移動します。

          • スタンドアロンモード

            コンソールの右上より [Profile] タブを選択します。
          • ドメインモード

            1. コンソールの右上より [Profiles] タブを選択します。
            2. 左上のドロップダウンボックスより該当するプロファイルを選択します。
            3. コンソールの左側にある [Subsystems] メニューを展開します。
        1. コンソールの左側にあるメニューより [Connector][Datasources] と選択します。
        データソースパネル

        図10.2 データソースパネル

      3. 新しいデータソースの作成

        1. [Datasources] パネル上部にある [Add] ボタンを選択します。
        2. Create Datasource ウィザードで新しいデータソースの属性を入力し、[Next] ボタンを押します。
        3. Create Datasource ウィザードで JDBC ドライバーの詳細を入力し、[Next] ボタンを押します。
        4. Create Datasource ウィザードで接続設定を入力し、[Done] ボタンを押します。
結果

非 XA データソースがサーバーに追加されます。standalone.xml または domain.xml ファイル、および管理インターフェースで追加を確認することができます。

10.6.2.5. データソースのパラメーター

表10.1 非 XA および XA データソースに共通のデータソースパラメーター

パラメーター 説明
jndi-name データソースの一意の JNDI 名。
pool-name データソースの管理プール名。
enabled データソースが有効かどうかを指定します。
use-java-context
データソースをグローバルの JNDI にバインドするかどうかを指定します。
spy
JDBC レイヤーで spy 機能を有効にします。この機能は、データソースへの JDBC トラフィックをすべてログに記録します。また、logging-category パラメーターを org.jboss.jdbc に設定する必要があります。
use-ccm キャッシュ接続マネージャーを有効にします。
new-connection-sql 接続プールに接続が追加された時に実行する SQL ステートメント。
transaction-isolation
次のいずれかになります。
  • TRANSACTION_READ_UNCOMMITTED
  • TRANSACTION_READ_COMMITTED
  • TRANSACTION_REPEATABLE_READ
  • TRANSACTION_SERIALIZABLE
  • TRANSACTION_NONE
url-delimiter 高可用性 (HA) クラスターデータベースの connection-url にある URL の区切り文字。 
url-selector-strategy-class-name インターフェース org.jboss.jca.adapters.jdbc.URLSelectorStrategy を実装するクラス。
security
セキュリティー設定である子要素が含まれます。表10.6「セキュリティーパラメーター」 を参照してください。
validation
検証設定である子要素が含まれます。表10.7「検証パラメーター」 を参照してください。
timeout
タイムアウト設定である子要素が含まれます。表10.8「タイムアウトパラメーター」 を参照してください。
statement
ステートメント設定である子要素が含まれます。表10.9「ステートメントのパラメーター」 を参照してください。

表10.2 非 XA データソースのパラメーター

パラメーター 説明
jta 非 XA データソースの JTA 統合を有効にします。XA データソースには適用されません。
connection-url JDBC ドライバーの接続 URL。
driver-class JDBC ドライバークラスの完全修飾名。
connection-property
Driver.connect(url,props) メソッドに渡される任意の接続プロパティー。各 connection-property は、文字列名と値のペアを指定します。プロパティー名は名前、値は要素の内容に基づいています。
pool
プーリング設定である子要素が含まれます。表10.4「非 XA および XA データソースに共通のプールパラメーター」 を参照してください。

表10.3 XA データソースのパラメーター

パラメーター 説明
xa-datasource-property
実装クラス XADataSource に割り当てるプロパティー。name=value で指定。 setName という形式で setter メソッドが存在する場合、プロパティーは setName(value) という形式の setter メソッドを呼び出すことで設定されます。
xa-datasource-class
実装クラス javax.sql.XADataSource の完全修飾名。
driver
JDBC ドライバーが含まれるクラスローダーモジュールへの一意参照。driverName#majorVersion.minorVersion の形式にのみ対応しています。
xa-pool
プーリング設定である子要素が含まれます。表10.4「非 XA および XA データソースに共通のプールパラメーター」表10.5「XA プールパラメーター」 を参照してください。
recovery
リカバリ設定である子要素が含まれます。表10.10「リカバリーパラメーター」 を参照してください。

表10.4 非 XA および XA データソースに共通のプールパラメーター

パラメーター 説明
min-pool-size プールが保持する最小接続数
max-pool-size プールが保持可能な最大接続数
prefill 接続プールのプレフィルを試行するかどうかを指定します。要素が空の場合は true を示します。デフォルトは、false です。
use-strict-min pool-size が厳密かどうかを指定します。デフォルトは false に設定されています。
flush-strategy
エラーの場合にプールをフラッシュするかどうかを指定します。有効な値は次のとおりです。
  • FailingConnectionOnly
  • IdleConnections
  • EntirePool
デフォルトは FailingConnectionOnly です。
allow-multiple-users 複数のユーザーが getConnection (user, password) メソッドを使いデータソースへアクセスするか、また内部プールタイプがこの動作に対応するかを指定します。

表10.5 XA プールパラメーター

パラメーター 説明
is-same-rm-override javax.transaction.xa.XAResource.isSameRM(XAResource) クラスが true あるいは false のどちらを返すかを指定します。
interleaving XA 接続ファクトリのインターリービングを有効にするかどうかを指定します。
no-tx-separate-pools コンテキスト毎に sub-pool を作成するかどうかを指定します。これには Oracle のデータソースが必要ですが、このデータソースは JTA トランザクションの内部、外部に関わらず、XA 接続の利用ができなくなります。
pad-xid Xid のパディングを行うかどうかを指定します。
wrap-xa-resource
XAResource を org.jboss.tm.XAResourceWrapper インスタンスでラップするかどうかを指定します。

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

パラメーター 説明
user-name 新規接続の作成に使うユーザー名
password 新規接続の作成に使うパスワード
security-domain 認証処理を行う JAAS security-manager 名が含まれます。この名前は、JAAS ログイン設定のapplication-policy/name 属性に相関します。
reauth-plugin 物理接続の再認証に使う再認証プラグインを定義します。

表10.7 検証パラメーター

パラメーター 説明
valid-connection-checker
SQLException.isValidConnection(Connection e) メソッドを提供し接続を検証するインターフェース org.jboss.jca.adaptors.jdbc.ValidConnectionChecker の実装。例外が発生すると接続が破棄されます。存在する場合、check-valid-connection-sql パラメーターが上書きされます。
check-valid-connection-sql プール接続の妥当性を確認する SQL ステートメント。これは、管理接続をプールから取得し利用する場合に呼び出される場合があります。
validate-on-match
接続ファクトリが指定のセットに対して管理対象接続をマッチしようとした時に接続レベルの検証を実行するかどうかを示します。
通常、validate-on-match に true を指定した時に background-validation を true に指定することはありません。クライアントが使用する前に接続を検証する必要がある場合に Validate-on-match が必要になります。このパラメーターはデフォルトでは true になっています。
background-validation
接続がバックグラウンドスレッドで検証されることを指定します。validate-on-match を使用しない場合、バックグラウンドの検証はパフォーマンスを最適化します。validate-on-match が true の時に background-validation を使用すると、チェックが冗長になることがあります。バックグラウンド検証では、不良の接続がクライアントに提供される可能性があります (検証スキャンと接続がクライアントに提供されるまでの間に接続が悪くなります)。そのため、クライアントアプリケーションはこの接続不良の可能性に対応する必要があります。
background-validation-millis バックグラウンド検証を実行する期間 (ミリ秒単位)。
use-fast-fail
true の場合、接続が無効であれば最初に接続を割り当てしようとした時点で失敗します。デフォルトは false です。
stale-connection-checker
ブール値の isStaleConnection(SQLException e) メソッドを提供する org.jboss.jca.adapters.jdbc.StaleConnectionChecker のインスタンス。このメソッドが true を返すと、SQLException のサブクラスである org.jboss.jca.adapters.jdbc.StaleConnectionException に例外がラップされます。
exception-sorter
ブール値である isExceptionFatal(SQLException e) メソッドを提供する org.jboss.jca.adapters.jdbc.ExceptionSorter のインスタンス。このメソッドは、例外が connectionErrorOccurred メッセージとして javax.resource.spi.ConnectionEventListener のすべてのインスタンスへブロードキャストされるべきであるかどうかを検証します。

表10.8 タイムアウトパラメーター

パラメーター 説明
use-try-lock lock() の代わりに tryLock() を使用します。これは、ロックが使用できない場合に即座に失敗するのではなく、設定された秒数間ロックの取得を試みます。デフォルトは 60 秒です。たとえば、タイムアウトを 5 分に設定するには、<use-try-lock>300</use-try-lock> を設定します。
blocking-timeout-millis 接続待機中にブロックする最大時間 (ミリ秒)。この時間を超過すると、例外がスローされます。これは、接続許可の待機中のみブロックし、新規接続の作成に長時間要している場合は例外をスローしません。デフォルトは 30000 (30 秒) です。
idle-timeout-minutes
アイドル接続が切断されるまでの最大時間 (分単位)。実際の最大時間は idleRemover のスキャン時間によって異なります。idleRemover のスキャン時間はプールの最小 idle-timeout-minutes の半分になります。
set-tx-query-timeout
トランザクションがタイムアウトするまでの残り時間を基にクエリのタイムアウトを設定するかどうかを指定します。トランザクションが存在しない場合は設定済みのクエリのタイムアウトが使用されます。デフォルトは false です。
query-timeout クエリのタイムアウト (秒)。デフォルトはタイムアウトなしです。
allocation-retry 例外をスローする前に接続の割り当てを再試行する回数。デフォルトは 0 で、初回の割り当て失敗で例外がスローされます。
allocation-retry-wait-millis
接続の割り当てを再試行するまで待機する期間 (ミリ秒単位)。デフォルトは 5000 (5 秒) です。
xa-resource-timeout
ゼロでない場合、この値は XAResource.setTransactionTimeout メソッドへ渡されます。

表10.9 ステートメントのパラメーター

パラメーター 説明
track-statements
接続がプールへ返され、ステートメントが準備済みステートメントキャッシュへ返された時に、閉じられていないステートメントをチェックするかどうかを指定します。false の場合、ステートメントは追跡されません。

有効な値

  • true: ステートメントと結果セットが追跡され、ステートメントが閉じられていない場合は警告が出力されます。
  • false: ステートメントと結果セットのいずれも追跡されません。
  • nowarn: ステートメントは追跡されますが、警告は出力されません。これがデフォルト設定となっています。
prepared-statement-cache-size LRU (Least Recently Used) キャッシュにある接続毎の準備済みステートメントの数。
share-prepared-statements
閉じずに同じステートメントを 2 回要求した場合に、同じ基盤の準備済みステートメントを使用するかどうかを指定します。デフォルトは false です。

表10.10 リカバリーパラメーター

パラメーター 説明
recover-credential リカバリーに使用するユーザー名とパスワードのペア、あるいはセキュリティドメイン。
recover-plugin
リカバリーに使用される org.jboss.jca.core.spi.recoveryRecoveryPlugin クラスの実装。

10.6.3. トランザクションロギング

10.6.3.1. トランザクションログメッセージについて

ログファイルが読み取り可能な状態でトランザクションの状態を追跡するには、トランザクションロガーに DEBUG ログレベルを使用します。詳細なデバッグでは TRACE ログレベルを使用します。トランザクションロガーの設定に関する詳細は 「トランザクションサブシステムのログ設定」 を参照してください。
TRACE ログレベルに設定すると、トランザクションマネージャーは多くのロギング情報を生成できます。一般的に表示されるメッセージの一部は次のとおりです。他のメッセージが表示されることもあります。

表10.11 トランザクションステートの変更

トランザクションの開始
トランザクションが開始されると、次のコードが実行されます。
com.arjuna.ats.arjuna.coordinator.BasicAction::Begin:1342
tsLogger.logger.trace("BasicAction::Begin() for action-id "+ get_uid());
トランザクションのコミット
トランザクションがコミットすると、次のコードが実行されます。
com.arjuna.ats.arjuna.coordinator.BasicAction::End:1342
tsLogger.logger.trace("BasicAction::End() for action-id "+ get_uid());
トランザクションのロールバック
トランザクションがロールバックすると、次のコードが実行されます。
com.arjuna.ats.arjuna.coordinator.BasicAction::Abort:1575
tsLogger.logger.trace("BasicAction::Abort() for action-id "+ get_uid());
トランザクションのタイムアウト
トランザクションがタイムアウトすると、次のコードが実行されます。
com.arjuna.ats.arjuna.coordinator.TransactionReaper::doCancellations:349
tsLogger.logger.trace("Reaper Worker " + Thread.currentThread() + " attempting to cancel " + e._control.get_uid());
その後、上記のように同じスレッドがトランザクションをロールバックすることが確認できます。

10.6.3.2. トランザクションサブシステムのログ設定

概要

JBoss Enterprise Application Platform の他のログ設定に依存せずにトランザクションログの情報量を制御する手順を説明します。主に Web ベースの管理コンソールを用いた手順を説明し、管理 CLI のコマンドはその説明の後で取り上げます。

手順10.4 管理コンソールを使用したトランザクションロガーの設定

  1. ログ設定エリアへの移動

    管理コンソールにて画面の左上にある [Profiles] タブをクリックします。管理対象ドメインを使用する場合は、右上の [Profile] 選択ボックスから設定したいサーバープロファイルを選択します。
    [Core] メニューを展開して、[Logging] ラベルをクリックします。
  2. com.arjuna 属性を編集します。

    ページの下の方にある [Details] セクションの [Edit] ボタンをクリックします。ここにクラス固有のログ情報を追加できます。com.arjuna クラスはすでに存在しています。ログレベルと親ハンドラーを使用するかどうか変更できます。
    ログレベル
    デフォルトのログレベルは WARN です。トランザクションはログを大量に出力できるため、標準的なログレベルの意味は、トランザクションロガーでは若干異なります。通常、選択したレベルより重要度が低いレベルでタグ付けされたメッセージは破棄されます。

    トランザクションログのレベル (詳細度が最高レベルから最低レベルまで)

    • TRACE
    • DEBUG
    • INFO
    • WARN
    • ERROR
    • FAILURE
    親ハンドラーの使用
    ロガーがログ出力を親ロガーに送信するかどうかを指定します。デフォルトの動作は true です。
  3. 変更は直ちに反映されます。

10.6.3.3. トランザクションの参照と管理

コマンドラインベースの管理 CLI では、トランザクションレコードを参照および操作する機能がサポートされます。この機能は、トランザクションマネージャーと JBoss Enterprise Application Platform 6 の管理 API との対話によって提供されます。
トランザクションマネージャーは、待機中の各トランザクションとトランザクションに関連する参加者に関する情報を、オブジェクトストアと呼ばれる永続ストレージに格納します。管理 API は、オブジェクトストアを log-store と呼ばれるリソースとして公開します。probe と呼ばれる API 操作はトランザクションログを読み取り、各ログに対してノードを作成します。probe コマンドは、log-store を更新する必要があるときに、いつでも手動で呼び出すことができます。トランザクションログが現れて、すぐに消失されるのは通常のことです。

例10.1 ログストアの更新

このコマンドは、管理対象ドメインでプロファイル default を使用するサーバーグループに対してログストアを更新します。スタンドアローンサーバーの場合は、コマンドから profile=default を削除します。
/profile=default/subsystem=transactions/log-store=log-store/:probe

例10.2 準備されたすべてのトランザクションの表示

準備されたすべてのトランザクションを表示するには、最初にログストアを更新し (例10.1「ログストアの更新」 を参照)、ファイルシステムの ls コマンドに類似した機能を持つ次のコマンドを実行します。
ls /profile=default/subsystem=transactions/log-store=log-store/transactions
各トランザクションが一意の ID とともに表示されます。個々の操作は、各トランザクションに対して実行できます (トランザクションの管理 を参照)。

トランザクションの管理

トランザクションの属性を表示します。
JNDI 名、EIS 製品名およびバージョン、ステータスなどのトランザクションに関する情報を表示するには、:read-resource CLIコマンドを使用します。
/profile=default/subsystem=transactions/log-store=log-store/transactions=0\:ffff7f000001\:-b66efc2\:4f9e6f8f\:9:read-resource
トランザクションの参加者を表示します。
各トランザクションログには、participants (参加者) と呼ばれる子要素が含まれます。トランザクションの参加者を確認するには、この要素に対して read-resource CLI コマンドを使用します。参加者は、JNDI 名によって識別されます。
/profile=default/subsystem=transactions/log-store=log-store/transactions=0\:ffff7f000001\:-b66efc2\:4f9e6f8f\:9/participants=java\:\/JmsXA:read-resource
結果は以下のようになります。
{
   "outcome" => "success",
   "result" => {
       "eis-product-name" => "HornetQ",
       "eis-product-version" => "2.0",
       "jndi-name" => "java:/JmsXA",
       "status" => "HEURISTIC",
       "type" => "/StateManager/AbstractRecord/XAResourceRecord"
   }
}
ここで示された結果ステータスは HEURISTIC であり、リカバリーが可能です。詳細については、「トランザクションをリカバリーします。」を参照してください。
トランザクションを削除します。
各トランザクションログは、トランザクションを表すトランザクションログを削除するために、:delete 操作をサポートします。
/profile=default/subsystem=transactions/log-store=log-store/transactions=0\:ffff7f000001\:-b66efc2\:4f9e6f8f\:9:delete
トランザクションをリカバリーします。
各トランザクションログは、:recover CLI コマンドを使用したリカバリーをサポートします。

ヒューリスティックなトランザクションと参加者のリカバリー

  • トランザクションのステータスが HEURISTIC である場合は、リカバリー操作によって、ステータスが PREPARE に変わり、リカバリーがトリガーされます。
  • トランザクションの参加者の 1 つがヒューリスティックな場合、リカバリー操作により、commit 操作の応答が試行されます。成功した場合、トランザクションログから参加者が削除されます。これを確認するには、log-store 上で :probe 操作を再実行し、参加者がリストされていないことを確認します。これが最後の参加者の場合は、トランザクションも削除されます。
リカバリーが必要なトランザクションのステータスを更新します。
トランザクションをリカバリーする必要がある場合は、リカバリーを試行する前に :refresh CLI コマンドを使用して、トランザクションのリカバリーが必要であるかを確認できます。
/profile=default/subsystem=transactions/log-store=log-store/transactions=0\:ffff7f000001\:-b66efc2\:4f9e6f8f\:9:refresh

注記

JTS トランザクションで、参加者がリモートサーバー上にある場合、トランザクションマネージャーは制限された量の情報のみ使用できることがあります。この場合は、HornetQ ストレージモードではなくファイルベースのオブジェクトストアを使用することが推奨されます。HornetQ ストレージモードを使用するには、トランザクションマネージャーの use-hornetq-store オプションの値を true に設定します。トランザクションマネージャーの設定については、「トランザクションマネージャーの設定」 を参照してください。
トランザクション統計情報の表示

トランザクションマネージャー (TM) の統計が有効になっていると、トランザクションマネージャーおよびトランザクションサブシステムに関する統計を表示できます。TM の統計を有効にする方法は 「トランザクションマネージャーの設定」 を参照してください。

統計は、Web ベースの管理コンソールまたはコマンドラインの管理 CLI より表示できます。Web ベースの管理コンソールでは、トランザクション統計情報は [Runtime][Subsystem Metrics][Transactions] を選択して取得できます。トランザクション統計情報は、管理対象ドメインの各サーバーでも利用できます。左上にある [Server] 選択ボックスで、サーバーを指定できます。
以下の表は、利用可能な各統計情報、その説明、および統計情報を表示する CLI コマンドを示しています。

表10.12 トランザクションサブシステム統計情報

統計 説明 CLI コマンド
Total (合計)
このサーバー上でトランザクションマネージャーにより処理されるトランザクションの合計数。
/host=master/server=server-one/subsystem=transactions/:read-attribute(name=number-of-transactions,include-defaults=true)
Committed (コミット済み)
このサーバー上でトランザクションマネージャーにより処理されるコミット済みトランザクションの数。
/host=master/server=server-one/subsystem=transactions/:read-attribute(name=number-of-committed-transactions,include-defaults=true)
Aborted (異常終了)
このサーバー上でトランザクションマネージャーにより処理される異常終了したトランザクションの数。
/host=master/server=server-one/subsystem=transactions/:read-attribute(name=number-of-aborted-transactions,include-defaults=true)
Timed Out (タイムアウト)
このサーバー上でトランザクションマネージャーにより処理されるタイムアウトのトランザクションの数。
/host=master/server=server-one/subsystem=transactions/:read-attribute(name=number-of-timed-out-transactions,include-defaults=true)
Heuristics (ヒューリスティック)
管理コンソールで利用不可です。ヒューリスティック状態のトランザクションの数。
/host=master/server=server-one/subsystem=transactions/:read-attribute(name=number-of-heuristics,include-defaults=true)
In-Flight Transactions (フライト状態のトランザクション)
管理コンソールでは使用できません。開始した未終了のトランザクションの数。
/host=master/server=server-one/subsystem=transactions/:read-attribute(name=number-of-inflight-transactions,include-defaults=true)
Failure Origin - Applications (障害の原因 - アプリケーション)
障害の原因がアプリケーションであった失敗トランザクションの数。
/host=master/server=server-one/subsystem=transactions/:read-attribute(name=number-of-application-rollbacks,include-defaults=true)
Failure Origin - Resources (障害の原因 - リソース)
障害の原因がリソースであった失敗トランザクションの数。
/host=master/server=server-one/subsystem=transactions/:read-attribute(name=number-of-resource-rollbacks,include-defaults=true)

10.7. JTA トランザクションの使用

10.7.2. トランザクションの制御

はじめに

この手順のリストでは、JTA または JTS API を使用するアプリケーションでトランザクションを制御するさまざまな方法を概説します。

10.7.3. トランザクションの開始

この手順では、Java Transaction Service (JTS) プロトコルを使用して、新しい JTA トランザクションを開始する方法、または分散トランザクションに散開する方法を示します。
分散トランザクション

分散トランザクションでは、トランザクション参加者が複数のサーバー上の個別アプリケーションに存在します。参加者が新しいトランザクションコンテキストを作成する代わりに、すでに存在するトランザクションに参加する場合は、コンテキストを共有する 2 人以上の参加者が分散トランザクションに参加します。分散トランザクションを使用するには、ORB を設定する必要があります。ORB 設定の詳細については、『管理および設定ガイド』の項 『ORB 設定』を参照してください。

  1. UserTransaction のインスタンスを取得します。

    @TransactionManagement(TransactionManagementType.BEAN) アノテーションを用いると、 JNDI やインジェクション (EJB が Bean 管理のトランザクションを使用する場合は EJB の EjbContext) を使用してインスタンスを取得できます。
    • JNDI

      new InitialContext().lookup("java:comp/UserTransaction")
    • インジェクション

      @Resource UserTransaction userTransaction;
    • EjbContext

      EjbContext.getUserTransaction()
  2. データソースに接続後、UserTransaction.begin() を呼び出します。

    ...
    try {
        System.out.println("\nCreating connection to database: "+url);
        stmt = conn.createStatement();  // non-tx statement
        try {
            System.out.println("Starting top-level transaction.");
            userTransaction.begin();
            stmtx = conn.createStatement(); // will be a tx-statement
            ...
        }
    }
    
JTS API を使用して既存のトランザクションに参加します。

EJB の利点の 1 つは、コンテナがすべてのトランザクションを管理することです。ORB をセットアップした場合は、コンテナによって分散トランザクションが管理されます。

結果

トランザクションが開始します。トランザクションをコミットまたはロールバックするまで、データソースのすべての使用でトランザクションに対応します。

注記

全体の例は 「JTA トランザクションの例」 を参照してください。

10.7.4. トランザクションのネスト

ネストトランザクションは、JTS API による分散トランザクションを使用する場合のみサポートされます。また、多くのデータベースベンダーはネストトランザクションをサポートしないため、ネストトランザクションをアプリケーションに追加する前に、データベースベンダーにお問い合わせください。
OTS 仕様では、ネストトランザクションのタイプが制限されます。サブトランザクションコミットプロトコルは最上位トランザクションと同じです。prepare フェーズと commit フェーズまたは abort フェーズの 2 つのフェーズがあります。このようなネストトランザクションを行うと、サブトランザクションコーディネーターがコミット中にリソースがコミットできないことを検出するなどの、不整合な結果が生じることがあります。コーディネーターはコミットされたリソースを中止するよう指示できず、ヒューリスティックな結果が生じます。この厳密な OTS のネストトランザクションは、CosTransactions::SubtransactionAwareResource インターフェースを介して利用できます。
JTS の JBoss Enterprise Application Platform の実装はこのタイプのネストトランザクションをサポートします。また、厳密な OTS モデルで発生する可能性がある問題を回避するマルチフェーズコミットプロトコルを使用するネストトランザクションのタイプもサポートします。このタイプのネストトランザクションは ArjunaOTS::ArjunaSubtranAwareResource を介して利用でき、ネストトランザクションをコミットするたびに 2 相コミットプロトコルにより駆動されます。
ネストトランザクションを作成するには、親トランザクション内で新しいトランザクションを作成します。トランザクションの作成については、「トランザクションの開始」を参照してください。
ネストトランザクションの効果は、エンクローズトランザクションのコミットまたはロールバックに依存します。エンクローズトランザクションが中止された場合は、ネストトランザクションがコミットされた場合であっても効果はリカバリされます。

10.7.5. トランザクションのコミット

この手順では、Java Transaction API (JTA) を使用してトランザクションをコミットする方法を示します。この API は、ローカルトランザクションと分散トランザクションの両方に使用されます。分散トランザクションは、Java Transaction Server (JTS) により管理され、Object Request Broker (ORB) の設定を必要とします。ORB の設定の詳細については、『管理および設定ガイド』の項 『ORB 設定』を参照してください。
要件

トランザクションは、コミットする前に開始する必要があります。トランザクションの開始方法については、「トランザクションの開始」を参照してください。

  1. UserTransactioncommit() メソッドを呼び出します。

    UserTransactioncommit() メソッドを呼び出すと、トランザクションマネージャーがトランザクションをコミットしようとします。
    @Inject
    private UserTransaction userTransaction;
    
    public void updateTable(String key, String value)
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        try {
            userTransaction.begin():
            <!-- Perform some data manipulation using entityManager -->
    			  ...
    			  // Commit the transaction
            userTransaction.commit();
        } catch (Exception ex) {
            <!-- Log message or notify Web page -->
            ...
            try {
                userTransaction.rollback();
            } catch (SystemException se) {
                throw new RuntimeException(se);
            }
            throw new RuntimeException(e);
        } finally {
            entityManager.close();
        }
    }
    
    
  2. Container Managed Transactions (CMT) を使用する場合は、手動でコミットする必要がありません。

    Bean が Container Managed Transactions を使用するよう設定すると、コンテナはコードで設定したアノテーションに基づいてトランザクションライフサイクルを管理します。
結果

データソースがコミットし、トランザクションが終了します。そうでない場合は、例外がスローされます。

注記

全体の例は 「JTA トランザクションの例」 を参照してください。

10.7.6. トランザクションのロールバック

この手順では、Java Transaction API (JTA) を使用してトランザクションをロールバックする方法を示します。この API は、ローカルトランザクションと分散トランザクションの両方に使用されます。分散トランザクションは、Java Transaction Server (JTS) により管理され、Object Request Broker (ORB) の設定を必要とします。ORB の設定の詳細については、『管理および設定ガイド』の項 『ORB 設定』を参照してください。
要件

トランザクションは、ロールバックする前に開始する必要があります。トランザクションの開始方法については、「トランザクションの開始」を参照してください。

  1. UserTransactionrollback() メソッドを呼び出します。

    UserTransactionrollback() メソッドを呼び出すと、トランザクションマネージャーがトランザクションをロールバックし、データを前の状態に戻そうとします。
     
    @Inject
    private UserTransaction userTransaction;
    
    public void updateTable(String key, String value)
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        try {
            userTransaction.begin():
            <!-- Perform some data manipulation using entityManager -->
    			  ...
    			  // Commit the transaction
            userTransaction.commit();
        } catch (Exception ex) {
            <!-- Log message or notify Web page -->
            ...
            try {
                userTransaction.rollback();
            } catch (SystemException se) {
                throw new RuntimeException(se);
            }
            throw new RuntimeException(e);
        } finally {
            entityManager.close();
        }
    }
    
    
  2. Container Managed Transactions (CMT) を使用する場合は、手動でトランザクションをロールバックする必要がありません。

    Bean が Container Managed Transactions を使用するよう設定すると、コンテナはコードで設定したアノテーションに基づいてトランザクションライフサイクルを管理します。
結果

トランザクションマネージャーにより、トランザクションがロールバックされます。

注記

全体の例は 「JTA トランザクションの例」 を参照してください。

10.7.7. トランザクションにおけるヒューリスティックな結果の処理方法

この手順では、Java Transaction Service (JTS) を使用して JTA トランザクション (ローカルまたは分散) でヒューリスティックな結果を処理する方法を示します。分散トランザクションを使用する場合は、ORB を設定する必要があります。ORB 設定の詳細については、『管理および設定ガイド』の項 『ORB 設定』 を参照してください。
ヒューリスティックな結果はよく発生するものではなく、通常は例外的な原因があります。ヒューリスティック という言葉は「手動」を意味し、こうした結果が通常処理される方法です。トランザクションのヒューリスティックな結果については、「ヒューリスティックな結果について」を参照してください。

手順10.5 トランザクションでのヒューリスティックな結果の処理方法

  1. 原因を突き止める

    トランザクションのヒューリスティックな結果の全体的な原因は、リソースマネージャーがコミットまたはロールバックの実行を約束したにも関わらず、失敗したことにあります。原因としては、サードパーティーコンポーネント、サードパーティーコンポーネントと JBoss Enterprise Application Platform 間の統合レイヤー、JBoss Enterprise Application Platform 自体に問題がある可能性があります。
    ヒューリスティックなエラーの最も一般的な原因として圧倒的に多いのが、環境の一時的な障害とリソースマネージャーを扱うコードのコーディングエラーの 2 つです。
  2. 環境内の一時的な障害を修正する

    通常、環境内で一時的な障害が発生した場合は、ヒューリスティックなエラーを発見する前に気づきます。原因としては、ネットワークの停止、ハードウェア障害、データベース障害、電源異常、その他多くの可能性があります。
    ストレステストの実施中にテスト環境でヒューリスティックな結果が発生した場合は、使用している環境の脆弱性に関する情報が提供されます。

    警告

    JBoss Enterprise Application Platform は、障害発生時に非ヒューリスティックな状態にあるトランザクションの自動回復を行いますが、ヒューリスティックなトランザクションの回復は試行しません。
  3. リソースマネージャーのベンダーに連絡する

    明らかに使用している環境に障害がない場合や、ヒューリスティックな結果が容易に再現可能な場合は、コーディングエラーである可能性があります。サードパーティーのベンダーに連絡して、解決方法の有無を確認してください。JBoss Enterprise Application Platform のトランザクションマネージャー自体に問題があると思われる場合は、Red Hat グローバルサポートサービスにご連絡ください。
  4. テスト環境の場合は、ログを削除して JBoss Enterprise Application Platform を再起動する

    テスト環境である場合や、データの整合性を気にしない場合は、トランザクションログを削除して JBoss Enterprise Application Platform を再起動すると、ヒューリスティックな結果はなくなります。デフォルトのトランザクションログの場所はスタンドアロンサーバーでは EAP_HOME/standalone/data/tx-object-store/、管理ドメインでは EAP_HOME/domain/servers/SERVER_NAME/data/tx-object-store になります。管理ドメインの SERVER_NAME は、サーバーグループに参加している個々のサーバー名になります。
  5. 手作業で結果を解決する

    トランザクションの結果を手作業で解決するプロセスは、障害の厳密な状況によって大きく左右されます。通常は、以下の手順に従い、それぞれの状況に適用してください。
    1. 関連するリソースマネージャーを特定する。
    2. トランザクションマネージャーの状態とリソースマネージャーを調べる。
    3. 関与する 1 つ以上のコンポーネント内でログのクリーンアップとデータ調整を手動で強制する。
    これらの手順を実行する方法の詳細は、本書の範囲外となります。

10.7.8. トランザクションのタイムアウト

10.7.8.1. トランザクションタイムアウトについて

原子性を確保し、トランザクションを ACID 標準に準拠させるため、トランザクションの一部が長期間実行される場合があります。トランザクションの参加者は、コミット時にデータソースの一部をロックする必要があります。また、トランザクションマネージャーは各トランザクション参加者からの応答を待ってからすべての参加者にコミットあるいはロールバックの指示を出す必要があります。ハードウェアあるいはネットワークの障害のため、リソースが永久にロックされることがあります。
トランザクションのタイムアウトをトランザクションと関連付け、ライフサイクルを制御することができます。タイムアウトのしきい値がトランザクションのコミットあるいはロールバック前に渡された場合、タイムアウトにより、自動的にトランザクションがロールバックされます。
トランザクションサブシステム全体に対しデフォルトのタイムアウト値を設定できます。または、デフォルトのタイムアウト値を無効にし、トランザクションごとにタイムアウトを指定できます。

10.7.8.2. トランザクションマネージャーの設定

トランザクションマネージャー (TM) は、Web ベースの管理コンソールかコマンドラインの管理 CLI を使用して設定できます。各コマンドやオプションでは、 JBoss Enterprise Application Platform を管理対象ドメインとして実行していると仮定します。スタンドアロンサーバーを使用する場合や default 以外のプロファイルを修正したい場合は、以下の方法で手順とコマンドを修正する必要があることがあります。

例のコマンドに関する注意点

  • 管理コンソールの場合、default プロファイルは最初のコンソールログイン時に選択されるものです。異なるプロファイルでトランザクションマネージャーの設定を修正する必要がある場合は、default の代わりに使用しているプロファイルを選択してください。
    同様に、例の CLI コマンドの default プロファイルを使用しているプロファイルに置き換えてください。
  • スタンドアロンサーバーを使用する場合、存在するプロファイルは 1 つのみです。特定のプロファイルを選択する手順は無視してください。CLI コマンドでは、例のコマンドの /profile=default 部分を削除してください。

注記

TM オプションが管理コンソールまたは管理 CLI で表示されるようにするには、transactions サブシステムが有効でなくてはなりません。これは、デフォルトで有効になっており、他の多くのサブシステムが適切に機能するために必要なため、無効にする可能性は大変低くなります。
管理コンソールを使用した TM の設定

Web ベースの管理コンソールを使用して TM を設定するには、管理コンソール画面の左上にある一覧から [Runtime] タブを選択します。管理対象ドメインを使用する場合、選択できるプロファイルがいくつかあります。プロファイル画面の右上にある [Profile] 選択ボックスから適切なプロファイルを選択してください。[Container] メニューを展開して、[Transactions] を選択します。

トランザクションマネージャーの設定ページには、さらなるオプションが表示されています。[Recovery] オプションはデフォルトでは非表示です。展開するには、[Recovery] ヘッダーをクリックします。オプションを編集するには、[Edit] ボタンをクリックします。変更は直ちに反映されます。
インラインヘルプを表示するには、[Need Help?] ラベルをクリックします。
管理 CLI を使用した TM の設定

管理 CLI では、一連のコマンドを使用して TM を設定できます。プロファイル default の管理対象ドメインの場合、コマンドはすべて /profile=default/subsystem=transactions/ で始まり、スタンドアロンサーバーの場合は /subsystem=transactions で始まります。

表10.13 TM 設定オプション

オプション 説明 CLI コマンド
統計の有効化 (Enable Statistics)
トランザクションの統計を有効にするかどうか指定します。統計は Runtime タブの Subsystem Metrics セクションにある管理コンソールで閲覧できます。
/profile=default/subsystem=transactions/:write-attribute(name=enable-statistics,value=true)
TSM ステータスの有効化 (Enable TSM Status)
トランザクションステータスマネージャー (TSM) のサービスを有効にするかどうか指定します。これは、アウトオブプロセスのリカバリに使用されます。
/profile=default/subsystem=transactions/:write-attribute(name=enable-tsm-status,value=false)
デフォルトのタイムアウト (Default Timeout)
デフォルトのトランザクションタイムアウトです。デフォルトでは 300 秒に設定されています。トランザクションごとにプログラムで上書きできます。
/profile=default/subsystem=transactions/:write-attribute(name=default-timeout,value=300)
パス (Path)
トランザクションマネージャーコアがデータを格納するファイルシステムの相対または絶対パスです。デフォルトの値は relative-to 属性の値と相対的なパスです。
/profile=default/subsystem=transactions/:write-attribute(name=path,value=var)
相対的 (Relative To)
ドメインモデルのグローバルなパス設定を参照します。デフォルト値は、JBoss Enterprise Application Platform 6 のデータディレクトリで、jboss.server.data.dir プロパティーの値です。デフォルトは、管理対象ドメインの場合は EAP_HOME/domain/data/、スタンドアロンサーバーインスタンスの場合は EAP_HOME/standalone/data/ です。path TM 属性の値は、このパスに相対的です。空の文字列を使用して、デフォルト動作を無効にし、path 属性の値が絶対パスとして強制的に扱われるようにします。
/profile=default/subsystem=transactions/:write-attribute(name=relative-to,value=jboss.server.data.dir)
オブジェクトストアパス (Object Store Path)
TM オブジェクトストアがデータを格納するファイルシステムの相対または絶対パスです。デフォルトでは、object-store-relative-to パラメーターの値に相対的です。
/profile=default/subsystem=transactions/:write-attribute(name=object-store-path,value=tx-object-store)
オブジェクトストアパスに相対的 (Object Store Path Relative To)
ドメインモデルのグローバルなパス設定を参照します。デフォルト値は、JBoss Enterprise Application Platform 6 のデータディレクトリで、jboss.server.data.dir プロパティーの値です。デフォルトは、管理対象ドメインの場合は EAP_HOME/domain/data/、スタンドアロンサーバーインスタンスの場合は EAP_HOME/standalone/data/ です。path TM 属性の値は、このパスに相対的です。空の文字列を使用して、デフォルト動作を無効にし、path 属性の値が絶対パスとして強制的に扱われるようにします。
/profile=default/subsystem=transactions/:write-attribute(name=object-store-relative-to,value=jboss.server.data.dir)
ソケットバインディング (Socket Binding)
ソケットベースのメカニズムを使用する場合に、トランザクションマネージャーの回復およびトランザクション識別子の生成に使用するソケットバインディングの名前を指定します。一意の識別子を生成する詳しい情報は、process-id-socket-max-ports を参照してください。ソケットバインディングは、管理コンソールの Server タブでサーバーグループごとに指定されます。
/profile=default/subsystem=transactions/:write-attribute(name=socket-binding,value=txn-recovery-environment)
ソケットバインディングのステータス (Status Socket Binding)
トランザクションステータスマネージャーで使用するソケットバインディングを指定します。
/profile=default/subsystem=transactions/:write-attribute(name=status-socket-binding,value=txn-status-manager)
リカバリーリスナー (Recovery Listener)
トランザクションリカバリのプロセスがネットワークソケットをリッスンするかどうかを指定します。デフォルトは false です。
/profile=default/subsystem=transactions/:write-attribute(name=recovery-listener,value=false)
以下は、高度なオプションで、修正は管理 CLI を使用することでのみ可能です。デフォルト設定の変更は注意して行ってください。詳細は Red Hat グローバルサポートサービスにお問い合わせください。

表10.14 高度な TM 設定オプション

オプション 説明 CLI コマンド
jts
Java Transaction Service (JTS) トランザクションを使用するかどうかを指定します。デフォルトは false で、JTA トランザクションのみ使用します。
/profile=default/subsystem=transactions/:write-attribute(name=jts,value=false)
node-identifier
JTS サービスのノード識別子です。トランザクションマネージャーがリカバリ時にこれを使用するため、JTS サービスごとに一意でなければなりません。
/profile=default/subsystem=transactions/:write-attribute(name=node-identifier,value=1)
process-id-socket-max-ports
トランザクションマネージャーは、各トランザクションログに対し一意の識別子を作成します。一意の識別子を生成するメカニズムは 2 種類あります。ソケットベースのメカニズムとプロセスのプロセス識別子をベースにしたメカニズムです。
ソケットベースの識別子の場合、あるソケットを開くと、そのポート番号が識別子用に使用されます。ポートがすでに使用されている場合は、空きのポートが見つかるまで次のポートがプローブされます。process-id-socket-max-ports は、TM が失敗するまでに試行するソケットの最大値を意味します。デフォルト値は 10 です。
/profile=default/subsystem=transactions/:write-attribute(name=process-id-socket-max-ports,value=10)
process-id-uuid
true に設定すると、プロセス識別子を使用して各トランザクションに一意の識別子を作成します。そうでない場合は、ソケットベースのメカニズムが使用されます。デフォルトは true です。詳細は process-id-socket-max-ports を参照してください。
/profile=default/subsystem=transactions/:write-attribute(name=process-id-uuid,value=true)
use-hornetq-store
トランザクションログ用に、ファイルベースのストレージの代わりに HornetQ のジャーナルストレージメカニズムを使用します。デフォルトでは無効になっていますが、I/O パフォーマンスが向上します。別々のトランザクションマネージャーで JTS トランザクションを使用することは推奨されません。
/profile=default/subsystem=transactions/:write-attribute(name=use-hornetq-store,value=false)

10.7.9. JTA トランザクションのエラー処理

10.7.9.1. トランザクションエラーの処理

トランザクションエラーは、多くの場合、タイミングに依存するため、解決するのが困難です。以下に、一部の一般的なエラーと、これらのエラーのトラブルシューティングに関するヒントを示します。

注記

これらのガイドラインはヒューリスティックエラーに適用されません。ヒューリスティックエラーが発生した場合は、「トランザクションにおけるヒューリスティックな結果の処理方法」 を参照し、Red Hat グローバルサポートサービスにお問い合わせください。
トランザクションがタイムアウトになったが、ビジネスロジックスレッドが認識しませんでした。

多くの場合、このようなエラーは、Hibernate がレイジーロードのためにデータベース接続を取得できない場合に発生します。頻繁に発生する場合は、タイムアウト値を大きくできます。「トランザクションマネージャーの設定」 を参照してください。

引き続き問題が解決されない場合は、パフォーマンスを向上させるために外部環境を調整するか、さらに効率的になるようコードを再構築できます。タイムアウトの問題が解消されない場合は、Red Hat グローバルサポートサービスにお問い合わせください。
トランザクションがすでにスレッドで実行されているか、NotSupportedException 例外が発生します。

NotSupportedException 例外は、通常、JTA トランザクションをネストしようとし、ネストがサポートされていないことを示します。トランザクションをネストしようとしないときは、多くの場合、スレッドプールタスクで別のトランザクションが開始されますが、トランザクションを中断または終了せずにタスクが終了します。

通常、アプリケーションは、これを自動的に処理する UserTransaction を使用します。その場合は、フレームワークに問題があることがあります。
コードで TransactionManager メソッドまたは Transaction メソッドを直接使用する場合は、トランザクションをコミットまたはロールバックするときに次の動作に注意してください。コードで TransactionManager メソッドを使用してトランザクションを制御する場合は、トランザクションをコミットまたはロールバックすると、現在のスレッドからトランザクションの関連付けが解除されます。ただし、コードで Transaction メソッドを使用する場合は、トランザクションを、実行中のスレッドに関連付けることができず、スレッドプールにスレッドを返す前にスレッドからトランザクションの関連付けを手動で解除する必要があります。
2 番目のローカルリソースを登録することはできません。

このエラーは、2 番目の非 XA リソースをトランザクションに登録しようとした場合に、発生します。1 つのトランザクションで複数のリソースが必要な場合、それらは XA である必要があります。

10.8. ORB 設定

10.8.1. Common Object Request Broker Architecture (CORBA) について

Common Object Request Broker Architecture (CORBA) は、アプリケーションとサービスが複数の互換性がない言語で記述され、異なるプラットフォームでホストされる場合でも、アプリケーションとサービスが連携することを可能にする標準です。CORBA 要求は Object Request Broker (ORB) というサーバーサイドコンポーネントにより JacORB コンポーネントを使用して処理されます。
ORB は Java Transaction Service (JTS) トランザクションに対して内部的に使用され、ユーザー独自のアプリケーションが使用することもできます。

10.8.2. JTS トランザクション用 ORB の設定

JBoss Enterprise Application Platform のデフォルトインストールでは、ORB が無効になります。ORB は、コマンドライン管理 CLI を使用して有効にすることができます。

注記

管理対象ドメインでは、JacORB サブシステムが full および full-ha プロファイルでのみ利用可能です。スタンドアロンサーバーでは、standalone-full.xml または standalone-full-ha.xml 設定で利用可能です。

手順10.6 管理コンソールを使用した ORB の設定

  1. プロファイル設定を表示します。

    管理コンソールの右上から [Profiles] (管理対象ドメイン) または [Profile] (スタンドアロンサーバー) を選択します。管理対象ドメインを使用する場合は、左上にある選択ボックスから [full] または [full-ha] プロファイルを選択します。
  2. Initializers 設定の変更

    必要な場合は、左側にある [Subsystems] メニューを展開します。[Container] サブメニューを展開し、[JacORB] をクリックします。
    メイン画面に表示されるフォームで、[Initializers] タブを選択し、[Edit] ボタンをクリックします。
    [Security] の値を on に設定して、セキュリティーインターセプターを有効にします。
    JTS 用 ORB を有効にするには、[Transaction Interceptors] 値をデフォルトの spec ではなく on に設定します。
    これらの値に関する詳細な説明については、フォームの [Need Help?] リンクを参照してください。値の編集が完了したら、[Save] をクリックします。
  3. 高度な ORB 設定

    高度な設定オプションについては、フォームの他のセクションを参照してください。各セクションには、パラメーターに関する詳細な情報とともに [Need Help?] リンクが含まれます。
管理 CLI を使用して ORB を設定

管理 CLI を使用して ORB の各側面を設定できます。以下のコマンドは、管理コンソールに対するイニシャライザーに上記の手順と同じ値を設定します。これは、JTS と使用する ORB の最小設定です。

これらのコマンドは、full プロファイルを使用して管理対象ドメインに対して設定されます。必要な場合は、設定する必要があるプロファイルに合わせてプロファイルを変更します。スタンドアロンサーバーを使用する場合は、コマンドの /profile=full 部分を省略します。

例10.3 セキュリティーインターセプターの有効化

/profile=full/subsystem=jacorb/:write-attribute(name=security,value=on)

例10.4 JTS 用 ORB の有効化

/profile=full/subsystem=jacorb/:write-attribute(name=transactions,value=on)

10.9. トランザクションに関する参考資料

10.9.1. JBoss Transactions エラーと例外

UserTransaction クラスのメソッドがスローする例外に関する詳細は、http://download.oracle.com/javaee/1.3/api/javax/transaction/UserTransaction.html の 『UserTransaction API』 の仕様を参照してください。

10.9.2. JTA クラスタリングの制限事項

JTA トランザクションは、複数の JBoss Enterprise Application Platform インスタンスでクラスター化できません。そのため、JTS トランザクションを使用します。
JTS トランザクションを使用するには、ORB を設定する必要があります (「JTS トランザクション用 ORB の設定」)。

10.9.3. JTA トランザクションの例

この例では、 JTA トランザクションを開始、コミット、およびロールバックする方法を示します。使用している環境に合わせて接続およびデータソースパラメーターを調整し、データベースで 2 つのテストテーブルをセットアップする必要があります。

例10.5 JTA トランザクションの例

public class JDBCExample {
    public static void main (String[] args) {
        Context ctx = new InitialContext();
        // Change these two lines to suit your environment.
        DataSource ds = (DataSource)ctx.lookup("jdbc/ExampleDS");
        Connection conn = ds.getConnection("testuser", "testpwd");
        Statement stmt = null; // Non-transactional statement
        Statement stmtx = null; // Transactional statement
        Properties dbProperties = new Properties();

        // Get a UserTransaction
        UserTransaction txn = new InitialContext().lookup("java:comp/UserTransaction");

        try {
            stmt = conn.createStatement();  // non-tx statement
            
            // Check the database connection.
            try {
                stmt.executeUpdate("DROP TABLE test_table");
                stmt.executeUpdate("DROP TABLE test_table2");
            }
            catch (Exception e) {
                // assume not in database.
            }
            
            try {
                stmt.executeUpdate("CREATE TABLE test_table (a INTEGER,b INTEGER)");
                stmt.executeUpdate("CREATE TABLE test_table2 (a INTEGER,b INTEGER)");
            }
            catch (Exception e) {
            }

            try {
                System.out.println("Starting top-level transaction.");