Red Hat Training

A Red Hat training course is available for Red Hat JBoss Enterprise Application Platform

開発ガイド

Red Hat JBoss Enterprise Application Platform 6.4

Red Hat JBoss Enterprise Application Platform 6 向け

概要

この本は、Red Hat JBoss Enterprise Application Platform 6 とそのパッチリリースを使用する Java EE 6 開発者向けのリファレンスと例を提供します。

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

1.1. はじめに

1.1.1. Red Hat JBoss Enterprise Application Platform 6

Red Hat JBoss Enterprise Application Platform 6 (JBoss EAP 6) は、オープン標準に構築されたミドルウェアプラットフォームで、Java Enterprise Edition 6 仕様に準拠します。これは、JBoss Application Server 7 を高可用性クラスターリング、メッセージング、分散キャッシング、およびその他のテクノロジーと統合します。
JBoss EAP 6 には、必要な場合にだけサービスを有効にできる新しいモジュール構造が含まれます (サービスの起動時間が短縮されます)。
管理コンソールと管理コマンドラインインターフェースにより、XML 設定ファイルの編集が不必要になり、タスクをスクリプト化および自動化する機能が追加されました。
また、JBoss EAP 6 には、セキュアでスケーラブルな Java EE アプリケーションの迅速な開発を可能にする API と開発フレームワークが含まれます。

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 フルプロファイルには、EE6 仕様に含まれるすべての API と仕様が含まれています。EE 6 Web プロファイルには、Web 開発者に役立つ API のサブセットが含まれています。
JBoss EAP 6 は、Java Enterprise Edition 6 フルプロファイルおよび Web プロファイル仕様の認定された実装です。

1.2.1.2. Java Enterprise Edition 6 Web プロファイル

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

Java EE 6 Web プロファイルの要件

  • Java Platform, Enterprise Edition 6
  • Java Web Technologies

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

    • コンテキストおよび依存関係の挿入 (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 のフルプロファイル

Java Enterprise Edition 6 (EE 6) 仕様では、プロファイルの概念が定義されており、そのうちの 2 つが仕様の一部として定義されています。Java Enterprise Edition 6 Web プロファイルでサポートされている項目に加えて (「Java Enterprise Edition 6 Web プロファイル」)、フルプロファイルは次の API をサポートします。

EE 6 フルプロファイルに含まれるアイテム

  • EJB 3.1(Lite ではない) (JSR 318)
  • Java EE コネクターアーキテクチャー 1.6 (JSR 322)
  • Java Message Service (JMS) API 1.1 (JSR 914)
  • JavaMail 1.4 (JSR 919)
  • Web サービステクノロジー

    • Jax-RS RESTful Web サービス 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)
    • コンテナー 1.3 の Java 認証契約 (JSR 115)
    • Java EE アプリケーションデプロイメント 1.2 (JSR 88)
    • J2EE Management 1.1 (JSR 77)

1.2.2. JBoss EAP 6 で使用されるモジュールと新しい Modular Class Loading System について

1.2.2.1. モジュール

モジュールは、クラスローディングおよび依存関係管理に使用されるクラスの論理グループです。JBoss EAP 6 は、静的モジュールと動的モジュールと呼ばれることもある 2 つの異なるタイプのモジュールを識別します。ただし、2 つの違いは、パッケージ方法だけです。
静的モジュール
静的モジュールは、アプリケーションサーバーの EAP_HOME/modules/ ディレクトリーで事前定義されます。各サブディレクトリーは 1 つのモジュールを表し、設定ファイル (module.xml) と必要な JAR ファイルを含む main/ サブディレクトリーを定義します。モジュールの名前は、module.xml ファイルで定義されています。アプリケーションサーバーが提供するすべての API は、Java EE API や JBoss Logging などの他の API を含む静的モジュールとして提供されます。

例1.1 module.xml ファイルの例

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="com.mysql">
  <resources>
    <resource-root path="mysql-connector-java-5.1.15.jar"/>
  </resources>
  <dependencies>
    <module name="javax.api"/>
    <module name="javax.transaction.api"/>
  </dependencies>
</module>
モジュール名、com.mysqlmain/ サブディレクトリー名を除いて、モジュールのディレクトリー構造と一致する必要があります。
JBoss EAP ディストリビューションで提供されるモジュールは、EAP_HOME/modules ディレクトリー内の system ディレクトリーにあります。このため、サードパーティーによって提供されるモジュールから分離されます。
JBoss EAP 6.1 以降の上にレイヤー化された Red Hat が提供するレイヤード製品も、system ディレクトリー内にモジュールをインストールします。
カスタム静的モジュールの作成は、同じサードパーティーライブラリーを使用する同じサーバー上に多くのアプリケーションがデプロイされる場合に役立ちます。これらのライブラリーを各アプリケーションとバンドルする代わりに、JBoss 管理者はこれらのライブラリーが含まれるモジュールを作成およびインストールできます。アプリケーションは、カスタム静的モジュールで明示的な依存関係を宣言できます。
モジュールレイアウトごとに 1 つのディレクトリーを使用して、カスタムモジュールが EAP_HOME/modules ディレクトリーにインストールされるようにする必要があります。こうすると、同梱されたバージョンではなく、system ディレクトリーに存在するカスタムバージョンのモジュールがロードされるようになります。これにより、ユーザー提供のモジュールがシステムモジュールよりも優先されます。
JBOSS_MODULEPATH 環境変数を使用して JBoss EAP がモジュールを検索する場所を変更する場合は、指定された場所の 1 つで system サブディレクトリー構造を探します。システム 構造体は、JBOSS_MODULEPATHで指定された場所のどこかに存在する必要があります。
動的モジュール
動的モジュールは、各 JAR または WAR デプロイメント (または、EAR 内のサブデプロイメント) に対してアプリケーションサーバーによって作成およびロードされます。動的モジュールの名前は、デプロイされたアーカイブの名前に由来します。デプロイメントはモジュールとしてロードされるため、依存関係を設定し、他のデプロイメントで依存関係として使用することが可能です。
モジュールは必要な場合にのみロードされます。通常、モジュールは、明示的または暗黙的な依存関係があるアプリケーションがデプロイされる場合にのみロードされます。

1.3. 開発環境のセットアップ

1.3.1. Red Hat JBoss Developer Studio をダウンロードしてインストールします

1.3.1.1. Setup Red Hat JBoss Developer Studio

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

  1. https://access.redhat.com/ にアクセスします。
  2. ページの上部にあるメニューから Downloads を選択します。
  3. リストから Red Hat Developer Studio を見つけて、クリックします。
  4. 適切なバージョンを選択し、Download をクリックします。

1.3.1.3. Install Red Hat JBoss Developer Studio

手順1.1 Install Red Hat JBoss Developer Studio

  1. Open a terminal.
  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. Red Hat JBoss Developer Studio のデスクトップショートカットを設定し、Next をクリックします。
  12. 完了 をクリックします。

1.3.1.4. Red Hat JBoss Developer Studio の起動

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

  1. Open a terminal.
  2. インストールディレクトリーに移動します。
  3. 次のコマンドを実行して、Red Hat JBoss Developer Studio を起動します。
    [localhost]$ ./jbdevstudio

1.3.1.5. Define New Server を使用して JBossEAP サーバーを追加します

これらの手順は、これが Red Hat JBoss Developer Studio の最初の紹介であり、Red Hat JBoss Enterprise Application Platform サーバーをまだ追加していないことを前提としています。以下の手順では、Define New Server ウィザードを使用して、JBoss EAP サーバーを追加します。

手順1.3 サーバーを追加します

  1. Servers タブを開きます。Servers タブがない場合は、次のようにパネルに追加します。
    1. WindowShow ViewOther...をクリックします。
    2. Server フォルダーから Servers を選択し、OK をクリックします。
  2. 以下をクリックします、No servers are available。このリンクをクリックして、新しいサーバーを作成します。または、必要に応じて、空白のサーバーパネル内を右クリックし、NewServer を選択します。

    図1.1 新しいサーバーを追加する - No servers available

    新しいサーバーを追加する - No servers available
  3. JBoss Enterprise Middleware を展開し、JBoss Enterprise Application Platform 6.1+ を選択します。JBoss Enterprise Application Platform 6.4 などのサーバー名を入力し、Next をクリックして JBoss ランタイムを作成し、サーバーを定義します。次回新しいサーバーを定義するとき、このダイアログには、新しいランタイム定義を含む Server runtime environment の選択が表示されます。

    図1.2 新しいサーバーを定義する

    新しいサーバーを定義する
  4. サーバーの起動と停止を管理するサーバーアダプターを作成します。デフォルトのままにして、Next をクリックします。

    図1.3 新しいサーバーアダプターを作成する

    新しいサーバーアダプターを作成する
  5. JBoss EAP 6.4 Runtime などの名前を入力します。Home Directory で、Browse をクリックして、JBoss EAP のインストール場所に移動します。Next をクリックします。

    図1.4 新しいサーバーランタイム環境を追加する

    新しいサーバーランタイム環境を追加する
    注記
    一部のクイックスタートでは、別のプロファイルまたは追加の引数を使用してサーバーを実行する必要があります。full プロファイルを必要とするクイックスタートをデプロイするには、新しいサーバーを定義し、Configuration filestandalone-full.xml を指定する Server Runtime Environment を追加する必要があります。新しいサーバーにはわかりやすい名前を付けてください。
  6. 新しいサーバー用に既存のプロジェクトを設定します。この時点ではプロジェクトがないため、Finish をクリックします。

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

    新しい JBoss サーバーのリソースを変更します

結果

JBoss EAP Runtime Server が Servers タブに一覧表示されます。

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

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

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

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

1.4.1.1. クイックスタートにアクセスする

概要

JBoss EAP 6 には、ユーザーが Java EE 6 テクノロジーを使用してアプリケーションを書き始めるのに役立つように設計された一連のクイックスタートの例が付属しています。

前提条件

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

  1. Web ブラウザーを開き、次の URL にアクセスします。https://access.redhat.com/jbossnetwork/restricted/listSoftware.html?product=appplatform
  2. リストからクイックスタートを見つけます。
  3. Download ボタンをクリックして、例を含む Zip アーカイブをダウンロードします。
  4. 選択したディレクトリーでアーカイブを解凍します。

結果

JBoss EAP クイックスタートがダウンロードされて解凍されました。各クイックスタートの展開手順については、クイックスタートアーカイブの最上位ディレクトリーにある README.md ファイルを参照してください。

1.4.2. クイックスタートを実行する

1.4.2.1. Red Hat JBoss Developer Studio でクイックスタートを実行します

このセクションでは、Red Hat JBoss Developer Studio を使用してクイックスタートをデプロイし、Arquillian テストを実行する方法について説明します。

手順1.5 クイックスタートを Red Hat JBoss Developer Studio にインポートします

各クイックスタートには、クイックスタートのプロジェクトおよび設定情報を含む POM(プロジェクトオブジェクトモデル) ファイルが付属しています。この POM ファイルを使用すると、クイックスタートを Red Hat JBoss Developer Studio に簡単にインポートできます。
重要
Red Hat JBoss Developer Studio へのインポート時にクイックスタートプロジェクトフォルダーが IDE ワークスペース内にある場合、IDE は無効なプロジェクト名と WAR アーカイブ名を生成します。作業を開始する前に、クイックスタートプロジェクトフォルダーが IDE ワークスペースの外部にあることを確認してください。
  1. Red Hat JBoss Developer Studio を起動します。
  2. メニューから FileImport を選択します。
  3. 選択リストで、MavenExisting Maven Projects を選択し、Next をクリックします。

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

    既存の Maven プロジェクトのインポート
  4. テストする予定のクイックスタートのディレクトリー (たとえば、helloworld クイックスタート) を参照し、OK をクリックします。Projects リストボックスに、選択したクイックスタートプロジェクトの pom.xml ファイルが示されます。

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

    Maven プロジェクトの選択
  5. Finish をクリックします。

手順1.6 helloworld クイックスタートをビルドしてデプロイする

helloworld クイックスタートは最もシンプルなクイックスタートの 1 つであり、JBoss サーバーが正しく設定され実行されていることを確認するための良い方法です。
  1. Servers タブが表示されない場合、またはサーバーをまだ定義していない場合は、次の手順に従ってください。「Define New Server を使用して JBossEAP サーバーを追加します」full プロファイルまたは追加のスタートアップ引数を必要とするクイックスタートをデプロイする場合は、クイックスタートの手順に記載されているように、必ずサーバーランタイム環境を作成してください。
  2. Project Explorer タブで jboss-helloworld プロジェクトを右クリックし、Run As を選択します。選択肢のリストが提供されます。Run on Server を選択します。

    図1.9 Run As - Run on Server

    Run As - Run on Server
  3. サーバーリストから JBoss EAP 6.1+ Runtime Server を選択し、Next をクリックします。

    図1.10 Run on Server

    Run on Server
  4. 次の画面には、サーバーで設定されているリソースが表示されます。jboss-helloworld クイックスタートが設定されています。Finish をクリックしてクイックスタートをデプロイします。

    図1.11 サーバーで設定されたリソースの変更

    サーバーで設定されたリソースの変更
  5. 結果を表示します。
    • Server タブで、JBoss EAP 6.x ランタイムサーバーのステータスが [Started, Republish] に変わります。
    • サーバーの Console タブには、JBoss EAP 6.x サーバーの起動と helloworld クイックスタートのデプロイメントの詳細を示すメッセージが表示されます。
    • URL (http://localhost:8080/jboss-helloworld/HelloWorld) とテキスト Hello World! を示す helloworld タブが表示されます。
    • Console の次のメッセージは、jboss-helloworld.war ファイルのデプロイを確認します。
      JBAS018210: Register web context: /jboss-helloworld
      JBAS018559: Deployed "jboss-helloworld.war" (runtime-name : "jboss-helloworld.war")
      
      登録された Web コンテキストは http://localhost:8080 に追加され、デプロイされたアプリケーションへのアクセスに使用される URL を提供します。
  6. JBoss サーバーに正常にデプロイされた helloworld クイックスタートを確認するには、Web ブラウザーを開き、次の URL でアプリケーションにアクセスします。http://localhost:8080/jboss-helloworld

手順1.7 bean-validation クイックスタート Arquillian テストの実行

一部のクイックスタートは、ユーザーインターフェイスレイヤーを提供せず、代わりにコード例を示すための Arquillian テストを提供します。bean-validation クイックスタートは、Arquillian テストを提供するクイックスタートの例です。
  1. 上記の手順に従って、bean-validation クイックスタートを Red Hat JBoss Developer Studio にインポートします。
  2. Servers タブでサーバーを右クリックし、Start を選択して JBoss EAP サーバーを起動します。Servers タブが表示されない場合、またはサーバーをまだ定義していない場合は、次の手順に従ってください。「Define New Server を使用して JBossEAP サーバーを追加します」
  3. Project Explorer タブで jboss-bean-validation プロジェクトを右クリックし、Run As を選択します。選択肢のリストが提供されます。Maven Build を選択します。
  4. Edit Configuration ダイアログの Goals 入力フィールドに、次のように入力します clean test -Parq-jbossas-remote
    次に、Run をクリックします。

    図1.12 設定の編集

    設定の編集
  5. 結果を表示します。
    サーバーの Console タブには、JBoss EAP サーバーの起動と bean-validation クイックスタート Arquillian テストの出力の詳細を示すメッセージが表示されます。
    -------------------------------------------------------
     T E S T S
    -------------------------------------------------------
    Running org.jboss.as.quickstarts.bean_validation.test.MemberValidationTest
    Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.189 sec
    
    Results :
    
    Tests run: 5, Failures: 0, Errors: 0, Skipped: 0
    
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    

1.4.2.2. コマンドラインを使用してクイックスタートを実行する

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

コマンドラインを使用して、クイックスタートを簡単にビルドおよびデプロイできます。コマンドラインを使用する場合、必要に応じて JBoss サーバーを起動する必要があることに注意してください。
  1. クイックスタートのルートディレクトリーにある README.html ファイルを確認します。
    このファイルには、システム要件、Maven の設定方法、ユーザーの追加方法、およびクイックスタートの実行方法に関する一般的な情報が含まれています。始める前に必ず読んでください。
    また、利用可能なクイックスタートを一覧表示する表も含まれています。この表には、各クイックスタート名とそれが示すテクノロジーがリストされています。各クイックスタートと、それを設定するために必要な経験のレベルについて簡単に説明します。クイックスタートの詳細は、クイックスタート名をクリックしてください。
    一部のクイック起動は、他のクイック起動を強化または拡張するように設計されています。これらは、Prerequisites の列に記載されています。クイックスタートに前提条件がリストされている場合は、クイックスタートを使用する前にまずそれらをインストールする必要があります。
    一部のクイックスタートでは、オプションのコンポーネントのインストールと設定が必要です。クイックスタートで必要な場合を除いて、これらのコンポーネントをインストールしないでください。
  2. helloworld クイックスタートを実行します。
    helloworld クイックスタートは最もシンプルなクイックスタートの 1 つであり、JBoss サーバーが正しく設定され実行されていることを確認するための良い方法です。helloworld クイックスタートのルートにある README.html ファイルを開きます。クイックスタートをビルドしてデプロイし、実行中のアプリケーションにアクセスする方法の詳細な手順が含まれています
  3. 他のクイックスタートを実行します。
    各クイックスタートのルートフォルダーにある README.html ファイルの指示に従って、例を実行します。

1.4.3. クイックスタートチュートリアルを確認する

1.4.3.1. helloworld クイックスタート

概要

helloworld クイックスタートは JBoss EAP 6 に単純なサーブレットをデプロイする方法を示します。ビジネスロジックは CDI (Contexts and Dependency Injection: コンテキストと依存関係の挿入) Bean として提供されるサービスにカプセル化され、サーブレットに挿入されます。このクイックスタートは非常に簡単です。HelloWorld を Web ページに出力するだけです。サーバーを適切に設定して起動したことを確認することは、良い出発点です。

コマンドラインを使用してこのクイックスタートをビルドしデプロイする手順の詳細については、helloworld クイックスタートディレクトリーのルートにある README.html ファイルを参照してください。ここでは、Red Hat JBoss Developer Studio を使用してクイックスタートを実行する方法を示します。このトピックは、Red Hat JBoss Developer Studio をインストールし、Maven を設定し、helloworld クイックスタートをインポートして正常に実行したことを前提としています。

前提条件

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

helloworld クイックスタートのコードは QUICKSTART_HOME/helloworld ディレクトリーにあります。helloworld クイックスタートはサーブレットと CDI Bean によって構成されます。また、JBoss EAP 6 にこのアプリケーションで Bean を検索し、CDI をアクティブ化するように指示する空の beans.xml ファイルも含まれています。
  1. Beans.xml ファイルは、クイックスタートの src/main/webapp/ ディレクトリーの WEB-INF/ フォルダーにあります。
  2. src/main/webapp/ ディレクトリーには、シンプルなメタリフレッシュを使用してユーザーのブラウザーをサーブレットにリダイレクトする index.html ファイルも含まれており、これはhttp://localhost:8080/jboss-helloworld/HelloWorldに配置されています。
  3. この例のすべての設定ファイルは、WEB-INF/ にあります。これは、例の src/main/webapp/ ディレクトリーにあります。
  4. クイックスタートには web.xml ファイルも必要ないことに注意してください。

手順1.10 コードの確認

パッケージの宣言とインポートはこれらのリストからは除外されています。完全リストはクイックスタートのソースコードで確認できます。
  1. HelloWorldServlet コードを確認します。

    HelloWorldServlet.java ファイルは src/main/java/org/jboss/as/quickstarts/helloworld/ ディレクトリーにあります。このサーブレットが情報をブラウザーに送ります。
    42.  @SuppressWarnings("serial")
    43.  @WebServlet("/HelloWorld")
    44.  public class HelloWorldServlet extends HttpServlet {
    45.  
    46.      static String PAGE_HEADER = "<html><head><title>helloworld</title></head><body>";
    47.  
    48.      static String PAGE_FOOTER = "</body></html>";
    49.  
    50.      @Inject
    51.      HelloService helloService;
    52.  
    53.      @Override
    54.      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    55.          resp.setContentType("text/html");
    56.          PrintWriter writer = resp.getWriter();
    57.          writer.println(PAGE_HEADER);
    58.          writer.println("<h1>" + helloService.createHelloMessage("World") + "</h1>");
    59.          writer.println(PAGE_FOOTER);
    60.          writer.close();
    61.      }
    62.  
    63.  }
    

    表1.1 HelloWorldServlet の詳細

    注記
    43 Java EE 6 より前は、XML ファイルを使用してサーブレットを登録していました。よりきれいになりました。必要な作業は @WebServlet アノテーションを追加し、サーブレットにアクセスするために使用する URL にマッピングを提供するだけです。
    46〜48 各 Web ページには適切な形式の HTML が必要になります。本クイックスタートは静的な文字列を使用して最低限のヘッダーとフッターの出力を書き出します。
    50〜51 これらの行は、実際のメッセージを生成する HelloService CDI Bean を挿入します。HelloService の API を変更しない限り、ビューレイヤーを変更せずに HelloService の実装を後で変更することが可能です。
    58 この行はサービスを呼び出し、「Hello World」というメッセージを生成して HTTP 要求へ書き出します。
  2. HelloService コードを確認します

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

1.4.3.2. numberguess クイックスタート

概要

このクイックスタートでは、簡単なアプリケーションを作成して JBoss EAP 6 にデプロイする方法を示します。このアプリケーションは情報を保持しません。情報は JSF ビューを使用して表示され、ビジネスロジックは 2 つの CDI (コンテキストと依存性注入) Bean にカプセル化されます。numberguess クイックスタートでは、1 から 100 までの数字を推測する試みが 10 回行われます。数字を選択した後、その数字が正解の数字よりも大きいかまたは小さいかが表示されます。

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

前提条件

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

この例のすべての設定ファイルは、クイックスタートの src/main/webapp/ ディレクトリーにある WEB-INF/ ディレクトリーに配置されています。
  1. faces-config.xml ファイルを確認します。
    本クイックスタートは faces-config.xml ファイル名の JSF 2.0 バージョンを使用します。Facelets の標準化されたバージョンは JSF 2.0 のデフォルトのビューハンドラーであるため、実際に設定する必要はありません。JBoss EAP 6 は、ここで JavaEE を超えています。この設定ファイルを含めると、JSF が自動的に設定されます。その結果、設定はルート要素のみで設定されます。
    19. <faces-config version="2.0"
    20.    xmlns="http://java.sun.com/xml/ns/javaee"
    21.    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    22.    xsi:schemaLocation="
    23.       http://java.sun.com/xml/ns/javaee>
    24.       http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">
    25.      
    26. </faces-config>
    
  2. beans.xml ファイルを確認します。
    空の beans.xml ファイルもあります。これは、JBoss EAP 6 にこのアプリケーションで Bean を検索し、CDI をアクティブ化するように指示します。
  3. web.xml ファイルはありません
    クイックスタートには web.xml ファイルも必要ないことに注意してください。

手順1.12 JSF コードの確認

JSF はソースファイルに .xhtml ファイル拡張子を使用しますが、レンダリングされたビューは .jsf 拡張子で提供されます。
  • home.xhtml コードを調べます。
    home.xhtml ファイルは src/main/webapp/ ディレクトリーにあります。
    19. <html xmlns="http://www.w3.org/1999/xhtml"
    20.    xmlns:ui="http://java.sun.com/jsf/facelets"
    21.    xmlns:h="http://java.sun.com/jsf/html"
    22.    xmlns:f="http://java.sun.com/jsf/core">
    23.
    24. <head>
    25. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    26. <title>Numberguess</title>
    27. </head>
    28.
    29. <body>
    30.    <div id="content">
    31.       <h1>Guess a number...</h1>
    32.       <h:form id="numberGuess">
    33.
    34.          <!-- Feedback for the user on their guess -->
    35.          <div style="color: red">
    36.             <h:messages id="messages" globalOnly="false" />
    37.             <h:outputText id="Higher" value="Higher!"
    38.                rendered="#{game.number gt game.guess and game.guess ne 0}" />
    39.             <h:outputText id="Lower" value="Lower!"
    40.                rendered="#{game.number lt game.guess and game.guess ne 0}" />
    41.          </div>
    42.
    43.          <!-- Instructions for the user -->
    44.          <div>
    45.             I'm thinking of a number between <span
    46.                id="numberGuess:smallest">#{game.smallest}</span> and <span
    47.                id="numberGuess:biggest">#{game.biggest}</span>. You have
    48.             #{game.remainingGuesses} guesses remaining.
    49.          </div>
    50.
    51.          <!-- Input box for the users guess, plus a button to submit, and reset -->
    52.          <!-- These are bound using EL to our CDI beans -->
    53.          <div>
    54.             Your guess:
    55.             <h:inputText id="inputGuess" value="#{game.guess}"
    56.                required="true" size="3"
    57.                disabled="#{game.number eq game.guess}"
    58.                validator="#{game.validateNumberRange}" />
    59.             <h:commandButton id="guessButton" value="Guess"
    60.                action="#{game.check}"
    61.                disabled="#{game.number eq game.guess}" />
    62.          </div>
    63.          <div>
    64.             <h:commandButton id="restartButton" value="Reset"
    65.                action="#{game.reset}" immediate="true" />
    66.          </div>
    67.       </h:form>
    68.
    69.    </div>
    70.
    71.    <br style="clear: both" />
    72.
    73. </body>
    74. </html>
    

    表1.2 JSF の詳細

    注記
    36〜40 これらはユーザーに送信できるメッセージ、「Higher」(より大きい) と「Lower」(より小さい) です。
    45〜48 ユーザーが数を選択するごとに数字の範囲が狭まります。有効な数の範囲が分かるようにこの文章は変更されます。
    55〜58 この入力フィールドは値式を使用して Bean プロパティーにバインドされます。
    58 ユーザーが誤って範囲外の数字を入力しないようにバリデーターのバインディングが使用されます。バリデーターがないと、ユーザーが範囲外の数字を使用する可能性があります。
    59〜61 ユーザーの選択した数字をサーバーに送る方法がなければなりません。ここでは、Bean 上のアクションメソッドをバインドします。

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

すべての numberguess クイックスタートソースファイルは、src/main/java/org/jboss/as/quickstarts/numberguess/ ディレクトリーにあります。パッケージの宣言とインポートはこれらのリストからは除外されています。完全リストはクイックスタートのソースコードで確認できます。
  1. Random.java 修飾子コードの検証
    修飾子は、型を基にしたインジェクションの対象となる 2 つの bean 間のあいまいさを取り除くために使用されます。修飾語の詳細については、以下を参照してください。 「修飾子を使用したあいまいなインジェクションの解決」
    @Random 修飾子は乱数のインジェクトに使用されます。
    @Target({ TYPE, METHOD, PARAMETER, FIELD })
    @Retention(RUNTIME)
    @Documented
    @Qualifier
    public @interface Random {
    
    }
  2. MaxNumber.java 修飾子コードの検証
    @MaxNumber qualifier は最大許可数の挿入に使用されます。
    @Target({ TYPE, METHOD, PARAMETER, FIELD })
    @Retention(RUNTIME)
    @Documented
    @Qualifier
    public @interface MaxNumber {
    
    }
  3. Generator.java コードの検証
    Generator クラスは、プロデューサーメソッドを介して乱数を作成するロールを果たします。また、プロデューサーメソッドを介して可能な最大数を公開します。このクラスはアプリケーションスコープであるため、毎回異なる乱数になることはありません。
    @SuppressWarnings("serial")
    @ApplicationScoped
    public class Generator implements Serializable {
    
        private java.util.Random random = new java.util.Random(System.currentTimeMillis());
    
        private int maxNumber = 100;
    
        java.util.Random getRandom() {
            return random;
        }
    
        @Produces
        @Random
        int next() {
            // a number between 1 and 100
            return getRandom().nextInt(maxNumber - 1) + 1;
        }
    
        @Produces
        @MaxNumber
        int getMaxNumber() {
            return maxNumber;
        }
    }
  4. Game.java コードの検証
    セッションスコープのクラス Game は、アプリケーションの主要なエントリーポイントです。ゲームの設定や再設定、ユーザーが選択する数字のキャプチャーや検証、FacesMessage によるユーザーへのフィードバック提供を行います。コンストラクト後の lifecycle メソッドを使用し、@Random Instance<Integer> bean から乱数を取得することによりゲームを初期化します。
    このクラスの @Named アノテーションを見てください。このアノテーションは式言語 (EL) を使用して Bean が JSF ビューにアクセスできるようにしたい場合のみ必要です。この場合 #{game} が EL になります。
    @SuppressWarnings("serial")
    @Named
    @SessionScoped
    public class Game implements Serializable {
    
        /**
         * The number that the user needs to guess
         */
        private int number;
    
        /**
         * The users latest guess
         */
        private int guess;
    
        /**
         * The smallest number guessed so far (so we can track the valid guess range).
         */
        private int smallest;
    
        /**
         * The largest number guessed so far
         */
        private int biggest;
    
        /**
         * The number of guesses remaining
         */
        private int remainingGuesses;
    
        /**
         * The maximum number we should ask them to guess
         */
        @Inject
        @MaxNumber
        private int maxNumber;
    
        /**
         * The random number to guess
         */
        @Inject
        @Random
        Instance<Integer> randomNumber;
    
        public Game() {
        }
    
        public int getNumber() {
            return number;
        }
    
        public int getGuess() {
            return guess;
        }
    
        public void setGuess(int guess) {
            this.guess = guess;
        }
    
        public int getSmallest() {
            return smallest;
        }
    
        public int getBiggest() {
            return biggest;
        }
    
        public int getRemainingGuesses() {
            return remainingGuesses;
        }
    
        /**
         * Check whether the current guess is correct, and update the biggest/smallest guesses as needed. Give feedback to the user
         * if they are correct.
         */
        public void check() {
            if (guess > number) {
                biggest = guess - 1;
            } else if (guess < number) {
                smallest = guess + 1;
            } else if (guess == number) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Correct!"));
            }
            remainingGuesses--;
        }
    
        /**
         * Reset the game, by putting all values back to their defaults, and getting a new random number. We also call this method
         * when the user starts playing for the first time using {@linkplain PostConstruct @PostConstruct} to set the initial
         * values.
         */
        @PostConstruct
        public void reset() {
            this.smallest = 0;
            this.guess = 0;
            this.remainingGuesses = 10;
            this.biggest = maxNumber;
            this.number = randomNumber.get();
        }
    
        /**
         * A JSF validation method which checks whether the guess is valid. It might not be valid because there are no guesses left,
         * or because the guess is not in range.
         * 
         */
        public void validateNumberRange(FacesContext context, UIComponent toValidate, Object value) {
            if (remainingGuesses <= 0) {
                FacesMessage message = new FacesMessage("No guesses left!");
                context.addMessage(toValidate.getClientId(context), message);
                ((UIInput) toValidate).setValid(false);
                return;
            }
            int input = (Integer) value;
    
            if (input < smallest || input > biggest) {
                ((UIInput) toValidate).setValid(false);
    
                FacesMessage message = new FacesMessage("Invalid guess");
                context.addMessage(toValidate.getClientId(context), message);
            }
        }
    }

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

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

手順1.14 デフォルトの 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 アプリケーションを設定します。

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

    最初のステップで変更したサーバーグループまたはサーバーにアプリケーションをデプロイします。アプリケーションは現在、http://SERVER_URL:PORT/

1.4.5. WS-AtomicTransaction の使用

wsat-simple クイックスタートは、Red Hat JBoss Enterprise Application Platform にデプロイするために WAR アーカイブにバンドルされた WS-AT(WS-AtomicTransaction) 対応の JAX-WSWeb サービスのデプロイを示しています。
レストランが提供する予約のための Web サービスです。このサービスでは、Atomic Transaction 内で予約を行うことができます。この例は、WS-AT 対応の Web サービスを実装するための基本を示しています。より高度な機能を示すことは、このクイックスタートの範囲を超えています。特に以下を確認します。
  • サービスは、障害が発生した場合の回復をサポートするために必要なフックを実装していません。
  • また、トランザクションバックエンドリソースを利用しません。
  • プロトコルに参加する Web サービスは 1 つだけです。WS-AT は 2PC 調整プロトコルであるため、複数の参加者がいるシナリオに最適です。
より完全な例については、Narayana プロジェクトに付属している XTS デモンストレーターアプリケーションを参照してください。http://www.jboss.org/narayana
また、WS-Atomic Transaction を理解していることを前提としています。詳細については、Narayana プロジェクトに付属している XTS ドキュメントを参照してください。このドキュメントは、http://www.jboss.org/narayana/documentation/4174_Final からダウンロードできます。
このアプリケーションは、WAR アーカイブ内にデプロイされた単一の JAX-WS Web サービスで設定されています。これは、JBoss Arquillian 対応の JUnit テストでテストされます。
org.jboss.as.quickstarts.wsat.simple.ClientTest#testCommit() メソッドを実行すると、次の手順が実行されます。
  1. 新しい Atomic Transaction (AT) がクライアントによって作成されます。
  2. WS-AT 対応の Web サービスでの操作は、クライアントによって呼び出されます。
  3. WS クライアントハンドラーチェーンの JaxWSHeaderContextProcessor は、WS-AT コンテキストを送信 SOAP メッセージに挿入します。
  4. サービスが SOAP 要求を受信すると、ハンドラーチェーン内の JaxWSHeaderContextProcessor が WS-AT コンテキストを検査し、要求をこの AT に関連付けます。
  5. Web サービス操作が呼び出されます。
  6. 参加者はこの AT に参加しています。これにより、Web サービスロジックがコミットやロールバックなどのプロトコルイベントに応答できるようになります。
  7. サービスはビジネスロジックを呼び出します。この場合、レストランへの予約となります。
  8. バックエンドリソースが準備されます。これにより、コーディネーターから指示されたときに、バックエンドリソースが変更を元に戻したり永続的にしたりできるようになります。
  9. その後、クライアントは AT をコミットするかロールバックするかを決定できます。クライアントがコミットすることを決定した場合、コーディネーターは 2PC プロトコルを開始します。参加者がロールバックすることを決定した場合、すべての参加者はロールバックするように指示されます。
クライアントが AT をロールバックすることを決定した場合に何が起こるかを示す別のテストがあります。

第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 EAP 6 には、Java EE 開発者が JBoss EAP 6 でアプリケーションをビルドする際に使用する要件の多くが含まれる Maven リポジトリーが含まれます。このリポジトリーを使用するようにプロジェクトを設定するには、「JBoss EAP Maven 6 リポジトリーを設定します」を参照してください。
リモートリポジトリーへのアクセスには、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 ファイル

Project Object Model (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.4-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.4-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 のダウンロードおよびインストール

Maven コマンドラインを使用して JBoss EAP にアプリケーションをビルドおよびデプロイする場合は、Maven をダウンロードおよびインストールする必要があります。Red Hat JBoss Developer Studio を使用してアプリケーションをビルドおよびデプロイする場合は、Maven が Red Hat JBoss Developer Studio とともに配布されるため、この手順をスキップできます。
  1. Apache Maven Project - Download Maven にアクセスし、ご使用のオペレーティングシステムに対応する最新のディストリビューションをダウンロードします。
  2. ご使用のオペレーシングシステムに Apache Maven をダウンロードおよびインストールする方法は、Maven のドキュメントを参照してください。

2.2.2. JBoss EAP 6 Maven リポジトリーをインストールします

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

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

概要

JBoss EAP 6 Maven リポジトリーはオンラインで利用できるため、ローカルにダウンロードしてインストールする必要はありません。ただし、JBoss EAP Maven リポジトリーをローカルにインストールする場合は、ローカルファイルシステム、Apache Web サーバー、または Maven リポジトリーマネージャーを使用する 3 つの方法があります。この例では、JBoss EAP 6 Maven リポジトリーをローカルファイルシステムにダウンロードする手順について説明します。このオプションは設定が簡単で、ローカルマシンですぐに実行することができます。開発時における Maven の使用方法を理解することができますが、チームの本番環境では推奨されません。

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

  1. Web ブラウザーを開き、次の URL にアクセスします。https://access.redhat.com/jbossnetwork/restricted/listSoftware.html?product=appplatform
  2. リストから Red Hat JBoss Enterprise Application Platform VERSION Maven Repository を探します。
  3. Download ボタンをクリックして、リポジトリーを含む .zip ファイルをダウンロードします。
  4. ローカルファイルシステム上のファイルを、選択したディレクトリーに解凍します。

結果

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

重要
古いローカルリポジトリーを使用する場合は、そのリポジトリーを Maven の settings.xml 設定ファイルで個別に設定する必要があります。各ローカルリポジトリーは、独自の <repository> タグ内で設定する必要があります。
重要
新しい Maven リポジトリーをダウンロードするときは、新しい Maven リポジトリーを使用する前に、.m2/ ディレクトリーの下にあるキャッシュされた repository/ サブディレクトリーを削除してください。

2.2.4. Apache httpd で使用する JBoss EAP 6 Maven レポジトリーのインストール

リポジトリーをインストールする方法は 3 つあります。ローカルファイルシステム、Apache Web サーバー、または Maven リポジトリーマネージャーを使用します。この例では、Apache httpd で使用するために JBoss EAP 6 リポジトリーをダウンロードする手順について説明します。このオプションは、Web サーバーにアクセスできる開発者なら誰でも Maven リポジトリーにアクセスできるため、マルチユーザーおよびチーム間の開発環境に適しています。

前提条件

Apache httpd を設定する必要があります。手順は、Apache HTTP Server Project ドキュメンテーションを参照してください。

手順2.2 JBoss EAP 6 Maven リポジトリーの ZIP アーカイブをダウンロードする

  1. Web ブラウザーを開き、次の URL にアクセスします。https://access.redhat.com/jbossnetwork/restricted/listSoftware.html?product=appplatform
  2. リストから Red Hat JBoss Enterprise Application Platform <VERSION> Maven リポジトリーを見つけます。
  3. Download ボタンをクリックして、リポジトリーを含む .zip ファイルをダウンロードします。
  4. Apache サーバー上で Web にアクセス可能なディレクトリーに Zip 形式のファイルを展開します。
  5. 作成されたディレクトリーで読み取りアクセスとディレクトリーの閲覧を許可するよう Apache を設定します。

結果

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

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

2.2.5. JBoss EAP 6 リポジトリーマネージャーを使用して JBoss EAP 6 Maven リポジトリーをインストールします

リポジトリーをインストールする方法は 3 つあります。ローカルファイルシステム、Apache Web サーバー、または Maven リポジトリーマネージャーを使用します。このオプションは、既存のリポジトリーと一緒に JBoss リポジトリーをホストできるため、ライセンスがあり、すでにリポジトリーマネージャーを使用している場合に最適です。Maven リポジトリーマネージャーの詳細については、「Maven リポジトリーマネージャー」を参照してください。
この例では、Sonatype Nexus Maven リポジトリーマネージャーを使用して JBoss EAP 6 リポジトリーをインストールする手順について説明します。詳細な手順については、Sonatype Nexus: アーティファクトの管理 を参照してください。

手順2.3 JBoss EAP 6 Maven リポジトリーの ZIP アーカイブをダウンロードする

  1. Web ブラウザーを開き、次の URL にアクセスします。https://access.redhat.com/jbossnetwork/restricted/listSoftware.html?product=appplatform
  2. リストから Red Hat JBoss Enterprise Application Platform <VERSION> Maven リポジトリーを見つけます。
  3. Download ボタンをクリックして、リポジトリーを含む .zip ファイルをダウンロードします。
  4. Nexus をホストしているサーバー上の選択したディレクトリーにファイルを解凍します。

手順2.4 JBoss EAP 6 リポジトリーマネージャーを使用して JBoss EAP 6 Maven リポジトリーを追加します

  1. 管理者として Nexus にログインします。
  2. リポジトリーマネージャーの左側にある ViewsRepositories メニューから Repositories セクションを選択します。
  3. Add... ドロップダウンをクリックし、Hosted Repository を選択します。
  4. 新しいリポジトリーに名前と ID を付けます。
  5. Override Local Storage するフィールドに、解凍したリポジトリーへのディスク上のパスを入力します。
  6. アーティファクトをリポジトリーグループで使用できるようにする場合は、続行します。これが希望どおりでない場合は、この手順を続行しないでください。
  7. リポジトリーグループを選択します。
  8. Configure タブをクリックします。
  9. 新しい JBoss Maven リポジトリーを Available Repositories リストから左側の Ordered Group Repositories リストにドラッグします。
    注記
    このリストの順序によって、Maven アーティファクトを検索するための優先順位が決まることに注意してください。

結果

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

2.2.6. Maven リポジトリーマネージャー

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

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

Sonatype Nexus
Nexus の詳細については、Sonatype Nexus: アーティファクトの管理 を参照してください。
Artifactory
Artifactory の詳細は、Artifactory オープンソース を参照してください。
Apache Archiva
Apache Archiva の詳細は、Apache Archiva: The Build Artifact Repository Manager を参照してください。

2.3. Maven リポジトリーの使用

2.3.1. JBoss EAP Maven 6 リポジトリーを設定します

概要

プロジェクトで JBoss EAP 6 Maven リポジトリーを使用するよう Maven に指示する方法は 2 つあります。

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

手順2.5 JBoss EAP 6 Maven リポジトリーを使用するように Maven 設定を設定する

  1. Maven 設定を使用して Maven リポジトリーを設定します

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

    この設定方法は、通常はお勧めしません。プロジェクトの POM ファイルでリポジトリーを設定する場合は、慎重に計画し、ビルドが遅くなる可能性があり、予期されたリポジトリーからではないアーティファクトが発生する可能性があることに注意してください。
    注記
    リポジトリーマネージャーが通常使用されるエンタープライズ環境では、Maven は、このマネージャーを使用してすべてのプロジェクトに対してすべてのアーティファクトを問い合わせる必要があります。Maven は、宣言されたすべてのリポジトリーを使用して不足しているアーティファクトを見つけるため、探しているものが見つからない場合に、central リポジトリー (組み込みの親 POM で定義されます) で検索を試行します。この central の場所をオーバーライドするには、central で定義を追加してデフォルトの central リポジトリーがリポジトリーマネージャーになるようにします。これは、確立されたプロジェクトには適切ですが、クリーンなプロジェクトや「新しい」プロジェクトの場合は、cyclic 依存関係が作成されるため、問題が発生します。
    推移的に含まれる POM も、このタイプの設定の問題です。Maven は、これらの外部リポジトリーに欠落しているアーティファクトを照会する必要があります。これにより、ビルドの速度が低下するだけでなく、アーティファクトの発生元を制御できなくなり、ビルドが破損する可能性があります。
    この設定方法は、設定されたプロジェクトのグローバル設定とユーザー Maven 設定をオーバーライドします。

2.3.2. Maven 設定を使用した JBoss EAP 6 Maven リポジトリーの設定

プロジェクトで JBoss EAP 6 Maven リポジトリーを使用するよう Maven に指示する方法は 2 つあります。
  • Maven の設定を変更できます。これにより、Maven はすべてのプロジェクトで設定を使用するように指示されます。
  • プロジェクトの POM ファイルを設定できます。これにより、設定が特定のプロジェクトに制限されます。
このトピックでは、Maven 設定を使用してすべてのプロジェクトで JBoss EAP 6 Maven リポジトリーを使用するように Maven に指示する方法を示します。これは、推奨の手法です。
オンラインまたはローカルにインストールされた JBoss EAP 6 リポジトリーを使用するように Maven を設定できます。オンラインリポジトリーを使用する場合は、事前設定された設定ファイルを使用するか、JBoss EAP 6 Maven プロファイルを既存の設定ファイルに追加できます。ローカルリポジトリーを使用するには、リポジトリーをダウンロードし、ローカルにインストールされたリポジトリーを指すように設定を設定する必要があります。以下の手順では、JBoss EAP 6 用に Maven を設定する方法について説明します。
注記
リポジトリーの URL はリポジトリーの場所 (ファイルシステムまたは Web サーバー) によって異なります。リポジトリーのインストール方法については、を参照してください。「JBoss EAP 6 Maven リポジトリーをインストールします」。各インストールオプションの例は次のとおりです。
ファイルシステム
file:///path/to/repo/jboss-eap-6.x-maven-repository
Apache Web Server
http://intranet.acme.com/jboss-eap-6.x-maven-repository/
Nexus リポジトリーマネージャー
https://intranet.acme.com/nexus/content/repositories/jboss-eap-6.x-maven-repository
Maven は、Maven インストールのグローバル設定またはユーザーインストール設定のいずれかを使用して設定できます。これらの手順は、これが最も一般的な設定であるため、ユーザーのインストール設定を設定します。

手順2.6 クイックスタートの例に含まれる設定を使って Maven を設定する

JBoss EAP 6 クイックスタートには、オンライン JBoss EAP 6 Maven リポジトリーを使用するように設定された settings.xml ファイルが付属しています。これが最も簡単なアプローチです。
  1. この手順では、既存の Maven 設定ファイルが上書きされるため、既存の Mavensettings.xml ファイルをバックアップする必要があります。
    1. オペレーティングシステムの Maven インストールディレクトリーを見つけます。通常、USER_HOME/.m2/ ディレクトリーにインストールされます。
      • Linux または Mac では、これは ~/.m2/ になります。
      • Windows の場合、これは次のとおりです。\Documents and Settings\USER_NAME\.m2\ または \Users\USER_NAME\.m2\
    2. 既存の USER_HOME/.m2/settings.xml ファイルがある場合は、後で復元できるように、ファイルの名前を変更するか、バックアップコピーを作成します。
  2. JBoss EAP 6 に付属のクイックスタートの例をダウンロードして解凍します。詳細は、「クイックスタートにアクセスする」 を参照してください
  3. QUICKSTART_HOME/settings.xml ファイルを USER_HOME/.m2/ ディレクトリーにコピーします。
  4. Red Hat JBoss Developer Studio の実行中に settings.xml ファイルを変更する場合は、以下のタイトルの手順に従ってください。手順2.9「Red Hat JBoss Developer Studio のユーザー設定を更新します」

手順2.7 Online JBoss EAP 6 Maven リポジトリーを使用するには、Maven 設定を手動で編集および設定します

JBoss EAP 6 プロファイルを既存の Maven 設定ファイルに手動で追加できます。
  1. オペレーティングシステムの Maven インストールディレクトリーを見つけます。通常、USER_HOME/.m2/ ディレクトリーにインストールされます。
    • Linux または Mac では、これは ~/.m2/ になります。
    • Windows の場合、これは \Documents and Settings\USER_NAME\.m2\ または \Users\USER_NAME\.m2\ です。
  2. settings.xml ファイルが見つからない場合、settings.xml ファイルをUSER_HOME/.m2/conf/ ディレクトリーからUSER_HOME/.m2/ ディレクトリへコピーします。
  3. 次の XML を<profiles> ファイルの要素にコピーします。
    <!-- Configure the JBoss GA Maven repository -->
    <profile>
      <id>jboss-ga-repository</id>
      <repositories>
        <repository>
          <id>jboss-ga-repository</id>
          <url>http://maven.repository.redhat.com/techpreview/all</url>
          <releases>
            <enabled>true</enabled>
          </releases>
          <snapshots>
            <enabled>false</enabled>
          </snapshots>
        </repository>
      </repositories>
      <pluginRepositories>
        <pluginRepository>
          <id>jboss-ga-plugin-repository</id>
          <url>http://maven.repository.redhat.com/techpreview/all</url>
          <releases>
            <enabled>true</enabled>
          </releases>
          <snapshots>
            <enabled>false</enabled>
          </snapshots>
        </pluginRepository>
      </pluginRepositories>
    </profile>
    <!-- Configure the JBoss Early Access Maven repository -->
    <profile>
      <id>jboss-earlyaccess-repository</id>
      <repositories>
        <repository>
          <id>jboss-earlyaccess-repository</id>
          <url>http://maven.repository.redhat.com/earlyaccess/all/</url>
          <releases>
            <enabled>true</enabled>
          </releases>
          <snapshots>
            <enabled>false</enabled>
          </snapshots>
        </repository>
      </repositories>
      <pluginRepositories>
        <pluginRepository>
          <id>jboss-earlyaccess-plugin-repository</id>
          <url>http://maven.repository.redhat.com/earlyaccess/all/</url>
          <releases>
            <enabled>true</enabled>
          </releases>
          <snapshots>
            <enabled>false</enabled>
          </snapshots>
        </pluginRepository>
      </pluginRepositories>
    </profile>
    
    次の XML をsettings.xml ファイルの要素 <activeProfiles> にコピーします。
    <activeProfile>jboss-ga-repository</activeProfile>
    <activeProfile>jboss-earlyaccess-repository</activeProfile>
    
  4. Red Hat JBoss Developer Studio の実行中に settings.xml ファイルを変更する場合は、以下のタイトルの手順に従ってください。手順2.9「Red Hat JBoss Developer Studio のユーザー設定を更新します」

手順2.8 ローカルにインストールされた JBoss EAP リポジトリーを使用するように設定を設定します

ローカルファイルシステムにインストールされている JBoss EAP 6 リポジトリーを使用するように設定を変更できます。
  1. オペレーティングシステムの Maven インストールディレクトリーを見つけます。通常、USER_HOME/.m2/ ディレクトリーにインストールされます。
    • Linux または Mac では、これは ~/.m2/ になります。
    • Windows の場合、これは \Documents and Settings\USER_NAME\.m2\ または \Users\USER_NAME\.m2\ です。
  2. settings.xml ファイルが見つからない場合、settings.xml ファイルをUSER_HOME/.m2/conf/ ディレクトリーからUSER_HOME/.m2/ ディレクトリへコピーします。
  3. 次の 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.x-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.x-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>
    
  4. Red Hat JBoss Developer Studio の実行中に settings.xml ファイルを変更する場合は、以下のタイトルの手順に従ってください。手順2.9「Red Hat JBoss Developer Studio のユーザー設定を更新します」

手順2.9 Red Hat JBoss Developer Studio のユーザー設定を更新します

Red Hat JBoss Developer Studio の実行中に settings.xml ファイルを変更する場合は、ユーザー設定を更新する必要があります。
  1. メニューから、WindowPreferences を選択します。
  2. Preferences ウインドウで Maven を展開表示し、User Settings を選択します。
  3. Update Settings ボタンをクリックし、Red Hat JBoss Developer Studio で Maven のユーザー設定を更新します。

    図2.1 Maven ユーザー設定を更新する

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

2.3.3. Red Hat JBoss Developer Studio で使用するための Maven の設定

アプリケーションをビルドし、Red Hat JBoss Enterprise Application Platform にデプロイするのに必要なアーティファクトと依存関係は、パブリックリポジトリーでホストされます。アプリケーションをビルドするときにこのリポジトリーを使用するよう Maven を設定する必要があります。このトピックでは、Red Hat JBoss Developer Studio を使用してアプリケーションをビルドおよびデプロイする場合に Maven を設定する手順について説明します。
Maven は Red Hat Developer Studio で配布されるため、個別にインストールする必要がありません。ただし、JBoss EAP へのデプロイメントのために Java EE Web Project ウィザードで使用する Maven を設定する必要があります。以下の手順は、Red Hat JBoss Developer Studio 内から Maven 設定ファイルを編集して、JBoss EAP で使用するために Maven を設定する方法を示しています。

手順2.10 Red Hat JBoss Developer Studio で Maven を設定する

  1. WindowPreferences の順にクリックし、JBoss Tools を展開して JBoss Maven Integration を選択します。

    図2.2 Preferences ウィンドウの JBoss Maven 統合ペイン

    Window → Preferences をクリックし、JBoss Tools を展開して、JBoss Maven Integration を選択します。
  2. Configure Maven Repositories をクリックします。
  3. Add Repository をクリックして、JBoss GA Tech Preview Maven リポジトリー を設定します。Add Maven Repository ダイアログで以下の手順を実行します。
    1. Profile IDRepository ID、および Repository Name の値を jboss-ga-repository に設定します。
    2. Repository URL 値を http://maven.repository.redhat.com/techpreview/all に設定します。
    3. Active by default チェックボックスをクリックして Maven リポジトリーを有効にします。
    4. OK をクリックします。

    図2.3 Maven リポジトリーの追加 -JBoss Tech Preview

    Maven プロファイルとリポジトリーの値を入力します。
  4. Add Repositoryをクリックして、JBoss Early Access Maven リポジトリーを設定します。Add Maven Repository ダイアログで以下の手順を実行します。
    1. Profile IDRepository ID、および Repository Name の値を jboss-earlyaccess-repository に設定します。
    2. Repository URL 値を http://maven.repository.redhat.com/earlyaccess/all/ に設定します。
    3. Active by default チェックボックスをクリックして Maven リポジトリーを有効にします。
    4. OK をクリックします。

    図2.4 Maven リポジトリーの追加 -JBoss Early Access

    Maven プロファイルとリポジトリーの値を入力します。
  5. リポジトリーを確認して、Finish をクリックします。

    図2.5 Maven リポジトリーを確認する

    Maven プロファイルとリポジトリーの値を確認します。
  6. Are you sure you want to update the file MAVEN_HOME/settings.xml? というメッセージが表示されます。Yes をクリックして設定を更新します。OK をクリックしてダイアログを閉じます。
    これで、JBoss EAP Maven リポジトリーが Red Hat JBoss Developer Studio で使用できるように設定されました。

2.3.4. プロジェクト POM を使用した JBoss EAP 6 Maven リポジトリーの設定

プロジェクトで JBoss EAP 6 Maven リポジトリーを使用するよう Maven に指示する方法は 2 つあります。
  • Maven の設定を変更できます。
  • プロジェクトの POM ファイルを設定できます。
このタスクでは、プロジェクト pom.xml にリポジトリー情報を追加して、JBoss EAP 6 Maven リポジトリーを使用するように特定のプロジェクトを設定する方法を示します。この設定方法は、グローバル設定とユーザー設定の設定に優先し、オーバーライドします。
この設定方法は、通常はお勧めしません。プロジェクトの POM ファイルでリポジトリーを設定する場合は、慎重に計画し、ビルドが遅くなる可能性があり、予期されたリポジトリーからではないアーティファクトが発生する可能性があることに注意してください。
注記
リポジトリーマネージャーが通常使用されるエンタープライズ環境では、Maven は、このマネージャーを使用してすべてのプロジェクトに対してすべてのアーティファクトを問い合わせる必要があります。Maven は、宣言されたすべてのリポジトリーを使用して不足しているアーティファクトを見つけるため、探しているものが見つからない場合に、central リポジトリー (組み込みの親 POM で定義されます) で検索を試行します。この central の場所をオーバーライドするには、central で定義を追加してデフォルトの central リポジトリーがリポジトリーマネージャーになるようにします。これは、確立されたプロジェクトには適切ですが、クリーンなプロジェクトや「新しい」プロジェクトの場合は、cyclic 依存関係が作成されるため、問題が発生します。
推移的に含まれる POM も、このタイプの設定の問題です。Maven は、これらの外部リポジトリーに欠落しているアーティファクトを照会する必要があります。これにより、ビルドの速度が低下するだけでなく、アーティファクトの発生元を制御できなくなり、ビルドが破損する可能性があります。
注記
リポジトリーの URL はリポジトリーの場所 (ファイルシステムまたは Web サーバー) によって異なります。リポジトリーのインストール方法については、以下を参照してください。「JBoss EAP 6 Maven リポジトリーをインストールします」。各インストールオプションの例は次のとおりです。
ファイルシステム
file:///path/to/repo/jboss-eap-6.x-maven-repository
Apache Web Server
http://intranet.acme.com/jboss-eap-6.x-maven-repository/
Nexus リポジトリーマネージャー
https://intranet.acme.com/nexus/content/repositories/jboss-eap-6.x-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.x.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.x.0-maven-repository/</url>
          <releases>
             <enabled>true</enabled>
          </releases>
          <snapshots>
             <enabled>true</enabled>
          </snapshots>
       </pluginRepository>
    </pluginRepositories>
    

2.3.5. プロジェクト依存関係の管理

本トピックでは、Red Hat JBoss Enterprise Application Platform 6 向けの Bill of Materials (BOM) POM の使用方法について説明します。
BOM は、指定モジュールに対するすべてのランタイム依存関係のバージョンを指定する Maven pom.xml (POM) ファイルです。バージョン依存関係は、ファイルの依存関係管理セクションにリストされています。
プロジェクトは、プロジェクトの pom.xml ファイルの依存関係管理セクションに groupId:artifactId:version (GAV) を追加し、<scope>import</scope><type>pom</type>の要素値を指定することで BOM を使用します。
注記
多くの場合、プロジェクト POM ファイルの依存関係によって provided スコープが使用されます。これは、これらのクラスが実行時にアプリケーションサーバーによって提供され、ユーザーアプリケーションとともにパッケージ化する必要がないためです。

サポート対象の Maven アーティファクト

製品のビルドプロセスの一部として、JBoss EAP のすべてのランタイムコンポーネントは制御された環境でソースからビルドされます。これにより、バイナリーアーティファクトに悪意のあるコードが含まれないようにし、製品のライフサイクルが終了するまでサポートを提供できるようにします。これらのアーティファクトは、1.0.0-redhat-1 のように使用される -redhat バージョン修飾子によって簡単に識別可能です。
サポートされるアーティファクトをビルド設定 pom.xml ファイルに追加すると、ローカルビルドおよびテスト向けの適切なバイナリーアーティファクトがビルドで使用されるようになります。-redhat バージョンのアーティファクトは、サポートされるパブリック API の一部とは限らず、今後の改訂で変更されることがあります。サポートされるパブリック API の詳細は、本リリースに含まれる JavaDoc ドキュメント を参照してください。
たとえば、サポートされているバージョンの hibernate を使用するには、ビルド設定に以下のようなコードを追加します。
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-core</artifactId>
  <version>4.2.16.Final-redhat-1</version>
  <scope>provided</scope>
</dependency>
上記の例では、<version/>のフィールドに値が含まれていることに注意してください。ただし、依存関係バージョンの設定には、Maven の依存関係管理を使用することが推奨されます。

依存関係管理

Maven には、ビルド全体で直接的および推移的な依存関係のバージョンを管理するメカニズムが含まれています。依存関係管理の使用に関する一般的な情報は、Apache Maven Project の Introduction to the Dependency Mechanism を参照してください。
サポートされる JBoss の依存関係を 1 つ以上ビルドに直接使用しても、ビルドの推移的な依存関係がすべて JBoss アーティファクトによって完全にサポートされるとは限りません。Maven ビルドでは、Maven central リポジトリー、JBoss.org Maven リポジトリー、およびその他の Maven リポジトリーからのアーティファクトソースを組み合わせて使用するのが一般的です。
JBoss EAP Maven リポジトリーには、サポートされているすべての JBoss EAP バイナリーアーティファクトを指定する依存関係管理 BOM が含まれています。この BOM は、ビルドの直接的および推移的依存関係に対して、サポートされる JBoss EAP 依存関係の優先順位を決定するためにビルドで使用できます。つまり、推移的な依存関係が、サポートされる正しい依存関係バージョン (該当する場合) に対して管理されます。この BOM のバージョンは、JBoss EAP リリースのバージョンと一致します。
<dependencyManagement>
  <dependencies>
    ...
    <dependency>
      <groupId>org.jboss.bom</groupId>
      <artifactId>eap6-supported-artifacts</artifactId>
      <version>6.4.0.GA</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
    ...
  </dependencies>
</dependencyManagement>

JBoss JavaEE Specs Bom

jboss-javaee-6.0BOM には、JBoss EAP で使用される Java EE 仕様 API JAR が含まれています。
プロジェクトでこの BOM を使用するには、アプリケーションのビルドとデプロイに必要な JSP とサーブレット API JAR のバージョンを含む GAV の依存関係を追加します。
次の例では、jboss-javaee-6.0BOM の 3.0.2.Final-redhat-x バージョンを使用しています。
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.jboss.spec</groupId>
      <artifactId>jboss-javaee-6.0</artifactId>
      <version>3.0.2.Final-redhat-x</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
    ...
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>org.jboss.spec.javax.servlet</groupId>
    <artifactId>jboss-servlet-api_3.0_spec</artifactId>
    <scope>provided</scope>
  </dependency>
  <dependency>
    <groupId>org.jboss.spec.javax.servlet.jsp</groupId>
    <artifactId>jboss-jsp-api_2.2_spec</artifactId>
    <scope>provided</scope>
  </dependency>
  ...
</dependencies>

JBoss EAP とクイックスタート

JBoss BOM は、次の jboss-bom プロジェクトにあります。https://github.com/jboss-developer/jboss-eap-boms
クイックスタートは、Maven リポジトリーの主なユースケースの例を提供します。次の表に、クイックスタートで使用される Maven BOM を示します。

表2.1 クイックスタートで使用される JBoss BOM

Maven artifactId Description
jboss-javaee-6.0-with-hibernate この BOM は、Java EE フルプロファイル BOM に基づいて構築されており、Hibernate ORM、Hibernate Search、HibernateValidator などの Hibernate コミュニティープロジェクトが追加されています。また、Hibernate JPA Model Gen や Hibernate Validator Annotation Processor などのツールプロジェクトも提供します。
jboss-javaee-6.0-with-hibernate3 この BOM は、Java EE フルプロファイル BOM に基づいて構築されており、Hibernate 3 ORM、Hibernate Entity Manager (JPA 1.0)、Hibernate Validator などの Hibernate コミュニティープロジェクトが追加されています。
jboss-javaee-6.0-with-logging この BOM は、Java EE フルプロファイル BOM に基づいて構築されており、JBoss Logging Tools と Log4j フレームワークが追加されています。
jboss-javaee-6.0-with-osgi この BOM は、Java EE フルプロファイル BOM に基づいて構築されており、OSGI が追加されています。
jboss-javaee-6.0-with-resteasy この BOM は、Java EE フルプロファイル BOM に基づいて構築されており、RESTEasy が追加されています。
jboss-javaee-6.0-with-security この BOM は、Java EE フルプロファイル BOM に基づいて構築されており、Picketlink が追加されています。
jboss-javaee-6.0-with-tools この BOM は、Java EE フルプロファイル BOM に基づいて構築されており、Arquillian がミックスに追加されています。また、Arquillian での使用が推奨されるバージョンの JUnit と TestNG も提供します。
jboss-javaee-6.0-with-transactions この BOM には、ワールドクラスのトランザクションマネージャーが含まれています。JBossTS API を使用して、その全機能にアクセスします。
次の例では、6.4.0.GA バージョンのjboss-javaee-6.0-with-hibernateBOM。
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.jboss.bom.eap</groupId>
      <artifactId>jboss-javaee-6.0-with-hibernate</artifactId>
      <version>6.4.0.GA</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
    ...
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <scope>provided</scope>
  </dependency>
  ...
</dependencies>

JBoss クライアント BOM

JBoss EAP サーバービルドには、jboss-as-ejb-client-bomjboss-as-jms-client-bom の 2 つのクライアント BOM が含まれています。
クライアント BOM は、依存関係管理セクションを作成したり、依存関係を定義したりしません。クライアント BOM は他の BOM の集合体であり、リモートクライアントのユースケースに必要な依存関係のセットをパッケージ化するために使用されます。
次の例では、7.4.0.Final-redhat-x バージョンのjboss-as-ejb-client-bomクライアント BOM。
<dependencies>
  <dependency>
    <groupId>org.jboss.as</groupId>
    <artifactId>jboss-as-ejb-client-bom</artifactId>
    <version>7.5.0.Final-redhat-x</version>
    <type>pom</type>
  </dependency>
  ...l
</dependencies>
この例では、7.4.0.Final-redhat-x バージョンのjboss-as-jms-client-bomクライアント BOM。
<dependencies>
  <dependency>
    <groupId>org.jboss.as</groupId>
    <artifactId>jboss-as-jms-client-bom</artifactId>
    <version>7.4.0.Final-redhat-x</version>
    <type>pom</type>
  </dependency>
  ...
</dependencies>

Maven 依存関係および BOM POM ファイルの詳細は、Apache Maven Project - Introduction to the Dependency Mechanism を参照してください。

2.4. Maven リポジトリーをアップグレードする

2.4.1. ローカル Maven リポジトリーにパッチを適用する

概要

Maven リポジトリーには、アプリケーションをビルドして JBoss EAP にデプロイするために必要な Java ライブラリー、プラグイン、およびその他のアーティファクトが保管されます。JBoss EAP リポジトリーはオンラインで利用でき、ダウンロードした ZIP ファイルとして使用することもできます。パブリックにホストされているリポジトリーを使用する場合、更新は自動的に適用されます。ただし、Maven リポジトリーをローカルにダウンロードしてインストールする場合は、更新を適用する責任があります。JBoss EAP のパッチが利用可能な場合は常に、対応するパッチが JBoss EAP Maven リポジトリーに提供されます。このパッチは、既存のローカルリポジトリーで展開される増分 ZIP ファイルで提供されます。ZIP ファイルには、新しい JAR ファイルと POM ファイルが含まれています。既存の JAR を上書きしたり、JAR を削除したりすることはないため、ロールバックの要件はありません。

JBoss EAP パッチ適用プロセスの詳細については、カスタマーポータルにある JBoss Enterprise Application Platform 6 の 『インストールガイド』 の 『JBoss EAP 6 の適用とアップグレード』 というタイトルの章を参照してください。https://access.redhat.com/documentation/ja-jp/red_hat_jboss_enterprise_application_platform/?version=6.4
このタスクでは、unzip コマンドを使用してローカルにインストールされた Maven リポジトリーに Maven 更新を適用する方法について説明します。

前提条件

  • Red Hat カスタマーポータルへの有効なアクセスおよびサブスクリプション。
  • Red Hat JBoss Enterprise Application Platform <VERSION> Maven リポジトリーの ZIP ファイル。ローカルにダウンロードおよびインストールされます。

手順2.11 Maven リポジトリーを更新します

  1. ブラウザーを開き、https://access.redhat.comにログインします。
  2. ページの上部にあるメニューから Downloads を選択します。
  3. リストで Red Hat JBoss Enterprise Application Platform を見つけ、クリックします。
  4. この画面に表示される Version ドロップダウンメニューから JBoss EAP の正しいバージョンを選択し、Patches をクリックします。
  5. リストから Red Hat JBoss Enterprise Application Platform <VERSION> CPx Incremental Maven Repository を見つけ、Download をクリックします。
  6. 選択したディレクトリーに ZIP ファイルを保存するように求められます。ディレクトリーを選択してファイルを保存します。
  7. オペレーティングシステムの JBoss EAP リポジトリーへのパス (以下のコマンドで EAP_MAVEN_REPOSITORY_PATH と呼ばれる) を見つけます。Maven リポジトリーをローカルファイルシステムにインストールする方法の詳細については、「JBoss EAP 6 Maven リポジトリーのローカルインストール」を参照してください。
  8. Maven パッチファイルを JBoss EAP <VERSION>.x Maven リポジトリーのインストールディレクトリーに直接解凍します。
    • Linux の場合は、ターミナルを開き、次のコマンドを入力します。
      [standalone@localhost:9999 /] unzip -o jboss-eap-<VERSION>.x-incremental-maven-repository.zip -d EAP_MAVEN_REPOSITORY_PATH
    • Windows の場合は、Windows 展開ユーティリティーを使用して ZIP ファイルを EAP_MAVEN_REPOSITORY_PATH ディレクトリーのルートに展開します。

結果

ローカルにインストールされた Maven リポジトリーは、最新のパッチで更新されます。

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

3.1. はじめに

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

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

3.1.2. クラスの読み込み

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

3.1.3. モジュール

モジュールは、クラスローディングおよび依存関係管理に使用されるクラスの論理グループです。JBoss EAP 6 は、静的モジュールと動的モジュールと呼ばれることもある 2 つの異なるタイプのモジュールを識別します。ただし、2 つの違いは、パッケージ方法だけです。
静的モジュール
静的モジュールは、アプリケーションサーバーの EAP_HOME/modules/ ディレクトリーで事前定義されます。各サブディレクトリーは 1 つのモジュールを表し、設定ファイル (module.xml) と必要な JAR ファイルを含む main/ サブディレクトリーを定義します。モジュールの名前は、module.xml ファイルで定義されています。アプリケーションサーバーが提供するすべての API は、Java EE API や JBoss Logging などの他の API を含む静的モジュールとして提供されます。

例3.1 module.xml ファイルの例

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="com.mysql">
  <resources>
    <resource-root path="mysql-connector-java-5.1.15.jar"/>
  </resources>
  <dependencies>
    <module name="javax.api"/>
    <module name="javax.transaction.api"/>
  </dependencies>
</module>
モジュール名、com.mysqlmain/ サブディレクトリー名を除いて、モジュールのディレクトリー構造と一致する必要があります。
JBoss EAP ディストリビューションで提供されるモジュールは、EAP_HOME/modules ディレクトリー内の system ディレクトリーにあります。このため、サードパーティーによって提供されるモジュールから分離されます。
JBoss EAP 6.1 以降の上にレイヤー化された Red Hat が提供するレイヤード製品も、system ディレクトリー内にモジュールをインストールします。
カスタム静的モジュールの作成は、同じサードパーティーライブラリーを使用する同じサーバー上に多くのアプリケーションがデプロイされる場合に役立ちます。これらのライブラリーを各アプリケーションとバンドルする代わりに、JBoss 管理者はこれらのライブラリーが含まれるモジュールを作成およびインストールできます。アプリケーションは、カスタム静的モジュールで明示的な依存関係を宣言できます。
モジュールレイアウトごとに 1 つのディレクトリーを使用して、カスタムモジュールが EAP_HOME/modules ディレクトリーにインストールされるようにする必要があります。こうすると、同梱されたバージョンではなく、system ディレクトリーに存在するカスタムバージョンのモジュールがロードされるようになります。これにより、ユーザー提供のモジュールがシステムモジュールよりも優先されます。
JBOSS_MODULEPATH 環境変数を使用して JBoss EAP がモジュールを検索する場所を変更する場合は、指定された場所の 1 つで system サブディレクトリー構造を探します。システム 構造体は、JBOSS_MODULEPATHで指定された場所のどこかに存在する必要があります。
動的モジュール
動的モジュールは、各 JAR または WAR デプロイメント (または、EAR 内のサブデプロイメント) に対してアプリケーションサーバーによって作成およびロードされます。動的モジュールの名前は、デプロイされたアーカイブの名前に由来します。デプロイメントはモジュールとしてロードされるため、依存関係を設定し、他のデプロイメントで依存関係として使用することが可能です。
モジュールは必要な場合にのみロードされます。通常、モジュールは、明示的または暗黙的な依存関係があるアプリケーションがデプロイされる場合にのみロードされます。

3.1.4. モジュールの依存性

モジュールの依存関係は、あるモジュールが機能するために別のモジュールのクラスを必要とするという宣言です。モジュールは、他の任意の数のモジュールへの依存関係を宣言できます。アプリケーションサーバーがモジュールをロードすると、モジュラークラスローダーはそのモジュールの依存関係を解析し、各依存関係からクラスをクラスパスに追加します。指定の依存関係が見つからない場合、モジュールはロードできません。
デプロイされたアプリケーション (JAR または WAR) は動的モジュールとしてロードされ、依存関係を利用して JBoss EAP 6 によって提供される API にアクセスします。
依存関係には明示的と暗黙的の 2 つのタイプがあります。

明示的な依存関係

明示的な依存関係は開発者が設定ファイルで宣言します。静的モジュールは、module.xml ファイルで依存関係を宣言できます。動的モジュールは、デプロイメントの MANIFEST.MF または jboss-deployment-structure.xml デプロイメント記述子で宣言された依存関係を持つことができます。

明示的な依存関係は、オプションとして指定できます。オプションの依存関係をロードできなくても、モジュールのロードは失敗しません。ただし、依存関係は後で使用できるようになっても、モジュールのクラスパスには追加されません。依存関係はモジュールがロードされるときに利用可能である必要があります。

暗黙的な依存関係

デプロイメントで特定の条件またはメタデータが検出されると、アプリケーションサーバーによって暗黙の依存関係が自動的に追加されます。JBoss EAP 6 に同梱される Java EE 6 API は、デプロイメントで暗黙的な依存関係が検出されたときに追加されるモジュールの例になります。

デプロイメントは、特定の暗黙の依存関係を除外するように設定することもできます。これは、jboss-deployment-structure.xml デプロイメント記述子ファイルを使用して行われます。これは通常、アプリケーションサーバーが暗黙的な依存関係として追加しようとする特定のバージョンのライブラリーをアプリケーションがバンドルする場合に行われます。
モジュールのクラスパスには独自のクラスとその直接の依存関係のクラスのみが含まれます。モジュールは 1 つの依存関係の依存関係クラスにはアクセスできませんが、暗黙的な依存関係のエクスポートを指定できます。ただし、モジュールは、明示的な依存関係をエクスポートするように指定できます。エクスポートした依存関係は、エクスポートするモジュールに依存するモジュールに提供されます。

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

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

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

クラスのロードの目的で、すべてのデプロイメントは JBoss EAP 6 によってモジュールとして扱われます。このようなデプロイメントは動的モジュールと呼ばれます。クラスローディングの動作はデプロイメントの種類によって異なります。
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 デプロイメント) は、自動的に親モジュールに依存しますが、サブデプロイメントモジュール同士が自動的に依存するわけではありません。ただし、相互で自動的な依存関係はありません。これはサブデプロイメントの分離と呼ばれ、デプロイメントごとに、またはアプリケーションサーバー全体に対して無効にすることができます。
サブデプロイメントモジュール間の明示的な依存関係は、他のモジュールと同じ方法で追加することが可能です。

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

JBoss EAP 6 のモジュール形式クラスローダーは、優先順位を決定してクラスローディングの競合が発生しないようにします。
デプロイメントに、パッケージとクラスの完全なリストがデプロイメントごとおよび依存関係ごとに作成されます。このリストは、クラスローディングの優先順位のルールに従って順序付けされます。実行時にクラスをロードすると、クラスローダーはこのリストを検索し、最初に一致したものをロードします。こうすることで、デプロイメントクラスパス内の同じクラスやパッケージの複数のコピーが競合しないようになります。
クラスローダーは上から順にクラスをロードします。
  1. 暗黙的な依存関係
    これらは、JAVA EE API などの JBoss EAP 6 によって自動的に追加される依存関係です。これらの依存関係には一般的な機能や JBoss EAP 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 EAP 6 によってモジュールとしてロードされ、以下の慣例に従って名前が付けられます。
  • WAR および JAR ファイルのデプロイメントは次の形式で名前が付けられます。
     deployment.DEPLOYMENT_NAME 
    例えば、inventory.warstore.jar は、それぞれdeployment.inventory.wardeployment.store.jarというモジュール名を持ちます。
  • エンタープライズアーカイブ内のサブデプロイメントは次の形式で名前が付けられます。
     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 EAP 6 の新しい任意のデプロイメント記述子です。このデプロイメント記述子を使用すると、デプロイメントでクラスローディングを制御できます。
このデプロイメント記述子の XML スキーマは EAP_HOME/docs/schema/jboss-deployment-structure-1_2.xsd にあります。

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

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

前提条件

  1. モジュールの依存関係を追加する作業用ソフトウェアプロジェクトがすでにある必要があります。
  2. 依存関係として追加するモジュールの名前を知っている必要があります。JBoss EAP 6 に含まれる静的モジュールの一覧は、「含まれるモジュール」を参照してください。モジュールが他のデプロイメントである場合は、「動的モジュールの名前付け」を参照してモジュール名を決定してください。
依存関係は、次の 2 つの異なる方法を使用して設定できます。
  1. デプロイメントの MANIFEST.MF ファイルにエントリーを追加します。
  2. jboss-deployment-structure.xml デプロイメント記述子にエントリーを追加します。

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

MANIFEST.MF ファイルの必要な依存関係エントリーを作成するよう Maven プロジェクトを設定できます。「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
  5. オプション: アノテーションを使用した依存関係

    この annotations フラグは、EJB インターセプターを宣言するときなど、アノテーションのスキャン中に処理する必要があるアノテーションがモジュールの依存関係に含まれる場合に必要になります。これを行わないと、モジュールで宣言された EJB インターセプターをデプロイメントで使用できなくなります。アノテーションのスキャンが関係するその他の状況でも、この設定が必要になる場合があります。
    このフラグを使用するには、モジュールに Jandex インデックスが含まれている必要があります。Jandex インデックスを作成および使用するための手順は、このトピックの最後に含まれています。

手順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. モジュール要素を追加する

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

    依存関係をオプションにするには、optional 属性をモジュールエントリーに追加し、値を true にします。この属性のデフォルト値は false です。
    <module name="org.javassist" optional="true" />
  5. オプション: 依存関係をエクスポートします

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

例3.3 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 EAP 6 では、デプロイ時に、指定されたモジュールからアプリケーションのクラスパスにクラスが追加されます。

Jandex インデックスの作成

annotations フラグは Jandex インデックスが含まれるモジュールを必要とします。モジュールに追加する新しいインデックス JAR を作成できます。Jandex JAR を使用してインデックスを構築し、新しい JAR ファイルに挿入します。

手順3.3

  1. インデックスの作成

    java -jar EAP_HOME/modules/org/jboss/jandex/main/jandex-1.0.3.Final-redhat-1.jar $JAR_FILE
  2. 一時作業領域の作成

    mkdir /tmp/META-INF
  3. インデックスファイルを作業ディレクトリーに移動します。

    mv $JAR_FILE.ifx /tmp/META-INF/jandex.idx
    • オプション 1: インデックスを新しい JAR ファイルに含めます。
      jar cf index.jar -C /tmp META-INF/jandex.idx
      JAR をモジュールディレクトリーに置き、module.xml を編集してリソースルートへ追加します。
    • オプション 2: インデックスを既存の JAR に追加します。
      java -jar EAP_HOME/modules/org/jboss/jandex/main/jandex-1.0.3.Final-redhat-1.jar -m $JAR_FILE
  4. モジュールのインポートに注釈インデックスを利用するように指示します

    アノテーションインデックスを使用するようモジュールインポートに指示し、アノテーションのスキャンでアノテーションを見つけられるようにします。
    状況に応じて、以下のいずれかの方法を選択してください。
    • MANIFEST.MF を使用してモジュールの依存関係を追加する場合は、annotations をモジュール名の後に追加します。
      例を以下に示します。
      Dependencies: test.module, other.module
      上記を以下のように変更します。
      Dependencies: test.module annotations, other.module
    • jboss-deployment-structure.xml を使用してモジュールの依存関係を追加する場合は、モジュールの依存関係に annotations="true" を追加します。

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 EAP 6 に含まれる静的モジュールの一覧は、「含まれるモジュール」を参照してください。モジュールが他のデプロイメントである場合、「動的モジュールの名前付け」を参照してモジュール名を決定します。

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

  1. 設定の追加

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

    <Dependencies>要素に、モジュールの依存関係のリストを追加します。MANIFEST.MF ファイルに依存関係を追加するときと同じ形式を使用します。そのフォーマットの詳細については、「デプロイメントへの明示的なモジュール依存関係の追加」を参照してください。
    <Dependencies>org.javassist, org.apache.velocity</Dependencies>
    ここでは、optional 属性と export 属性を使用することもできます。
    <Dependencies>org.javassist optional, org.apache.velocity export</Dependencies>
  3. プロジェクトをビルドします。

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

例3.4 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.5 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.5 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 設定ファイルを編集することによって行われます。サブシステムの除外は、サブシステムの削除と同じ効果がありますが、単一のデプロイメントにのみ適用されます。

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

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

結果

サブシステムは正常に除外されました。サブシステムのデプロイメントユニットプロセッサーがデプロイメント上で実行されなくなります。

例3.6 例: 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="jaxrs" />
    </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. デプロイメントでのプログラムによるクラスおよびリソースのロード

プログラムを用いて、アプリケーションコードでクラスやリソースを検索またはロードできます。選択する方法は、いくつかの要因によって異なります。本トピックでは、使用できる方法を説明し、それらの方法を使用するガイドラインを提供します。
Class.forName() メソッドを使用したクラスのロード
Class.forName()メソッドを使用すると、プログラムでクラスをロードして初期化することができます。このメソッドには 2 つのシグネチャーがあります。
Class.forName(String className)
このシグネチャーは、1 つのパラメーター (ロードする必要があるクラスの名前) のみを取ります。このメソッドシグネチャーを使用すると、現在のクラスのクラスローダーによってクラスがロードされ、デフォルトで新たにロードされたクラスが初期化されます。
Class.forName(String className, boolean initialize, ClassLoader loader)
このシグネチャーは、クラス名、クラスを初期化するかどうかを指定するブール値、およびクラスをロードする ClassLoader の 3 つのパラメーターを想定します。
プログラムでクラスをロードする場合は、3 つの引数のシグネチャーを用いる方法が推奨されます。このシグネチャーを使用すると、ロード時に目的のクラスを初期化するかどうかを制御できます。また、JVM はコールスタックをチェックして、使用するクラスローダーを判断する必要がないため、クラスローダーの取得および提供がより効率的になります。コードを含むクラスがCurrentClassという名前だとすると、CurrentClass.class.getClassLoader()メソッドを使ってそのクラスのクラスローダーを取得することができます。
次の例は、TargetClass クラスをロードして初期化するためのクラスローダーを提供します。

例3.7 TargetClass をロードして初期化するためのクラスローダーを提供します。

Class<?> targetClass = Class.forName("com.myorg.util.TargetClass", true, CurrentClass.class.getClassLoader());
名前ですべてのリソースを検索
リソースの名前とパスが分かり、直接そのリソースをロードする場合は、標準的な Java development kit の Class または ClassLoader API を使用するのが最良の方法です。
単一のリソースをロードします。
自分のクラスまたはデプロイメント内の別のクラスと同じディレクトリーにある単一のリソースをロードするには、Class.getResourceAsStream()メソッドを使用します。

例3.8 デプロイメントに単一のリソースをロードします。

InputStream inputStream = CurrentClass.class.getResourceAsStream("targetResourceName");
単一リソースのインスタンスをすべてロードします。
デプロイメントのクラスローダーが認識できる単一リソースのすべてのインスタンスをロードするには、Class.getClassLoader().getResources(String resourceName) メソッドを使用します。ここで、resourceName はリソースの完全修飾パスに置き換えます。このメソッドは、指定の名前でクラスローダーがアクセスできるリソースに対し、すべての URL オブジェクトの列挙を返します。その後、URL の配列で繰り返し処理し、 openStream() メソッドを使用して各ストリームを開くことができます。

例3.9 リソースのすべてのインスタンスをロードし、結果を繰り返し処理します。

Enumeration<URL> urls = CurrentClass.class.getClassLoader().getResources("full/path/to/resource");
while (urls.hasMoreElements()) {
    URL url = urls.nextElement();
    InputStream inputStream = null;
    try {
        inputStream = url.openStream();
        // Process the inputStream
        ...
    } catch(IOException ioException) {
        // Handle the error
    } finally {
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (Exception e) {
                // ignore
            }
        }
    }
}
注記
URL インスタンスはローカルストレージからロードされるため、openConnection() や他の関連するメソッドを使用する必要はありません。ストリームは非常に簡単に使用でき、ストリームを使用することにより、コードの複雑さが最小限に抑えられます。
クラスローダーからクラスファイルをロードします。
クラスがすでにロードされている場合は、以下の構文を使用して、そのクラスに対応するクラスファイルをロードできます。

例3.10 ロードされたクラスのクラスファイルをロードします。

InputStream inputStream = CurrentClass.class.getResourceAsStream(TargetClass.class.getSimpleName() + ".class");
クラスがロードされていない場合は、クラスローダーを使用し、パスを変換する必要があります。

例3.11 ロードされていないクラスのクラスファイルをロードします。

String className = "com.myorg.util.TargetClass"
InputStream inputStream = CurrentClass.class.getClassLoader().getResourceAsStream(className.replace('.', '/') + ".class");

3.6.2. デプロイメントでのプログラムによるリソースの繰り返し

JBoss Modules ライブラリーは、すべてのデプロイメントリソースを繰り返し処理するために複数の API を提供します。JBossModulesAPI の JavaDoc は次の場所にあります。http://docs.jboss.org/jbossmodules/1.3.0.Final/api/。これらの API を使用するには、以下の依存関係を MANIFEST.MF に追加する必要があります。
Dependencies: org.jboss.modules
これらの API により柔軟性が向上しますが、直接パスを検索するよりも動作がかなり遅くなることに注意してください。
本トピックでは、アプリケーションコードでプログラムを用いてリソースを繰り返す方法を説明します。
デプロイメント内およびすべてのインポート内のリソースをリストします。
場合によっては、正確なパスでリソースを検索できないことがあります。たとえば、正確なパスがわからない場合や、特定のパス内の複数のファイルを調べる必要がある場合があります。このような場合、JBoss Modules ライブラリーはすべてのデプロイメントを繰り返し処理するための API を複数提供します。2 つのメソッドのいずれかを使用すると、デプロイメントでリソースを繰り返し処理できます。
単一のモジュールで見つかったすべてのリソースを繰り返し処理します。
TheModuleClassLoader.iterateResources()メソッドは、このモジュールクラ出力ダー内のすべてのリソースを繰り返します。このメソッドは、検索を開始するディレクトリーの名前と、サブディレクトリーで再帰的に処理するかどうかを指定するブール値の 2 つの引数を取ります。
以下の例は、ModuleClassLoader の取得方法と、bin/ ディレクトリーにあるリソースのイテレーターの取得方法 (サブディレクトリーを再帰的に検索) を示しています。

例3.12 bin ディレクトリーでリソースを検索し、サブディレクトリーに繰り返します。

ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader();
Iterator<Resource> mclResources = moduleClassLoader.iterateResources("bin",true);
取得されたイテレーターは、一致した各リソースをチェックし、名前とサイズのクエリー (可能な場合) を行うために使用できます。また、読み取り可能ストリームを開いたり、リソースの URL を取得するために使用できます。
単一のモジュールで見つかったすべてのリソースとインポートされたリソースを繰り返し処理します。
TheModule.iterateResources()メソッドは、モジュールにインポートされたリソースを含む、このモジュールクラ出力ダー内のすべてのリソースを繰り返します。このメソッドは、前述のメソッドよりもはるかに大きなセットを返します。このメソッドには、特定パターンの結果を絞り込むフィルターとなる引数が必要になります。代わりに、PathFilters.acceptAll() を指定してセット全体を返すことも可能です。

例3.13 インポートを含む、このモジュールのリソースのセット全体を検索します。

ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader();
Module module = moduleClassLoader.getModule();
Iterator<Resource> moduleResources = module.iterateResources(PathFilters.acceptAll());
パターンと一致するすべてのリソースを検索します。
デプロイメント内またはデプロイメントの完全なインポートセット内で特定のリソースのみを見つける必要がある場合は、リソースの繰り返しをフィルターする必要があります。JBoss Modules のフィルター API は、リソースの繰り返しをフィルターする複数のツールを提供します。
依存関係の完全セットを確認します。
依存関係の完全なセットを調べる必要がある場合は、Module.iterateResources()メソッドのPathFilter各リソースの名前が一致するかどうかを確認するパラメーター。
デプロイメント依存関係を確認します。
デプロイメント内のみを調べる必要がある場合は、ModuleClassLoader.iterateResources()方法。が、追加のメソッドを使用して結果となるイテレーターをフィルターする必要があります。ThePathFilters.filtered()この場合、メソッドはリソースイテレータのフィルタリングされたビューを提供できます。PathFilters クラスには、さまざまな関数を実行するフィルターを作成する多くの静的メソッドが含まれています。これには、子パスや完全一致の検索、Ant 形式の「glob」パターンの一致などが含まれます。
リソースのフィルターに関する追加のコード例。
以下の例は、異なる基準を基にしてリソースをフィルターする方法を示しています。

例3.14 デプロイメントでファイル名が messages.properties のファイルをすべて検索

ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader();
Iterator<Resource> mclResources = PathFilters.filtered(PathFilters.match("**/messages.properties"), moduleClassLoader.iterateResources("", true));

例3.15 デプロイメントおよびインポートでファイル名が messages.properties のファイルをすべて検索

ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader();
Module module = moduleClassLoader.getModule();
Iterator<Resource> moduleResources = module.iterateResources(PathFilters.match("**/message.properties));

例3.16 デプロイメントでディレクトリー名が my-resources であるディレクトリー内部のファイルをすべて検索

ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader();
Iterator<Resource> mclResources = PathFilters.filtered(PathFilters.match("**/my-resources/**"), moduleClassLoader.iterateResources("", true));

例3.17 デプロイメントおよびインポートで messages または errors という名前のファイルをすべて検索

ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader();
Module module = moduleClassLoader.getModule();
Iterator<Resource> moduleResources = module.iterateResources(PathFilters.any(PathFilters.match("**/messages"), PathFilters.match("**/errors"));

例3.18 デプロイメントで指定のパッケージにあるすべてのファイルを検索

ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader();
Iterator<Resource> mclResources = moduleClassLoader.iterateResources("path/form/of/packagename", false);

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

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

エンタープライズアーカイブ (EAR) は、JAR または WAR デプロイメントのように、単一モジュールとしてロードされません。これらは、複数の一意のモジュールとしてロードされます。
以下のルールによって、EAR に存在するモジュールが決定されます。
  • EAR アーカイブのルートにある lib/ ディレクトリーの内容はモジュールです。これは、親モジュールと呼ばれます。
  • 各 WAR および EJB JAR サブデプロイメントはモジュールです。これらのモジュールの動作は、他のモジュールおよび親モジュールの暗黙的な依存関係と同じです。
  • サブデプロイメントでは、親モジュールとすべての他の非 WAR サブデプロイメントに暗黙的な依存関係が存在します。
JBoss EAP 6 ではサブデプロイメントクラスローダーの分離がデフォルトで無効になっているため、WAR サブデプロイメント以外の暗黙的な依存関係が発生します。親モジュールの依存関係は、サブデプロイメントクラスローダーの分離に関係なく永続します。
重要
サブデプロイメントでは、WAR サブデプロイメントに暗黙的な依存関係が存在しません。他のモジュールと同様に、サブデプロイメントは、別のサブデプロイメントの明示的な依存関係で設定できます。
サブデプロイメントクラスローダーの分離は、厳密な互換性が必要な場合に有効にできます。これは、単一の EAR デプロイメントまたはすべての EAR デプロイメントに対して有効にできます。Java EE 6 の仕様では、依存関係が各サブデプロイメントの MANIFEST.MF ファイルの Class-Path エントリーとして明示的に宣言されている場合を除き、移植可能なアプリケーションがお互いにアクセスできるサブデプロイメントに依存しないことが推奨されます。

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

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

3.7.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>true のコンテンツで jboss-deployment-structure.xml ファイルがまだ存在しない場合は、要素を jboss-deployment-structure.xml ファイルに追加します。
    <ear-subdeployments-isolated>true</ear-subdeployments-isolated>

結果:

これで、この EAR デプロイメントでサブデプロイメントクラ出力ダーの分離が有効になります。つまり、EAR のサブデプロイメントは WAR ではないサブデプロイメントごとに自動的な依存関係を持ちません。

3.8. カスタムモードでのタグライブラリー記述子 (TLD) のデプロイ

概要

共通のタグライブラリー記述子 (TLD) を使用する複数のアプリケーションがある場合、アプリケーションから TLD を分離し、一元的で一意な場所に置くと有用であることがあります。これにより、TLD を使用するアプリケーションごとに更新を行う必要がなくなり、TLD への追加や更新が簡単になります。

これを行うには、TLD JAR が含まれるカスタム JBoss EAP 6 モジュールを作成し、アプリケーションでそのモジュールの依存関係を宣言します。

前提条件

  • TLD を含む少なくとも 1 つの JAR。TLD がパックされていることを確認しますMETA-INF

手順3.7 カスタムモジュールでの TLD のデプロイ

  1. 管理 CLI を使用して、JBoss EAP 6 インスタンスへ接続し、以下のコマンドを実行して TLD JAR が含まれるカスタムモジュールを作成します。
    module add --name=MyTagLibs --resources=/path/to/TLDarchive.jar
    TLD が依存関係を必要とするクラスとともにパッケージ化されている場合は、--dependencies=DEPENDENCY オプションを使用して、カスタムモジュールの作成時にこれらの依存関係を指定するようにします。
    モジュールを作成するときに、それぞれを : で区切ることにより、複数の JAR リソースを指定できます。以下に例を示します。--resources=/path/to/one.jar:/path/to/two.jar
  2. アプリケーションで、で説明されているメソッドの 1 つを使用して、新しい MyTagLibs カスタムモジュールへの依存関係を宣言します。「デプロイメントへの明示的なモジュール依存関係の追加」
    重要
    インポートすることも確認してくださいMETA-INF依存関係を宣言するとき。たとえば、MANIFEST.MF の場合は以下のようになります。
    Dependencies: com.MyTagLibs meta-inf
    または、jboss-deployment-structure.xml の場合は、meta-inf属性。

結果

アプリケーションでは、新しいカスタムモジュールに含まれている TLD を使用できます。

3.9. 参照

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

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

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

依存関係を追加するサブシステム 常に追加される依存関係 条件付きで追加される依存関係 依存関係の追加を引き起こす条件
Core Server
  • javax.api
  • ibm.jdk
  • sun.jdk
  • org.jboss.vfs
EE サブシステム
  • javaee.api
  • org.hibernate.validator
  • org.jboss.invocation
  • org.jboss.as.ee
EJB3 サブシステム
  • javax.ejb.api
  • org.jboss.ejb-client
  • org.jboss.iiop-client
  • org.jboss.as.ejb3
  • org.jboss.as.jacorb
Java EE 6 仕様で説明されているように、デプロイメント内の有効な場所に ejb-jar.xml ファイルが存在する。
注釈ベースの EJB の存在。例:@Stateless@Stateful@MessageDriven
JAX-RS(RESTEasy) サブシステム
  • javax.xml.bind.api
  • javax.ws.rs.api
  • org.jboss.resteasy.resteasy-atom-provider
  • org.jboss.resteasy.resteasy-hibernatevalidator-provider
  • org.jboss.resteasy.resteasy-jaxrs
  • org.jboss.resteasy.resteasy-jaxb-provider
  • org.jboss.resteasy.resteasy-jackson-provider
  • org.jboss.resteasy.resteasy-jettison-provider
  • org.jboss.resteasy.resteasy-jsapi
  • org.jboss.resteasy.resteasy-multipart-provider
  • org.jboss.resteasy.resteasy-yaml-provider
  • org.codehaus.jackson.jackson-core-asl
デプロイメントに JAX-RS アノテーションが存在すること。
JCA サブシステム
  • javax.resource.api
  • javax.jms.api
  • javax.validation.api
  • org.jboss.ironjacamar.api
  • org.jboss.ironjacamar.impl
  • org.hibernate.validator
リソースアダプター (RAR) アーカイブのデプロイメント。
JPA(Hibernate) サブシステム
  • javax.persistence.api
  • javaee.api
  • org.jboss.as.jpa
  • org.jboss.as.jpa.spi
  • org.javassist
  • org.jboss.as.jpa.hibernate:3 / org.jboss.as.jpa.hibernate3.HibernatePersistenceProviderAdaptor
  • org.hibernate.envers
  • org.jboss.as.naming
  • org.jboss.jandex
の存在@PersistenceUnitまた@PersistenceContext注釈、または<persistence-unit-ref>また<persistence-context-ref>デプロイメント記述子の要素。
JBoss EAP 6 は永続プロバイダー名をモジュール名にマップします。persistence.xml ファイルで特定のプロバイダーに名前を付けると、適切なモジュールに対して依存関係が追加されます。これが希望の挙動ではない場合は、jboss-deployment-structure.xml を使用して除外できます。
ロギングサブシステム
  • org.jboss.logging
  • org.apache.log4j
  • org.apache.commons.logging
  • org.slf4j
  • org.jboss.logging.jul-to-slf4j-stub
これらの依存関係は、add-logging-api-dependencies属性が false に設定されています。
SAR サブシステム
  • org.jboss.modules
  • org.jboss.as.system-jmx
  • org.jboss.common-beans
SAR アーカイブの展開。
セキュリティーサブシステム
  • org.picketbox
  • org.jboss.as.security
  • javax.security.jacc.api
  • javax.security.auth.message.api
Web サブシステム
  • javax.servlet.api
  • javax.servlet.jsp.api
  • javax.websocket.api
  • javax.servlet.jstl.api
  • org.jboss.as.web
WAR アーカイブの展開。JavaServer Faces (JSF) は、使用されている場合にのみ追加されます。
Web サービスサブシステム
  • javax.jws.api
  • javax.xml.soap.api
  • javax.xml.ws.api
  • org.jboss.ws.api
  • org.jboss.ws.spi
アプリケーションクライアントタイプでない場合は、条件付き依存関係が追加されます。
溶接 (CDI) サブシステム
  • javax.enterprise.api
  • javax.inject.api
  • javax.persistence.api
  • javaee.api
  • org.javassist
  • org.jboss.as.weld
  • org.jboss.weld.core
  • org.jboss.weld.api
  • org.jboss.weld.spi
デプロイメントに beans.xml ファイルが存在すること。
コンテナー管理による永続性 (CMP) サブシステム
  • org.jboss.as.cmp

3.9.2. 含まれるモジュール

JBoss EAP 6 に含まれるモジュールと、それらがサポートされているかどうかをリストした表は、カスタマーポータルにあります。https://access.redhat.com/articles/1122333

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

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

第4章 バルブ

4.1. バルブ

Valve は、アプリケーションのリクエスト処理パイプラインに挿入される Java クラスです。サーブレットフィルターの前にパイプラインに挿入されます。バルブは、リクエストを渡す前にリクエストに変更を加えたり、認証やリクエストのキャンセルなどの他の処理を実行したりできます。
バルブは、サーバーレベルまたはアプリケーションレベルで設定できます。唯一の違いは、それらの設定とパッケージ化の方法にあります。
  • グローバルバルブはサーバーレベルで設定され、サーバーにデプロイされたすべてのアプリケーションに適用されます。グローバルバルブを設定する手順は、JBoss EAP の 『管理および設定ガイド』 に記載されています。
  • アプリケーションレベルで設定されたバルブは、アプリケーションデプロイメントにパッケージ化されており、特定のアプリケーションにのみ影響します。アプリケーションレベルでバルブを設定する手順は、JBoss EAP の 『開発ガイド』 に記載されています。
6.1.0 およびそれ以降のバージョンはグローバルバルブをサポートします。

4.2. グローバルバルブ

グローバルバルブは、デプロイされたすべてのアプリケーションのリクエスト処理パイプラインに挿入されるバルブです。バルブは、JBoss EAP 6 に静的モジュールとしてパッケージ化およびインストールされることにより、グローバルになります。グローバルバルブは Web サブシステムで設定されます。
6.1.0 およびそれ以降のバージョンのみがグローバルバルブをサポートします。
グローバルバルブを設定する方法については、JBossEAP の 『JBoss EAP および設定ガイド』 の 『グローバルバルブ』 というタイトルの章を参照してください。

4.3. オーセンティケーターバルブ

オーセンティケーターバルブは、リクエストのクレデンシャルを認証するバルブです。このようなバルブは、org.apache.catalina.authenticator.AuthenticatorBaseとオーバーライドしますauthenticate(Request request, Response response, LoginConfig config)方法。
このバルブを使用して追加の認証スキームを実装できます。

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

グローバルバルブとしてインストールされていないバルブは、アプリケーションに含まれ、jboss-web.xml デプロイメント記述子で設定されている必要があります。
重要
グローバルバルブとしてインストールされたバルブは、展開されたすべてのアプリケーションに自動的に適用されます。グローバルバルブを設定する方法については、JBoss EAP 『管理および設定ガイド』 の 『グローバルバルブ』 を参照してください。

前提条件

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

手順4.1 ローカルバルブのアプリケーションを設定します

  1. バルブを設定する

    作成するvalveを含む要素class-nameアプリケーションの jboss-web.xml ファイルの子要素。Theclass-nameバルブクラスの名前です。
    <valve>
      <class-name>VALVE_CLASS_NAME</class-name>
    </valve>

    例4.1 jboss-web.xml ファイルで設定されたバルブ要素

    <valve>
      <class-name>org.jboss.security.negotiation.NegotiationAuthenticator</class-name>
    </valve>
  2. カスタムバルブを設定する

    バルブに設定可能なパラメーターがある場合は、param子要素valve各パラメーターの要素、指定param-nameparam-valueそれぞれのために。

    例4.2 jboss-web.xml ファイルで設定されたカスタムバルブエレメント

    <valve>   
      <class-name>org.jboss.web.tomcat.security.GenericHeaderAuthenticator</class-name>  
      <param>  
        <param-name>httpHeaderForSSOAuth</param-name>  
        <param-value>sm_ssoid,ct-remote-user,HTTP_OBLIX_UID</param-value>  
      </param>  
      <param>  
        <param-name>sessionCookieForSSOAuth</param-name>  
        <param-value>SMSESSION,CTSESSION,ObSSOCookie</param-value>  
      </param>
    </valve>
アプリケーションがデプロイされると、指定された設定のアプリケーションに対してバルブが有効になります。

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

<valve>
  <class-name>org.jboss.samplevalves.RestrictedUserAgentsValve</class-name>
  <param>  
    <param-name>restrictedUserAgents</param-name>
    <param-value>^.*MS Web Services Client Protocol.*$</param-value>
  </param>
 </valve>

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

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

前提条件

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

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

  1. バルブを設定する

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

    security-constraintlogin-configsecurity-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. カスタムバルブを作成する

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

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

  1. Maven の依存関係を設定します。

    次の依存関係設定をプロジェクト pom.xml ファイルに追加します。
    <dependency>
      <groupId>org.jboss.web</groupId>
      <artifactId>jbossweb</artifactId>
      <version>7.5.7.Final-redhat-1</version>
      <scope>provided</scope>
    </dependency>
    注記
    jbossweb -VERSION.jar ファイルをアプリケーションに含めないでください。これは、JBoss EAP サーバーのランタイムクラスパスで JBoss モジュールとして次の場所で利用できます: EAP_HOME/modules/system/layers/base/org/jboss/as/web/main/jbossweb-7.5.7.Final-redhat-1。jar
  2. Valve クラスを作成します

    のサブクラスを作成します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 {
    
    }
  3. invoke メソッドを実装します。

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

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

    バルブを設定可能にする必要がある場合は、パラメーターを追加してこれを有効にします。これを行うには、各パラメーターにインスタンス変数とセッターメソッドを追加します。
    private String restrictedUserAgents = null;
    
    public void setRestricteduserAgents(String mystring) 
    {
       this.restrictedUserAgents = mystring;
    }
  6. 完成したコード例を確認します。

    これで、クラスは次の例のようになります。

    例4.4 サンプルカスタムバルブ

    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 は次のロギングフレームワークをサポートします。
JBoss LogManager では以下の API がサポートされます。
  • java.util.logging
  • JBoss Logging
  • Log4j
  • SLF4J
  • commons-logging
JBoss LogManager では以下の SPI もサポートされます。
  • java.util.logging Handler
  • Log4j Appender
注記
Log4j APILog4J Appender を使用している場合、オブジェクトは渡される前に string に変換されます。

5.1.3. ログレベル

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

5.1.4. サポート対象のログレベル

表5.1 サポート対象のログレベル

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

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

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

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

ログファイル Description
EAP_HOME/standalone/log/server.log
Server Log.サーバー起動メッセージを含む、すべてのサーバーログメッセージが含まれます。
EAP_HOME/standalone/log/gc.log
ガベージコレクションログ。すべてのガベージコレクションの詳細が含まれています。

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

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

5.2. JBoss Logging Framework を用いたロギング

5.2.1. JBoss Logging について

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

5.2.2. JBossLogging の機能

  • 革新的で使いやすい型付きロガーを提供します。
  • 国際化およびローカリゼーションの完全なサポート。翻訳者は properties ファイルのメッセージバンドルを、開発者はインターフェースやアノテーションを使い作業を行います。
  • 実稼働用の型指定されたロガーを生成し、開発用の型指定されたロガーを実行時に生成する構築時ツール。

5.2.3. JBoss Logging を使用したアプリケーションへのロギングの追加

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

前提条件

  • ビルドシステムとして Maven を使用している場合は、JBossMaven リポジトリーを含めるようにプロジェクトを設定する必要があります。「Maven 設定を使用した JBoss EAP 6 Maven リポジトリーの設定」 を参照してください。
  • JBoss Logging JAR ファイルがアプリケーションのビルドパスに指定されている必要があります。これを行う方法は、Red Hat JBossDeveloperStudio を使用してアプリケーションをビルドするか Maven を使用してアプリケーションをビルドするかによって異なります。
    • Red Hat JBoss Developer Studio を使用してビルドする場合は、プロジェクト メニューから プロパティー を選択し、ターゲット ランタイムを選択して、JBoss EAP 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 EAP 6 がデプロイされたアプリケーションに提供するため、ビルドされたアプリケーションに含める必要はありません。

手順5.1 アプリケーションにロギングを追加する

ロギングを追加するクラスごとに、次の手順を実行します。
  1. インポートを追加

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

    のインスタンスを作成しますorg.jboss.logging.Logger静的メソッドを呼び出して初期化しますLogger.getLogger(Class)。Red Hat は、これをクラスごとに単一のインスタンス変数として作成することをお勧めします。
    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 メソッドの完全なリストについては、以下を参照してください。org.jboss.loggingJBoss EAP 6 ドキュメントのパッケージ。

例5.1 プロパティーファイルを開くときに JBossLogging を使用する

この例は、プロパティーファイルからアプリケーションのカスタマイズされた設定をロードするクラスからのコードの抽出を示しています。指定されたファイルが見つからない場合は、ERROR レベルログメッセージが記録されます。
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. デプロイメントごとのロギング

デプロイメントごとのロギングを使用すると、開発者はアプリケーションのロギング設定を事前に設定できます。アプリケーションがデプロイされると、定義された設定に従ってロギングが開始されます。この設定によって作成されたログファイルにはアプリケーションの動作に関する情報のみが含まれます。
この方法では、システム全体のロギングを使用する利点と欠点があります。利点は、JBoss EAP インスタンスの管理者がロギングを設定する必要がないことです。欠点は、デプロイメントごとのロギング設定は起動時に読み取り専用であるため、実行時に変更できないことです。

5.3.2. デプロイメントごとのロギングをアプリケーションに追加

デプロイメントごとのロギングを設定するには、ロギング設定ファイル logging.properties をデプロイメントに追加します。この設定ファイルは、JBoss Log Manager が基礎となるログマネージャーである場合にどのロギングファサードとも使用できるため、推奨されます。
Simple Logging Facade for Java (SLF4J) または Apache log4j を使用している場合は、logging.properties 設定ファイルが適しています。Apache log4j アペンダーを使用している場合は、log4j.properties 設定ファイルが必要になります。jboss-logging.properties 設定ファイルはレガシーデプロイメントのみでサポートされます。

手順5.2 アプリケーションに設定ファイルを追加する

  • 設定ファイルが追加されるディレクトリーは、デプロイメント方法によって異なります。EARWARJAR のいずれかです。

    • EAR デプロイメント

      ロギング設定ファイルを META-INF ディレクトリーにコピーします。
    • WAR または JAR デプロイメント

      ロギング設定ファイルを META-INF または WEB-INF/classes ディレクトリーにコピーします。

5.3.3. logging.properties ファイルの例

# Additional loggers to configure (the root logger is always configured)
loggers=
# Root logger configuration
logger.level=INFO
logger.handlers=FILE
 
# A handler configuration
handler.FILE=org.jboss.logmanager.handlers.FileHandler
handler.FILE.level=ALL
handler.FILE.formatter=PATTERN
handler.FILE.properties=append,autoFlush,enabled,suffix,fileName
handler.FILE.constructorProperties=fileName,append
handler.FILE.append=true
handler.FILE.autoFlush=true
handler.FILE.enabled=true
handler.FILE.fileName=${jboss.server.log.dir}/app.log
 
# The formatter to use
formatter.PATTERN=org.jboss.logmanager.formatters.PatternFormatter
formatter.PATTERN.properties=pattern
formatter.PATTERN.constructorProperties=pattern
formatter.PATTERN.pattern=%d %-5p %c: %m%n

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

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

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

5.4.2. アプリケーションでのロギングプロファイルの指定

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

要件:

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

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

  • 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 Logging Tools

6.2.1. 概要

6.2.1.1. JBoss Logging Tools の国際化および現地語化

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

6.2.1.2. JBossLoggingTools クイックスタート

JBoss Logging Tools のクイックスタートである logging-tools には、JBossLoggingTools の機能を示す単純な Maven プロジェクトが含まれています。このドキュメントでは、コードサンプルとして広く使用されています。
このドキュメントで説明されているすべての機能の完全に機能するデモンストレーションについては、このクイックスタートを参照してください。

6.2.1.3. メッセージロガー

メッセージロガーは、国際化されたログメッセージを定義するために使用されるインターフェイスです。メッセージロガーインターフェイスには、@org.jboss.logging.MessageLogger

6.2.1.4. メッセージバンドル

メッセージバンドルは、国際化されたメッセージを使用して、一般的な翻訳可能なメッセージと例外オブジェクトを定義するために使用できるインターフェイスです。メッセージバンドルは、ログメッセージの作成には使用されません。
メッセージバンドルインターフェイスには、@org.jboss.logging.MessageBundle

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

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

6.2.1.6. 国際化された例外

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

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

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

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

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

6.2.1.9. JBoss Logging Tools のプロジェクトコード

プロジェクトコードはメッセージのグループを識別する文字列です。プロジェクトコードは各ログメッセージの最初に表示され、メッセージ Id の前に付けられます。プロジェクトコードは、projectCodeの属性@MessageLogger注釈。

6.2.1.10. JBoss Logging Tools のメッセージ ID

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

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

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

このタスクでは、JBoss Logging Tools を使用して、MessageLogger インターフェイスを作成することにより国際化されたログメッセージを作成する方法を示します。すべてのオプション機能またはそれらのログメッセージのローカリゼーションを網羅しているわけではありません。
完全な例については、logging-tools クイックスタートを参照してください。

要件:

  1. 作業用の Maven プロジェクトがすでに存在している必要があります。「JBoss Logging Tools の Maven 設定」 を参照してください。
  2. プロジェクトには、JBossLoggingTools に必要な Maven 設定が必要です。

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

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

    プロジェクトに Java インターフェイスを追加して、ログメッセージ定義を含めます。インターフェイスに定義されるログメッセージの説明的な名前を付けます。
    ログメッセージインターフェースの要件は次のとおりです。
    • 注釈を付ける必要があります@org.jboss.logging.MessageLogger
    • 延長する必要がありますorg.jboss.logging.BasicLogger
    • インターフェイスは、このインターフェイスを実装する型付きロガーであるフィールドを定義する必要があります。でこれを行うgetMessageLogger()の方法org.jboss.logging.Logger
    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 EAP 6 リポジトリーを使用する Maven プロジェクトが機能しています。「Maven 設定を使用した JBoss EAP 6 Maven リポジトリーの設定」 を参照してください。
  2. JBossLoggingTools に必要な Maven 設定が追加されました。「JBoss Logging Tools の Maven 設定」 を参照してください。

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

  1. 例外のインターフェースを作成します。

    JBoss Logging Tools はインターフェースで国際化されたメッセージを定義します。各インターフェイスに、そのインターフェイスで定義されるメッセージの説明的な名前を付けます。
    インターフェースの要件は以下のとおりです。
    • public として宣言する必要があります。
    • 注釈を付ける必要があります@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. invoke メソッド

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

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

このタスクでは、国際化された例外を作成する方法とその使用方法を示します。本タスクでは、これらの例外のすべてのオプション機能または国際化のプロセスについて説明しません。
完全な例については、logging-tools クイックスタートを参照してください。
このタスクでは、Red Hat JBoss Developer Studio または Maven のいずれかでビルドされているソフトウェアプロジェクトがすでにあり、それに国際化された例外を追加することを前提としています。

手順6.3 国際化された例外を作成して使用する

  1. JBossLoggingTools 設定を追加します

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

    JBoss Logging Tools はインターフェースで国際化されたメッセージを定義します。定義される例外について、各インターフェイスにわかりやすい名前を付けます。
    インターフェースの要件は以下のとおりです。
    • 次のように宣言する必要があります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. invoke メソッド

    例外を取得する必要があるコードでインターフェースメソッドを呼び出します。メソッドによって例外は発生されず、発生できるな例外オブジェクトがメソッドによって返されます。
    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 Logging Tools に対してプロジェクトが設定されていなければなりません。
  3. 国際化されたログメッセージや例外を定義する 1 つ以上のインターフェースがプロジェクトに含まれていなければなりません。

手順6.4 Maven での新しい翻訳プロパティーファイルの作成

  1. Maven 設定を追加する

    追加します-AgenereatedTranslationFilePathMaven コンパイラープラグイン設定へのコンパイラー引数を指定し、新しいファイルが作成されるパスを割り当てます。
    <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
注釈が付けられたインターフェイスごとに 1 つのプロパティーファイルが作成されます@MessageBundleまた@MessageLogger。各インターフェースが宣言された Java パッケージに対応するサブディレクトリーに新しいファイルが作成されます。
新しい各ファイルには、次の構文を使用して名前が付けられます。InterfaceNameこのファイルが生成されたインターフェイスの名前です: InterfaceName.i18n_locale_COUNTRY_VARIANT.properties
これらのファイルは新しい翻訳の基礎としてプロジェクトにコピーできます。

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

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

前提条件

  1. 作業用の Maven プロジェクトがすでに存在している必要があります。
  2. JBoss Logging Tools に対してプロジェクトが設定されていなければなりません。
  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 Logging Tools は、アプリケーションサーバーの現在のロケールに合わせて適切なクラスを自動的に使用するため、明示的にメソッドを呼び出したり、特定言語のパラメーターを提供したりする必要はありません。
生成されたクラスのソースコードは target/generated-sources/annotations/ で確認できます。

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

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

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

前提条件

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

手順6.6 ログメッセージへのメッセージ ID とプロジェクトコードの追加

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

    の projectCode 属性を使用してプロジェクトコードを指定します@MessageLoggerカスタムロガーインターフェイスに付加された注釈。インターフェースに定義されるすべてのメッセージがこのプロジェクトコードを使用します。
    @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 Logging Tools のインターフェースによって定義されるメッセージのデフォルトのログレベルは INFO です。別のログレベルを指定できますlevelの属性@LogMessageロギングメソッドに付加されたアノテーション。

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

  1. レベル属性を指定する

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

    を割り当てますlevelこのメッセージのログレベルの値を属性付けします。の有効な値levelで定義されている 6 つの列挙型定数ですorg.jboss.logging.Logger.Level:DEBUGERRORFATALINFOTRACE、とWARN
    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 番目のパラメーターが挿入されます。
    • 明示的なインデックスを使用するには、文字 %{#$}s をメッセージに挿入します。ここで、# は表示したいパラメーターの数を示します。
重要
明示的なインデックスを使用すると、メッセージのパラメーター参照の順番がメソッドで定義される順番とは異なるようになります。これは、パラメーターの異なる順序を必要とする可能性のある翻訳されたメッセージにとって重要です。
指定されたメッセージでは、パラメーターの数とパラメーターへの参照の数が同じでなければなりません。同じでないとコードがコンパイルされません。@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, user:%2$s, customerid:%1$s")
void customerLookupFailed(Long customerid, String username);

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

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

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

  1. パラメーターを追加します。

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

    追加します@Causeパラメーターへの注釈。
    import org.jboss.logging.Cause
    
    @LogMessage
    @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 およびプロジェクトコードの例外メッセージへの追加

次の手順は、JBossLoggingTools を使用して作成された国際化された例外メッセージにメッセージ ID とプロジェクトコードを追加するために必要な手順を示しています。
メッセージ ID およびプロジェクトコードは、国際化された例外によって表示される各メッセージの前に付けられる一意の識別子です。これらの識別コードにより、アプリケーションのすべての例外メッセージの参照を作成できるため、誰かが理解できない言語で書かれた例外メッセージの意味を検索できます。

前提条件

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

手順6.10 メッセージ ID およびプロジェクトコードの例外メッセージへの追加

  1. プロジェクトコードを指定する

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

    を使用して、各例外のメッセージ ID を指定します。idの属性@Message例外を定義するメソッドに付加されたアノテーション。
    @Message(id=143, value = "The config file could not be opened.")
    IOException configFileAccessError();
重要
プロジェクトコードとメッセージ ID を両方持つメッセージでは、メッセージの前にプロジェクトコードとメッセージ ID が表示されます。プロジェクトコードとメッセージ ID の両方がない場合は、どちらも表示されません。

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

この例外バンドルインターフェイスには、プロジェクトコード ACCTS があり、ID が 143 の単一の例外メソッドがあります。
@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 番目のパラメーターが挿入されます。
    • 明示的なインデックスを使用するには、文字 %{#$}s をメッセージに挿入します。ここで、# は表示したいパラメーターの数を示します。
    明示的なインデックスを使用すると、メッセージのパラメーター参照の順番がメソッドで定義される順番とは異なるようになります。これは、パラメーターの異なる順序を必要とする可能性のある翻訳されたメッセージにとって重要です。
重要
指定されたメッセージでは、パラメーターの数とパラメーターへの参照の数が同じでなければなりません。同じでないとコードがコンパイルされません。@Cause アノテーションが付けられたパラメーターはパラメーターの数には含まれません。

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

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

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

@Message(id=2, value="Customer query failed, user:%2$s, customerid:%1$s")
void customerLookupFailed(Long customerid, String username);

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. メソッドを呼び出します。

    例外オブジェクトを取得するため、インターフェースメソッドを呼び出します。catch ブロックから新しい例外を発生させ、キャッチした例外を原因として使用するのが最も一般的なユースケースです。
    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 Logging Tools の Maven 設定

国際化のために JBossLoggingTools を使用する Maven プロジェクトをビルドするには、pom.xml ファイルのプロジェクトの設定に次の変更を加える必要があります。
完全に機能する pom.xml ファイルの例については、logging-tools クイックスタートを参照してください。
  1. プロジェクトで JBossMaven リポジトリーを有効にする必要があります。「Maven 設定を使用した JBoss EAP 6 Maven リポジトリーの設定」 を参照してください。
  2. jboss-logging および jboss-logging-processor の Maven 依存関係を追加する必要があります。両方の依存関係は JBoss EAP 6 で使用できるため、それぞれのスコープ要素を次のように 提供 するように設定できます。
    <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 Logging Tools でのメッセージの翻訳に使用されるプロパティーファイルは標準的な Java プロパティーファイルです。ファイルの形式は、key=value クラス http://docs.oracle.com/javase/6/docs/api/java/util/Properties.html のドキュメントで説明されている単純な行指向の java.util.Properties ペア形式です。
ファイル名の形式は次のようになります。
InterfaceName.i18n_locale_COUNTRY_VARIANT.properties 
  • InterfaceName は、翻訳が適用されるインターフェイスの名前です。
  • localeCOUNTRY、とVARIANT翻訳が適用される地域の設定を特定します。
  • localeCOUNTRYISO-639 および 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 Logging Tools のアノテーションに関するリファレンス

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

表6.1 JBoss Logging Tools のアノテーション

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

第7章 リモート JNDI ルックアップ

7.1. JNDI へのオブジェクトの登録

Java Naming and Directory Interface (JNDI) は、Java ソフトウェアクライアントによる名前を使ったオブジェクトの検出およびルックアップを可能にするディレクトリーサービスの Java API です。オブジェクトを検索するには、最初にそのオブジェクトを JNDI に登録する必要があります。java:jboss/exported環境。
以下は、JMS キューを メッセージング サブシステムの JNDI に登録して、リモート JNDI クライアントが検索できるようにする方法の例です。
java:jboss/exported/jms/queue/myTestQueue
リモート JNDI クライアントは、上記の名前を使用してオブジェクトを検索できます。ただし、を指定する必要はありません。java:jboss/exported/リモートクライアントを検索するときの接頭辞。リモート JNDI クライアントは、次の名前を使用してリモートオブジェクトを検索できます。
jms/queue/myTestQueue

例7.1 スタンドアロンサーバーの JMS キュー設定の例

<subsystem xmlns="urn:jboss:domain:messaging:1.4">
   <hornetq-server>
      ...
      <jms-destinations>
         <jms-queue name="myTestQueue">
            <entry name="java:jboss/exported/jms/queue/myTestQueue"/>
         </jms-queue>
      </jms-destinations>
   </hornetq-server>
</subsystem>

7.2. リモート JNDI クライアントの設定

リモート JNDI クライアントは、JNDI を使用して、名前でオブジェクトを検索して接続できます。クライアントのクラスパスには jboss-client.jar が必要です。
次の例は、myTestQueueリモート JNDI クライアントからの JMS キュー:

例7.2 リモート JNDI ルックアップの例

Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
properties.put(Context.PROVIDER_URL, "remote://<hostname>:4447");
context = new InitialContext(properties);
Queue myTestQueue = (Queue) context.lookup("jms/queue/myTestQueue");

第8章 Enterprise JavaBeans 3.2

8.1. はじめに

8.1.1. Enterprise JavaBeans の概要

Enterprise JavaBeans (EJB) 3.1 は、Enterprise Bean と呼ばれるサーバー側のコンポーネントを使用して、分散型のトランザクション型のセキュアな移植可能な Java EE アプリケーションを開発するための API です。エンタープライズ Bean は、再利用を促すような分離方法でアプリケーションのビジネスロジックを実装します。Enterprise JavaBeans 3.1 は、JavaEE 仕様 JSR-318 として文書化されています。
JBoss EAP 6 では、Enterprise JavaBeans 3.1 仕様を使用してビルドされたアプリケーションが完全にサポートされます。

8.1.2. EJB 3.1 機能セット

次の機能は EJB3.1 でサポートされています
  • セッション Bean
  • メッセージ駆動 Bean
  • インターフェースなしビュー
  • ローカルインターフェース
  • リモートインターフェース
  • JAX-WS Web サービス
  • JAX-RSWeb サービス
  • タイマーサービス
  • 非同期呼び出し
  • インターセプター
  • RMI/IIOP の相互運用性
  • トランザクションサポート
  • セキュリティー
  • 組み込み API
以下の機能は EJB3.1 でサポートされていますが、プルーニング用に提案されています。これは、これらの機能が JavaEE7 でオプションになる可能性があることを意味します。
  • エンティティー Bean (コンテナーおよび Bean で管理された永続性)
  • EJB 2.1 エンティティー Bean クライアントビュー
  • EJB クエリー言語 (EJB QL)
  • JAX-RPC ベースの Web サービス: エンドポイントおよびクライアントビュー

8.1.3. EJB 3.1 Lite

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

8.1.4. EJB3.1Lite の機能

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

8.1.5. エンタープライズ Bean

エンタープライズ Bean は、Enterprise JavaBeans (EJB)3.1 仕様、JSR-318 で定義されているサーバー側のアプリケーションコンポーネントです。エンタープライズ Bean は、再利用を促進するために、分離された方法でアプリケーションビジネスロジックを実装するように設計されています。
エンタープライズ Bean は Java クラスとして記述され、適切な EJB アノテーションが付けられます。Java EE アプリケーションの一部としてデプロイすることも、独自のアーカイブ (JAR ファイル) でアプリケーションサーバーにデプロイできます。アプリケーションサーバーは、各エンタープライズ bean のライフサイクルを管理し、セキュリティー、トランザクション、同時実行管理などのサービスを提供します。
また、エンタープライズ Bean は任意の数のビジネスインターフェースを定義できます。ビジネスインターフェースは、クライアントで利用できる Bean のメソッドの制御を強化し、リモート JVM で実行しているクライアントへのアクセスも許可します。
エンタープライズ Bean には、セッション Bean、メッセージ駆動型 Bean、およびエンティティー Bean の 3 種類があります。
重要
エンティティー Bean は EJB3.1 で非推奨になり、Red Hat は代わりに JPA エンティティーの使用を推奨しています。Red Hat は、レガシーシステムとの下位互換性のためにエンティティー Bean の使用のみを推奨しています。

8.1.6. EnterpriseBeans の作成の概要

エンタープライズ Bean は、特定のアプリケーションクライアントから切り離された方法でビジネスロジックをカプセル化するように設計されたサーバー側コンポーネントです。エンタープライズ Bean 内にビジネスロジックを実装することにより、それらの Bean を複数のアプリケーションで再利用できるようになります。
エンタープライズ Bean は、注釈付きの Java クラスとして記述されており、特定の EJB インターフェイスを実装したり、エンタープライズ Bean と見なされるために EJB スーパークラスからサブクラス化したりする必要はありません。
EJB 3.1 エンタープライズ Bean は、Java アーカイブ (JAR) ファイルにパッケージ化され、デプロイされます。エンタープライズ BeanJAR ファイルは、アプリケーションサーバーにデプロイすることも、エンタープライズアーカイブ (EAR) ファイルに含めてそのアプリケーションとともにデプロイすることもできます。エンタープライズ Bean を Web アプリケーションと一緒に WAR ファイルにデプロイすることも可能です。

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

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

EJB ビジネスインターフェースは、Bean 開発者が作成する Java インターフェースで、クライアントで利用可能なセッション Bean のパブリックメソッドの宣言を提供する 。セッション Bean は任意の数のインターフェースを実装できます。なし ("no-interface" bean) も含まれます。
ユーザーインターフェースは、ローカルインターフェースまたはリモートインターフェースとして宣言できますが、両方に宣言することはできません。

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

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

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

EJB リモートビジネスインターフェースは、リモートクライアントで使用できるメソッドを宣言します。リモートインターフェースを実装するセッション Bean へのリモートアクセスは、EJB コンテナーにより自動的に提供されます。
リモートクライアントは、異なる JVM で実行されているクライアントです。また、デスクトップアプリケーションや、異なるアプリケーションサーバーにデプロイされた Web アプリケーション、サービス、およびエンタープライズ Bean を含めることができます。
ローカルクライアントは、リモートビジネスインタフェースで公開されるメソッドにアクセスできます。

8.1.7.4. EJB No-interface Beans

いずれのビジネスインターフェースも実装しないセッション Bean は、インターフェースなしの bean (no-interface bean) と呼ばれます。no-interface Bean のすべてのパブリックメソッドは、ローカルクライアントからアクセスできます。
また、ビジネスインターフェースを実装するセッション Bean を作成して、"no-interface" ビューを公開することもできます。

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

8.2.1. Red Hat JBossDeveloperStudio を使用して EJB アーカイブプロジェクトを作成する

このタスクでは、Red Hat JBoss DeveloperStudio で EnterpriseJavaBeans (EJB) プロジェクトを作成する方法について説明します。

前提条件

手順8.1 Red Hat JBossDeveloperStudio で EJB プロジェクトを作成します

  1. 新規プロジェクトを作成します。

    新規 EJB プロジェクトウィザードを開くには、ファイル メニューに移動し、新規EJB プロジェクト の順に選択します。

    図8.1 新しい EJB プロジェクトウィザード

    新しい EJB プロジェクトウィザード
  2. 詳細を指定

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

    この画面では、Java ソースファイルとビルドされた出力が配置されるディレクトリーを含むディレクトリーをカスタマイズできます。
    この設定は変更せず、Next をクリックします。
  4. EJB モジュールの設定

    デプロイメント記述子が必要な場合は、ejb-jar.xml デプロイメント記述子を生成 するチェックボックスをオンにします。デプロイメント記述子は EJB 3 1 では任意で、必要な場合は後で追加できます。
    Finish をクリックするとプロジェクトが作成され、Project Explorer に表示されます。

    図8.2 Project Explorer で新たに作成された EJB プロジェクト

    Project Explorer で新たに作成された EJB プロジェクト
  5. デプロイのためにビルドアーティファクトをサーバーに追加する

    ビルドされたアーティファクトをデプロイするサーバーをサーバータブで右クリックして 追加と削除 ダイアログを開き、追加と削除を選択します。
    Available コラムからデプロイする リソースを選択し、Add ボタンをクリックします。リソースは Configured コラムに移動します。Finish をクリックしてダイアログを閉じます。

    図8.3 ダイアログの追加または削除

    ダイアログの追加または削除

結果

これで、Red Hat JBoss Developer Studio に EJB プロジェクトがあり、指定したサーバーにビルドしてデプロイできます。

プロジェクトにエンタープライズ bean が追加されない場合、Red Hat JBoss Developer Studio は、An EJB module must contain one or more enterprise beans (EJB モジュールには、1 つ以上のエンタープライズ Bean が必要です) という警告が表示されます。 この警告は、エンタープライズ Bean がプロジェクトに追加されると消えます。

8.2.2. Maven での EJB アーカイブプロジェクトの作成

このタスクは、JAR ファイルにパッケージ化されたエンタープライズ Bean を含む Maven を使用してプロジェクトを作成する方法を示しています。

要件:

  • Maven がすでにインストールされている。
  • Maven の基本的な使用方法を理解している。

手順8.2 Maven での EJB アーカイブプロジェクトの作成

  1. Maven プロジェクトを作成する

    EJB プロジェクトは、Maven のアーキタイプシステムとejb-javaee6アーキタイプ。これを実行するには、以下のパラメーターを指定して mvn コマンドを実行します。
     mvn archetype:generate -DarchetypeGroupId=org.codehaus.mojo.archetypes -DarchetypeArtifactId=ejb-javaee6 
    Maven はプロンプトを表示します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 ファイルと同じディレクトリーで mvnpackage コマンドを実行します。これにより、Java クラスがコンパイルされ、JAR ファイルがパッケージ化されます。ビルドされた JAR ファイルの名前は artifactId -- version.jar で、target/ ディレクトリーに配置されます。
結果: これで、JAR ファイルをビルドし、パッケージ化する Maven プロジェクトが作成されました。これでプロジェクトにはエンタープライズ Bean を含めることができるようになりました。このプロジェクトは、JAR ファイルはアプリケーションサーバーにデプロイできます。

8.2.3. EJB プロジェクトを含む EAR プロジェクトの作成

このタスクでは、EJB プロジェクトを含む Red Hat JBoss Developer Studio で新しいエンタープライズアーカイブ (EAR) プロジェクトを作成する方法について説明します。

前提条件

手順8.3 EJB プロジェクトを含む EAR プロジェクトの作成

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

    ファイル メニューに移動し、新規、プロジェクト の順に選択すると、新規プロジェクト ウィザードが表示されます。Java EE/Enterprise Application Project を選択し、Next をクリックします。

    図8.4 新規 EAR アプリケーションプロジェクトウィザード

    新規 EAR アプリケーションプロジェクトウィザード
  2. 供給の詳細

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

    ウィザードの Enterprise Applicaiton ページから、新しいモジュールを追加できます。新しい EJB Project をモジュールとして追加するには、以下の手順に従います。
    1. 新しい EJB モジュールを追加する

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

      新しい EJB プロジェクト ウィザードは、新しいスタンドアロン EJB プロジェクトの作成に使用されるウィザードと同じであり、「Red Hat JBossDeveloperStudio を使用して EJB アーカイブプロジェクトを作成する」
      プロジェクトの作成に必要な最低限の詳細は、以下のとおりです。
      • プロジェクト名
      • ターゲットランタイム
      • EJB モジュールバージョン
      • 設定
      ウィザードの他のすべての手順はオプションです。Finish をクリックし、EJB プロジェクトの作成を完了します。
    新規作成した EJB プロジェクトは Java EE モジュール依存関係に一覧表示され、チェックボックスにチェックが付けられます。
  4. オプション: application.xml デプロイメント記述子を追加します。

    必要な場合は、Generate application.xml deployment descriptor チェックボックスにチェックを入れます。
  5. Finish をクリックします。

    EJB と EAR という 2 つのプロジェクトが表示されます。
  6. デプロイのためにビルドアーティファクトをサーバーに追加する

    Server タブで、ビルドされたアーティファクトをデプロイするサーバーの Servers タブで Add and Remove ダイアログを開き、Add and Remove を選択します。
    Available コラムからデプロイする EAR リソースを選択し、Add ボタンをクリックします。リソースは Configured コラムに移動します。Finish をクリックしてダイアログを閉じます。

    図8.5 ダイアログの追加または削除

    ダイアログの追加または削除

結果

これで、メンバー EJB プロジェクトを含む Enterprise Application Project ができました。これにより、EJB サブデプロイメントを含む単一の EAR デプロイメントとして指定のサーバーにビルドされ、デプロイされます。

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

EJB デプロイメント記述子は、記述子なしで作成された EJB プロジェクトに追加することができます。以下の手順に従います。

必要条件:

  • Red Hat JBoss Developer Studio に EJB プロジェクトがあり、そこに EJB デプロイメント記述子を追加します。

手順8.4 EJB プロジェクトへのデプロイメント記述子の追加

  1. プロジェクトを開く

    Red Hat JBossDeveloperStudio でプロジェクトを開きます。
  2. デプロイメント記述子を追加する

    プロジェクトビューの Deployment Descriptor フォルダーを右クリックして、Generate Deployment Descriptor Stub タブを選択します。

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

    デプロイメント記述子の追加
新しいファイル ejb-jar.xmlejbModule/META-INF/ に作成されます。プロジェクトビューで DeploymentDescriptor フォルダーをダブルクリックすると、このファイルも開きます。

8.3. セッション Bean

8.3.1. セッション Bean

セッション Bean は、関連する一連のビジネスプロセスまたはタスクをカプセル化し、それらを要求するクラスにインジェクトするエンタープライズ Bean です。セッション bean のタイプには、ステートレス、ステートフル、シングルトンの 3 つがあります。

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

ステートレスセッション Bean は、最も広く使用されているセッション Bean のタイプです。クライアントアプリケーションにビジネスメソッドを提供しますが、メソッド呼び出し間の状態を維持しません。各メソッドは、セッション Bean 内の共有状態に依存しない完全なタスクです。状態がないため、アプリケーションサーバーでは、各メソッド呼び出しが同じインスタンスで実行されるようにする必要はありません。これにより、ステートレスセッション Bean は非常に効率的でスケーラブルなものになります。

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

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

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

シングルトンセッション Bean はアプリケーションごとにインスタンス化されるセッション Bean で、シングルトン bean に対する各クライアントリクエストは同じインスタンスに送信されます。シングルトン bean は、1994 年に出版された Erich Gamma、Richard Helm、Ralph Jonson、John Vlissides 著の 『 Design Patterns: Elements of Reusable Object-Oriented Software』 で説明されている Singleton Design Pattern の実装です。
シングルトン bean は、すべてのセッション bean タイプのメモリーフットプリントを最小限に抑えますが、スレッドセーフとして設計する必要があります。EJB 3.1 では、開発者がスレッドセーフシングルトン Bean を簡単に実装できるように、コンテナー管理コンカレンシー(デプロイメント) を利用できます。ただし、CMC が詳細な柔軟性を提供しない場合、従来のマルチスレッドコード (Bean-managed Concurrency または BMC) を使用してシングルトン bean を書き込むこともできます。

8.3.5. Red Hat JBossDeveloperStudio のプロジェクトにセッション Bean を追加します

Red Hat JBoss Developer Studio には、エンタープライズ Bean クラスを迅速に作成するために使用できるいくつかのウィザードがあります。次の手順は、Red Hat JBossDeveloperStudio ウィザードを使用してセッション Bean をプロジェクトに追加する方法を示しています。

要件:

  • 1 つ以上のセッション Bean を追加する EJB または動的 Web プロジェクトが Red Hat にあります。

手順8.5 Red Hat JBossDeveloperStudio のプロジェクトにセッション Bean を追加します

  1. プロジェクトを開く

    Red Hat JBossDeveloperStudio でプロジェクトを開きます。
  2. ”Create EJB 3.x Session Bean” ウィザードを開きます。

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

    図8.7 Create EJB 3.x Session Bean ウィザード

    Create EJB 3.x Session Bean ウィザード
  3. クラス情報を指定する

    次の詳細を入力します。
    • プロジェクト
      正しいプロジェクトが選択されていることを確認します。
    • ソースフォルダー
      これは、Java ソースファイルが作成されるフォルダーです。通常、これは変更する必要はありません。
    • Package
      クラスが属するパッケージを指定します。
    • クラス名
      セッション Bean となるクラスの名前を指定します。
    • スーパークラス
      セッション Bean クラスは、スーパークラスから継承できます。セッションにスーパークラスがある場合は、これを指定します。
    • 状態タイプ
      セッション Bean の状態タイプ (stateless、stateful、または singleton) を指定します。
    • ビジネスインターフェイス
      デフォルトでは、インターフェイスなしボックスがオンになっているため、インターフェイスは作成されません。定義するインターフェースのボックスにチェックを入れ、必要に応じて名前を調整します。
      Web アーカイブ (WAR) のエンタープライズ Bean は EJB 3.1 Lite のみをサポートし、これにはリモートビジネスインターフェースが含まれないことに注意してください。
    Next をクリックします。
  4. セッション Bean 固有の情報

    ここで追加情報を入力して、セッション Bean をさらにカスタマイズできます。ここで情報を変更する必要はありません。
    変更可能なアイテムは次のとおりです。
    • Bean 名
    • マップされた名前
    • トランザクションタイプ (管理対象コンテナーまたは管理対象 Bean)
    • Bean が実装する必要のある追加のインターフェースを指定可能
    • EJB 2.x Home and Component インターフェースを必要に応じて指定することもできます。
  5. Finish

    Finish をクリックすると、新しいセッション Bean が作成され、プロジェクトに追加されます。新しいビジネスインターフェースのファイルが指定されていれば、それらも作成されます。

図8.8 Red Hat JBossDeveloperStudio の新しいセッション Bean

Red Hat JBossDeveloperStudio の新しいセッション Bean

8.4. メッセージ駆動 Bean

8.4.1. メッセージ駆動 Bean

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

8.4.2. リソースアダプター

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

8.4.3. Red Hat JBossDeveloperStudio で JMS ベースのメッセージ駆動型 Bean を作成する

この手順は、JMS ベースのメッセージドリブン Bean を Red Hat JBossDeveloperStudio のプロジェクトに追加する方法を示しています。この手順では、アノテーションを使用する EJB 3.x メッセージ駆動 Bean を作成します。

要件:

  1. Red Hat JBossDeveloperStudio で既存のプロジェクトを開いておく必要があります。
  2. Bean がリッスンする JMS 宛先の名前とタイプを知っている必要があります。
  3. Java Messaging Service (JMS) のサポートは、この Bean がデプロイされる JBoss EAP 6 設定で有効にする必要があります。

手順8.6 Red Hat JBossDeveloperStudio に JMS ベースのメッセージ駆動型 Bean を追加します

  1. Create EJB 3.x Message-LoadBalancern Bean ウィザードを開きます。

    ファイル新規その他 に移動します。EJB/Message-Driven Bean (EJB 3.x) を選択し、Next ボタンをクリックします。

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

    Create EJB 3.x Message-Driven Bean ウィザード
  2. クラスファイル宛先の詳細を指定します。

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

    ここでのデフォルト値は、コンテナー管理トランザクションを使用する JMS ベースのメッセージ駆動 Bean に適しています。
    • Bean が Bean 管理対象トランザクションを使用する場合は、Transaction type を Bean に変更します。
    • クラス名とは異なる Bean 名が必要な場合は Bean name を変更します。
    • JMS Message Listener インターフェースはすでにリストされています。インターフェースがアプリケーションのビジネスロジックに固有のものでない場合は、インターフェースを追加または削除する必要はありません。
    • メソッドスタブを作成するためのチェックボックスは選択したままにしておきます。
    Finish ボタンをクリックします。
結果: メッセージ駆動 Bean は、デフォルトのコンストラクターと onMessage() メソッド用のスタブメソッドで作成されます。対応するファイルで開かれた Red Hat エディターウィンドウ。

8.4.4. MDB に対して jboss-ejb3.xml でのリソースアダプターの指定

jboss-ejb3.xml デプロイメント記述子では、MDB が使用するリソースアダプターを指定できます。または、MDB 用に JBoss EAP 6 サーバー全体のデフォルトリソースアダプターを設定するには、『管理および設定ガイド』 の 『メッセージドリブン Bean』 の設定を参照してください。
MDB に対して jboss-ejb3.xml でリソースアダプターを指定するには、以下の例を使用します。

例8.1 例: MDB リソースアダプターの jboss-ejb3.xml 設定

<jboss xmlns="http://www.jboss.com/xml/ns/javaee"
  xmlns:jee="http://java.sun.com/xml/ns/javaee"
  xmlns:mdb="urn:resource-adapter-binding">
  <jee:assembly-descriptor>  
    <mdb:resource-adapter-binding>  
      <jee:ejb-name>MyMDB</jee:ejb-name>  
      <mdb:resource-adapter-name>MyResourceAdapter.rar</mdb:resource-adapter-name>  
    </mdb:resource-adapter-binding>  
  </jee:assembly-descriptor>
</jboss>
EAR にあるリソースアダプターの場合、次の構文を使用する必要があります。<mdb:resource-adapter-name>:
  • 別の EAR にあるリソースアダプターの場合:
    <mdb:resource-adapter-name>OtherDeployment.ear#MyResourceAdapter.rar</mdb:resource-adapter-name>
  • MDB と同じ EAR にあるリソースアダプターでは、EAR 名を省略できます。
    <mdb:resource-adapter-name>#MyResourceAdapter.rar</mdb:resource-adapter-name>

8.4.5. アプリケーションで EJB および MDB プロパティーの置換を有効にする

Red Hat JBoss Enterprise Application Platform の新機能により、EJB および MDB でプロパティー置換を有効にできます。@ActivationConfigProperty@Resource注釈。プロパティーの置換には、以下の設定およびコードの変更が必要です。
  • JBoss EAP サーバー設定ファイルでプロパティー置換を有効にする必要があります。
  • JBoss EAP サーバーの起動時に、システムプロパティーをサーバー設定ファイルに定義するか、引数として渡す必要があります。
  • 置換変数を使用するには、コードを変更する必要があります。

手順8.7 MDB アプリケーションにプロパティー置換を実装する

以下のコード例は、JBoss EAP 以降に同梱されている helloworld-mdb クイックスタートに基づいています。このトピックでは、そのクイックスタートを変更してプロパティーの置換を有効にする方法を示します。
  1. プロパティー置換を有効にするように JBoss EAP サーバーを設定します。

    プロパティーの置換を有効にするように JBoss EAP サーバーを設定する必要があります。これを行うには、<annotation-property-replacement>サーバー設定ファイルの ee サブシステムの属性を true に設定します。
    1. サーバー設定ファイルをバックアップします。helloworld-mdb クイックスタートの例では、スタンドアロンサーバーの完全なプロファイルが必要であるため、これは standalone/configuration/standalone-full.xml ファイルです。管理対象ドメインでサーバーを実行している場合は、domain/configuration/domain.xml ファイルになります。
    2. フルプロファイルで JBoss EAP サーバーを起動します。
      Linux の場合
      EAP_HOME/bin/standalone.sh -c standalone-full.xml
      Windows の場合:
      EAP_HOMEbin\standalone.bat -c standalone-full.xml
    3. ご使用のオペレーティングシステム向けのコマンドを使用して、管理 CLI を起動します。
      Linux の場合
      EAP_HOME/bin/jboss-cli.sh --connect
      Windows の場合:
      EAP_HOME\bin\jboss-cli.bat --connect
    4. アノテーションプロパティーの置換を有効にするには、以下のコマンドを実行します。
      /subsystem=ee:write-attribute(name=annotation-property-replacement,value=true) 
    5. 以下の結果が表示されるはずです。
      {"outcome" => "success"}
    6. JBoss EAP サーバー設定ファイルへの変更を確認します。ee サブシステムには以下の XML が含まれるはずです。
      <subsystem xmlns="urn:jboss:domain:ee:1.2">
          <spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
          <jboss-descriptor-property-replacement>true</jboss-descriptor-property-replacement>
          <annotation-property-replacement>true</annotation-property-replacement>
      </subsystem>
  2. システムプロパティーの定義

    サーバー設定ファイルでシステムプロパティーを指定するか、JBoss EAP サーバーの起動時にコマンドラインの引数としてプロパティーを渡すことができます。サーバー設定ファイルで定義されたシステムプロパティーは、サーバーの起動時にコマンドラインに渡されるプロパティーよりも優先されます。
    • サーバー設定でのシステムプロパティーの定義
      1. 前のステップで説明したように、JBoss EAP サーバーと管理 API を起動します。
      2. 以下のコマンド構文を使用して、JBoss EAP サーバーのシステムプロパティーを設定します。
        /system-property=PROPERTY_NAME:add(value=PROPERTY_VALUE) 
        helloworld-mdb クイックスタートでは、次のシステムプロパティーを設定します。
        /system-property=property.helloworldmdb.queue:add(value=java:/queue/HELLOWORLDMDBPropQueue)
        /system-property=property.helloworldmdb.topic:add(value=java:/topic/HELLOWORLDMDBPropTopic)
        /system-property=property.connection.factory:add(value=java:/ConnectionFactory)
      3. JBoss EAP サーバー設定ファイルへの変更を確認します。以下のシステムプロパティーは、<extensions> の後に表示されるはずです。
        <system-properties>
            <property name="property.helloworldmdb.queue" value="java:/queue/HELLOWORLDMDBPropQueue"/>
            <property name="property.helloworldmdb.topic" value="java:/topic/HELLOWORLDMDBPropTopic"/>
            <property name="property.connection.factory" value="java:/ConnectionFactory"/>
        </system-properties>
    • JBoss EAP サーバーを起動するときにコマンドラインでシステムプロパティーを引数として -DPROPERTY_NAME=PROPERTY_VALUE の形式で渡します。以下は、前の手順で定義されたシステムプロパティーの引数を渡す方法の例になります。
      EAP_HOME/bin/standalone.sh -c standalone-full.xml -Dproperty.helloworldmdb.queue=java:/queue/HELLOWORLDMDBPropQueue -Dproperty.helloworldmdb.topic=java:/topic/HELLOWORLDMDBPropTopic -Dproperty.connection.factory=java:/ConnectionFactory
  3. システムプロパティーの置換を使用するようにコードを変更します。

    ハードコードされたものを置き換える@ActivationConfigProperty@Resource新しく定義されたシステムプロパティーを置換した注釈値。以下は、helloworld-mdb クイックスタートを変更して、ソースコードのアノテーション内で新しく定義されたシステムプロパティーの置換を使用する方法の例です。
    1. 変更@ActivationConfigPropertyシステムプロパティーの置換を使用するための HelloWorldQueueMDB クラスの 宛先 プロパティー値。The@MessageDriven注釈は次のようになります。
      @MessageDriven(name = "HelloWorldQueueMDB", activationConfig = {
          @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
          @ActivationConfigProperty(propertyName = "destination", propertyValue = "${property.helloworldmdb.queue}"),   
          @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") })
      
    2. 変更@ActivationConfigPropertyシステムプロパティーの置換を使用するための HelloWorldTopicMDB クラスの 宛先 プロパティー値。The@MessageDriven注釈は次のようになります。
      @MessageDriven(name = "HelloWorldQTopicMDB", activationConfig = {
          @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"),
          @ActivationConfigProperty(propertyName = "destination", propertyValue = "${property.helloworldmdb.topic}"),   
          @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") })
    3. HelloWorldMDBServletClient クラスの @Resource アノテーションを変更して、システムプロパティーの置換を使用します。コードは以下のようになります。
      @Resource(mappedName = "${property.connection.factory}")
      private ConnectionFactory connectionFactory;
      
      @Resource(mappedName = "${property.helloworldmdb.queue}")   
      private Queue queue;
      
      @Resource(mappedName = "${property.helloworldmdb.topic}")
      private Topic topic;
      
    4. hornetq-jms.xml ファイルを変更して、システムプロパティーの置換値を使用します。
      <?xml version="1.0" encoding="UTF-8"?>
      <messaging-deployment xmlns="urn:jboss:messaging-deployment:1.0">
          <hornetq-server>
              <jms-destinations>
                  <jms-queue name="HELLOWORLDMDBQueue">
                      <entry name="${property.helloworldmdb.queue}"/>
                  </jms-queue>
                  <jms-topic name="HELLOWORLDMDBTopic">
                      <entry name="${property.helloworldmdb.topic}"/>
                  </jms-topic>
              </jms-destinations>
          </hornetq-server>
      </messaging-deployment>
  4. アプリケーションをデプロイします。アプリケーションは、システムプロパティーで指定された値を使用します。@Resource@ActivationConfigPropertyプロパティー値。

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

8.5.1. JNDI を使用してリモートで SessionBean を呼び出す

このタスクでは、JNDI を使用してセッション Bean を呼び出すためのサポートをリモートクライアントに追加する方法について説明します。このタスクは、プロジェクトが Maven を使用してビルドされていることを前提としています。
ejb-remote クイックスタートには、この機能を実証する動作中の Maven プロジェクトが含まれています。クイックスタートには、デプロイするセッション Bean とリモートクライアントの両方のプロジェクトが含まれています。以下のコードサンプルは、リモートクライアントプロジェクトから取得したものです。
このタスクは、セッション Bean が認証を必要としないことを前提としています。
警告
Red Hat は、影響するすべてのパッケージで TLSv1.1 または TLSv1.2 を利用するために SSL を明示的に無効化することを推奨しています。

前提条件

開始する前に、次の前提条件を満たしている必要があります。
  • Maven プロジェクトを作成してすぐに使用できるようにしておく必要があります。
  • JBoss EAP 6Maven リポジトリーの設定はすでに追加されています。
  • 呼び出すセッション Bean はすでにデプロイされています。
  • デプロイされたセッション Bean は、リモートビジネスインターフェイスを実装します。
  • セッション Bean のリモートビジネスインターフェイスは、Maven 依存関係として利用できます。リモートビジネスインターフェイスが JAR ファイルとしてのみ利用可能な場合は、JAR をアーティファクトとして Maven リポジトリーに追加することをお勧めします。指示については、install:install-file の 目標について Maven のドキュメントを参照してください。 http://maven.apache.org/plugins/maven-install-plugin/usage.html
  • セッション Bean をホストしているサーバーのホスト名と JNDI ポートを知っている必要があります。
リモートクライアントからセッション Bean を呼び出すには、最初にプロジェクトを正しく設定する必要があります。

手順8.8 セッション Bean のリモート呼び出し用の Maven プロジェクト設定の追加

  1. 必要なプロジェクトの依存関係を追加します
    プロジェクトの pom.xml を更新して、必要な依存関係を含める必要があります。
  2. jboss-ejb-client.properties ファイルを追加します
    JBoss EJB クライアント API は、JNDI サービスの接続情報を含む jboss-ejb-client.properties という名前のプロジェクトのルートでファイルを見つけることを想定しています。このファイルをプロジェクトの src/main/resources/ ディレクトリーに次の内容で追加します。
    # In the following line, set SSL_ENABLED to true for SSL
    remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
    remote.connections=default
    # Uncomment the following line to set SSL_STARTTLS to true for SSL
    # remote.connection.default.connect.options.org.xnio.Options.SSL_STARTTLS=true
    remote.connection.default.host=localhost
    remote.connection.default.port = 4447
    remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
    # Add any of the following SASL options if required
    # remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
    # remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT=false
    # remote.connection.default.connect.options.org.xnio.Options.SASL_DISALLOWED_MECHANISMS=JBOSS-LOCAL-USER
    
    サーバーに一致するようにホスト名とポートを変更します。4447 はデフォルトのポート番号です。安全な接続のために、SSL_ENABLED 行を true に設定し、SSL_STARTTLS 行のコメントを解除します。コンテナーの Remoting インターフェイスは、同じポートを使用したセキュリティーで保護された接続とセキュリティーで保護されていない接続をサポートします。
  3. リモートビジネスインターフェイスの依存関係を追加する
    セッション Bean のリモートビジネスインターフェイスの pom.xml に Maven 依存関係を追加します。
    <dependency>
       <groupId>org.jboss.as.quickstarts</groupId>
       <artifactId>jboss-ejb-remote-server-side</artifactId>
       <type>ejb-client</type>
       <version>${project.version}</version>
    </dependency>
プロジェクトが正しく設定されたので、セッション Bean にアクセスして呼び出すためのコードを追加できます。

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

  1. チェックされた例外を処理する
    次のコードで使用される 2 つのメソッド (InitialContext()lookup()) タイプのチェックされた例外がありますjavax.naming.NamingException。これらのメソッド呼び出しは、キャッチする try/catch ブロックで囲む必要がありますNamingExceptionまたは出力するように宣言されているメソッドでNamingExceptionejb-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 プロキシーを取得します
    を呼び出すlookup()Bean プロキシーのメソッドを渡し、必要なセッション Bean の JNDI 名を渡します。これにより、呼び出すメソッドを含むリモートビジネスインターフェイスのタイプにキャストする必要があるオブジェクトが返されます。
    
    final RemoteCalculator statelessRemoteCalculator = (RemoteCalculator) context.lookup(
        "ejb:/jboss-ejb-remote-server-side//CalculatorBean!" + 
        RemoteCalculator.class.getName());
    
    セッション Bean の JNDI 名は、特別な構文を使用して定義されます。詳細は、「EJB JNDI 命名リファレンス」 を参照してください。
  4. invoke メソッド
    プロキシー 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 の間の通信は、呼び出し元に対して透過的です。
これで、リモートサーバーでのセッション Bean の呼び出しをサポートするように Maven プロジェクトを設定し、JNDI を使用してサーバーから取得したプロキシー Bean を使用してセッション Bean メソッドを呼び出すコードを記述できるようになります。

8.5.2. EJB クライアントコンテキスト

JBoss EAP 6 には、リモート EJB 呼び出しを管理するための EJB クライアント API が導入されました。JBoss EJB クライアント API は、EJBClientContext を使用します。これは、1 つ以上のスレッドで割り当てられ、複数のスレッドと同時に使用される可能性があります。つまり、EJBClientContext には任意の数の EJB レシーバーが含まれる可能性があります。EJB レシーバーは、EJB 呼び出しを処理できるサーバーと通信する方法を認識しているコンポーネントです。通常、EJB リモートアプリケーションは以下のように分類できます。
  • スタンドアロン Java アプリケーションとして実行されるリモートクライアント。
  • 別の JBoss EAP 6 インスタンス内で実行されるリモートクライアント。
リモートクライアントのタイプによっては、EJB クライアント API の観点からすべば、JVM 内に複数の EJBClientContext が存在する可能性があります。
通常、スタンドアロンアプリケーションには任意の数の EJB レシーバーでサポートされる単一の EJBClientContext がありますが、これは必須ではありません。スタンドアロンアプリケーションに複数の EJBClientContext がある場合、EJB クライアントコンテキストセレクターは適切なコンテキストを返します。
別の JBoss EAP 6 インスタンス内で実行されるリモートクライアントの場合には、デプロイされた各アプリケーションに対応する EJB クライアントコンテキストがあります。アプリケーションが別の EJB を呼び出すたびに、対応する EJB クライアントコンテキストを使用して正しい EJB レシーバーを検索し、呼び出しを処理します。

8.5.3. 単一の EJB コンテキストを使用する場合の考慮事項

概要

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

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

リモートスタンドアロンクライアントには、通常、任意の数の EJB レシーバーによってサポートされる EJB クライアントコンテキストが 1 つだけあります。次に、スタンドアロンのリモートクライアントアプリケーションの例を示します。

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 ルックアップは通常、EJB クライアントコンテキストと EJB レシーバーを設定するために使用される jboss-ejb-client.properties ファイルによってサポートされます。この設定にはセキュリティークレデンシャルも含まれ、JBoss EAP 6 サーバーに接続する EJB レシーバーを作成するために使用されます。上記のコードが呼び出されると、EJB クライアント API は EJB クライアントコンテキストを検索します。このコンテキストは、EJB 呼び出し要求を受信して処理する EJB レシーバーを選択するために使用されます。この場合、EJB クライアントコンテキストは 1 つしかないため、上記のコードでコンテキストを使用して Bean を呼び出します。JNDI を使用してリモートでセッション Bean を呼び出す手順については、以下で詳しく説明します。「JNDI を使用してリモートで SessionBean を呼び出す」

異なる資格情報を必要とするリモートスタンドアロンクライアント

ユーザーアプリケーションが Bean を複数回呼び出したい場合がありますが、異なるセキュリティークレデンシャルを使用して JBoss EAP 6 サーバーに接続します。以下は、同じ 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 クライアントコンテキストがあり、サーバーインスタンスごとに 1 つの EJB レシーバーしか持てないため、上記のコードはサーバーに接続するために 1 つのクレデンシャルのみを使用し、アプリケーションが期待するとおりにコードが実行されないことを意味します。

解決策

スコープ付き EJB クライアントコンテキストは、この問題の解決策を提供します。これらは、EJB クライアントコンテキストとそれに関連する JNDI コンテキスト (通常は EJB 呼び出しに使用される) をより詳細に制御する方法を提供します。スコープ付き EJB クライアントコンテキストの詳細については、以下を参照してください。「スコープ付き EJB クライアントコンテキストの使用」「スコープ付き EJB クライアントコンテキストを使用して EJB を設定する」

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

概要

EJB を呼び出すには JBoss EAP 6 の以前のバージョンでは、通常、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();
        ...
        ctxOne.close();
 
        // 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();
        ...
        ctxTwo.close();
    }
}

スコープ付き 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 クライアントコンテキストは、以前のバージョンの JBoss EAP での JNP ベースの JNDI 呼び出しに関連付けられていた柔軟性をユーザーアプリケーションに提供します。これにより、ユーザーアプリケーションは、どの JNDI コンテキストがどのサーバーと通信し、どのようにそのサーバーに接続するかをより細かく制御できます。
注記
スコープコンテキストでは、基になるリソースはコンテナーまたは API によって処理されなくなるため、InitialContext不要になったとき。いつInitialContextが閉じられると、リソースはすぐに解放されます。それにバインドされているプロキシーは無効になり、呼び出しは例外を出力します。を閉じられなかったInitialContextリソースとパフォーマンスの問題が発生する可能性があります。

8.5.5. スコープ付き EJB クライアントコンテキストを使用して EJB を設定する

概要

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

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

手順8.10 マップベースのスコープコンテキストを使用して EJB を設定する

  1. プロパティーを設定します。

    標準の jboss-ejb-client.properties ファイルで使用されているのと同じプロパティーのセットを指定して、EJB クライアントのプロパティーをプログラムで設定します。スコープコンテキストを有効にするには、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 名を使用して不要なターゲットを呼び出したりする可能性があります。

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

概要

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

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

次の表に、同じスコープ内のライブラリー全体に有効なプロパティーを示します。

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

プロパティー名 Description
endpoint.name
クライアントエンドポイントの名前。設定されていない場合、デフォルト値は client-endpoint です。
スレッド名にはこのプロパティーが含まれているため、これはさまざまなエンドポイント設定を区別するのに役立ちます。
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED
すべての接続で SSL プロトコルを有効にするかどうかを指定するブール値。
警告
Red Hat は、影響するすべてのパッケージで TLSv1.1 または TLSv1.2 を利用するために 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 は、接続を一意に識別するためにのみ使用されるローカル識別子です。

表8.2 Connection Properties

プロパティー名 Description
remote.connections
アクティブな 接続名 のコンマ区切りのリスト。各接続は、この名前を使用して設定されます。
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 プロトコルを有効にするかどうかを指定するブール値。
警告
Red Hat は、影響するすべてのパッケージで TLSv1.1 または TLSv1.2 を利用するために SSL を明示的に無効化することを推奨しています。
remote.connection.CONNECTION_NAME.connect.options.org.jboss.remoting3.RemotingOptions.HEARTBEAT_INTERVAL
ファイアウォールの場合など、自動クローズを防ぐためにクライアントとサーバー間でハートビートを送信する間隔。値はミリ秒単位です。

EJB クライアントクラスターのプロパティー

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

表8.3 クラスターのプロパティー

プロパティー名 Description
remote.cluster.CLUSTER_NAME.clusternode.selector
org.jboss.ejb.client.ClusterNodeSelector の実装の完全修飾名。
org.jboss.ejb.client.DeploymentNodeSelector ではなく、このクラスは、クラスター化された環境で EJB 呼び出しの負荷を分散するために使用されます。クラスターが完全にダウンしている場合、呼び出しは失敗し、使用可能な ejb レシーバーがありません
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
この特定のクラスターノードに対して実行できるアウトバウンド要求の最大数を指定する整数値。

8.5.7. リモート EJB データ圧縮

これまでのバージョンの JBoss EAP には、EJB プロトコルメッセージが含まれるメッセージストリームを圧縮できる機能が含まれていました。この機能は JBoss EAP 6.3 以降に含まれています。
圧縮は現在、クライアントおよびサーバー側にあるべき EJB インターフェース上のアノテーションでのみ指定できます。現在、圧縮ヒントを指定するのと同等の XML はありません。
データ圧縮のヒントは、JBoss アノテーションを介して指定できますorg.jboss.ejb.client.annotation.CompressionHint。ヒントの値では、リクエスト、応答、要求、応答を圧縮するかどうかを指定します。@CompressionHint デフォルトをcompressResponse=truecompressRequest=true に追加。
アノテーションはインターフェースレベルで指定して、以下のように EJB のインターフェース内のすべてのメソッドに適用できます。
import org.jboss.ejb.client.annotation.CompressionHint;

@CompressionHint(compressResponse = false)
public interface ClassLevelRequestCompressionRemoteView {
    String echo(String msg);
}
また、アノテーションは EJB のインターフェースにある特定のメソッドに適用できます。以下に例を示します。
import org.jboss.ejb.client.annotation.CompressionHint;

public interface CompressableDataRemoteView {

    @CompressionHint(compressResponse = false, compressionLevel = Deflater.BEST_COMPRESSION)
    String echoWithRequestCompress(String msg);

    @CompressionHint(compressRequest = false)
    String echoWithResponseCompress(String msg);

    @CompressionHint
    String echoWithRequestAndResponseCompress(String msg);

    String echoWithNoCompress(String msg);
}
上記の compressionLevel 設定は、以下の値にすることができます。
  • BEST_COMPRESSION
  • BEST_SPEED
  • DEFAULT_COMPRESSION
  • NO_COMPRESSION
CompressionLevel のデフォルト設定は Deflater.DEFAULT_COMPRESSION です。
メソッドレベルでのクラスレベルのアノテーションの上書き:
@CompressionHint
public interface MethodOverrideDataCompressionRemoteView {

    @CompressionHint(compressRequest = false)
    String echoWithResponseCompress(final String msg);

    @CompressionHint(compressResponse = false)
    String echoWithRequestCompress(final String msg);

    String echoWithNoExplicitDataCompressionHintOnMethod(String msg);
}
クライアント側で、org.jboss.ejb.client.view.annotation.scan.enabled システムプロパティーが true に設定されていることを確認します。このプロパティーは JBoss EJB Client に対してアノテーションをスキャンするように指示します。

8.6. コンテナーインターセプター

8.6.1. コンテナーインターセプターについて

JSR 318, Enterprise JavaBeans 3.1 仕様で定義されている標準の Java EE インターセプターは、コンテナーがセキュリティーコンテキストの伝搬、トランザクション管理、およびその他コンテナーによる呼び出し処理の完了後に実行されることが予想されます。これは、特定のコンテナーインターセプターを実行する前にアプリケーションが呼び出しをインターセプトする必要がある場合に問題になります。
JBoss EAP 6.0 より前のリリースでは、サーバー側インターセプターを呼び出しフローにプラグインする方法が提供されていたため、コンテナーが呼び出し処理を完了する前に特定のアプリケーションロジックを実行できました。この機能は JBoss EAP に実装されました。この実装により、標準の Java EE インターセプターをコンテナーインターセプターとして使用できます。つまり、3.1 バージョンの ejb-jar デプロイメント記述子の ejb-jar.xml ファイルで許可されているものと同じ XSD 要素を使用します。

インターセプターチェーン内のコンテナーインターセプターの配置

EJB 用に設定されたコンテナーインターセプターは、JBoss EAP が提供するセキュリティーインターセプター、トランザクション管理インターセプター、およびその他のサーバーが提供するインターセプターの前に実行されることが保証されています。これにより、特定のアプリケーションコンテナーインターセプターは、呼び出しが進む前に、関連するコンテキストデータを処理または設定できます。

コンテナーインターセプターと Java EE インターセプター API の違い

コンテナーインターセプターは Java EE インターセプターと同様にモデル化されますが、API のセマンティクスにはいくつかの違いがあります。たとえば、コンテナーインターセプターがjavax.interceptor.InvocationContext.getTarget()これらのインターセプターは、EJB コンポーネントがセットアップまたはインスタンス化されるずっと前に呼び出されるためです。

8.6.2. コンテナーインターセプタークラスを作成する

概要

コンテナーインターセプタクラスは、単純な Plain Old Java Object (POJO) です。彼らは使用します@javax.annotation.AroundInvokeBean での呼び出し中に呼び出されるメソッドをマークします。

以下は、をマークするコンテナーインターセプタークラスの例です。iAmAround呼び出しの方法:

例8.2 コンテナーインターセプタークラスの例


public class ClassLevelContainerInterceptor {
    @AroundInvoke
    private Object iAmAround(final InvocationContext invocationContext) throws Exception {
        return this.getClass().getName() + " " + invocationContext.proceed();
    }
}
このクラスを使用するように設定されたコンテナーインターセプター記述子ファイルの例については、以下で説明する jboss-ejb3.xml ファイルを参照してください。「コンテナーインターセプターの設定」

8.6.3. コンテナーインターセプターの設定

概要

コンテナーインターセプタは、標準の Java EE インターセプタライブラリーを使用します。つまり、3.1 バージョンの ejb-jar デプロイメント記述子の ejb-jar.xml ファイルで許可されているものと同じ XSD 要素を使用します。それらは標準の Java EE インターセプターライブラリーをベースとしているため、コンテナーインターセプターはデプロイメント記述子を使用してのみ設定できます。これは設計によって行われたため、アプリケーションは JBoss 固有のアノテーションやその他のライブラリー依存関係を必要としません。コンテナーインターセプターの詳細については、以下を参照してください。「コンテナーインターセプターについて」

手順8.11 記述子ファイルを作成して、コンテナーインターセプターを設定します

  1. EJB デプロイメントの META-INF ディレクトリーに jboss-ejb3.xml ファイルを作成します。
  2. 記述子ファイルにコンテナーインターセプター要素を設定します。
    1. urn:container-interceptors:1.0 ネームスペースを使用して、コンテナーインターセプター要素の設定を指定します。
    2. <container-interceptors> 要素を使用してコンテナーインターセプターを指定します。
    3. >interceptor-binding> 要素を使用してコンテナーインターセプターを EJB にバインドします。インターセプターは、次のいずれかの方法でバインドできます。
      • ワイルドカード * を使用して、インターセプターをデプロイメントのすべての EJB にバインドします。
      • 特定の EJB 名を使用して、個々の Bean レベルでインターセプターをバインドします。
      • EJB の特定のメソッドレベルでインターセプターをバインドします。
      注記
      これらの要素は、JavaEE インターセプターの場合と同じ方法で EJB3.1XSD を使用して設定されます。
  3. 上記の要素の例については、次の記述子ファイルを確認してください。

    例8.3 jboss-ejb3.xml

    <jboss xmlns="http://www.jboss.com/xml/ns/javaee"
           xmlns:jee="http://java.sun.com/xml/ns/javaee"
           xmlns:ci ="urn:container-interceptors:1.0">
     
        <jee:assembly-descriptor>
            <ci:container-interceptors>
                <!-- Default interceptor -->
                <jee:interceptor-binding>
                    <ejb-name>*</ejb-name>
                    <interceptor-class>org.jboss.as.test.integration.ejb.container.interceptor.ContainerInterceptorOne</interceptor-class>
                </jee:interceptor-binding>
                <!-- Class level container-interceptor -->
                <jee:interceptor-binding>
                    <ejb-name>AnotherFlowTrackingBean</ejb-name>
                    <interceptor-class>org.jboss.as.test.integration.ejb.container.interceptor.ClassLevelContainerInterceptor</interceptor-class>
                </jee:interceptor-binding>
                <!-- Method specific container-interceptor -->
                <jee:interceptor-binding>
                    <ejb-name>AnotherFlowTrackingBean</ejb-name>
                    <interceptor-class>org.jboss.as.test.integration.ejb.container.interceptor.MethodSpecificContainerInterceptor</interceptor-class>
                    <method>
                        <method-name>echoWithMethodSpecificContainerInterceptor</method-name>
                    </method>
                </jee:interceptor-binding>
                <!-- container interceptors in a specific order -->
                <jee:interceptor-binding>
                    <ejb-name>AnotherFlowTrackingBean</ejb-name>
                    <interceptor-order>
                        <interceptor-class>org.jboss.as.test.integration.ejb.container.interceptor.ClassLevelContainerInterceptor</interceptor-class>
                        <interceptor-class>org.jboss.as.test.integration.ejb.container.interceptor.MethodSpecificContainerInterceptor</interceptor-class>
                        <interceptor-class>org.jboss.as.test.integration.ejb.container.interceptor.ContainerInterceptorOne</interceptor-class>
                    </interceptor-order>
                    <method>
                        <method-name>echoInSpecificOrderOfContainerInterceptors</method-name>
                    </method>
                </jee:interceptor-binding>
            </ci:container-interceptors>
        </jee:assembly-descriptor>
    </jboss>
    
    
    urn:container-interceptors:1.0 名前空間の XSD は、EAP_HOME/docs/schema/jboss-ejb -container-interceptors_1_0.xsd で入手できます。

8.6.4. セキュリティーコンテキスト ID を変更する

概要

デフォルトでは、アプリケーションサーバーにデプロイされた EJB にリモート呼び出しを行うと、サーバーへの接続が認証され、この接続を介して受信した要求はすべて、接続を認証した ID として実行されます。これは、クライアントとサーバー間の呼び出しの両方に適用されます。同じクライアントから異なるアイデンティティーを使用する必要がある場合は、通常は、異なるアイデンティティーとして認証されるように、サーバーへの接続を複数開く必要があります。複数のクライアント接続を開くのではなく、認証されたユーザーに別のユーザーとしてリクエストを実行する権限を与えることができます。

このトピックでは、既存のクライアント接続で ID を切り替える方法について説明します。コード例は、クイックスタートのコードの要約版です。完全な実例については、ejb-security-interceptors クイックスタートを参照してください。

手順8.12 セキュリティーコンテキストの ID を変更する

保護された接続の ID を変更するには、次の 3 つのコンポーネントを作成する必要があります。
  1. クライアント側インターセプターを作成する

    クライアント側インターセプターは、org.jboss.ejb.client.EJBClientInterceptor インターフェイスを実装する必要があります。インターセプターは、要求された ID をコンテキストデータマップを介して渡す必要があります。コンテキストデータマップは、EJBClientInvocationContext.getContextData()。以下は、クライアント側のインターセプターコードの例です。
    public class ClientSecurityInterceptor implements EJBClientInterceptor {
    
        public void handleInvocation(EJBClientInvocationContext context) throws Exception {
            Principal currentPrincipal = SecurityActions.securityContextGetPrincipal();
    
            if (currentPrincipal != null) {
                Map<String, Object> contextData = context.getContextData();
                contextData.put(ServerSecurityInterceptor.DELEGATED_USER_KEY, currentPrincipal.getName());
            }
            context.sendRequest();
        }
    
        public Object handleInvocationResult(EJBClientInvocationContext context) throws Exception {
            return context.getResult();
        }
    }
    
    ユーザーアプリケーションは、次のいずれかの方法で、EJBClientContext のインターセプターチェーンにインターセプターを挿入できます。
    • プログラムで

      このアプローチでは、org.jboss.ejb.client.EJBClientContext.registerInterceptor(int order, EJBClientInterceptor interceptor)メソッドとパスorderそしてそのinterceptor実例。Theorderこのクライアントインターセプターがインターセプターチェーンのどこに配置されるかを決定します。
    • ServiceLoader メカニズム

      このアプローチでは、META-INF/services/org.jboss.ejb.client.EJBClientInterceptor ファイルを作成し、クライアントアプリケーションのクラスパスに配置またはパッケージ化します。ファイルのルールは、Java ServiceLoader Mechanism によって指示されます。このファイルには、EJB クライアントインターセプター実装の完全修飾クラス名ごとに個別の行が含まれることが予想されます。EJB クライアントインターセプタークラスはクラスパスで利用できる必要があります。ServiceLoader メカニズムを使用して追加された EJB クライアントインターセプターは、クラスパスで検出された順序で、クライアントインターセプターチェーンの最後に追加されます。ejb-security-interceptors クイックスタートはこのアプローチを使用します。
  2. サーバー側コンテナーインターセプターを作成して設定する

    コンテナーインターセプタクラスは、単純な Plain Old Java Object (POJO) です。彼らは使用します@javax.annotation.AroundInvokeBean での呼び出し中に呼び出されるメソッドをマークします。コンテナーインターセプターの詳細については、以下を参照してください。「コンテナーインターセプターについて」
    1. コンテナーインターセプターを作成する

      このインターセプターは、ID を含む InvocationContext を受信し、その新しい ID への切り替えを要求します。以下は、実際のコード例の要約版です。
          public class ServerSecurityInterceptor {
      
          private static final Logger logger = Logger.getLogger(ServerSecurityInterceptor.class);
      
          static final String DELEGATED_USER_KEY = ServerSecurityInterceptor.class.getName() + ".DelegationUser";
      
          @AroundInvoke
          public Object aroundInvoke(final InvocationContext invocationContext) throws Exception {
              Principal desiredUser = null;
              UserPrincipal connectionUser = null;
      
              Map<String, Object> contextData = invocationContext.getContextData();
              if (contextData.containsKey(DELEGATED_USER_KEY)) {
                  desiredUser = new SimplePrincipal((String) contextData.get(DELEGATED_USER_KEY));
      
                  Collection<Principal> connectionPrincipals = SecurityActions.getConnectionPrincipals();
      
                  if (connectionPrincipals != null) {
                      for (Principal current : connectionPrincipals) {
                          if (current instanceof UserPrincipal) {
                              connectionUser = (UserPrincipal) current;
                              break;
                          }
                      }
      
                  } else {
                      throw new IllegalStateException("Delegation user requested but no user on connection found.");
                  }
              }
      
      
              ContextStateCache stateCache = null;
              try {
                  if (desiredUser != null && connectionUser != null
                      && (desiredUser.getName().equals(connectionUser.getName()) == false)) {
                      // The final part of this check is to verify that the change does actually indicate a change in user.
                      try {
                          // We have been requested to use an authentication token
                          // so now we attempt the switch.
                          stateCache = SecurityActions.pushIdentity(desiredUser, new OuterUserCredential(connectionUser));
                      } catch (Exception e) {
                          logger.error("Failed to switch security context for user", e);
                          // Don't propagate the exception stacktrace back to the client for security reasons
                          throw new EJBAccessException("Unable to attempt switching of user.");
                      }
                  }
      
                  return invocationContext.proceed();
              } finally {
                  // switch back to original context
                  if (stateCache != null) {
                      SecurityActions.popIdentity(stateCache);;
                  }
              }
          }
      
    2. コンテナーインターセプターを設定する

      サーバー側のコンテナーインターセプターを設定する方法については、以下を参照してください。「コンテナーインターセプターの設定」
  3. JAASLoginModule を作成します

    このコンポーネントは、ユーザーが要求された ID として要求を実行できることを確認するロールを果たします。次の簡略化されたコード例は、ログインと検証を実行するメソッドを示しています。
        @SuppressWarnings("unchecked")
        @Override
        public boolean login() throws LoginException {
            if (super.login() == true) {
                log.debug("super.login()==true");
                return true;
            }
    
            // Time to see if this is a delegation request.
            NameCallback ncb = new NameCallback("Username:");
            ObjectCallback ocb = new ObjectCallback("Password:");
    
            try {
                callbackHandler.handle(new Callback[] { ncb, ocb });
            } catch (Exception e) {
                if (e instanceof RuntimeException) {
                    throw (RuntimeException) e;
                }
                return false; // If the CallbackHandler can not handle the required callbacks then no chance.
            }
    
            String name = ncb.getName();
            Object credential = ocb.getCredential();
    
            if (credential instanceof OuterUserCredential) {
                // This credential type will only be seen for a delegation request, if not seen then the request is not for us.
    
                if (delegationAcceptable(name, (OuterUserCredential) credential)) {
    
                    identity = new SimplePrincipal(name);
                    if (getUseFirstPass()) {
                        String userName = identity.getName();
                        if (log.isDebugEnabled())
                            log.debug("Storing username '" + userName + "' and empty password");
                        // Add the username and an empty password to the shared state map
                        sharedState.put("javax.security.auth.login.name", identity);
                        sharedState.put("javax.security.auth.login.password", "");
                    }
                    loginOk = true;
                    return true;
                }
            }
    
            return false; // Attempted login but not successful.
        }
    
        protected boolean delegationAcceptable(String requestedUser, OuterUserCredential connectionUser) {
        if (delegationMappings == null) {
            return false;
        }
    
        String[] allowedMappings = loadPropertyValue(connectionUser.getName(), connectionUser.getRealm());
        if (allowedMappings.length == 1 && "*".equals(allowedMappings[1])) {
            // A wild card mapping was found.
            return true;
        }
        for (String current : allowedMappings) {
            if (requestedUser.equals(current)) {
                return true;
            }
        }
        return false;
    }
    
コードの完全な手順と詳細については、ejb-security-interceptors クイックスタート README.html ファイルを参照してください。

8.6.5. アプリケーションでクライアント側インターセプターを使用する

プログラムで、または ServiceLoader メカニズムを使用して、クライアント側インターセプターをアプリケーションにプラグインできます。次の手順では、2 つの方法について説明します。

プログラムでインターセプターをアプリケーションに接続します

このアプローチでは、org.jboss.ejb.client.EJBClientContext.registerInterceptor(int order, EJBClientInterceptor interceptor)API とパスorderそしてそのinterceptor実例。Theorderクライアントインターセプターチェーンのどこに正確にこれを決定するために使用されますinterceptor配置されます。

ServiceLoader メカニズムを介してインターセプターをアプリケーションに接続します

このアプローチでは、META-INF/services/org.jboss.ejb.client.EJBClientInterceptor ファイルを作成し、クライアントアプリケーションのクラスパスに配置またはパッケージ化します。ファイルのルールは、Java ServiceLoader Mechanism によって指示されます。このファイルには、EJB クライアントインターセプター実装の完全修飾クラス名ごとに個別の行が含まれることが予想されます。EJB クライアントインターセプタークラスはクラスパスで利用できる必要があります。ServiceLoader メカニズムを使用して追加された EJB クライアントインターセプターは、クラスパスで検出された順序で、クライアントインターセプターチェーンの最後に追加されます。ejb-security-interceptors クイックスタートはこのアプローチを使用します。

8.7. Clustered Enterprise JavaBeans

8.7.1. Clustered Enterprise JavaBeans (EJB) について

高可用性シナリオの EJB コンポーネントはクラスター化できます。HTTP コンポーネントとは異なるプロトコルを使用するため、複数の方法でクラスター化されます。EJB 2 および 3 のステートフル Bean およびステートレス Bean はクラスター化できます。
シングルトンについては、こちらを参照してください。「HA シングルトンを実装する」
注記
EJB 2 エンティティー Bean は、EAP6 以降ではクラスター化できません。これは移行の問題です。

8.7.2. スタンドアロンおよびサーバー内クライアントの設定

EJB クライアントをクラスター化された EJB アプリケーションに接続するには、スタンドアロン EJB クライアントまたはサーバー内 EJB クライアントの既存の設定を拡張して、クラスター接続設定を組み込む必要があります。スタンドアロン EJB クライアントの jboss-ejb-client.properties、またはサーバー側のアプリケーションの jboss-ejb-client.xml ファイルを拡張してクラスター設定を組み込む必要があります。
注記
EJB クライアントは、リモートサーバーで EJB を使用するプログラムです。リモートサーバーへの呼び出しを行う JVM 自体がサーバー内で実行されている場合、クライアントは サーバー 内にあります。つまり、別の EAP インスタンスを呼び出す EAP インスタンスは、サーバー内クライアントと見なされます。

例8.4 jboss-ejb-client.properties 設定のスタンドアロンクライアント

以下の例は、スタンドアロン EJB クライアントに必要な追加のクラスター設定を示しています。
remote.clusters=ejb
remote.cluster.ejb.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
remote.cluster.ejb.connect.options.org.xnio.Options.SSL_ENABLED=false
remote.cluster.ejb.username=test
remote.cluster.ejb.password=password
アプリケーションが remote-outbound-connection を使用する場合は、以下の例のように jboss-ejb-client.xml ファイルを設定し、クラスター設定を追加する必要があります。

例8.5 別の EAP6 インスタンスにデプロイされているクライアントアプリケーション (jboss-ejb-client.xml ファイルの設定)

<jboss-ejb-client xmlns:xsi="urn:jboss:ejb-client:1.2" xsi:noNamespaceSchemaLocation="jboss-ejb-client_1_2.xsd">
   <client-context>
      <ejb-receivers>
            <!-- this is the connection to access the app-one -->
        <remoting-ejb-receiver outbound-connection-ref="remote-ejb-connection-1" />
            <!-- this is the connection to access the app-two -->
        <remoting-ejb-receiver outbound-connection-ref="remote-ejb-connection-2" />
      </ejb-receivers>
        
<!-- if an outbound connection connects to a cluster; a list of members is provided after successful connection.
To connect to this node this cluster element must be defined. -->
        
    <clusters>
       <!-- cluster of remote-ejb-connection-1 -->
       <cluster name="ejb" security-realm="ejb-security-realm-1" username="quickuser1">
          <connection-creation-options>
            <property name="org.xnio.Options.SSL_ENABLED" value="false" />
            <property name="org.xnio.Options.SASL_POLICY_NOANONYMOUS" value="false" />
          </connection-creation-options>
       </cluster>
    </clusters>
   </client-context>
</jboss-ejb-client>
注記
セキュアな接続では、認証例外を回避するために認証情報をクラスター設定に追加する必要があります。

8.7.3. EJB 呼び出しのカスタムロードバランシングポリシーの実装

アプリケーションのサーバーが一般的にまたは特定の期間に同じ量の EJB 呼び出しを処理しないように、カスタム/代替の負荷分散ポリシーを実装することができます。
EJB 呼び出しに AllClusterNodeSelector を実装することができます。AllClusterNodeSelector のノード選択の動作はデフォルトのセレクターと似ていますが、大規模なクラスター (ノード数 >20) の場合でも AllClusterNodeSelector は利用可能なすべてのクラスターノードを使用する点が異なります。接続されていないクラスターノードが返されると、そのクラスターノードは自動的に開きます。以下の例は、AllClusterNodeSelector 実装を示しています。
package org.jboss.as.quickstarts.ejb.clients.selector;

import java.util.Arrays;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jboss.ejb.client.ClusterNodeSelector;
public class AllClusterNodeSelector implements ClusterNodeSelector {
  private static final Logger LOGGER = Logger.getLogger(AllClusterNodeSelector.class.getName());
  
  @Override
  public String selectNode(final String clusterName, final String[] connectedNodes, final String[] availableNodes) {
    if(LOGGER.isLoggable(Level.FINER)) {
      LOGGER.finer("INSTANCE "+this+ " : cluster:"+clusterName+" connected:"+Arrays.deepToString(connectedNodes)+" available:"+Arrays.deepToString(availableNodes));
    }
    
    if (availableNodes.length == 1) {
        return availableNodes[0];
    }
    final Random random = new Random();
    final int randomSelection = random.nextInt(availableNodes.length);
    return availableNodes[randomSelection];
  }

}
EJB 呼び出しの SimpleLoadFactorNodeSelector を実装することもできます。SimpleLoadFactorNodeSelector での負荷分散は、負荷係数に基づいて実行されます。負荷係数 (2/3/4) は、各ノードの負荷に関係なく、ノードの名前 (A/B/C) を基に計算されます。以下の例は、SimpleLoadFactorNodeSelector 実装を示しています。
package org.jboss.as.quickstarts.ejb.clients.selector;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jboss.ejb.client.DeploymentNodeSelector;
public class SimpleLoadFactorNodeSelector implements DeploymentNodeSelector {
  private static final Logger LOGGER = Logger.getLogger(SimpleLoadFactorNodeSelector.class.getName());
  private final Map<String, List<String>[]> nodes = new HashMap<String, List<String>[]>();
  private final Map<String, Integer> cursor = new HashMap<String, Integer>();
  
  private ArrayList<String> calculateNodes(Collection<String> eligibleNodes) {
    ArrayList<String> nodeList = new ArrayList<String>();
    
    for (String string : eligibleNodes) {
      if(string.contains("A") || string.contains("2")) {
        nodeList.add(string);
        nodeList.add(string);
      } else if(string.contains("B") || string.contains("3")) {
        nodeList.add(string);
        nodeList.add(string);
        nodeList.add(string);
      } else if(string.contains("C") || string.contains("4")) {
        nodeList.add(string);
        nodeList.add(string);
        nodeList.add(string);
        nodeList.add(string);
      }
    }
    return nodeList;
  }
  
  @SuppressWarnings("unchecked")
  private void checkNodeNames(String[] eligibleNodes, String key) {
    if(!nodes.containsKey(key) || nodes.get(key)[0].size() != eligibleNodes.length || !nodes.get(key)[0].containsAll(Arrays.asList(eligibleNodes))) {
      // must be synchronized as the client might call it concurrent
      synchronized (nodes) {
        if(!nodes.containsKey(key) || nodes.get(key)[0].size() != eligibleNodes.length || !nodes.get(key)[0].containsAll(Arrays.asList(eligibleNodes))) {
          ArrayList<String> nodeList = new ArrayList<String>();
          nodeList.addAll(Arrays.asList(eligibleNodes));
          
          nodes.put(key, new List[] { nodeList, calculateNodes(nodeList) });
        }
      }
    }
  }
   private synchronized String nextNode(String key) {
    Integer c = cursor.get(key);
    List<String> nodeList = nodes.get(key)[1];
    
    if(c == null || c >= nodeList.size()) {
      c = Integer.valueOf(0);
    }
    
    String node = nodeList.get(c);
    cursor.put(key, Integer.valueOf(c + 1));
    
    return node;
  }
  
  @Override
  public String selectNode(String[] eligibleNodes, String appName, String moduleName, String distinctName) {
    if (LOGGER.isLoggable(Level.FINER)) {
      LOGGER.finer("INSTANCE " + this + " : nodes:" + Arrays.deepToString(eligibleNodes) + " appName:" + appName + " moduleName:" + moduleName
          + " distinctName:" + distinctName);
    }

    // if there is only one there is no sense to choice
    if (eligibleNodes.length == 1) {
      return eligibleNodes[0];
    }
    final String key = appName + "|" + moduleName + "|" + distinctName;
    
    checkNodeNames(eligibleNodes, key);
    return nextNode(key);
  }
}

jboss-ejb-client.properties を使用した設定

remote.cluster.ejb.clusternode.selector プロパティーを実装クラスの名前 (AllClusterNodeSelector または SimpleLoadfactorNodeSelector) とともに追加する必要があります。セレクターは、呼び出し時に利用可能な設定済みのサーバーをすべて表示します。次の例では、デプロイメントノードセレクターとして AllClusterNodeSelector を使用しています。

remote.clusters=ejb
remote.cluster.ejb.clusternode.selector=org.jboss.as.quickstarts.ejb.clients.selector.AllClusterNodeSelector
remote.cluster.ejb.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
remote.cluster.ejb.connect.options.org.xnio.Options.SSL_ENABLED=false
remote.cluster.ejb.username=test
remote.cluster.ejb.password=password

remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=one,two
remote.connection.one.host=localhost
remote.connection.one.port = 4447
remote.connection.one.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
remote.connection.one.username=user
remote.connection.one.password=user123
remote.connection.two.host=localhost
remote.connection.two.port = 4547
remote.connection.two.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false

JBossejb-clientAPI の使用

プロパティー remote.cluster.ejb.clusternode.selectorPropertiesBasedEJBClientConfiguration コンストラクターの一覧に追加する必要があります。次の例では、デプロイメントノードセレクターとして AllClusterNodeSelector を使用しています。

Properties p = new Properties();
p.put("remote.clusters", "ejb");
p.put("remote.cluster.ejb.clusternode.selector", "org.jboss.as.quickstarts.ejb.clients.selector.AllClusterNodeSelector");
p.put("remote.cluster.ejb.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS", "false");
p.put("remote.cluster.ejb.connect.options.org.xnio.Options.SSL_ENABLED", "false");
p.put("remote.cluster.ejb.username", "test");
p.put("remote.cluster.ejb.password", "password");

p.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED", "false");
p.put("remote.connections", "one,two");
p.put("remote.connection.one.port", "4447");
p.put("remote.connection.one.host", "localhost");
p.put("remote.connection.two.port", "4547");
p.put("remote.connection.two.host", "localhost");

EJBClientConfiguration cc = new PropertiesBasedEJBClientConfiguration(p);
ContextSelector<EJBClientContext> selector = new ConfigBasedEJBClientContextSelector(cc);
EJBClientContext.setSelector(selector);

p = new Properties();
p.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
InitialContext context = new InitialContext(p);

jboss-ejb-client.xml を使用したサーバーアプリケーション側の設定

サーバー間の通信に負荷分散ポリシーを使用するには、クラスをアプリケーションとともにパッケージ化し、(META-INF フォルダーにある) jboss-ejb-client.xml で設定します。次の例では、デプロイメントノードセレクターとして AllClusterNodeSelector を使用しています。

<jboss-ejb-client xmlns:xsi="urn:jboss:ejb-client:1.2" xsi:noNamespaceSchemaLocation="jboss-ejb-client_1_2.xsd">
  <client-context deployment-node-selector="org.jboss.ejb.client.DeploymentNodeSelector">
    <ejb-receivers>
      <!-- this is the connection to access the app -->
      <remoting-ejb-receiver outbound-connection-ref="remote-ejb-connection-1" />
    </ejb-receivers>
        
    <!-- if an outbound connection connect to a cluster a list of members is provided after successful connection.
To connect to this node this cluster element must be defined.
-->
    <clusters>
      <!-- cluster of remote-ejb-connection-1 -->
      <cluster name="ejb" security-realm="ejb-security-realm-1" username="test" cluster-node-selector="org.jboss.as.quickstarts.ejb.clients.selector.AllClusterNodeSelector">
        <connection-creation-options>
          <property name="org.xnio.Options.SSL_ENABLED" value="false" />
          <property name="org.xnio.Options.SASL_POLICY_NOANONYMOUS" value="false" />
        </connection-creation-options>
      </cluster>
    </clusters>
  </client-context>
</jboss-ejb-client>
上記のセキュリティー設定を使用するには、client-server 設定に ejb-security-realm-1 を追加する必要があります。以下の例は、セキュリティーレルムを追加する CLI コマンド (ejb-security-realm-1) を示しています。値は、ユーザー "test" の base64 でエンコードされたパスワードです。

core-service=management/security-realm=ejb-security-realm-1:add()
core-service=management/security-realm=ejb-security-realm-1/server-identity=secret:add(value=cXVpY2sxMjMr)
備考
スタンドアロンモードを使用している場合は、開始オプション -Djboss.node.name = またはサーバー設定ファイル standalone.xml を使用して、サーバー名 (server name = "") を設定します。サーバー名が一意であることを確認します。ドメインモードでは、コントローラーは名前が一意であることを自動的に検証します。

8.7.4. EJB 呼び出しのトランザクション動作

サーバー間の呼び出し

分散 JBoss EAP アプリケーションのトランザクション属性は、アプリケーションが同じサーバー上で呼び出されているかのように処理する必要があります。トランザクションを中止するには、別のインターフェイスを使用して宛先メソッドに REQUIRES_NEW のマークを付ける必要があります。

備考
両方のサーバーが JBoss EAP 6 の場合、JBoss EAP 6 はサーバー間 EJB 呼び出しでのトランザクション伝播に Java Transaction Services (JTS) を必要としません。JBossEJB クライアント API ライブラリーはそれ自体を処理します。

クライアント側の呼び出し

JBoss EAP 6 スタンドアロンクライアントで EJB セッション Bean を呼び出すには、EJB プロキシーまたは UserTransaction が使用されている間、クライアントは InitialContext オブジェクトへの参照を持っている必要があります。また、EJB プロキシーまたは UserTransaction が使用されている間、InitialContext オブジェクトを開いたままにしておくことも重要です。接続の制御は、InitialContext によってプロパティーを使用して作成されたクラス内で行われます。

次の例は、InitialContext オブジェクトへの参照を保持する EJB クライアント API を示しています。

例8.6 InitialContext オブジェクトを参照する EJB クライアント API

package org.jboss.as.quickstarts.ejb.multi.server;

import java.util.Date;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

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

import org.jboss.as.quickstarts.ejb.multi.server.app.MainApp;
import org.jboss.ejb.client.ContextSelector;
import org.jboss.ejb.client.EJBClientConfiguration;
import org.jboss.ejb.client.EJBClientContext;
import org.jboss.ejb.client.PropertiesBasedEJBClientConfiguration;
import org.jboss.ejb.client.remoting.ConfigBasedEJBClientContextSelector;

public class Client {

/**
* @param args no args needed
* @throws Exception
*/
    public static void main(String[] args) throws Exception {
        // suppress output of client messages
        Logger.getLogger("org.jboss").setLevel(Level.OFF);
        Logger.getLogger("org.xnio").setLevel(Level.OFF);
        
        Properties p = new Properties();
        p.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED", "false");
        p.put("remote.connections", "one");
        p.put("remote.connection.one.port", "4447");
        p.put("remote.connection.one.host", "localhost");
        p.put("remote.connection.one.username", "quickuser");
        p.put("remote.connection.one.password", "quick-123");

        EJBClientConfiguration cc = new PropertiesBasedEJBClientConfiguration(p);
        ContextSelector<EJBClientContext> selector = new ConfigBasedEJBClientContextSelector(cc);
        EJBClientContext.setSelector(selector);

        Properties props = new Properties();
        props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
        InitialContext context = new InitialContext(props);

        
        final String rcal = "ejb:jboss-ejb-multi-server-app-main/ejb//" + ("MainAppBean") + "!" + MainApp.class.getName();
        final MainApp remote = (MainApp) context.lookup(rcal);
        final String result = remote.invokeAll("Client call at "+new Date());

        System.out.println("InvokeAll succeed: "+result);
    }

}
注記
クライアントでの UserTransaction 参照の取得は、スコープ付き EJB クライアントコンテキストを使用するシナリオ、および リモートネーミング プロトコルを使用する呼び出しではサポートされていません。これは、これらのシナリオでは、InitialContext が独自の EJB クライアントコンテキストインスタンスをカプセル化するためです。これは、EJBClient クラスの静的メソッドを使用してアクセスすることはできません。いつEJBClient.getUserTransaction()が呼び出されると、デフォルトの (グローバル)EJB クライアントコンテキスト (初期化されていない可能性があります) からではなく、目的のコンテキストからトランザクションを返します。

クライアント側の UserTransaction リファレンス

次の例は、スタンドアロンクライアントで UserTransaction 参照を取得する方法を示しています。

例8.7 UserTransaction オブジェクトを参照するスタンドアロンクライアント

import org.jboss.ejb.client.EJBClient;
import javax.transaction.UserTransaction;
.
.
    Context context=null;
    UserTransaction tx=null;
    try {
      Properties props = new Properties();
      // REMEMBER: there must be a jboss-ejb-client.properties with the connection parameter
      //           in the clients classpath
      props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
      context = new InitialContext(props);  
      System.out.println("\n\tGot initial Context: "+context);
      tx=EJBClient.getUserTransaction("yourServerName");
      System.out.println("UserTransaction = "+tx.getStatus());
      tx.begin();
      // do some work
      ...
    }catch (Exception e) {
      e.printStackTrace();
      tx.rollback();
    }finally{
      if(context != null) {
        context.close();
      }
    }

注記
クライアント側で UserTransaction 参照を取得するには;次のシステムプロパティー -Djboss.node.name=yourServerName を使用してサーバーを起動し、クライアント側で次のように使用します。
tx=EJBClient.getUserTransaction("yourServerName");
yourServerName をサーバーの名前に置き換えます。ユーザートランザクションがノードで開始された場合、すべての呼び出しはノードでスティッキーであり、ノードには必要なすべての EJB が必要です。リモートネーミングプロトコルとスコープコンテキストで UserTransaction を使用することはできません。

8.8. 参照

8.8.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 EAP 6 では、各デプロイメントでオプションの個別の名前を指定できます。デプロイメントに明確な名前がない場合は、これを空白のままにします。
<beanName>
Bean 名は、呼び出されるセッション Bean のクラス名です。
<viewClassName>
ビュークラス名は、リモートインターフェイスの完全修飾クラス名です。これには、インターフェースのパッケージ名が含まれます。
?stateful
The?statefulJNDI 名がステートフルセッション Bean を参照する場合は、接尾辞が必要です。他の Bean タイプには含まれません。

8.8.2. EJB リファレンス解決

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

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

  • The@EJB注釈にもmappedName()属性。仕様ではこれをベンダー固有のメタデータとして残していますが、JBoss はこれを認識しますmappedName()参照している EJB のグローバル JNDI 名として。mappedName() を指定した場合は、他のすべての属性は無視され、このグローバル JNDI 名がバインディングに使用されます。
  • 指定した場合@EJB属性が定義されていない場合:
    @EJB 
    ProcessPayment myEjbref;
    次に、以下のルールが適用されます。
    • 参照 Bean の EJB jar は、@EJB インジェクションで使用されるインターフェースで EJB を検索します。同じビジネスインターフェースを公開する EJB が複数ある場合、例外が発生します。このインターフェースを持つ BIOSean が 1 つしかない場合は、その Bean が使用されます。
    • EAR でインターフェースを公開する EJB を検索します。重複が生じると、例外が発生します。それ以外の場合は、一致する Bean を返します。
    • JBoss ランタイムで、そのインターフェースの EJB をグローバルに検索します。同様に、複製が見つかると、例外が発生します。
  • @EJB.beanName() に対応<ejb-link>。の場合beanName()が定義されたら、と同じアルゴリズムを使用します@EJBを使用する以外に属性が定義されていないbeanName()検索のキーとして。この規則の例外は、ejb-link'#' 構文を使用する場合です。'#' 構文を使用すると、参照している EJB が配置されている EAR 内の jar への相対パスを設定できます。詳細は EJB 3.1 仕様を参照してください。

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

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

表8.4 リモート EJB クライアントの Maven 依存関係

グループ ID アーティファクト ID
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、これらの依存関係をに追加する必要があります<dependencies>pom.xml ファイルのセクション。
Thejboss-javaee-6.0jboss-as-ejb-client-bom依存関係をに追加する必要があります<dependencyManagement>スコープimport
注記
TheartifactIDのバージョンは変更される可能性があります。関連するバージョンについては、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 呼び出しの依存関係設定の完全な例については、クイックスタートファイルの ejb-remote/client/pom.xml を参照してください。

8.8.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/標準の名前空間に関するドキュメント。
ルート namespace は http://www.jboss.com/xml/ns/javaee です。

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

次の名前空間はすべて、<assembly-descriptor>エレメント。これらを使用して、設定を単一の Bean に適用することも、デプロイメント内のすべての Bean に適用することもできます。*としてejb-name
クラスターリング名前空間: 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"
これにより、security-domainそしてそのrun-as-principalEJB の場合。
<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>myResourceAdapter</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>

例8.8 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"
    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>
注記
jboss-ejb3-spec-2_0.xsd には、スキーマバリデーションエラーが発生する可能性がある既知の問題があります。これらのエラーは無視して構いません。詳細は、https://bugzilla.redhat.com/show_bug.cgi?id=1192591 を参照してください。

第9章 JBossMBean サービス

9.1. JBoss MBean Service の記述

JBoss サービスに依存するカスタム MBean サービスを記述するには、サービスインターフェースメソッドパターンが必要です。JBoss MBean のサービスインターフェースメソッドパターンは createstartstop、および destroy が実行可能である場合に MBean サービスに通知する複数のライフサイクル操作で構成されます。
以下の方法を使用すると依存関係の状態を管理できます。
  • MBean で特定のメソッドを呼び出したい場合は、これらのメソッドを MBean インターフェースで宣言します。この方法では、MBean 実装で JBoss 固有クラスの依存関係を回避できます。
  • JBoss 固有クラスの依存関係を気にしない場合は、MBean インターフェースで ServiceMBean インターフェースおよび ServiceMBeanSupport クラスを拡張できます。ServiceMBeanSupport クラスは、次のようなサービスライフサイクルメソッドの実装を提供します。createstartstop。次のような特定のイベントを処理するにはstart()イベント、オーバーライドする必要がありますstartService()ServiceMBeanSupport クラスによって提供されるメソッド。

9.2. 標準の MBean の例

ここでは、サービスアーカイブ (.sar) で一緒にパッケージ化される 2 つの MBean サービスのサンプルを開発します。
ConfigServiceMBean インターフェイスは、次のような特定のメソッドを宣言します。startgetTimeoutstopJBoss 固有のクラスを使用せずに、MBean を正しく 開始保持、および 停止 するためのメソッド。ConfigService クラスは ConfigServiceMBean インターフェースを実装した後、このインターフェース内で使用されたメソッドを実装します。
PlainThread クラスは ServiceMBeanSupport クラスを拡張し、PlainThreadMBean インターフェイスを実装します。PlainThread はスレッドを開始し、ConfigServiceMBean.getTimeout()スレッドがスリープする時間を決定します。

例9.1 サンプル MBean サービス

package org.jboss.example.mbean.support;

public interface ConfigServiceMBean {

    int getTimeout();

    void start();

    void stop();

}

package org.jboss.example.mbean.support;

public class ConfigService implements ConfigServiceMBean {
    int timeout;


    @Override
    public int getTimeout() {
        return timeout;
    }

    @Override
    public void start() {
        //Create a random number between 3000 and 6000 milliseconds
        timeout = (int)Math.round(Math.random() * 3000) + 3000;
        System.out.println("Random timeout set to " + timeout + " seconds");
    }

    @Override
    public void stop() {
        timeout = 0;
    }

}
  
package org.jboss.example.mbean.support;

import org.jboss.system.ServiceMBean;

public interface PlainThreadMBean extends ServiceMBean {
    void setConfigService(ConfigServiceMBean configServiceMBean);
}

package org.jboss.example.mbean.support;

import org.jboss.system.ServiceMBeanSupport;

public class PlainThread extends ServiceMBeanSupport implements PlainThreadMBean {

    private ConfigServiceMBean configService;
    private Thread thread;
    private volatile boolean done;

    @Override
    public void setConfigService(ConfigServiceMBean configService) {
        this.configService = configService;
    }

    @Override
    protected void startService() throws Exception {
        System.out.println("Starting Plain Thread MBean");
        done = false;
        thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    while (!done) {
                        System.out.println("Sleeping....");
                        Thread.sleep(configService.getTimeout());
                        System.out.println("Slept!");
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });
        thread.start();
    }

    @Override
    protected void stopService() throws Exception {
        System.out.println("Stopping Plain Thread MBean");
        done = true;
    }


}
jboss-service.xml 記述子は、イン ジェクト タグを使用して ConfigService クラスが PlainThread クラスにインジェクトされる方法を示します。inject タグは PlainThreadMBeanConfigServiceMBean 間の依存関係を確立し、PlainThreadMBean が簡単に ConfigServiceMBean を使用できるようにします。

例9.2 JBoss-service.xml サービス記述子

<server xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="urn:jboss:service:7.0 jboss-service_7_0.xsd"
        xmlns="urn:jboss:service:7.0">
 <mbean code="org.jboss.example.mbean.support.ConfigService" name="jboss.support:name=ConfigBean"/>
 <mbean code="org.jboss.example.mbean.support.PlainThread" name="jboss.support:name=ThreadBean">
  <attribute name="configService">
   <inject bean="jboss.support:name=ConfigBean"/>
  </attribute>
 </mbean>
</server>
MBean のサンプルを記述した後、クラスと jboss-service.xml 記述子をサービスアーカイブ (.sar) の META-INF/ フォルダーでパッケージ化できます。

9.3. JBoss MBean サービスのデプロイ

サンプル MBean (ServiceMBeanTest.sar) を ドメイン モードでビルドおよびデプロイするには、次のコマンドを使用します。
[domain@localhost:9999 /] deploy ~/Desktop/ServiceMBeanTest.sar
[domain@localhost:9999 /] deploy ~/Desktop/ServiceMBeanTest.sar --all-server-groups
サンプル MBean (ServiceMBeanTest.sar) を スタンドアロン モードでビルドおよびデプロイするには、次のコマンドを使用します。
[standalone@localhost:9999 /] deploy ~/Desktop/ServiceMBeanTest.sar
サンプル MBean をアンデプロイするには、次のコマンドを使用します。
[standalone@localhost:9999 /] undeploy ServiceMBeanTest.sar

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

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

10.1.1. HTTP セッションレプリケーション

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

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

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

キャッシュモード

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

REPL
TheREPLモードは、キャッシュ全体をクラスター内の他のすべてのノードに複製します。これは最も安全なオプションですが、より多くのオーバーヘッドが発生します。
DIST
TheDISTモードは、以前の実装で提供された バディモード に似ています。所有者 パラメーターで指定されたノード数にキャッシュを分散することにより、オーバーヘッドを削減します。この所有者の数のデフォルトは 2 です。

所有者

所有者 パラメーターは、セッションの複製されたコピーを保持するクラスターノードの数を制御します。デフォルトは 2 です。

10.1.3. Web セッションキャッシュを設定する

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

手順10.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 キャッシュモードを変更した後、サーバーを再起動する必要があります。

結果

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

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

概要

JBoss EAP 6 高可用性 (HA) 機能を利用するには、アプリケーションを配布可能に設定する必要があります。この手順では、その方法を示し、次に、使用できるいくつかの高度な設定オプションについて説明します。

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

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

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

    例10.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.xml ファイルの <jboss-web> 要素の子要素である <replication-config> 要素内でそれらをオーバーライドできます。該当する要素で、デフォルト値をオーバーライドする場合のみ値を含めます。次の例は、すべてのデフォルト設定をリストし、その後に最も一般的に変更されるオプションを説明する表が続きます。

    例10.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>
          <replication-trigger>SET_AND_NON_PRIMITIVE_GET</replication-trigger>
          <replication-granularity>SESSION</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>
    
    

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

オプション
Description
<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 を設定すると、ほとんどの属性は変更されずにセッションのパフォーマンスを向上させることができます。

<replication-granularity> の有効値

ATTRIBUTE
これは、セッション内のダーティ属性と、最後にアクセスされたタイムスタンプなどの一部のセッションデータにのみ適用されます。
SESSION
デフォルトの値です。属性がダーティーである場合に、セッションオブジェクト全体がレプリケートされます。共有されるオブジェクト参照は、1 つのユニットでセッション全体がシリアライズされるため、リモートノードで維持されます。
注記
JBoss EAP 6 では FIELD はサポートされていません。
次のオプションを変更する必要はほとんどありません。

表10.2 あまり一般的に変更されないセッションレプリケーションのオプション

オプション
Description
<use-jk>
次のようなロードバランサーを想定するかどうかmod_clustermod_jk、またmod_proxy使用中です。デフォルトは false です。true に設定されている場合、コンテナーは各リクエストに関連付けられているセッション ID を調べ、jvmRouteフェイルオーバーがある場合は、セッション ID の一部。
<max-unreplicated-interval>
セッションが変更されていないと見なされた場合でも、セッションがアクセスされた後、セッションのタイムスタンプのレプリケーションをトリガーする前に待機する最大間隔 (秒単位)。これにより、クラスターノードが各セッションのタイムスタンプを認識し、フェイルオーバー中に複製されていないセッションが誤って期限切れになることがなくなります。また、メソッドの呼び出しに正しい値を信頼できることも保証しますHttpSession.getLastAccessedTime()フェイルオーバー中。
デフォルトでは、値は指定されていません。値が 0 の場合、セッションにアクセスするたびにタイムスタンプが複製されます。値が -1 の場合、要求中の他のアクティビティーがレプリケーションをトリガーした場合にのみ、タイムスタンプがレプリケートされます。より大きい正の値HttpSession.getMaxInactiveInterval()設定ミスとして扱われ、0 に変換されます。
<snapshot-mode>
セッションを他のノードに複製するタイミングを指定します。デフォルトは INSTANT で、他の可能な値は INTERVAL です。
インスタント モードでは、変更はリクエスト処理スレッドを使用して、リクエストの最後に複製されます。<snapshot-interval> オプションは無視されます。
INTERVAL モードでは、バックグラウンドタスクは <snapshot-interval> で指定された間隔で実行され、変更されたセッションを複製します。
<snapshot-interval>
<snapshot-mode> の値に INTERVAL を使用するときに、変更されたセッションが複製される間隔 (ミリ秒単位)。
<session-notification-policy>
インターフェイスの実装の完全修飾クラス名ClusteredSessionNotificationPolicyこれは、サーブレット仕様通知が登録済みに発行されるかどうかを管理しますHttpSessionListenerHttpSessionAttributeListener、またHttpSessionBindingListener

10.2. HttpSession のパッシベーションとアクティベーション

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

パッシベーションとは、比較的利用されていないセッションをメモリーから削除し、永続ストレージへ保存することでメモリーの使用量を制御するプロセスのことです。
アクティベーションとは、パッシベートされたデータを永続ストレージから取得し、メモリーに戻すことです。
パッシベーションは、HTTP セッションの存続期間中の 3 つの異なる時間に発生します。
  • コンテナーが新規セッションの作成を要求するときに現在アクティブなセッションの数が設定上限を超えている場合、サーバーはセッションの一部をパッシベートして新規セッションのスペースを作成しようとします。
  • 定期的に、設定された間隔で、バックグラウンドタスクがセッションを非アクティブ化する必要があるかどうかを確認します。
  • Web アプリケーションがデプロイされ、他のサーバーでアクティブなセッションのバックアップコピーが、新たにデプロイされる Web アプリケーションのセッションマネージャーによって取得された場合、セッションはパッシベートされることがあります。
次の条件を満たす場合、セッションは非アクティブ化されます。
  • セッションは、設定可能な最大アイドル時間より長く使用されていません。
  • アクティブなセッションの数が設定可能な最大値を超えており、セッションが設定可能な最小アイドル時間より長く使用されていません。
セッションは常に LRU (Least Recently Used) アルゴリズムを使ってパッシベートされます。

10.2.2. アプリケーションで HttpSession パッシベーションを設定する

概要

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

例10.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 は、最大非アクティブに基づくパッシベーションを無効にします。
REPLDISTレプリケーションモード
メモリーのセッションの合計数には、このノードでアクセスされていない他のクラスターノードからレプリケートされたセッションが含まれます。これを考慮して <max-active-sessions> を設定してください。他のノードから複製されるセッションの数は、REPLまたDISTキャッシュモードが有効になっています。REPL キャッシュモードでは、各セッションは各ノードにレプリケートされます。のDISTキャッシュモードの場合、各セッションは、で指定された数のノードにのみ複製されます。ownersパラメーター。見る「Web セッションキャッシュについて」「Web セッションキャッシュを設定する」セッションキャッシュモードの設定についての情報。
たとえば、各ノードが 100 ユーザーからの要求を処理する 8 つのノードクラスターがあるとします。この場合、REPL キャッシュモードでは、各ノードのメモリーに 800 のセッションが格納されます。とDISTキャッシュモードが有効で、デフォルトowners2 に設定すると、各ノードは 200 セッションをメモリーに保存します。

10.3. HA シングルトンを実装する

概要

次の手順は、SingletonService デコレータでラップされ、クラスター全体のシングルトンサービスとして使用されるサービスをデプロイする方法を示しています。このサービスは、クラスター内で 1 回だけ開始されるスケジュールされたタイマーをアクティブにします。

手順10.3 HA シングルトンサービスを実装する

  1. HA シングルトンサービスアプリケーションを作成します。
    以下は、シングルトンサービスとしてデプロイされる SingletonService デコレータでラップされた サービス の簡単な例です。完全な例は、Red Hat JBoss Enterprise Application Platform に同梱されている cluster-ha-singleton クイックスタートにあります。このクイックスタートには、アプリケーションをビルドおよびデプロイするためのすべての手順が含まれています。
    1. サービスを作成します。
      次のリストは、サービスの例です。
      package org.jboss.as.quickstarts.cluster.hasingleton.service.ejb;
      
      import java.util.Date;
      import java.util.concurrent.atomic.AtomicBoolean;
      
      import javax.naming.InitialContext;
      import javax.naming.NamingException;
      
      import org.jboss.logging.Logger;
      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;
      
      
      /**
       * @author <a href="mailto:wfink@redhat.com">Wolf-Dieter Fink</a>
       */
      public class HATimerService implements Service<String> {
          private static final Logger LOGGER = Logger.getLogger(HATimerService.class);
          public static final ServiceName SINGLETON_SERVICE_NAME = ServiceName.JBOSS.append("quickstart", "ha", "singleton", "timer");
      
          /**
           * A flag whether the service is started.
           */
          private final AtomicBoolean started = new AtomicBoolean(false);
      
          /**
           * @return the name of the server node
           */
          public String getValue() throws IllegalStateException, IllegalArgumentException {
              LOGGER.infof("%s is %s at %s", HATimerService.class.getSimpleName(), (started.get() ? "started" : "not started"), System.getProperty("jboss.node.name"));
              return "";
          }
      
          public void start(StartContext arg0) throws StartException {
              if (!started.compareAndSet(false, true)) {
                  throw new StartException("The service is still started!");
              }
              LOGGER.info("Start HASingleton timer service '" + this.getClass().getName() + "'");
      
              final String node = System.getProperty("jboss.node.name");
              try {
                  InitialContext ic = new InitialContext();
                  ((Scheduler) ic.lookup("global/jboss-cluster-ha-singleton-service/SchedulerBean!org.jboss.as.quickstarts.cluster.hasingleton.service.ejb.Scheduler")).initialize("HASingleton timer @" + node + " " + new Date());
              } catch (NamingException e) {
                  throw new StartException("Could not initialize timer", e);
              }
          }
      
          public void stop(StopContext arg0) {
              if (!started.compareAndSet(true, false)) {
                  LOGGER.warn("The service '" + this.getClass().getName() + "' is not active!");
              } else {
                  LOGGER.info("Stop HASingleton timer service '" + this.getClass().getName() + "'");
                  try {
                      InitialContext ic = new InitialContext();
                      ((Scheduler) ic.lookup("global/jboss-cluster-ha-singleton-service/SchedulerBean!org.jboss.as.quickstarts.cluster.hasingleton.service.ejb.Scheduler")).stop();
                  } catch (NamingException e) {
                      LOGGER.error("Could not stop timer", e);
                  }
              }
          }
      }
      
    2. クラスター化されたシングルトンとして サービス をインストールするアクティベーターを作成します。
      次のリストは、HATimerService をクラスター化されたシングルトンサービスとしてインストールするサービスアクティベーターの例です。
      package org.jboss.as.quickstarts.cluster.hasingleton.service.ejb;
      
      import org.jboss.as.clustering.singleton.SingletonService;
      import org.jboss.logging.Logger;
      import org.jboss.msc.service.DelegatingServiceContainer;
      import org.jboss.msc.service.ServiceActivator;
      import org.jboss.msc.service.ServiceActivatorContext;
      import org.jboss.msc.service.ServiceController;
      
      
      /**
       * Service activator that installs the HATimerService as a clustered singleton service
       * during deployment.
       *
       * @author Paul Ferraro
       */
      public class HATimerServiceActivator implements ServiceActivator {
          private final Logger log = Logger.getLogger(this.getClass());
      
          @Override
          public void activate(ServiceActivatorContext context) {
              log.info("HATimerService will be installed!");
      
              HATimerService service = new HATimerService();
              SingletonService<String> singleton = new SingletonService<String>(service, HATimerService.SINGLETON_SERVICE_NAME);
              /*
               * To pass a chain of election policies to the singleton, for example, 
               * to tell JGroups to prefer running the singleton on a node with a
               * particular name, uncomment the following line:
               */
              // singleton.setElectionPolicy(new PreferredSingletonElectionPolicy(new SimpleSingletonElectionPolicy(), new NamePreference("node1/singleton")));
      
              singleton.build(new DelegatingServiceContainer(context.getServiceTarget(), context.getServiceRegistry()))
                      .setInitialMode(ServiceController.Mode.ACTIVE)
                      .install()
              ;
          }
      }
      
      注記
      上記のコード例では、クラスを使用しています。org.jboss.as.clustering.singleton.SingletonService、これは JBoss EAP プライベート API の一部です。パブリック API は JBoss EAP リリースで利用可能になり、プライベートクラスは非推奨になりますが、これらのクラスは維持され、JBoss EAP リリースサイクルの間利用可能になります。
    3. ServiceActivator ファイルを作成する
      アプリケーションの resources/META-INF/services/ ディレクトリーに org.jboss.msc.service.ServiceActivator という名前のファイルを作成します。前の手順で作成した ServiceActivator クラスの完全修飾名を含む行を追加します。
      org.jboss.as.quickstarts.cluster.hasingleton.service.ejb.HATimerServiceActivator 
    4. クラスター全体のシングルトンタイマーとして使用されるタイマーを実装するシングルトン Bean を作成します。
      このシングルトン Bean にはリモートインターフェイスがなく、アプリケーション内の別の EJB からローカルインターフェイスを参照してはなりません。これにより、クライアントまたは他のコンポーネントによるルックアップが防止され、SingletonService がシングルトンを完全に制御できるようになります。
      1. スケジューラーインターフェイスを作成する
        package org.jboss.as.quickstarts.cluster.hasingleton.service.ejb;
        
        /**
         * @author <a href="mailto:wfink@redhat.com">Wolf-Dieter Fink</a>
         */
        public interface Scheduler {
        
            void initialize(String info);
        
            void stop();
        
        }
        
      2. クラスター全体のシングルトンタイマーを実装するシングルトン Bean を作成します。
        package org.jboss.as.quickstarts.cluster.hasingleton.service.ejb;
        
        import javax.annotation.Resource;
        import javax.ejb.ScheduleExpression;
        import javax.ejb.Singleton;
        import javax.ejb.Timeout;
        import javax.ejb.Timer;
        import javax.ejb.TimerConfig;
        import javax.ejb.TimerService;
        
        import org.jboss.logging.Logger;
        
        
        /**
         * A simple example to demonstrate a implementation of a cluster-wide singleton timer.
         *
         * @author <a href="mailto:wfink@redhat.com">Wolf-Dieter Fink</a>
         */
        @Singleton
        public class SchedulerBean implements Scheduler {
            private static Logger LOGGER = Logger.getLogger(SchedulerBean.class);
            @Resource
            private TimerService timerService;
        
            @Timeout
            public void scheduler(Timer timer) {
                LOGGER.info("HASingletonTimer: Info=" + timer.getInfo());
            }
        
            @Override
            public void initialize(String info) {
                ScheduleExpression sexpr = new ScheduleExpression();
                // set schedule to every 10 seconds for demonstration
                sexpr.hour("*").minute("*").second("0/10");
                // persistent must be false because the timer is started by the HASingleton service
                timerService.createCalendarTimer(sexpr, new TimerConfig(info, false));
            }
        
            @Override
            public void stop() {
                LOGGER.info("Stop all existing HASingleton timers");
                for (Timer timer : timerService.getTimers()) {
                    LOGGER.trace("Stop HASingleton timer: " + timer.getInfo());
                    timer.cancel();
                }
            }
        }
        
  2. クラスターリングを有効にして各 JBoss EAP 6 インスタンスを起動します。
    スタンドアロンサーバーのクラスターリングを有効にするには、インスタンスごとに一意のノード名とポートオフセットを使用して、HA プロファイルを使用して各サーバーを起動する必要があります。
    • Linux の場合、次のコマンド構文を使用してサーバーを起動します。
      EAP_HOME/bin/standalone.sh --server-config=standalone-ha.xml -Djboss.node.name=UNIQUE_NODE_NAME -Djboss.socket.binding.port-offset=PORT_OFFSET

      例10.4 Linux で複数のスタンドアロンサーバーを起動する

      $ EAP_HOME/bin/standalone.sh --server-config=standalone-ha.xml -Djboss.node.name=node1
      $ EAP_HOME/bin/standalone.sh --server-config=standalone-ha.xml -Djboss.node.name=node2 -Djboss.socket.binding.port-offset=100
    • Microsoft Windows の場合、次のコマンド構文を使用してサーバーを起動します。
      EAP_HOME\bin\standalone.bat --server-config=standalone-ha.xml -Djboss.node.name=UNIQUE_NODE_NAME -Djboss.socket.binding.port-offset=PORT_OFFSET

      例10.5 Microsoft Windows で複数のスタンドアロンサーバーを起動します

      C:> EAP_HOME\bin\standalone.bat --server-config=standalone-ha.xml -Djboss.node.name=node1
      C:> EAP_HOME\bin\standalone.bat --server-config=standalone-ha.xml -Djboss.node.name=node2 -Djboss.socket.binding.port-offset=100
    注記
    コマンドライン引数を使用したくない場合は、サーバーインスタンスごとに standalone-ha.xml ファイルを設定して、個別のインターフェイスにバインドできます。
  3. アプリケーションをサーバーにデプロイします
    次の Maven コマンドは、デフォルトのポートで実行されているスタンドアロンサーバーにアプリケーションをデプロイします。
    mvn clean install jboss-as:deploy
    追加のサーバーにデプロイするには、サーバー名を渡します。別のホストにある場合は、コマンドラインでホスト名とポート番号を渡します。
    mvn clean package jboss-as:deploy -Djboss-as.hostname=localhost -Djboss-as.port=10099
    Maven の設定とデプロイの詳細については、JBoss EAP 6 に同梱されている cluster-ha-singleton クイックスタートを参照してください。

10.4. Apache mod_cluster-manager アプリケーション

10.4.1. mod_cluster-manager アプリケーション

mod_cluster-manager アプリケーションは、Apache HTTP サーバーで利用可能な管理 Web ページです。接続されたワーカーノードを監視し、コンテキストの有効化/無効化やクラスター内のワーカーノードの負荷分散プロパティーの設定などのさまざまな管理タスクを実行するために使用されます。

10.4.2. mod_cluster-manager アプリケーションの使用

mod_cluster-manager アプリケーションは、ワーカーノードでさまざまな管理タスクを実行するために使用されます。
次の図は、mod_cluster-manager アプリケーションの Web ページを表しており、ページ上の重要なコンポーネントと管理オプションを強調するための注釈が付いています。

図10.1 mod_cluster 管理 Web ページ

Description
注釈については、以下で説明します。
  • 1 mod_cluster/1.2.8.Final: これは mod_cluster ネイティブライブラリーのバージョンを示します
  • 2 ajp://192.168.122.204:8099: これは、使用されるプロトコル (AJP、HTTP、HTTPS のいずれか)、ワーカーノードおよびポートのホスト名または IP アドレスを示します。
  • 3 jboss-eap-6.3-2: これはワーカーノードの JVMRoute を示します。
  • 4 仮想ホスト 1: これはワーカーノードで設定された仮想ホストを示します
  • 5 無効: これは、特定のコンテキストでの新しいセッションの作成を無効にするために使用できる管理オプションです。ただし、現在のセッションは無効にされず、そのまま処理されます。
  • 6 停止: これは、コンテキストへのセッション要求のルーティングを停止するために使用できる管理オプションです。プロパティー sticky-session-force が true に設定されていない限り、残りのセッションは別のノードにフェイルオーバーします
  • 7 コンテキストの有効化コンテキストの無効化コンテキストの停止: これらは、ノード全体で実行できる操作を示します。これらのいずれかのオプションを選択すると、すべての仮想ホストのノードのコンテキストすべてが影響を受けます。
  • Load balancing group (LBGroup): すべてのワーカーノードをカスタム負荷分散グループにグループ化するために、 load-balancing-group プロパティーは EAP 設定の modcluster サブシステムで設定されます。負荷分散グループ (LBGroup) は、設定されたすべての負荷分散グループに関する情報を提供する情報フィールドです。このフィールドが設定されていないと、すべてのワーカーノードは単一のデフォルト負荷分散グループにグループ化されます。
    備考
    これは唯一の情報フィールドであるため、load-balancing-group プロパティーの設定に使用できません。プロパティーは、EAP 設定の mod_cluster サブシステムで設定する必要があります。
  • 9 負荷 (値): これは、ワーカーノードの負荷率を示します。負荷率は次のように評価されます。
    -load > 0  : A load factor with value 1 indicates that the worker node is overloaded. A load factor of 100 denotes a free and not-loaded node.
    -load = 0  :A load factor of value 0 indicates that the worker node is in a standby mode. This means that no session requests will be routed to this node until and unless the other worker nodes are unavailable
    -load = -1 : A load factor of value -1 indicates that the worker node is in an error state.
    -load = -2 : A load factor of value -2 indicates that the worker node is undergoing CPing/CPong and is in a transition state
    

第11章 CDI

11.1. CDI の概要

11.1.1. CDI の概要

11.1.2. コンテキストと依存関係の注入 (CDI)

Contexts and Dependency Injection (CDI) は、EJB3.0 コンポーネントを JavaServer Faces (JSF) マネージド Bean として使用できるように設計された仕様であり、2 つのコンポーネントモデルを統合し、Web ベースのアプリケーションのプログラミングモデルを大幅に簡素化します。Java。 上記の引用は、JSR-299 仕様から引用したものです。http://www.jcp.org/en/jsr/detail?id=299
JBoss EAP には、JSR-299 のリファレンス実装である Weld が含まれています。タイプセーフな依存性注入の詳細については、を参照してください。「タイプセーフな依存性注入について」

11.1.3. CDI の利点

CDI の利点は次のとおりです。
  • コードの大きなチャンクを注釈に置き換えることで、コードベースを簡素化および縮小します。
  • 柔軟であり、インジェクションおよびイベントを無効または有効にしたり、代替の Bean を使用したり、非 CDI オブジェクトを簡単にインジェクトしたりできます。
  • CDI で古いコードを使用するのは簡単です。META-INF/ または WEB-INF/ ディレクトリーに beans.xml を含めるだけで済みます。ファイルは空にすることができます。
  • パッケージ化とデプロイメントを簡素化し、デプロイメントに追加する必要のある XML の量を削減します。
  • コンテキストを介したライフサイクル管理を提供します。インジェクションを要求、セッション、会話、またはカスタムコンテキストに割り当てることができます。
  • また、文字列ベースのインジェクションよりも安全かつ簡単にデバッグを行える、タイプセーフな依存関係の注入が提供されます。
  • インターセプターを Bean から切り離します。
  • 複雑なイベント通知を提供します。

11.1.4. タイプセーフな依存性注入について

JSR-299 および CDI の前は、Java に依存性を注入する唯一の方法は文字列を使用することでした。これはエラーが発生しがちでした。CDI には、タイプセーフな方法で依存性を注入する機能が導入されています。
CDI の詳細については、を参照してください。「コンテキストと依存関係の注入 (CDI)」

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

Seam 2 の目標は、Enterprise Java Beans (EJB) と JavaServer Faces (JSF) で管理される Bean を統合することでした。
JavaServer Faces (JSF) は JSR-314 を実装しています。これは、サーバーサイドユーザーインターフェースをビルドするための API です。JBoss Web Framework Kit には、JavaServerFaces と AJAX の実装である RichFaces が含まれています。
Weld は、JSR-299 で定義されている Contexts and Dependency Injection (CDI) のリファレンス実装です。Weld は、Seam2 およびその他の依存性注入フレームワークに触発されました。溶接は JBoss EAP 6 に含まれています。

11.2. CDI を使用する

11.2.1. 最初の手順

11.2.1.1. CDI を有効にする

概要

Contexts and Dependency Injection (CDI) は、JBoss EAP 6 のコアテクノロジーの 1 つであり、デフォルトで有効になっています。何らかの理由で無効になっていて、有効にする必要がある場合は、次の手順に従ってください。

手順11.1 JBoss EAP 6 で CDI を有効にする

  1. CDI サブシステムの詳細が設定ファイルからコメント化されているかどうかを確認してください。

    サブシステムを無効にするには、domain.xml または standalone.xml 設定ファイルの関連セクションをコメントアウトするか、関連セクションを完全に削除します。
    EAP_HOME/domain/configuration/domain.xml または EAP_HOME/standalone/configuration/standalone.xml で CDI サブシステムを見つけるには、次の文字列を検索します。存在する場合は、<extensions> セクション内にあります。
    <extension module="org.jboss.as.weld"/>
    使用しているプロファイルには、次の行も含まれている必要があります。プロファイルは、<profiles> セクション内の個々の <profile> 要素にあります。
    <subsystem xmlns="urn:jboss:domain:weld:1.0"/>
  2. ファイルを編集する前に、JBoss EAP 6 を停止します。

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

    CDI サブシステムがコメント化されている場合は、コメントを削除します。
    完全に削除された場合は、ファイルの </extensions> タグのすぐ上にある新しい行に次の行を追加して復元します。
    <extension module="org.jboss.as.weld"/>
  4. また、<profiles> セクションの関連するプロファイルに次の行を追加する必要があります。
    <subsystem xmlns="urn:jboss:domain:weld:1.0"/>
  5. JBoss EAP 6 を再起動します。

    更新した設定で JBoss EAP 6 を起動します。

結果

JBoss EAP 6 は、CDI サブシステムを有効にして起動します。

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

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

はじめに

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

11.2.2.2. 既存のコードで CDI を使用する

パラメーターのないコンストラクター、またはアノテーション @Inject で指定されたコンストラクターを持つほとんどすべての具象 Java クラスは Bean です。Bean の注入を開始する前に行う必要があるのは、アーカイブの META-INF/ または WEB-INF/ ディレクトリーに beans.xml というファイルを作成することだけです。ファイルは空にすることができます。

手順11.2 CDI アプリケーションでレガシー Bean を使用する

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

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

    Beans.xml ファイルを JAR アーカイブの META-INF/ または WAR アーカイブの WEB-INF/ ディレクトリーに配置します。ファイルは空にすることができます。

結果:

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

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

概要

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

例11.1 Bean からパッケージを除外します

次の例には、いくつかの <weld:exclude> タグがあります。
  1. 最初のものはすべての Swing クラスを除外します。
  2. 2 つ目は、Google Web Toolkit がインストールされていない場合、GoogleWebToolkit クラスを除外します。
  3. 3 番目は、システムプロパティーの場合、文字列 Blether (正規表現を使用) で終わるクラスを除外します verbosity に設定されます。
  4. 4 つ目は、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

11.2.2.4. インジェクションを使用した実装の拡張

概要

インジェクションを使用して、既存のコードの機能を追加または変更できます。この例は、既存のクラスに翻訳機能を追加する方法を示しています。翻訳は架空の機能であり、例で実装される方法は擬似コードであり、説明のためにのみ提供されています。

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

例11.2 注入するTranslatorBean Into theWelcomeクラス

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

    @Inject Translator translator;

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

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

11.2.3.1. あいまいな依存関係または満たされていない依存関係について

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

11.2.3.2. 予選について

修飾子は、Bean を Bean タイプに関連付けるアノテーションです。注入する Bean を正確に指定できます。修飾子には、以下の例のように定義された保持とターゲットがあります。

例11.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 {}

例11.4 使用@Synchronous@Asynchronous修飾子

@Synchronous
public class SynchronousPaymentProcessor implements PaymentProcessor {

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

}
@Asynchronous
public class AsynchronousPaymentProcessor implements PaymentProcessor {

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

11.2.3.3. 修飾子を使用したあいまいなインジェクションの解決

概要

このタスクは、あいまいなインジェクションを示し、修飾子を使用してあいまいさを取り除きます。あいまいな注入について詳しくは、「あいまいな依存関係または満たされていない依存関係について」

例11.5 あいまいな注入

Welcome の 2 つの実装があります。1 つは変換し、もう 1 つは変換しません。そのような状況では、以下のインジェクションはあいまいであり、翻訳する Welcome を使用するように指定する必要があります。
public class Greeter {
  private Welcome welcome;

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

手順11.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"));
      }
    }
    

結果

翻訳ウェルカム が使用され、あいまいさはありません。

11.2.4. 管理 Bean

11.2.4.1. マネージド Bean について

Java EE 6 より前は、JavaEE プラットフォームでの Bean という用語の明確な定義はありませんでした。Java EE 仕様では、EJB Bean や JSF マネージド Bean など、Bean と呼ばれる概念がいくつかありました。Spring や Seam などのサードパーティーのフレームワークは、Bean を定義するものについて独自のアイデアを導入しました。
Java EE 6 は、ManagedBeans 仕様で共通の定義を確立しました。管理対象 Bean は、プログラミングの制限が最小限であるコンテナー管理オブジェクトとして定義され、POJO (Plain Old Java Object) として知られるようになりました。管理対象 Bean はリソースのインジェクション、ライフサイクルコールバック、インターセプターなどの基本サービスの小さなセットをサポートします。EJBや CDI などのコンパニオン仕様は、この基本モデルに基づいて構築されます。
ごくわずかな例外を除き、パラメーターのないコンストラクター (または @Inject アノテーションが指定されたコンストラクター) を持つ具象 Java クラスは bean になります。これには、すべての Java Bean と EJB セッション bean が含まれます。上記のサービスを Bean で有効にするための唯一の要件は、それらが特別なマーカーファイル META-INF/beans.xml を含むアーカイブ (JAR、または WAR や EJB JAR などの JavaEE モジュール) に存在することです。

11.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 スコープが必要です。

11.2.4.3. CDI を用いたオブジェクトの Bean へのインジェクト

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

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

    例11.6 TextTranslator インスタンスを TranslateController に挿入します

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

    注入されたオブジェクトのメソッドを直接使用できます。TextTranslator にメソッドがあると仮定しますtranslate

    例11.7 注入されたオブジェクトのメソッドを使用する

    // in TranslateController class
    
    public void translate() {
    
       translation = textTranslator.translate(inputText); 
    
    }
    
  3. Bean のコンストラクターでインジェクションを使用します。

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

    例11.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 のインスタンスを返すことができます。

    例11.9 プログラムでインスタンスを取得する

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

結果:

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

11.2.5. コンテキスト、スコープ、および依存関係

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

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

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

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

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

11.2.6. Bean ライフサイクル

11.2.6.1. Bean のライフサイクルを管理する

概要

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

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

手順11.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 は、指定するスコープに関連するコンテキストに保存され、スコープが適用される限り存続します。

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

概要

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

例11.10 デプロイ後のポリモーフィズムを可能にするために、代替の代わりにプロデューサーメソッドを使用します

The@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;

例11.11 プロデューサーメソッドにスコープを割り当てます

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

例11.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 ではないオブジェクトをインジェクトし、コードを動的に変更できます。

11.2.7. 名前付き Bean と代替 Bean

11.2.7.1. 名前付き Bean について

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

11.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 ビューのコントロールにアクションとして割り当てられます。

11.2.7.3. 代替 Bean について

実装が特定のクライアントモジュールまたはデプロイメントシナリオに固有である Bean が代替となります。

例11.13 代替案の定義

この代替手段は、@SynchronousPaymentProcessor と @AsynchronousPaymentProcessor の両方の模擬実装をすべて 1 つに定義します。
@Alternative @Synchronous @Asynchronous

public class MockPaymentProcessor implements PaymentProcessor {

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

}
デフォルトでは、@Alternative Bean が無効になります。これらは、beans.xml ファイルを編集することにより、特定の Bean アーカイブに対して有効になります。

11.2.7.4. 代替を用いたインジェクションのオーバーライド

概要

代替 Bean を使用すると、既存の Bean をオーバーライドできます。これらは、同じ役割を満たすクラスをプラグインする方法として考慮できますが、動作が異なります。代替の Bean はデフォルトで無効になります。このタスクは、代替を指定し、有効にする方法を示しています。

手順11.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>

結果

元の実装の代わりに代替実装が使用されます。

11.2.8. ステレオタイプ

11.2.8.1. ステレオタイプについて

多くのシステムでは、アーキテクチャーパターンを使用して繰り返し発生する Bean ロールのセットを生成します。ステレオタイプを使用すると、このようなロールを指定し、中心的な場所で、このロールを持つ Bean に対する共通メタデータを宣言できます。
ステレオタイプにより、以下のいずれかの組み合わせがカプセル化されます。
  • デフォルトのスコープ。
  • インターセプターバインディングのセット。
ステレオタイプは、次の 2 つのシナリオのいずれかを指定する場合もあります。
  • ステレオタイプを持つすべての Bean には、デフォルトの BeanEL 名があります
  • ステレオタイプを持つすべての Bean は代替です
Bean は、ゼロ、1 つ、または複数のステレオタイプを宣言できます。ステレオタイプアノテーションは、Bean クラスまたはプロデューサーメソッドまたはフィールドに適用できます。
ステレオタイプは、@ Stereotype アノテーションが付けられたアノテーションであり、他のいくつかのアノテーションをパッケージ化します。
ステレオタイプからスコープを継承するクラスは、そのステレオタイプをオーバーライドし、bean に直接スコープを指定できます。
また、ステレオタイプが @Named アノテーションを持つ場合、配置された bean はデフォルトの bean 名を持ちます。この bean は、@Named アノテーションが bean で直接指定された場合に、この名前をオーバーライドできます。名前付き Bean の詳細については、を参照してください。「名前付き Bean について」

11.2.8.2. ステレオタイプの使用

概要

ステレオタイプを使用しないと、アノテーションが煩雑になる可能性があります。このタスクは、ステレオタイプを使用して煩雑さを軽減し、コードを効率化する方法を示しています。ステレオタイプとは何かについての詳細は、を参照してください。「ステレオタイプについて」

例11.14 注釈が乱雑

@Secure
@Transactional
@RequestScoped
@Named
public class AccountManager {
  public boolean transfer(Account a, Account b) {
    ...
  }
}

手順11.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) {
        ...
      }
    }
    

結果:

ステレオタイプは、コードを合理化および簡素化します。

11.2.9. オブザーバーメソッド

11.2.9.1. オブザーバーメソッドについて

オブザーバーメソッドは、イベント発生時に通知を受け取ります。
また、CDI は、イベントが発生したトランザクションの完了前または完了後フェーズ中にイベント通知を受け取るトランザクションオブザーバーメソッドを提供します。

11.2.9.2. トランザクションオブザーバー

トランザクションオブザーバーは、イベントが発生したトランザクションの完了フェーズ前または完了フェーズ後にイベント通知を受け取ります。たとえば、以下のオブザーバーメソッドは、カテゴリーツリーを更新するトランザクションが正常に実行される場合のみアプリケーションコンテキストにキャッシュされたクエリー結果セットを更新します。
public void refreshCategoryTree(@Observes(during = AFTER_SUCCESS) CategoryUpdateEvent event) { ... }
トラザクションオブザーバーには 5 つの種類があります。
  • IN_PROGRESS: デフォルトではオブザーバーは即座に呼び出されます。
  • AFTER_SUCCESS: トランザクションが正常に完了する場合のみ、オブザーバーはトランザクションの完了フェーズの後に呼び出されます。
  • AFTER_FAILURE: トランザクションの完了に失敗する場合のみ、オブザーバーはトランザクションの完了フェーズの後に呼び出されます。
  • AFTER_COMPLETION: オブザーバーはトランザクションの完了フェーズの後に呼び出されます。
  • BEFORE_COMPLETION: オブザーバーはトランザクションの完了フェーズの前に呼び出されます。
トランザクションオブザーバーは、単一のアトミックトランザクションよりも状態が保持される期間が長いため、トランザクションオブザーバーはステートフルオブジェクトモデルで重要になります。
JPA クエリー結果セットをアプリケーションスコープにキャッシュしたと仮定します。
	
import javax.ejb.Singleton;
import javax.enterprise.inject.Produces;

@ApplicationScoped @Singleton

public class Catalog {
   @PersistenceContext EntityManager em;
   List<Product> products;
   @Produces @Catalog
   List<Product> getCatalog() {
      if (products==null) {
         products = em.createQuery("select p from Product p where p.deleted = false")
            .getResultList();
      }
      return products;
   }
}
Product はときどき作成および削除されます。この場合は、製品カタログを更新する必要があります。ただし、この更新を実行する前に、トランザクションが正常に完了するのを待つ必要があります。
Products を作成および削除する Bean は、次のようなイベントをトリガーします。
	
import javax.enterprise.event.Event;

@Stateless

public class ProductManager {
   @PersistenceContext EntityManager em;
   @Inject @Any Event<Product> productEvent;
   public void delete(Product product) {
      em.delete(product);
      productEvent.select(new AnnotationLiteral<Deleted>(){}).fire(product);
   }

   public void persist(Product product) {
      em.persist(product);
      productEvent.select(new AnnotationLiteral<Created>(){}).fire(product);
   }
   ...
}
トランザクションが正常に完了した後に、Catalog がイベントを監視できるようになりました。
	
import javax.ejb.Singleton;

@ApplicationScoped @Singleton
public class Catalog {
   ...
   void addProduct(@Observes(during = AFTER_SUCCESS) @Created Product product) {
      products.add(product);
   }

   void removeProduct(@Observes(during = AFTER_SUCCESS) @Deleted Product product) {
      products.remove(product);
   }

}

11.2.9.3. イベントの発生と確認

例11.15 イベントを開始する

このコードは、メソッドで注入および使用されるイベントを示しています。
public class AccountManager {
  @Inject Event<Withdrawal> event;
  
  public boolean transfer(Account a, Account b) {
    ...
    event.fire(new Withdrawal(a));
  }
}

例11.16 修飾子を使用してイベントを発生させる

修飾子を使用すると、より具体的にイベントのインジェクションにアノテーションを付けられます。修飾子の詳細については、を参照してください。「予選について」
public class AccountManager {
  @Inject @Suspicious Event <Withdrawal> event;
  
  public boolean transfer(Account a, Account b) {
    ...
    event.fire(new Withdrawal(a));
  }
}

例11.17 イベントを観察する

イベントを確認するには、@Observes アノテーションを使用します。
public class AccountObserver {
  void checkTran(@Observes Withdrawal w) {
    ...
  }
}

例11.18 資格のあるイベントを観察する

修飾子を使用すると、特定の種類のイベントのみを確認できます。修飾子の詳細については、を参照してください。「予選について」
public class AccountObserver {
  void checkTran(@Observes @Suspicious Withdrawal w) {
    ...
  }
}

11.2.10. インターセプター

11.2.10.1. インターセプターについて

インターセプターは Enterprise JavaBeans 仕様の一部として定義され、で http://jcp.org/aboutJava/communityprocess/final/jsr318/ 確認できます。インターセプターを使用すると、Bean のメソッドを直接変更せずに Bean のビジネスメソッドに機能を追加できます。インターセプターは、Bean のビジネスメソッドの前に実行されます。
CDI により、インターセプターと Bean をバインドするアノテーションを利用できるため、この機能が強化されます。

インターセプションポイント

ビジネスメソッドの傍受
ビジネスメソッドインターセプターは、Bean のクライアントによる Bean のメソッドの呼び出しに適用されます。
ライフサイクルコールバックインターセプト
ライフサイクルコールバックインターセプターは、コンテナーによるライフサイクルコールバックの呼び出しに適用されます。
タイムアウトメソッドのインターセプト
タイムアウトメソッドインターセプターは、コンテナーによる EJB タイムアウトメソッドの呼び出しに適用されます。

11.2.10.2. CDI とのインターセプターの使用

例11.19 CDI のないインターセプター

CDI がない場合、インターセプターには 2 つの問題があります。
  • Bean は、インターセプター実装を直接指定する必要があります。
  • アプリケーションの各 Bean は、インターセプターの完全なセットを適切な順序で指定する必要があります。この場合、アプリケーション全体でインターセプターを追加または削除するには時間がかかり、エラーが発生する傾向があります。
@Interceptors({
  SecurityInterceptor.class,
  TransactionInterceptor.class,
  LoggingInterceptor.class
})
@Stateful public class BusinessComponent {
  ...
}

手順11.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 は、インターセプターコードを簡素化し、ビジネスコードへの適用を容易にします。

11.2.11. デコレータについて

デコレーターは、特定の Java インターフェースからの呼び出しをインターセプトし、そのインターフェースに割り当てられたすべてのセマンティクスを認識します。デコレーターは、何らかの業務をモデル化するのに役に立ちますが、インターセプターの一般性を持ちません。それらは、それが装飾する型を実装し、注釈が付けられた Bean、または抽象クラスですらあります。@Decorator。CDI アプリケーションでデコレーターを呼び出すには、beans.xml ファイルで指定する必要があります。

例11.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);

      ...

   }

}
デコレートされたオブジェクトへの参照を取得するために、デコレーターには @Delegate インジェクションポイントが 1 つ必要になります。

11.2.12. ポータブル拡張機能について

CDI は、フレームワーク、拡張機能、および他のテクノロジーとの統合の基礎となることを目的としています。したがって、CDI は、移植可能な CDI の拡張機能の開発者が使用する SPI のセットを公開します。拡張機能は、以下のような種類の機能を提供できます。
  • ビジネスプロセス管理エンジンとの統合。
  • Spring、Seam、GWT、Wicket などのサードパーティーフレームワークとの統合。
  • CDI プログラミングモデルに基づく新しいテクノロジー。
JSR-299 仕様に基づいて、移植可能な拡張機能は次の方法でコンテナーと統合できます。
  • 独自の Bean、インターセプター、およびデコレーターをコンテナーに提供します。
  • 依存関係注入サービスを使用した独自のオブジェクトへの依存関係のインジェクション。
  • カスタムスコープのコンテキスト実装を提供します。
  • アノテーションベースのメタデータを別のソースからのメタデータで拡大またはオーバーライドします。

11.2.13. Bean プロキシー

11.2.13.1. Bean プロキシーについて

通常、インジェクトされた bean のクライアントは bean インスタンスへの直接参照を保持しません。bean が依存オブジェクト (スコープ @Dependent) でない場合、コンテナーはプロキシーオブジェクトを使用して、インジェクトされたすべての参照を bean にリダイレクトする必要があります。
この bean プロキシーはクライアントプロキシと呼ばれ、メソッド呼び出しを受け取る bean インスタンスが、現在のコンテキストと関連するインスタンスになるようにします。またクライアントプロキシは、他のインジェクトされた bean を再帰的にシリアライズせずに、セッションコンテキストなどのコンテキストにバインドされる bean をディスクへシリアライズできるようにします。
Java の制限により、コンテナーによるプロキシーの作成が不可能な Java の型があります。これらの型の 1 つで宣言されたインジェクションポイントが、@Dependent 以外のスコープを持つ bean に解決すると、コンテナーがデプロイメントをアボートします。

コンテナーでプロキシーできない Java タイプ

  • パラメーターのない非プライベートコンストラクターを持たないクラス
  • 宣言されたクラスfinalまたは持っているfinal方法
  • アレイおよびプリミティブ型。

11.2.13.2. インジェクションでのプロキシーの使用

概要

各 bean のライフサイクルが異なる場合に、インジェクションにプロキシーが使用されます。プロキシーは起動時に作成されたbean のサブクラスで、bean クラスのプライベートメソッド以外のメソッドをすべて上書きします。プロキシーは実際の bean インスタンスへ呼び出しを転送します。

この例では、PaymentProcessorインスタンスは直接注入されませんShop。代わりに、プロキシーが注入され、processPayment()メソッドが呼び出されると、プロキシーは現在のPaymentProcessorBean インスタンスを呼び出し、processPayment()その上でメソッド。

例11.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 プロキシーについて」

第12章 Java Transaction API (JTA)

12.1. 概要

12.1.1. Java Transactions API(JTA) の概要

はじめに

これらのトピックは、Java Transactions API(JTA) の基本的な理解を提供します。

12.2. トランザクションの概念

12.2.1. トランザクション

トランザクションは 2 つ以上のアクションで構成されており、アクションすべてが成功または失敗する必要があります。成功した場合はコミット、失敗した場合はロールバックが結果的に実行されます。ロールバックでは、トランザクションがコミットを試行する前に、各メンバーの状態が元の状態に戻ります。
適切に設計されたトランザクションの一般的な基準は、ACID (Atomic、Consistent、Isolated、および Durable) であることです。

12.2.2. トランザクションの ACID プロパティー

ACID は 原子性 (Atomicity)、一貫性 (Consistency)、独立性 (Isolation)、永続性 (Durability) の略語です。通常、この用語はデータベースやトランザクション操作において使用されます。

ACID の定義

原子性 (Atomicity)
トランザクションの原子性を保つには、すべてのトランザクションメンバーが同じ決定を行う必要があります。これらのメンバーはコミットまたはロールバックを行います。原子性が保たれない場合の結果はヒューリスティックな結果と呼ばれます。
一貫性
一貫性とは、データベーススキーマの観点から、データベースに書き込まれたデータが有効なデータであることを保証するという意味です。データベースあるいは他のデータソースは常に一貫した状態でなければなりません。一貫性のない状態の例には、操作が中断される前にデータの半分が書き込まれてしまったフィールドなどがあります。すべてのデータが書き込まれた場合や、書き込みが完了しなかった時に書き込みがロールバックされた場合に、一貫した状態となります。
分離
独立性とは、トランザクションのスコープ外のプロセスがデータを変更できないように、トランザクションで操作されたデータが変更前にロックされる必要があることを意味します。
持続性 (Durability)
持続性とは、トランザクションのメンバーがコミットするよう指示されてから外部で問題が発生した場合に、問題が解決されるとすべてのメンバーがトランザクションを継続してコミットできることを意味します。このような問題には、ハードウェア、ソフトウェア、ネットワーク、またはその他の関与するシステムが関連することがあります。

12.2.3. トラザクションコーディネーターまたはトランザクションマネージャー

JBoss EAP 6 のトランザクションでは、Transaction CoordinatorTransaction Manager という言葉は、ほとんど同じことを意味します。トランザクションコーディネーターという言葉は通常、分散トランザクションのコンテキストで使用されます。
JTA トランザクションでは、TransactionManager は JBoss EAP 6 内で実行され、2 フェーズコミット プロトコル中にトランザクション参加者と通信します。
トランザクションマネージャー はトランザクションの参加者に対して、他のトランザクションの参加者の結果に従い、データをコミットするか、ロールバックするか指示します。こうすることで、確実にトランザクションが ACID 標準に準拠するようにします。
JTS トランザクションでは、トランザクションコーディネーターは、異なるサーバー上のトランザクションマネージャー間の相互作用を管理します。

12.2.4. トランザクションの参加者

トランザクション参加者は、トランザクション内の任意のプロセスであり、状態をコミットまたはロールバックする機能があります。これは、データベースまたは他のアプリケーションである可能性があります。トランザクションの各参加者は、状態をコミットまたはロールバックできるかどうかを独自に決定します。そして、すべての参加者がコミットできる場合のみ、トランザクション全体が成功します。コミットできない参加者がある場合は、各参加者がそれぞれの状態をロールバックし、トランザクション全体が失敗します。トランザクションマネージャーは、コミットまたはロールバック操作を調整し、トランザクションの結果を決定します。

12.2.5. Java Transactions API(JTA) について

Java Transaction API (JTA) は Java Enterprise Edition 仕様の一部です。JSR-907 で定義されています。
JTA の実装は、JBoss EAP アプリケーションサーバーのプロジェクト Narayana によってカバーされるトランザクションマネージャーを使用して行われます。トランザクションマネージャーを使用すると、アプリケーションは、単一のグローバルトランザクションを介して、データベースや JMS ブローカーなどのさまざまなリソースを割り当てることができます。グローバルトランザクションは XA トランザクションと呼ばれます。XA 機能を備えたリソースのみをトランザクションに含めることができます。
このドキュメントでは、JTA は Java Transaction API を指します。この用語は、トランザクションマネージャーがトランザクションを処理する方法を示すために使用されます。トランザクションマネージャーは JTA トランザクションモードで動作し、データはメモリーを介して共有され、トランザクションコンテキストはリモート EJB 呼び出しによって転送されます。JTS モードでは、データは CORBA (Common Object Request Broker Architecture) メッセージを送信して共有され、トランザクションコンテキストは IIOP 呼び出しによって転送されます。どちらのモードも、複数の EAP サーバーへのトランザクションの分散をサポートしています。
アノテーションは、コード内でトランザクションを作成および制御するための方法です。

12.2.6. Java Transaction Service (JTS)

Java Transaction Service (JTS) は、Object Transaction Service (OTS) と Java のマッピングです。Java アプリケーションは JTA API を使用してトランザクションを管理します。JTA はトランザクションマネージャーが JTS モードに切り替わったときに JTS トランザクション実装と対話します。ネストされたトランザクションなどの特別な JTS 機能を使用するには、JTSAPI を手動で使用する必要があります。
JTS は IIOP プロトコル上で動作します。JTS を使用するトランザクションマネージャーは Object Request Broker (ORB) と呼ばれるプロセスと Common Object Request Broker Architecture (CORBA) と呼ばれる通信標準を使用してお互いに通信します。
アプリケーションの観点で JTA API を使用すると、JTS トラザクションは JTA トランザクションと同じように動作します。
注記
JBoss EAP 6 に含まれる JTS の実装は、分散トランザクションをサポートします。完全準拠の JTS トランザクションとの違いは、外部のサードパーティー ORB との相互運用性です。この機能は、JBoss EAP 6 ではサポートされません。サポートされる設定では、複数の JBoss EAP 6 コンテナーでのみトランザクションが分散されます。

12.2.7. XA データソースおよび XA トランザクション

XA データソースは、XA グローバルトランザクションに参加できるデータソースです。
XA トランザクションは、複数のリソースにまたがることができるトランザクションです。これには、1 つ以上のデータベースまたはその他のトランザクションリソースを備えたトランザクションマネージャーの調整が含まれ、すべてが単一のグローバルトランザクションに関与します。

12.2.8. XA リカバリー

Java Transaction API(JTA) を使用すると、複数の X/OpenXA リソース に分散トランザクションを実行できます。XA は Extended Architecture を表し、複数のバックエンドデータストアを使用するトランザクションを定義するために X/Open Group によって開発されました。XA 標準は、グローバル トランザクションマネージャー (TM) とローカルリソースマネージャーの間のインターフェイスを記述します。XA を使用すると、トランザクションの原子性を維持しながら、アプリケーションサーバー、データベース、キャッシュ、メッセージキューなどの複数のリソースを同じトランザクションに参加させることができます。原子性とは、参加者の 1 人が変更をコミットできなかった場合、他の参加者がトランザクションを中止し、トランザクションが発生する前と同じステータスに状態を復元することを意味します。
XA Recovery は、リソースやトランザクションの参加者がクラッシュしたり利用できない状態になっても、トランザクションの影響を受けるすべてのリソースが更新またはロールバックされるようにするプロセスです。JBoss EAP 6 の範囲内では、XA データソース、JMS メッセージキュー、JCA リソースアダプターなどの XA リソースまたはサブシステムに対して、transactions サブシステムが XA リカバリーのメカニズムを提供します。
XA リカバリーはユーザーの介入がなくても実行されます。XA リカバリーに失敗すると、エラーがログ出力に記録されます。サポートが必要な場合は、Red Hat グローバルサポートサービスまでご連絡ください。

12.2.9. 2 フェーズコミットプロトコル

2 フェーズコミット プロトコル (2PC)は、トランザクションの結果を決定するアルゴリズムを参照します。

フェーズ 1

最初のフェーズでは、トランザクションをコミットできるか、あるいはロールバックする必要があるかをトランザクションの参加者がトランザクションコーディネーターに通知します。

フェーズ 2

2 番目のフェーズでは、トランザクションコーディネーターがトランザクション全体をコミットするか、またはロールバックするかを決定します。いずれの参加者もコミットできない場合、トランザクションはロールバックしなければなりません。それ以外の場合、トランザクションはコミットできます。コーディネーターは何を行うかをリソースに指示し、トランザクションはその完了時にコーディネーターに通知します。この時点で、トランザクションは完了します。

12.2.10. トランザクションタイムアウト

原子性を確保し、トランザクションを ACID 標準に準拠させるために、トランザクションの一部が長期間実行される場合があります。トランザクション参加者は、コミットするときにデータソースの一部をロックする必要があります。トランザクションマネージャーは、コミットするかロールバックするかをすべて指示する前に、各トランザクション参加者からの応答を待つ必要があります。ハードウェアあるいはネットワークの障害のため、リソースが永久にロックされることがあります。
トランザクションのタイムアウトをトランザクションと関連付け、ライフサイクルを制御することができます。タイムアウトのしきい値がトランザクションのコミットあるいはロールバック前に渡された場合、タイムアウトにより、自動的にトランザクションがロールバックされます。
トランザクションサブシステム全体に対しデフォルトのタイムアウト値を設定できます。または、デフォルトのタイムアウト値を無効にし、トランザクションごとにタイムアウトを指定できます。

12.2.11. 分散トランザクション

distributed transaction は、複数の JBoss EAP 6 サーバー上に参加者が存在するトランザクションです。Java Transaction Service (JTS) 仕様では、JTS トランザクションをさまざまなベンダーのアプリケーションサーバーに分散できることが義務付けられています (さまざまなベンダーのサーバー間のトランザクション分散はサポートされている機能ではありません)。Java Transaction API (JTA) はこれを定義していませんが、JBoss EAP 6 は JBoss EAP 6 サーバー間での分散 JTA トランザクションをサポートしています。
注記
他のアプリサーバーベンダーのドキュメントでは、分散トランザクションという用語は XA トランザクションを意味することがわかります。JBoss EAP 6 のドキュメントのコンテキストでは、分散トランザクションとは、複数のアプリケーションサーバーに分散されたトランザクションを指します。このドキュメントでは、さまざまなリソース (たとえば、データベースリソースと jms リソース) で設定されるトランザクションを XA トランザクションと呼びます。詳細は、「Java Transaction Service (JTS)」「XA データソースおよび XA トランザクション」 を参照してください。

12.2.12. ORB 移植性 API

Object Request Broker (ORB) とは、複数のアプリケーションサーバーで分散されるトランザクションの参加者、コーディネーター、リソース、および他のサービスにメッセージを送受信するプロセスのことです。ORB は標準的なインターフェース記述言語 (IDL) を使用してメッセージを通信し解釈します。Common Object Request Broker Architecture (CORBA) (CORBA) は JBoss EAP の ORB によって使用される IDL です。
ORB を使用するサービスの主なタイプは、Java Transaction Service (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 Portability API に含まれるメソッドとプロパティーの詳細は、Red Hat カスタマーポータルの JBoss EAP 6 Javadocs バンドルを参照してください。

12.2.13. ネストされたトランザクションについて

ネストされたトランザクションは、一部の参加者がトランザクションでもあるトランザクションです。

ネストされたトランザクションの利点

誤った隔離
サブトランザクションがロールバックする場合、おそらくそれが使用しているオブジェクトが失敗したために、囲んでいるトランザクションはロールバックする必要はありません。
モジュール性
新しいトランザクションの開始時にトランザクションがすでに呼び出しに関連付けられている場合、新しいトランザクションはその中にネストされます。したがって、オブジェクトにトランザクションが必要であることがわかっている場合は、オブジェクト内にトランザクションを作成できます。オブジェクトのメソッドがクライアントトランザクションなしで呼び出された場合、オブジェクトのトランザクションは最上位になります。それ以外の場合は、クライアントのトランザクションのスコープ内にネストされます。同様に、クライアントはオブジェクトがトランザクションであるかどうかを知る必要はありません。独自のトランザクションを開始できます。
ネストされたトランザクションは、Java Transaction Service (JTS)API の一部としてのみサポートされ、Java Transaction API(JTA) の一部としてはサポートされません。(非分散)JTA トランザクションをネストしようとすると、例外が発生します。
トランザクションサブシステムの JBoss EAP 6 設定を JTS を使用するように変更しても、ネストされたトランザクションが使用またはアクティブ化されることを示すものではありません。それらを使用する必要がある場合は、ORB API を直接使用する必要があります。これは、JTAAPI がネストされたトランザクションを開始するためのメソッドを提供しないためです。

12.2.14. XML トランザクションサービス

XML トランザクションサービス (XTS) コンポーネントは、ビジネストランザクションのプライベートおよびパブリック Web サービスの調整をサポートします。XTS を使用すると、複雑なビジネストランザクションを制御され信頼できる状態で調整できます。XTS API は WS-Coordination、WS-Atomic Transaction、および WS-Business Activity プロトコルを基にしたトランザクションコーディネーションモデルをサポートします。

12.2.14.1. XTS によって使用されるプロトコルの概要

このトピックでは、各プロトコルの仕様で定義されている、WS-Coordination (WS-C)、WS-Atomic Transaction (WS-AT)、および WS-Business Activity (WS-BA) プロトコルに関連する基本的な概念について説明します。
WS-C 仕様は、異なるコーディネーションプロトコルがプラグインできるようにするフレームワークを定義し、クライアント、サービス、および参加者の間で作業を調整します。
WS-T プロトコルは、WS-C によって提供されるコーディネーションフレームワークを利用する WS-Atomic Transaction (WS-AT) および WS-Business Activity (WS-BA) の 2 つのトランザクションコーディネーションプロトコルで構成されます。WS-T は、既存の従来のトランザクション処理システムを統一するために開発され、これらのシステム間で確実に通信が行われるようにします。

12.2.14.2. Web Services-Atomic Transaction (WS-AT) プロセス

アトミックトランザクション (AT) は、ACID セマンティックが適切である場合に短期間の対話をサポートするよう設計されています。AT の範囲内では、Web サービスは通常 WS-T の制御下でブリッジングを用いてデータベースやメッセージキューなどの XA リソースにアクセスします。トランザクションが終了すると、参加者は AT の決定結果を XA リソースに伝搬し、各参加者によって適切なコミットまたはロールバックが実行されます。

アトミックトランザクション (AT) プロセス

  1. AT を開始する際、クライアントは最初に WS-T をサポートする WS-C Activation Coordinator Web サービスを見つけます。
  2. クライアントはコーディネーション型として指定 http://schemas.xmlsoap.org/ws/2004/10/wsat して WS-C CreateCoordinationContext メッセージをサービスに送信します。
  3. クライアントは適切な WS-T コンテキストをアクティベーションサービスから受け取ります。
  4. CreateCoordinationContext メッセージの応答であるトランザクションコンテキストの CoordinationType 要素は WS-AT 名前空間 http://schemas.xmlsoap.org/ws/2004/10/wsat に設定されます。また、参加者を登録できるアトミックトランザクションコーディネーターエンドポイントである WS-C Registration Service への参照も含まれます。
  5. クライアントは通常、続いて Web サービスの呼び出しを行い、Web サービスによるすべての変更をコミットまたはロールバックしてトランザクションを完了します。完了できるようにするには、エンドポイントがコーディネーションコンテキストで返された登録サービスに登録メッセージを送信し、クライアントを完了プロトコルの参加者として登録する必要があります。
  6. クライアントを登録したら、クライアントアプリケーションは Web サービスと対話してビジネスレベルの作業を達成します。クライアントは、ビジネス Web サービスが呼び出されるごとに、トランザクションコンテキストを SOAP ヘッダーブロックの挿入し、各呼び出しがトランザクションによって暗黙的にスコープ付けされます。WS-AT 対応 Web サービスをサポートするツールキットは、SOAP ヘッダーブロックで見つかったコンテキストをバックエンド操作と関連付ける機能を提供します。これにより、Web サービスによる変更がクライアントと同じトランザクションの範囲内で行われるようにし、トランザクションコーディネーターによるコミットまたはロールバックの対象になるようにします。
  7. 必要なアプリケーションの作業がすべて完了したら、クライアントはサービス状態の変更を永続する目的でトランザクションを終了することができます。完了参加者は、トランザクションをコミットまたはロールバックするようコーディネーターに指示します。コミットまたはロールバック操作が完了すると、トランザクションの結果を示すために状態が参加者に返されます。

詳細については、Web サービス - トランザクションドキュメント を参照してください。

12.2.14.3. Web Services-Business Activity (WS-BA) プロセス

Web Services-Business Activity (WS-BA) は、既存のビジネスプロセスおよびワークフローシステムがプロプライエタリーメカニズムをラップし、実装およびビジネス境界全体で相互運用できるようにする、Web サービスアプリケーションのプロトコルを定義します。
要求時のみ参加者が状態をトランザクションコーディネーターに伝える WS-AT プロトコルモデルとは異なり、BA 内の子アクティビティーは要求を待たずに結果を直接コーディネーターに指定できます。参加者はいつでもアクティビティーを終了するかコーディネーターへ失敗を通知するかを選択できます。失敗を特定するためにトランザクションの最後まで待たずに、通知を使用してゴールを編集し、処理を継続できるため、この機能はタスクが失敗したときに便利です。

WS-BA プロセス

  1. サービスは作業をするよう要求されます。
  2. これらのサービスに作業を元に戻す機能があるのであれば、BA が後でその作業の取り消しを決定した場合に備えて BA に通知します。WS-BA に障害が発生した場合は、元に戻す undo 動作を実行するようサービスに指示することができます。

BA プロトコルは補正ベースのトランザクションモデルを利用します。ビジネスアクティビティーの参加が作業を完了すると、アクティビティーを終了することを選択できます。この選択は、その後のロールバックを許可しません。この代わりに、参加者はアクティビティーを完了し、後で別の参加者が障害をコーディネーターに通知した場合に、行った作業を補正できることをコーディネーターに伝えることができます。この場合、コーディネーターは終了していない各参加者に障害を補正するよう要求し、適切であると見なされる補正アクションを実行する機会を与えます。すべての参加者が障害なしで終了または完了した場合、コーディネーターは完了した各参加者に対してアクティビティーがクローズしたことを通知します。
詳細については、Web サービス - トランザクションドキュメント を参照してください。

12.2.14.4. トランザクションブリッジングの概要

トランザクションブリッジングは、Java EE と WS-T ドメインをリンクするプロセスを説明します。トランザクションブリッジコンポーネントである txbridge は双方向のリンクを提供し、トランザクションのいずれの型も、別の型と使用するよう設計されているビジネスロジックを含めることができます。ブリッジによって使用される技術は、介入とプロトコルマッピングの組み合わせです。
トランザクションブリッジでは、介入されるコーディネーターは既存のトランザクションに登録され、プロトコルマッピングの追加タスクを実行します。これらのトランザクション型が異なっても、その親コーディネーターに対してはネイティブトランザクション型のリソースとして見られ、その子に対してはネイティブトランザクション型のコーディネーターとして見られます。
トランザクションブリッジはパッケージに存在しますorg.jboss.jbossts.txbridgeおよびそのサブパッケージ。これは、クラスの 2 つのセットによって構成され、セットごとに各方向のブリッジング用になります。
詳細については、TransactionBridge のドキュメント を参照してください。

12.3. トランザクションの最適化

12.3.1. トランザクション最適化の概要

はじめに

JBoss EAP 6 のトランザクションサブシステムには、アプリケーションで利用できるいくつかの最適化が含まれています。

12.3.2. 1 フェーズコミット (1PC) の LRCO 最適化

トランザクションでは、2 フェーズコミットプロトコル (2PC) がより一般的に使用されますが、両フェーズに対応する必要がなかったり、対応できない場合もあります。そのような場合、1 フェーズコミット (1PC) プロトコルを使用できます。これが発生する可能性のある状況の 1 つは、XA に対応していないデータソースがトランザクションに参加する必要がある場合です。
このような状況では、Last Resource Commit Optimization (LRCO) と呼ばれる最適化が採用されます。単一フェーズのリソースは、トランザクションの準備フェーズの最後に処理され、コミットが試行されます。コミットが成功すると、トランザクションログが書き込まれ、残りのリソースは 2PC を経由します。最終リソースがコミットに失敗すると、トランザクションはロールバックされます。
このプロトコルにより、ほとんどのトランザクションは正常に完了しますが、一部のエラーによってトランザクションの結果の一貫性が失われることがあります。そのため、この方法は最終手段として使用してください。
ローカルの TX データソースが 1 つのみトランザクションで使用されると、LRCO が自動的に適用されます。

12.3.2.1. Commit Markable Resource (CMR)

概要

Commit Markable Resource (CMR) インターフェイスを介してリソースマネージャーへのアクセスを設定すると、1PC リソースマネージャーを 2PC トランザクションに確実に参加させることができます。これは、非 XA リソースを完全にリカバリー可能にする LRCO アルゴリズムの実装です。

以前は、1PC リソースを 2PC トランザクションに追加することは、LRCO 方式を介して実現されていましたが、LRCO には失敗のウィンドウがあります。LRCO メソッドを介して 1PC リソースを 2PC トランザクションに追加するには、以下の手順に従います。
  1. 2PC を準備する
  2. LRCO をコミットします。
  3. tx ログを書き込む
  4. 2PC をコミットする
手順 2 と手順 3 の間に手順がクラッシュした場合、2PC をコミットすることはできません。CMR はこの制限を取り除き、1PC を 2PC トランザクションに確実に参加させることができます。
注記
データソース設定で exception-sorter パラメーターを使用します。JBoss EAP 『管理および設定ガイド』 に記載されているデータソース設定例に従うことができます。

制約

トランザクションには、CMR リソースを 1 つだけ含めることができます。

前提条件

次の SQL が機能するテーブルを作成する必要があります。

SELECT xid,actionuid FROM _tableName_ WHERE transactionManagerID IN (String[])
DELETE FROM _tableName_ WHERE xid IN (byte[[]])
INSERT INTO _tableName_ (xid, transactionManagerID, actionuid) VALUES (byte[],String,byte[])

例12.1 SQL クエリーのいくつかの例

Sybase:
CREATE TABLE xids (xid varbinary(144), transactionManagerID varchar(64), actionuid varbinary(28))
Oracle:
CREATE TABLE xids (xid RAW(144), transactionManagerID varchar(64), actionuid RAW(28))
CREATE UNIQUE INDEX index_xid ON xids (xid)
IBM:
CREATE TABLE xids (xid VARCHAR(255) for bit data not null, transactionManagerID
varchar(64), actionuid VARCHAR(255) for bit data not null)
CREATE UNIQUE INDEX index_xid ON xids (xid)
SQL Server:
CREATE TABLE xids (xid varbinary(144), transactionManagerID varchar(64), actionuid varbinary(28))
CREATE UNIQUE INDEX index_xid ON xids (xid)
Postgres:
CREATE TABLE xids (xid bytea, transactionManagerID varchar(64), actionuid bytea)
CREATE UNIQUE INDEX index_xid ON xids (xid)

リソースマネージャーを CMR として有効にする

デフォルトでは、CMR 機能はデータソースに対して無効になっています。有効にするには、データソースの設定を作成または変更し、connectable 属性を true に設定する必要があります。サーバー xml 設定ファイルの datasources セクションの設定エントリーの例は次のとおりです。

<datasource enabled="true" jndi-name="java:jboss/datasources/ConnectableDS" pool-name="ConnectableDS" jta="true" use-java-context="true" spy="false" use-ccm="true" connectable="true"/>
注記
この機能は XA データソースには適用されません。
次のように、CLI を使用して CMR としてリソースマネージャーを有効にすることもできます。
/subsystem=datasources/data-source=ConnectableDS:add(enabled="true", jndi-name="java:jboss/datasources/ConnectableDS", jta="true", use-java-context="true", spy="false", use-ccm="true", connectable="true", connection-url="validConnectionURL", exception-sorter="org.jboss.jca.adapters.jdbc.extensions.mssql.MSSQLExceptionSorter", driver-name="h2")

新しい CMR 機能を使用するために既存のリソースを更新

新しい CMR 機能を使用するために既存のリソースを更新するだけでよい場合は、接続可能な属性を変更するだけです。

/subsystem=datasources/data-source=ConnectableDS:write-attribute(name=connectable,value=true)

CMR 対応のデータソースの特定

トランザクションサブシステムは、以下に示すように、トランザクションサブシステム設定セクションへのエントリーを通じて CMR 対応のデータソースを識別します。

<subsystem xmlns="urn:jboss:domain:transactions:3.0">
    ...
    <commit-markable-resources>
        <commit-markable-resource jndi-name="java:jboss/datasources/ConnectableDS">
            <xid-location name="xids" batch-size="100" immediate-cleanup="false"/>
        </commit-markable-resource>
        ...
    </commit-markable-resources>
</subsystem>
注記
CMR を追加した後、サーバーを再起動する必要があります。

12.3.3. 推定中止 (presumed-abort) の最適化

トランザクションをロールバックする場合、この情報をローカルで記録し、エンリストされたすべての参加者に通知します。この通知は形式的なもので、トランザクションの結果には影響しません。すべての参加者が通知されると、このトランザクションに関する情報を削除できます。
トランザクションのステータスに対する後続の要求が行われる場合、利用可能な情報はありません。このような場合、要求側はトランザクションが中断され、ロールバックされたと見なします。推定中止 presumed-abort の最適化は、トランザクションがコミットの実行を決定するまで参加者に関する情報を永続化する必要がないことを意味します。 これは、トランザクションがコミットの実行を決定する前に発生した障害はトランザクションの中止であると推定されるためです。

12.3.4. 読み取り専用の最適化

参加者は、準備するよう要求されると、トランザクション中に変更したデータがないことをコーディネーターに伝えることができます。参加者が最終的にどうなってもトランザクションに影響を与えることはないため、このような参加者にトランザクションの結果について通知する必要はありません。この読み取り専用の参加者はコミットプロトコルの第 2 フェーズから省略可能です。

12.4. トランザクションの結果

12.4.1. トランザクションの結果

可能なトランザクションの結果は次の 3 つになります。
ロールバック
トランザクションの参加者のいずれかがコミットできなかったり、トランザクションコーディネーターが参加者にコミットを指示できない場合は、トランザクションがロールバックされます。詳細は、「トランザクションのロールバックについて」 を参照してください。
Commit
トランザクションの参加者すべてがコミットできる場合、トランザクションコーディネーターはコミットの実行を指示します。詳細は、「トランザクションのコミット」 を参照してください。
ヒューリスティックな結果
トランザクションの参加者の一部がコミットし、他の参加者がロールバックした場合をヒューリスティックな結果と呼びます。ヒューリスティックな結果には、人間の介入が必要になります。詳細は、「ヒューリスティックな結果」 を参照してください。

12.4.2. トランザクションのコミット

トランザクションの参加者がコミットすると、新規の状態が永続化されます。新規の状態はトランザクションで作業を行った参加者により作成されます。トランザクションのメンバーがデータベースに記録を書き込む時などが最も一般的な例になります。
コミット後、トランザクションの情報はトランザクションコーディネーターから削除され、新たに書き込まれた状態が永続状態となります。

12.4.3. トランザクションのロールバックについて

トランザクションの参加者は、トランザクションの開始前に、状態を反映するために状態をリストアし、ロールバックを行います。ロールバック後の状態はトランザクション開始前の状態と同じになります。

12.4.4. ヒューリスティックな結果

ヒューリスティックな結果、または非アトミックな結果は、トランザクションの異常です。これは、一部のトランザクション参加者が状態をコミットし、他の参加者がロールバックした状況を指します。ヒューリスティックな結果により、状態に一貫性がなくなります。
通常、ヒューリスティックな結果は、2 フェーズコミット (2PC) プロトコルの 2 番目のフェーズで発生します。多くの場合、これは基盤のハードウェアまたは基盤のサーバーの通信サブシステムの障害によって引き起こされます。
ヒューリスティックな結果には 4 種類あります。
ヒューリスティックロールバック
一部またはすべての参加者が一方的にトランザクションをロールバックしたため、コミット操作が失敗しました。
ヒューリスティックコミット
参加者のすべてが一方的にコミットしたため、ロールバック操作に失敗します。たとえば、コーディネーターが正常にトランザクションを準備したにも関わらず、ログ更新の失敗などでコーディネーター側で障害が発生したため、ロールバックの実行を決定した場合などに発生します。暫定的に、参加者はコミットすることを決定することができます。
ヒューリスティック混合
一部の参加者がコミットし、その他の参加者はロールバックした状態です。
ヒューリスティックハザード
一部の更新の結果は不明です。既知のものについては、すべてコミットされているか、すべてロールバックされています。
ヒューリスティックな結果が起こると、システムの整合性が保たれなくなることがあり、通常、解決に人的介入が必要になります。ヒューリスティックな結果に依存するようなコードは記述しないようにしてください。

12.4.5. JBoss Transactions エラーと例外

UserTransaction クラスのメソッドによって発生する例外の詳細については、『UserTransaction API』 仕様 (http://docs.oracle.com/javaee/6/api/javax/transaction/UserTransaction.html) を参照してください。

12.5. JTA トランザクションの概要

12.5.1. Java Transactions API(JTA) について

Java Transaction API (JTA) は Java Enterprise Edition 仕様の一部です。JSR-907 で定義されています。
JTA の実装は、JBoss EAP アプリケーションサーバーのプロジェクト Narayana によってカバーされるトランザクションマネージャーを使用して行われます。トランザクションマネージャーを使用すると、アプリケーションは、単一のグローバルトランザクションを介して、データベースや JMS ブローカーなどのさまざまなリソースを割り当てることができます。グローバルトランザクションは XA トランザクションと呼ばれます。XA 機能を備えたリソースのみをトランザクションに含めることができます。
このドキュメントでは、JTA は Java Transaction API を指します。この用語は、トランザクションマネージャーがトランザクションを処理する方法を示すために使用されます。トランザクションマネージャーは JTA トランザクションモードで動作し、データはメモリーを介して共有され、トランザクションコンテキストはリモート EJB 呼び出しによって転送されます。JTS モードでは、データは CORBA (Common Object Request Broker Architecture) メッセージを送信して共有され、トランザクションコンテキストは IIOP 呼び出しによって転送されます。どちらのモードも、複数の EAP サーバーへのトランザクションの分散をサポートしています。
アノテーションは、コード内でトランザクションを作成および制御するための方法です。

12.5.2. JTA トランザクションのライフサイクル

リソースがトランザクションへの参加を要求すると、一連のイベントが開始されます。Transaction Manager は、アプリケーションサーバー内に存在するプロセスであり、トランザクションを管理します。トランザクションの参加者は、トランザクションに参加するオブジェクトです。リソースは、データソース、JMS 接続ファクトリー、または他の JCA 接続です。
  1. アプリケーションは新しいトランザクションを開始します。

    トランザクションを開始するために、アプリケーションは JNDI から (EJB の場合はアノテーションから) UserTransaction クラスのインスタンスを取得します。UserTransaction インターフェースには、トップレベルのトランザクションを開始、コミット、およびロールバックするメソッドが含まれています。新規作成されたトランザクションは、そのトランザクションを呼び出すスレッドと自動的に関連付けされます。ネストされたトランザクションは JTA ではサポートされないため、すべてのトランザクションがトップレベルのトランザクションとなります。
    UserTransaction を呼び出します。begin()アノテーションを使用すると、EJB メソッドが呼び出されたときにトランザクションが開始されます (TransactionAttribute ルールによって駆動されます)。この時点以降に使用されたリソースは、このトランザクションと関連付けられます。2 つ以上のリソースが登録された場合、トランザクションは XA トランザクションになり、コミット時に 2 フェーズコミットプロトコルに参加します。
    注記
    UserTransaction オブジェクトは、BMT トランザクションにのみ使用されます。CMT では、UserTransaction オブジェクトは許可されていません。
  2. アプリケーションが状態を変更します。

    次のステップでは、アプリケーションがその作業を実行し、その状態を変更します。
  3. アプリケーションはコミットまたはロールバックの実行を決定します。

    アプリケーションの状態の変更が完了すると、アプリケーションはコミットするか、またはロールバックするかを決定します。UserTransaction のいずれかの適切なメソッドを呼び出します。commit()または UserTransactionrollback()
  4. トランザクションマネージャーは、そのレコードからトランザクションを削除します。

    コミットまたはロールバックが完了すると、トランザクションマネージャーはレコードをクリーンアップし、トランザクションに関する情報をトランザクションログから削除します。

障害回復

障害回復は自動的に行われます。リソース、トランザクションの参加者、またはアプリケーションサーバーが使用できなくなった場合は、障害が解決され、リソースが再度使用できるようになったときにトランザクションマネージャーがリカバリーを実行します。

12.6. トランザクションサブシステムの設定

12.6.1. トランザクション設定の概要

はじめに

次の手順は、JBoss EAP 6 のトランザクションサブシステムを設定する方法を示しています。

12.6.2. トランザクションデータソースの設定

12.6.2.1. XA Datasource の設定

前提条件

管理コンソールへのログイン

  1. 新しいデータソースを追加します。

    JBoss EAP 6 に新しいデータソースを追加します。上部の XA データソース タブをクリックします。
    注記
    JBoss EAP 6 に新しいデータソースを追加する方法については、Red Hat Customer Portal の 『管理および設定ガイド』 の 『管理インターフェイスを使用した XA データソースの作成』 セクションを参照してください。
  2. 必要に応じて他のプロパティーを設定します。

    すべてのデータソースパラメーターは、「データソースのパラメーター」

結果

XA Datasource が設定され、使用する準備ができます。

12.6.2.2. 管理インターフェースによる非 XA データソースの作成

概要

ここでは、管理コンソールまたは管理 CLI のいずれかを使用して非 XA データソースを作成する手順について取り上げます。

前提条件

  • JBoss EAP 6 サーバーが稼働している必要があります。
Oracle のデータソース
Oracle データソースのバージョン 10.2 より前では、非トランザクション接続とトランザクション接続を混在させるとエラーが発生するため、<no-tx-separate-pools/> パラメーターが必要でした。このパラメーターは、特定のアプリケーションでは不要になる場合があります。
ドメインモード
ドライバーリストの重複、選択したドライバーがプロファイルで使用できない、プロファイルのサーバーが実行されていない場合にドライバーが表示されないなどの問題を防ぐため、JBoss EAP 6.4 以降では、モジュールとしてインストールされ、ドメインモードで管理コンソールを使用してデータソースを作成しているときに、プロファイルを検出できます。

手順12.1 管理 CLI または管理コンソールのいずれかを使用したデータソースの作成

    • 管理 CLI

      1. CLI ツールを起動し、サーバーに接続します。
      2. 次の管理 CLI コマンドを実行して、非 XA データソースを作成し、必要に応じて変数を設定します。
        注記
        DRIVER_NAME の値は、JDBC ドライバー JAR にある /META-INF/services/java.sql.Driver ファイルにリストされているクラスの数によって異なります。クラスが 1 つしかない場合、値は JAR の名前です。複数のクラスがある場合、値は JAR の名前 + driverClassName + "_" + majorVersion + "_"+minorVersion です。そうしないと、次のエラーがログに記録されます。
        JBAS014775:    New missing/unsatisfied dependencies
        たとえば、MySQL 5.1.31 ドライバーに必要な DRIVER_NAME 値は、mysql-connector-java-5.1.31-bin.jarcom.mysql.jdbc.Driver_5_1 です。
        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. 管理コンソールの データソース パネルに移動します

        1. コンソール上部の Configuration タブを選択します。
        2. ドメインモードの場合は、左上のドロップダウンボックスからプロファイルを選択します。
        3. コンソールの左側にある サブシステム メニューを展開し、コネクター メニューを展開します。
        4. コンソールの左側にあるメニューから データソース を選択します。
      3. 新しいデータソースを作成します。

        1. データソース パネルの上部にある 追加 をクリックします。
        2. データソースの 作成 ウィザードに新しいデータソース属性を入力し、次へ ボタンに進みます。
        3. データソースの作成 ウィザードに JDBC ドライバーの詳細を入力し、 へをクリックして続行します。
        4. データソースの作成 ウィザードで接続設定を入力します。
        5. 接続のテスト ボタンをクリックして、データソースへの接続をテストし、設定が正しいことを確認します。
        6. 完了 をクリックして終了します

結果

非 XA データソースがサーバーに追加されました。これで、standalone.xml ファイルまたは domain.xml ファイルのいずれか、および管理インターフェイスに表示されます。

12.6.2.3. JTA Transaction API を使用するようデータソースを設定

概要

ここでは、データソースで Java Transaction API (JTA) を有効にする方法を説明します。

前提条件

このタスクを続行するには、次の条件を満たしている必要があります。

  • データベースまたはその他のリソースは、JavaTransactionAPI をサポートしている必要があります。疑わしい場合は、データベースまたはその他のリソースのドキュメントを参照してください。
  • データソースを作成します。「管理インターフェースによる非 XA データソースの作成」 を参照してください。
  • JBoss EAP 6 を停止します。
  • テキストエディターで設定ファイルを直接編集できる権限を持たなければなりません。

手順12.2 Java Transaction API を使用するようデータソースを設定

  1. テキストエディターで設定ファイルを開きます。

    JBoss EAP 6 を管理対象ドメインまたはスタンドアロンサーバーで実行するかによって、設定ファイルの場所は異なります。
    • 管理対象ドメイン

      管理対象ドメインのデフォルトの設定ファイルは、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 に設定します。

    前の手順で表示されたように、<datasource> タグの内容に次を追加します 。jta= "true"
    特定のユースケース (読み取り専用データソースの定義など) がない限り、Red Hat はデフォルト値の jta=true をオーバーライドすることをお勧めしません。この設定は、データソースが Java Transaction API を尊重し、JCA 実装による接続の追跡を改善できることを示しています。
  4. 設定を保存します。

    設定ファイルを保存しテキストエディターを終了します。
  5. JBoss EAP 6 を起動します。

    JBoss EAP 6 サーバーを再起動します。

結果

JBoss EAP 6 が起動し、データソースが Java Transaction API を使用するように設定されます。

12.6.2.4. データベース接続検証設定の指定

概要

データベースのメンテナンス、ネットワークの問題、またはその他の障害により、JBoss EAP 6 からデータベースへの接続が失われることがあります。サーバー設定ファイルの <datasource> セクション内の <validation> 要素を使用して、データベース接続の検証を有効にします。以下の手順に従って、JBoss EAP 6 でデータベース接続の検証を有効にするようにデータソース設定を設定します。

手順12.3 データベース接続検証設定の指定

  1. 検証方法の選択

    以下のいずれかの検証方法を選択します。
    • <validate-on-match>true</validate-on-match>

      <validate-on-match> オプションが true に設定されている場合は、データ接続が、次の手順で指定された検証メカニズムを使用して接続プールからチェックアウトされるたびに検証されます。
      接続が有効でない場合は、警告がログに書き込まれ、プール内の次の接続が取得されます。このプロセスは、有効な接続が見つかるまで続行します。プール内の各接続を繰り返し処理しない場合は、<use-fast-fail> オプションを使用できます。有効な接続がプールにない場合は、新しい接続が作成されます。接続の作成に失敗すると、例外が要求元アプリケーションに返されます。
      この設定により、最も早いリカバリーが実現されますが、データベースへの負荷が最も大きくなります。ただし、これは、パフォーマンスを気にする必要がない場合は最も安全な方法です。
    • <background-validation>true</background-validation>

      <background-validation> オプションが true に設定されている場合、これを <background-validation-millis> 値と組み合わせて使用して、バックグラウンド検証を実行する頻度を決定します。<background-validation-millis> パラメーターのデフォルト値は 0 ミリ秒です。これは、デフォルトで無効になっていることを意味します。この値は <idle-timeout-minutes> 設定とは違う値に設定してください。
      これは、特定のシステムに最適な <background-validation-millis> 値を決定するためのバランスを取る行為です。値が小さいほどプールの検証頻度が高くなり、より迅速に無効な接続がプールから削除されます。ただし、値が小さいほど、より多くのデータベースリソースが必要になります。値が大きいほど接続検証チェックの頻度が低くなり、データベースリソースの使用量が減りますが、無効な接続が検出されない期間が長くなります。
    注記
    <validate-on-match> オプションが true に設定されている場合、<background-validation> オプションは false に設定する必要があります。その逆も同様です。<background-validation> オプションが true に設定されている場合、<validate-on-match> オプションは false に設定する必要があります。
  2. 検証メカニズムの選択

    以下のいずれかの検証メカニズムを選択します。
    • <valid-connection-checker> クラス名を指定します

      これは、使用中の特定の RDBMS に最適化されているため、推奨されるメカニズムです。JBoss EAP 6 は以下の接続チェッカーを提供します。
      • org.jboss.jca.adapters.jdbc.extensions.db2.DB2ValidConnectionChecker
      • org.jboss.jca.adapters.jdbc.extensions.mssql.MSSQLValidConnectionChecker
      • org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLReplicationValidConnectionChecker
      • org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLValidConnectionChecker
      • org.jboss.jca.adapters.jdbc.extensions.novendor.JDBC4ValidConnectionChecker
      • org.jboss.jca.adapters.jdbc.extensions.novendor.NullValidConnectionChecker
      • org.jboss.jca.adapters.jdbc.extensions.oracle.OracleValidConnectionChecker
      • org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker
      • org.jboss.jca.adapters.jdbc.extensions.sybase.SybaseValidConnectionChecker
    • <check-valid-connection-sql> に SQL を指定します

      接続を検証するために使用する SQL ステートメントを提供します。
      以下は、Oracle 用接続を検証するために SQL ステートメントをどのように指定するかの例です。
      <check-valid-connection-sql>select 1 from dual</check-valid-connection-sql>
      MySQL または PostgreSQL の場合は、以下の SQL ステートメントを指定する必要があります。
      <check-valid-connection-sql>select 1</check-valid-connection-sql>
  3. <exception-sorter> クラス名を設定します。

    例外が致命的とマークされた場合、接続はトランザクションに参加していてもすぐに閉じられます。致命的な接続例外を適切に検出およびクリーンアップするには、例外ソータークラスオプションを使用します。JBoss EAP 6 は、以下の例外ソーターを提供します。
    • org.jboss.jca.adapters.jdbc.extensions.db2.DB2ExceptionSorter
    • org.jboss.jca.adapters.jdbc.extensions.informix.InformixExceptionSorter
    • org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLExceptionSorter
    • org.jboss.jca.adapters.jdbc.extensions.novendor.NullExceptionSorter
    • org.jboss.jca.adapters.jdbc.extensions.oracle.OracleExceptionSorter
    • org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLExceptionSorter
    • org.jboss.jca.adapters.jdbc.extensions.sybase.SybaseExceptionSorter
    • org.jboss.jca.adapters.jdbc.extensions.mssql.MSSQLExceptionSorter

12.6.2.5. データソースのパラメーター

表12.1 非 XA および XA データソースに共通のデータソースパラメーター

パラメーター 説明
jndi-name データソースの一意の JNDI 名。
pool-name データソースの管理プール名。
enabled データソースが有効かどうかを指定します。
use-java-context
データソースをグローバルの JNDI にバインドするかどうかを指定します。
spy
JDBC レイヤーで spy 機能を有効にします。この機能は、データソースへの JDBC トラフィックをすべてログに記録します。ロギングカテゴリーの jboss.jdbc.spy も logging サブシステムのログレベルである DEBUG に設定する必要があることに注意してください。
use-ccm キャッシュ接続マネージャーを有効にします。
new-connection-sql 接続プールに接続が追加された時に実行する SQL ステートメント。
transaction-isolation
次のいずれかになります。
  • TRANSACTION_READ_UNCOMMITTED
  • TRANSACTION_READ_COMMITTED
  • TRANSACTION_REPEATABLE_READ
  • TRANSACTION_SERIALIZABLE
  • TRANSACTION_NONE
url-selector-strategy-class-name インターフェイスを実装するクラスorg.jboss.jca.adapters.jdbc.URLSelectorStrategy
security
セキュリティー設定である子要素が含まれています。表12.6「セキュリティーパラメーター」を参照してください。
検証
検証設定である子要素が含まれます。表12.7「検証パラメーター」を参照してください。
timeout
タイムアウト設定である子要素が含まれています。表12.8「タイムアウトパラメーター」を参照してください。
statement
ステートメント設定である子要素が含まれます。表12.9「ステートメントのパラメーター」を参照してください。

表12.2 非 XA データソースのパラメーター

パラメーター Description
jta XA 以外のデータソースの JTA 統合を有効にします。XA データソースには適用されません。
connection-url JDBC ドライバーの接続 URL。
driver-class JDBC ドライバークラスの完全修飾名。
connection-property
メソッドに渡される任意の接続プロパティーDriver.connect(url,props)。各接続プロパティーは、文字列の名前と値のペアを指定します。プロパティー名は名前に由来し、値は要素の内容に由来します。
pool
プーリング設定である子要素が含まれます。表12.4「非 XA および XA データソースに共通のプールパラメーター」を参照してください。
url-delimiter
高可用性 (HA) クラスター化されたデータベースの connection-url にある URL の区切り文字。 

表12.3 XA データソースのパラメーター

パラメーター Description
xa-datasource-property
実装クラス XADataSource に割り当てるプロパティー。名前 = で指定します。セッターメソッドが存在する場合は、次の形式でsetName、プロパティーは、次の形式で setter メソッドを呼び出すことによって設定されます。setName(value)
xa-datasource-class
実装クラスの完全修飾名javax.sql.XADataSource
driver
JDBC ドライバーを含むクラ出力ダーモジュールへの一意の参照。受け入れられる形式は driverName # majorVersion です。minorVersion
xa-pool
プーリング設定である子要素が含まれます。表12.4「非 XA および XA データソースに共通のプールパラメーター」 および 表12.5「XA プールパラメーター」 を参照してください。
recovery
リカバリ設定である子要素が含まれています。表12.10「リカバリーパラメーター」を参照してください。

表12.4 非 XA および XA データソースに共通のプールパラメーター

パラメーター Description
min-pool-size プールが保持する最小接続数
max-pool-size プールが保持可能な最大接続数
prefill 接続プールを事前に入力するかどうか。デフォルトは false です。
use-strict-min min-pool-size に達した後、アイドル接続スキャンがそれ以降の接続を閉じるためのマーキングを厳密に停止する必要があるかどうか。デフォルト値は false です。
flush-strategy
エラーが発生した場合にプールがフラッシュされるかどうか。有効な値は以下のとおりです。
  • FailingConnectionOnly
  • IdleConnections
  • EntirePool
デフォルトは FailingConnectionOnly です。
allow-multiple-users 複数のユーザーが getConnection(user, password) メソッドを使いデータソースへアクセスするかどうか、および内部プールタイプがこの動作に対応するかを指定します。

表12.5 XA プールパラメーター

パラメーター Description
is-same-rm-override javax.transaction.xa.XAResource.isSameRM(XAResource) クラスが true または false を返すかどうか。
interleaving XA 接続ファクトリーのインターリービングを有効にするかどうかを指定します。
no-tx-separate-pools
コンテキストごとに個別のサブプールを作成するかどうか。これは、JTA トランザクションの内部と外部の両方で XA 接続を使用できない Oracle データソースに必要です。
このオプションを使用すると、実際のプールがつ作成されるため、合計プールサイズが max-pool-size の倍になります。
pad-xid Xid のパディングを行うかどうかを指定します。
wrap-xa-resource
XAResource をラップするかどうかorg.jboss.tm.XAResourceWrapper実例。

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

パラメーター Description
user-name 新規接続の作成に使うユーザー名
password 新規接続の作成に使うパスワード
security-domain 認証処理を行う JAAS security-manager の名前を含みます。この名前は、JAAS ログイン設定の application-policy/name 属性に相関します。
reauth-plugin 物理接続の再認証に使う再認証プラグインを定義します。

表12.7 検証パラメーター

パラメーター Description
valid-connection-checker
インターフェイスの実装org.jboss.jca.adaptors.jdbc.ValidConnectionCheckerこれはSQLException.isValidConnection(Connection e)接続を検証するメソッド。接続が破棄されると例外が発生します。これは、パラメーター check-valid-connection-sql が存在する場合、それをオーバーライドします。
check-valid-connection-sql プール接続の妥当性を確認する SQL ステートメント。これは、管理対象接続がプールから取得されて使用されるときに呼び出される場合があります。
validate-on-match
接続ファクトリーが指定のセットに対して管理された接続に一致させようとした時に接続レベルの検証を実行するかどうかを示します。
一致検証に true を指定することは、通常、background-validation に true を指定することと組み合わせて実行されません。クライアントが使用前に接続を検証する必要がある場合は、Validate-on-match が必要です。このパラメーターはデフォルトで false です)。
background-validation
接続がバックグラウンドスレッドで検証されることを指定します。バックグラウンド検証は、validate-on-match で 使用しない場合のパフォーマンスの最適化です。validate-on-match が true の場合、background-validation を使用すると、冗長なチェックが発生する可能性があります。バックグラウンド検証では、使用するためにクライアントに不正な接続が提供される可能性があります (検証スキャンの時点からクライアントに渡される前までの間に接続が不良になる) ため、クライアントアプリケーションはこの可能性を考慮する必要があります。
background-validation-millis バックグラウンド検証を実行する期間 (ミリ秒単位)。
use-fast-fail
true の場合、接続が無効であれば最初に接続を割り当てしようとした時点で失敗します。デフォルトは false です。
stale-connection-checker
のインスタンスorg.jboss.jca.adapters.jdbc.StaleConnectionCheckerブール値を提供しますisStaleConnection(SQLException e)方法。このメソッドが true を返す場合、例外はorg.jboss.jca.adapters.jdbc.StaleConnectionException、のサブクラスですSQLException
exception-sorter
のインスタンスorg.jboss.jca.adapters.jdbc.ExceptionSorterブール値を提供しますisExceptionFatal(SQLException e)方法。このメソッドは、例外がのすべてのインスタンスにブロードキャストされるかどうかを検証しますjavax.resource.spi.ConnectionEventListenerconnectionErrorOccurred メッセージとして。

表12.8 タイムアウトパラメーター

パラメーター Description
use-try-lock 用途tryLock()それ以外のlock()。ロックが使用できない場合に即座に失敗するのではなく、タイムアウトする前に設定された秒数間ロックの取得を試みます。デフォルトは 60 秒です。例として、5 分のタイムアウトを設定するには、<use-try-lock>300</use-try-lock>
blocking-timeout-millis 接続の待機中にブロックする最大時間 (ミリ秒単位)。この時間を超えると、例外が出力されます。これは、接続の許可を待っている間のみブロックし、新しい接続の作成に時間がかかる場合でも例外を出力しません。デフォルトは 30000、つまり 30 秒です。
idle-timeout-minutes
アイドル状態の接続が閉じられるまでの最大時間 (分単位)。指定がない場合、デフォルトは 30 分になります。実際の最大時間は、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

表12.9 ステートメントのパラメーター

パラメーター Description
track-statements
接続がプールへ返され、ステートメントが準備済みステートメントキャッシュへ返された時に、閉じられていないステートメントをチェックするかどうか。false の場合、ステートメントは追跡されません。

有効な値

  • true: ステートメントと結果セットが追跡され、ステートメントが閉じられていない場合は警告が出力されます。
  • false: ステートメントと結果セットのいずれも追跡されません。
  • nowarn: ステートメントは追跡されますが、警告は出力されません。これがデフォルトです。
prepared-statement-cache-size LRU (Least Recently Used) キャッシュにある接続毎の準備済みステートメントの数。
share-prepared-statements
アプリケーションに提供されたラッパーがアプリケーションコードによって閉じられたときに、JBoss EAP が基盤の物理ステートメントを閉じたり終了せずに、キャッシュするかどうか。デフォルトは false です。

表12.10 リカバリーパラメーター

パラメーター Description
recover-credential リカバリーに使用するユーザー名とパスワードのペア、あるいはセキュリティードメイン。
recover-plugin
の実装org.jboss.jca.core.spi.recoveryRecoveryPluginクラス、リカバリに使用されます。

12.6.3. トランザクションログ

12.6.3.1. トランザクションログメッセージ

ログファイルを読み取り可能に保ちながらトランザクションステータスを追跡するには、DEBUGトランザクションロガーのログレベル。詳細なデバッグについては、TRACEログレベル。参照する「トランザクションサブシステムのログ設定」トランザクションロガーの設定についての情報。
TRACE ログレベルでログを記録するよう設定すると、トランザクションマネージャー は多くのロギング情報を生成できます。最も一般的なメッセージの一部は次のとおりです。このリストは包括的ではないため、これら以外のメッセージが表示される場合があります。

表12.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());
この結果、上記のように同じスレッドがトランザクションをロールバックすることが示されます。

12.6.3.2. トランザクションサブシステムのログ設定

概要

この手順を使用して、JBoss EAP 6 の他のログ設定とは関係なく、トランザクションに関してログに記録される情報の量を制御します。主な手順は、Web ベースの管理コンソールでこれを行う方法を示しています。その後、管理 CLI コマンドが実行されます。

手順12.4 管理コンソールを使用したトランザクションロガーの設定

  1. ログ設定領域に移動します。

    管理コンソールで、Configuration タブをクリックします。管理対象ドメインを使用する場合は、左上の プロファイル 選択ボックスから、設定するサーバープロファイルを選択します。
    コア メニューを展開し、ログ を選択します。
  2. 編集しますcom.arjuna属性。

    Log Categories タブを選択します。選択するcom.arjuna詳細 セクションで 編集 をクリックします。ここで、クラス固有のログ情報を追加できます。Thecom.arjunaクラスはすでに存在しています。ログレベルと、親ハンドラーを使用するかどうかを変更できます。
    ログレベル
    ログレベルはデフォルトで WARN です。トランザクションは大量のログ出力を生成する可能性があるため、標準のログレベルの意味はトランザクションロガーではわずかに異なります。一般に、選択したレベルよりも低い重大度のレベルでタグ付けされたメッセージは破棄されます。

    トランザクションログのレベル (詳細度の高い順)

    • TRACE
    • DEBUG
    • INFO
    • WARN
    • ERROR
    • FAILURE
    親ハンドラーの使用
    ロガーがその出力を親ロガーに送信する必要があるかどうか。デフォルトの動作は true です。
  3. 変更は直ちに反映されます。

12.6.3.3. トランザクションの参照と管理

管理 CLI では、トランザクションレコードを参照および操作する機能がサポートされます。この機能は、TransactionManager と JBoss EAP 6 の管理 API 間の相互作用によって提供されます。
トランザクションマネージャーは、待機中の各トランザクションとトランザクションに関連する参加者に関する情報を、オブジェクトストアと呼ばれる永続ストレージに格納します。管理 API は、オブジェクトストアを log-store と呼ばれるリソースとして公開します。と呼ばれる API 操作probeトランザクションログを読み取り、ログごとにノードを作成します。あなたは呼び出すことができますprobeコマンドを手動で更新する必要があるときはいつでもlog-store。トランザクションログが即座に表示され非表示になるのは、正常な挙動です。

例12.2 ログストアの更新

このコマンドは、管理対象ドメインでプロファイル default を使用するサーバーグループに対してログストアを更新します。スタンドアローンサーバーの場合は、コマンドから profile=default を削除します。
/profile=default/subsystem=transactions/log-store=log-store/:probe

例12.3 準備済みトランザクションすべての表示

準備済みトランザクションをすべて表示するには、最初に 例12.2「ログストアの更新」し、ファイルシステムの ls コマンドに類似した機能を持つ次のコマンドを実行します。
ls /profile=default/subsystem=transactions/log-store=log-store/transactions
各トランザクションが一意の識別子とともに表示されます。個々の操作は、各トランザクションに対して実行できます (トランザクションの管理 を参照してください)。

トランザクションの管理

トランザクションの属性を表示します。
JNDI 名、EIS 製品名とバージョン、またはそのステータスなどのトランザクションに関する情報を表示するには、:read-resourceCLI コマンド。
/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状態であり、回復の資格があります。詳細は、トランザクションをリカバリーします。 を参照してください。
特別な場合では、ログに対応するトランザクションレコードがないオーファンレコード (XAResourceRecords) をオブジェクトストアに作成できます。たとえば、準備済みの XA リソースが TM の記録前にクラッシュし、ドメイン管理 API はアクセス不可能である場合などです。このようなレコードにアクセスするには、管理オプション expose-all-logstrue に設定する必要があります。このオプションは管理モデルには保存されず、サーバーが再起動されると false に戻ります。
/profile=default/subsystem=transactions/log-store=log-store:write-attribute(name=expose-all-logs, value=true)
トランザクションを削除します。
各トランザクションログは、トランザクションを表すトランザクションログを削除する :delete 操作をサポートします。
/profile=default/subsystem=transactions/log-store=log-store/transactions=0\:ffff7f000001\:-b66efc2\:4f9e6f8f\:9:delete
トランザクションをリカバリーします。
各トランザクション参加者は、:recoverCLI コマンド。
/profile=default/subsystem=transactions/log-store=log-store/transactions=0\:ffff7f000001\:-b66efc2\:4f9e6f8f\:9/participants=2:recover

ヒューリスティックなトランザクションと参加者のリカバリー

  • トランザクションのステータスが HEURISTIC の場合、リカバリ操作は状態を PREPARE に変更し、リカバリをトリガーします。
  • トランザクションの参加者の 1 人がヒューリスティックである場合、リカバリ操作は再生を試みますcommit手術。成功すると、参加者はトランザクションログから削除されます。これを確認するには、:probeの操作log-store参加者がリストされていないことを確認します。最後の参加者が削除されると、トランザクションも削除されます。
リカバリーが必要なトランザクションの状態を更新します。
トランザクションをリカバリーする必要がある場合は、リカバリーを試行する前に :refresh CLI コマンドを使用して、トランザクションのリカバリーが必要であるかを確認できます。
/profile=default/subsystem=transactions/log-store=log-store/transactions=0\:ffff7f000001\:-b66efc2\:4f9e6f8f\:9/participants=2:refresh

トランザクション統計情報の表示

トランザクションマネージャーの統計が有効になっている場合は、トランザクションマネージャーとトランザクションサブシステムに関する統計を表示できます。見る「トランザクションマネージャーの設定」TransactionManager 統計を有効にする方法については。

統計は、管理コンソールまたは管理 CLI のいずれかを介して表示できます。管理コンソールでは、トランザクション統計は ランタイムステータスサブシステムトランザクション を介して利用できます。トランザクション統計は、管理対象ドメイン内のサーバーごとに利用できます。別のサーバーのステータスを表示するには、左側のメニューでサーバーの 変更 を選択し、リストからサーバーを選択します。
以下の表は、利用可能な各統計情報、その説明、および統計情報を表示する 管理 CLI コマンドを示しています。

表12.12 トランザクションサブシステム統計情報

統計 説明 CLI コマンド
合計
このサーバー上でトランザクションマネージャーにより処理されるトランザクションの合計数。
/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)
強制終了
このサーバー上でトランザクションマネージャーにより処理されるアボートされたトランザクションの数。
/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)
フライト状態のトランザクション
管理コンソールでは使用できません。開始済みであるが終了されていないトランザクション数。
/host=master/server=server-one/subsystem=transactions/:read-attribute(name=number-of-inflight-transactions,include-defaults=true)
障害の原因 - アプリケーション
障害の原因がアプリケーションであった失敗トランザクションの数。
/host=master/server=server-one/subsystem=transactions/:read-attribute(name=number-of-application-rollbacks,include-defaults=true)
障害の原因 - リソース
障害の原因がリソースであった失敗トランザクションの数。
/host=master/server=server-one/subsystem=transactions/:read-attribute(name=number-of-resource-rollbacks,include-defaults=true)
参加者 ID
参加者の ID。
/host=master/server=server-one/subsystem=transactions/log-store=log-store/transactions=0\:ffff7f000001\:-b66efc2\:4f9e6f8f\:9:read-children-names(child-type=participants)
トランザクションすべてのリスト
トランザクションの完全リスト。
/host=master/server=server-one/subsystem=transactions/log-store=log-store:read-children-names(child-type=transactions)

12.7. JTA トランザクションを使用する

12.7.1. トランザクション JTA タスクの概要

はじめに

次の手順は、アプリケーションでトランザクションを使用する必要がある場合に役に立ちます。

12.7.2. トランザクションの制御

はじめに

この手順のリストでは、JTS API または JTS API を使用するアプリケーションでトランザクションを制御するさまざまな方法を概説します。

12.7.3. トランザクションの開始

この手順では、新しいトランザクションの開始方法を示します。API は、JTA または JTS で設定されたトランザクションマネージャーを実行する場合と同じです。
  1. UserTransaction のインスタンスを取得します。

    @TransactionManagement(TransactionManagementType.BEAN) アノテーションを用いると、JNDI、インジェクション、または EJB のコンテキスト EJB が Bean 管理のトランザクションを使用する場合) を使用してインスタンスを取得できます 。
    • JNDI

      new InitialContext().lookup("java:comp/UserTransaction")
    • 注入

      @Resource UserTransaction userTransaction;
    • コンテキスト

      • ステートレス/ステートフル Bean の場合
        @Resource SessionContext ctx;
        ctx.getUserTransaction();
      • メッセージ駆動型 Bean の場合
        @Resource MessageDrivenContext ctx;
        ctx.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
            ...
        }
    }
    

JTSAPI を使用して既存のトランザクションに参加します。

EJB (CMT または BMT のいずれかと使用) の利点の 1 つは、コンテナーがトランザクション処理の内部をすべて管理することです。 そのため、ユーザーは EAP コンテナー間の XA トランザクションまたはトランザクションディストリビューションの一部であるトランザクションを処理する必要がありません。

結果:

トランザクションが開始します。トランザクションをコミットまたはロールバックするまで、データソースの使用はすべてトランザクションになります。

注記
完全な例については、を参照してください。「JTA トランザクションの例」

12.7.4. Nested Transactions

ネストされたトランザクションを用いると、アプリケーションは既存のトランザクションに埋め込まれるトランザクションを作成できます。このモデルでは、再帰的に複数のサブトランザクションをトランザクションに埋め込むことができます。親トランザクションをコミットまたはロールバックせずにサブトランザクションをコミットまたはロールバックできます。しかし、コミット操作の結果は、先祖のトランザクションがすべてコミットしたかどうかによって決まります。
実装固有の情報に https://docs.jboss.org/jbosstm/latest/guides/narayana-jts-development_guide ついては、JBossTS JTS 開発ガイドを参照してください。
ネストされたトランザクションは、JTSAPI で使用される場合にのみ使用できます。ネストされたトランザクションは、EAP アプリケーションサーバーでサポートされている機能ではありません。また、多くのデータベースベンダーがネストされたトランザクションをサポートしないため、ネストされたトランザクションをアプリケーションに追加する前にデータベースベンダーにお問い合わせください。

12.7.5. トランザクションのコミット

この手順では、Java Transaction API (JTA) を使用してトランザクションをコミットする方法を説明します。

要件

トランザクションは、コミットする前に開始する必要があります。トランザクションの開始方法については、を参照してください。「トランザクションの開始」

  1. 電話するcommit()UserTransaction のメソッド。

    あなたが電話するときcommit()UserTransaction のメソッドである場合、トランザクションマネージャーはトランザクションのコミットを試みます。
    @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. CMT (Container Managed Transaction) を使用する場合は、手動でコミットする必要はありません。

    Bean がコンテナー管理トランザクションを使用するよう設定すると、コンテナーはコードで設定したアノテーションに基づいてトランザクションライフサイクルを管理します。
    @PersistenceContext
    private EntityManager em;
    
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void updateTable(String key, String value)
      <!-- Perform some data manipulation using entityManager -->
      ...
    }
    

結果

データソースがコミットされ、トランザクションが終了します。 そうでない場合は、例外が発生します。

注記
完全な例については、を参照してください。「JTA トランザクションの例」

12.7.6. トランザクションのロールバック

この手順では、Java Transaction API (JTA) を使用してトランザクションをロールバックする方法を説明します。

要件

トランザクションは、ロールバックする前に開始する必要があります。トランザクションの開始方法については、を参照してください。「トランザクションの開始」

  1. 電話するrollback()UserTransaction のメソッド。

    あなたが電話するときrollback()UserTransaction のメソッドである場合、トランザクションマネージャーはトランザクションをロールバックし、データを以前の状態に戻そうとします。
     
    @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. CMT (Container Managed Transaction) を使用する場合は、トランザクションを手動でロールバックする必要はありません。

    Bean がコンテナー管理トランザクションを使用するよう設定すると、コンテナーはコードで設定したアノテーションに基づいてトランザクションライフサイクルを管理します。
    注記
    CMT のロールバックは RuntimeException が発生すると実行されます。setRollbackOnly メソッドを明示的に呼び出してロールバックを発生させることもできます。または、アプリケーション例外の @ApplicationException(rollback=true) を使用してロールバックできます。

結果

トランザクションは、トランザクションマネージャーによってロールバックされます。

注記
完全な例については、を参照してください。「JTA トランザクションの例」

12.7.7. トランザクションにおけるヒューリスティックな結果の処理方法

この手順では、Java Transaction API (JTA) を使用してトランザクションのヒューリスティックな結果を処理する方法を説明します。
ヒューリスティックなトランザクションの結果はよく発生するものではなく、通常は例外的な原因が存在します。ヒューリスティックという言葉は「手動」を意味し、こうした結果は通常手動で処理する必要があります。参照する「ヒューリスティックな結果」ヒューリスティックトランザクションの結果の詳細については。

手順12.5 トランザクションにおけるヒューリスティックな結果の処理方法

  1. 原因を確認する

    トランザクションのヒューリスティックな結果の最大の原因は、リソースマネージャーがコミットまたはロールバックの実行を約束したにも関わらず、約束を守らなかったことにあります。原因としては、サードパーティーコンポーネント、サードパーティーコンポーネントと JBoss EAP 6 間の統合レイヤー、または JBoss EAP 6 自体の問題が考えられます。
    ヒューリスティックなエラーの最も一般的な 2 つの原因は、環境での一時的な障害と、リソースマネージャー対応時のコーディングエラーです。
  2. 環境の一時的な障害を修正する

    通常、環境内で一時的な障害が発生した場合は、ヒューリスティックなエラーを発見する前に気づくはずです。ネットワークの停止、ハードウェア障害、データベース障害、電源異常などが考えられます。
    テスト環境でヒューリスティックな結果を経験した場合、ストレステスト中に、環境の弱点に関する情報が提供されます。
    ヒューリスティックトランザクションは回復されません
    JBoss EAP 6 は、障害時に非ヒューリスティック状態であったトランザクションを自動的に回復しますが、ヒューリスティックトランザクションの回復は試みません。
  3. リソースマネージャーベンダーに連絡する

    環境に明白な障害が発生していない場合や、ヒューリスティックな結果を簡単に再現できる場合は、おそらくコーディングエラーです。サードパーティーベンダーに連絡して、解決策が利用可能かどうかを確認してください。問題が JBoss EAP 6 自体のトランザクションマネージャーにあると思われる場合は、Red Hat グローバルサポートサービスに連絡してください。
  4. テスト環境で、ログを削除して JBoss EAP 6 を再起動します。

    テスト環境である場合や、データの整合性を気にしない場合は、トランザクションログを削除して JBoss EAP 6 を再起動すると、ヒューリスティックな結果はなくなります。トランザクションログは、デフォルト では、スタンドアロンサーバーの場合は EAP_HOME/Standalone/data/tx-object-store/に、管理対象ドメインの場合は EAP_HOME/domain/servers/SERVER_NAME/data/tx-object-store にあります。管理対象ドメインの場合、SERVER_NAME は、サーバーグループに参加している個々のサーバー名を示します。
    注記
    トラザクションログの場所は、使用中のオブジェクトストアや、object-store-relative-to および object-store-path パラメーターに設定された値にも左右されます。ファイルシステムログ (標準のシャドウログや HornetQ ログなど) の場合、デフォルトの方向の場所が使用されますが、JDBC オブジェクトストアを使用する場合、トランザクションログはデータベースに保存されます。
  5. 手作業で結果を解決する

    トランザクションの結果を手動で解決するプロセスは、障害の正確な状況に大きく依存します。通常、次の手順を実行して、状況に適用する必要があります。
    1. 関係しているリソースマネージャーを特定します。
    2. トランザクションマネージャーとリソースマネージャーの状態を調べます。
    3. 関係するコンポーネントの 1 つまたは複数で、ログの消去とデータの照合を手動で強制します。
    これらの手順を実行する方法の詳細は、このドキュメントの範囲外です。

12.7.8. トランザクションタイムアウト

12.7.8.1. トランザクションタイムアウト

原子性を確保し、トランザクションを ACID 標準に準拠させるために、トランザクションの一部が長期間実行される場合があります。トランザクション参加者は、コミットするときにデータソースの一部をロックする必要があります。トランザクションマネージャーは、コミットするかロールバックするかをすべて指示する前に、各トランザクション参加者からの応答を待つ必要があります。ハードウェアあるいはネットワークの障害のため、リソースが永久にロックされることがあります。
トランザクションのタイムアウトをトランザクションと関連付け、ライフサイクルを制御することができます。タイムアウトのしきい値がトランザクションのコミットあるいはロールバック前に渡された場合、タイムアウトにより、自動的にトランザクションがロールバックされます。
トランザクションサブシステム全体に対しデフォルトのタイムアウト値を設定できます。または、デフォルトのタイムアウト値を無効にし、トランザクションごとにタイムアウトを指定できます。

12.7.8.2. トランザクションマネージャーの設定

トランザクションマネージャー (TM) は、Web ベースの管理コンソールまたはコマンドライン管理 CLI を使用して設定できます。与えられたコマンドまたはオプションごとに、JBoss EAP 6 を管理対象ドメインとして実行していると想定されます。スタンドアロンサーバーを使用している場合、または別のプロファイルを変更する場合default、次の方法で手順とコマンドを変更する必要がある場合があります。

例のコマンドに関する注意点

  • 管理コンソールの場合、defaultプロファイルは、コンソールに最初にログインしたときに選択されるプロファイルです。別のプロファイルでトランザクションマネージャーの設定を変更する必要がある場合は、代わりにプロファイルを選択してくださいdefault、各命令で。
    同様に、プロファイルをdefaultサンプル CLI コマンドのプロファイル。
  • スタンドアロンサーバーを使用する場合、プロファイルは 1 つだけ存在します。特定のプロファイルを選択するための指示は無視してください。CLI コマンドで、/profile=defaultサンプルコマンドの一部。
注記
TM オプションを管理コンソールまたは管理 CLI に表示するには、transactionsサブシステムを有効にする必要があります。これはデフォルトで有効になっており、他の多くのサブシステムが正しく機能するために必要であるため、無効になる可能性はほとんどありません。

管理コンソールを使用した TM の設定

Web ベースの管理コンソールを使用して TM を設定するには、画面上部の 設定 タブを選択します。管理対象ドメインを使用している場合は、左上の プロファイル 選択ボックスから正しいプロファイルを選択してください。コンテナー メニューを展開し、トランザクション を選択します。

ほとんどのオプションは、トランザクションマネージャーの設定ページに表示されます。リカバリ オプションはデフォルトで非表示になっています。リカバリ タブをクリックして、リカバリオプションを確認します。編集 をクリックして、オプションを編集します。変更は直ちに反映されます。
ヘルプが必要ですか? をクリックします。インラインヘルプテキストを表示するためのラベル。

管理 CLI を使用した TM の設定

管理 CLI では、一連のコマンドを使用して TM を設定できます。コマンドはすべてで始まります/profile=default/subsystem=transactions/プロファイル付きの管理対象ドメインの場合default、また/subsystem=transactionsスタンドアロンサーバーの場合。

重要
トランザクションサブシステムがトランザクションログのストレージタイプとして hornetq ジャーナルを使用するように設定されている場合、JBoss EAP の 2 つのインスタンスがジャーナルの保存に同じディレクトリーを使用することは許可されていません。アプリケーションサーバーインスタンスは同じ場所を共有することはできず、アプリケーションサーバーインスタンスごとに一意な場所を設定する必要があります。

表12.13 TM 設定オプション

オプション 説明 CLI コマンド
統計の有効化 (Enable Statistics)
トランザクション統計を有効にするかどうか。これらの統計は、ランタイム タブの サブシステムメトリック セクションの管理コンソールで表示できます。
/profile=default/subsystem=transactions/:write-attribute(name=enable-statistics,value=true)
Enable TSM Status
アウトオブプロセスのリカバリーに使用される TSM (トランザクションステータスマネージャー) サービスを有効にするかどうか。アウトオブプロセスリカバリマネージャーを実行して、別のプロセスから ActionStatusService に接続することはサポートされていません (通常はメモリー内で接続されます)。
この設定オプションはサポートされていません。
デフォルトのタイムアウト (Default Timeout)
デフォルトのトランザクションタイムアウトです。デフォルトでは 300 秒に設定されています。トランザクションごとにプログラムで上書きできます。
/profile=default/subsystem=transactions/:write-attribute(name=default-timeout,value=300)
オブジェクトストアパス (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 EAP 6 のデータディレクトリーで、jboss.server.data.dir プロパティーの値です。デフォルトは、管理対象ドメインの場合は EAP_HOME/domain/data/、スタンドアロンサーバーインスタンスの場合は EAP_HOME/standalone/data/ です。オブジェクトストアの値object-store-pathTM 属性は、このパスに関連しています。
/profile=default/subsystem=transactions/:write-attribute(name=object-store-relative-to,value=jboss.server.data.dir)
ソケットバインディング
ソケットベースのメカニズムが使用されている場合に、トランザクションマネージャーが回復およびトランザクション ID の生成に使用するソケットバインディングの名前を指定します。参照するprocess-id-socket-max-ports一意の識別子の生成の詳細については。ソケットバインディングは、管理コンソールの サーバー タブでサーバーグループごとに指定されます。
/profile=default/subsystem=transactions/:write-attribute(name=socket-binding,value=txn-recovery-environment)
Status Socket Binding
トランザクションステータスマネージャーに使用するソケットバインディングを指定します。
この設定オプションはサポートされていません。
リカバリーリスナー (Recovery Listener)
トランザクションリカバリーのプロセスがネットワークソケットをリッスンするかどうかを指定します。デフォルトは false です。
/profile=default/subsystem=transactions/:write-attribute(name=recovery-listener,value=false)
次のオプションは高度な使用を目的としており、管理 CLI を使用してのみ変更できます。デフォルト設定から変更する場合は注意が必要です。詳細は Red Hat グローバルサポートサービスまでお問い合わせください。

表12.14 高度な TM 設定オプション

オプション 説明 CLI コマンド
jts
Java Transaction Service (JTS) トランザクションを使用するかどうかを指定します。デフォルト値は false で、JTA トランザクションのみを使用します。
/profile=default/subsystem=transactions/:write-attribute(name=jts,value=false)
node-identifier
トランザクションマネージャーのノード識別子。このオプションは以下の場合に必要になります。
  • JTS 対 JTS の通信
  • 2 つのトランザクションマネージャーが共有のリソースマネージャーにアクセスする場合
  • 2 つのトランザクションマネージャーが共有のオブジェクトマネージャーにアクセスする場合
リカバリー中にデータの整合性を維持する必要があるため、各トランザクションマネージャーの node-identifier は一意である必要があります。複数のノードが同じリソースマネージャーと対話したり、トランザクションオブジェクトストアを共有したりするため、node-identifier は JTA に対しても一意である必要があります。
/profile=default/subsystem=transactions/:write-attribute(name=node-identifier,value=1)
process-id-socket-max-ports
トランザクションマネージャーは、各トランザクションログに対し一意の識別子を作成します。一意の識別子を生成するメカニズムは 2 種類あります。 ソケットベースのメカニズムとプロセスのプロセス識別子をベースにしたメカニズムです。
ソケットベースの識別子の場合、あるソケットを開くと、そのポート番号が識別子に使用されます。ポートがすでに使用されている場合は、空きのポートが見つかるまで次のポートがプローブされます。Theprocess-id-socket-max-portsTM が失敗する前に試行するソケットの最大数を表します。デフォルト値は 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 を参照してください。有効にするprocess-id-socket-binding、設定process-id-uuidfalse
/profile=default/subsystem=transactions/:write-attribute(name=process-id-uuid,value=true)
process-id-socket-binding
トランザクションマネージャーがソケットベースのプロセス id を使用する必要がある場合に使用するソケットバインディング設定の名前。になりますundefinedもしもprocess-id-uuidtrue;それ以外の場合は設定する必要があります。
/profile=default/subsystem=transactions/:write-attribute(name=process-id-socket-binding,value=true)
use-hornetq-store
トランザクションログには、ファイルベースのストレージではなく、HornetQ のジャーナルストレージメカニズムを使用します。デフォルトでは無効になっていますが、I/O パフォーマンスが改善されます。別々のトランザクションマネージャーで JTS トランザクションを使用することは推奨されません。このオプションの変更を反映するには shutdown コマンドを使用してサーバーを再起動する必要があります。
/profile=default/subsystem=transactions/:write-attribute(name=use-hornetq-store,value=false)

12.7.9. JTA トランザクションのエラー処理

12.7.9.1. トランザクションエラーの処理

トランザクションエラーは、多くの場合、タイミングに依存するため、解決するのが困難です。以下に、一部の一般的なエラーと、これらのエラーのトラブルシューティングに関するヒントを示します。
トランザクションエラーの処理
これらのガイドラインはヒューリスティックエラーに適用されません。ヒューリスティックエラーが発生した場合は、を参照してください「トランザクションにおけるヒューリスティックな結果の処理方法」支援が必要な場合は、Red Hat グローバルサポートサービスにお問い合わせください。

トランザクションがタイムアウトになったが、ビジネスロジックスレッドが認識しませんでした。

多くの場合、このようなエラーは、Hibernate がレイジーロードのデータベース接続を取得できない場合に発生します。頻繁に発生する場合は、タイムアウト値を増加できます。「トランザクションマネージャーの設定」 を参照してください。

引き続き問題が解決されない場合、外部環境を調整して実行をさらに速くしたり、さらなる効率化のためにコードを再構築できることがあります。タイムアウトの問題が解消されない場合は、Red Hat グローバルサポートサービスにお問い合わせください。

トランザクションはすでにスレッドで実行されているか、NotSupportedException例外

The NotSupportedException例外は通常、JTA トランザクションをネストしようとしたことを示しますが、これはサポートされていません。トランザクションをネストしようとしないときは、多くの場合、スレッドプールタスクで別のトランザクションが開始されますが、トランザクションを中断または終了せずにタスクが終了します。

アプリケーションは通常、 UserTransaction、これを自動的に処理します。その場合、フレームワークに問題がある可能性があります。
コードが使用する場合 TransactionManagerまた Transactionメソッドを直接使用する場合は、トランザクションをコミットまたはロールバックするときに次の動作に注意してください。コードで TransactionManager メソッドを使用してトランザクションを制御する場合は、トランザクションをコミットまたはロールバックすると、現在のスレッドからトランザクションの関連付けが解除されます。ただし、コードで Transaction メソッドを使用する場合は、トランザクションが実行されているスレッドと関連付けられていないことがあり、スレッドプールに返す前に手動でスレッドからトランザクションの関連付けを解除する必要があります。

2 番目のローカルリソースを登録することはできません。

このエラーは、2 番目の非 XA リソースをトランザクションに登録しようとした場合に、発生します。1 つのトランザクションで複数のリソースが必要な場合、それらのリソースは XA である必要があります。

12.8. ORB 設定

12.8.1. Common Object Request Broker Architecture (CORBA)

Common Object Request Broker Architecture (CORBA) は、アプリケーションとサービスが複数の互換性がない言語で記述され、異なるプラットフォームでホストされる場合でも、アプリケーションとサービスが連携することを可能にする標準です。CORBA のリクエストは Object Request Broker (ORB)) というサーバーサイドコンポーネントが仲介します。JBoss EAP 6 は、JacORB コンポーネントを使用して ORB インスタンスを提供します。
ORB は Java Transaction Service (JTS) トランザクションに対して内部的に使用され、ユーザー独自のアプリケーションが使用することもできます。

12.8.2. JTS トランザクション用 ORB の設定

JBoss EAP 6 のデフォルトのインストールでは、ORB は無効になっています。コマンドライン管理 CLI を使用して ORB を有効にできます。

手順12.6 管理コンソールを使用した ORB の設定

  1. プロファイル設定の表示

    管理コンソールの上部から 設定 を選択します。管理対象ドメインを使用する場合は、左上の選択ボックスから フル または フルヘクタールの プロファイルを選択します。
  2. イニシャライザ の設定を変更する

    サブシステム メニューを展開します。コンテナー メニューを展開し、JacORB を選択します。
    メイン画面に表示されるフォームで、初期化 タブを選択し、編集 ボタンをクリックします。
    Security の値を on に 設定して、セキュリティーインターセプターを有効にします。
    JTS の ORB を有効にするには、Transaction Interceptors の値をデフォルトの 仕様 ではなく、on に設定します。
    ヘルプが必要ですか? を参照してください。これらの値の詳細な説明については、フォームのリンクを参照してください。値の編集が終了したら、保存 をクリックします。
  3. 高度な ORB 設定

    高度な設定オプションについては、フォームの他のセクションを参照してください。各セクションには ヘルプが必要ですか? パラメーターに関する詳細情報へのリンク。

管理 CLI を使用して ORB を設定

管理 CLI を使用して ORB を設定できます。次のコマンドは、管理コンソールの初期化子を上記の手順と同じ値に設定します。これは、JTS と使用するために行う ORB の最低限の設定です。

これらのコマンドは、完全な プロファイルを使用して管理対象ドメイン用に設定されます。必要な場合は設定に応じてプロファイルを変更してください。スタンドアロンサーバーを使用する場合は、コマンドの /profile=full 部分を省略してください。

例12.4 セキュリティーインターセプターの有効化

/profile=full/subsystem=jacorb/:write-attribute(name=security,value=on)

例12.5 JacORB サブシステムでのトラザクションの有効化

/profile=full/subsystem=jacorb/:write-attribute(name=transactions,value=on)

例12.6 トランザクションサブシステムでの JTS の有効化

/profile=full/subsystem=transactions:write-attribute(name=jts,value=true)
注記
JTS をアクティベートするにはリロードでは不十分なため、サーバーを再起動する必要があります。

12.9. トランザクションに関するリファレンス

12.9.1. JBoss Transactions エラーと例外

UserTransaction クラスのメソッドによって発生する例外の詳細については、『UserTransaction API』 仕様 (http://docs.oracle.com/javaee/6/api/javax/transaction/UserTransaction.html) を参照してください。

12.9.2. JTA トランザクションの例

この例では、 JTA トランザクションを開始、コミット、およびロールバックする方法を示します。使用している環境に合わせて接続およびデータソースパラメーターを調整し、データベースで 2 つのテストテーブルをセットアップする必要があります。

例12.7 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.");
                
                txn.begin();
                
                stmtx = conn.createStatement(); // will be a tx-statement

                // First, we try to roll back changes
                
                System.out.println("\nAdding entries to table 1.");
                
                stmtx.executeUpdate("INSERT INTO test_table (a, b) VALUES (1,2)");
                
                ResultSet res1 = null;
                
                System.out.println("\nInspecting table 1.");
                
                res1 = stmtx.executeQuery("SELECT * FROM test_table");
                
                while (res1.next()) {
                    System.out.println("Column 1: "+res1.getInt(1));
                    System.out.println("Column 2: "+res1.getInt(2));
                }
                System.out.println("\nAdding entries to table 2.");

                stmtx.executeUpdate("INSERT INTO test_table2 (a, b) VALUES (3,4)");
                res1 = stmtx.executeQuery("SELECT * FROM test_table2");

                System.out.println("\nInspecting table 2.");

                while (res1.next()) {
                    System.out.println("Column 1: "+res1.getInt(1));
                    System.out.println("Column 2: "+res1.getInt(2));
                }

                System.out.print("\nNow attempting to rollback changes.");

                txn.rollback();

                // Next, we try to commit changes
                txn.begin();
                stmtx = conn.createStatement();
                ResultSet res2 = null;

                System.out.println("\nNow checking state of table 1.");

                res2 = stmtx.executeQuery("SELECT * FROM test_table");

                while (res2.next()) {
                    System.out.println("Column 1: "+res2.getInt(1));
                    System.out.println("Column 2: "+res2.getInt(2));
                }

                System.out.println("\nNow checking state of table 2.");

                stmtx = conn.createStatement();

                res2 = stmtx.executeQuery("SELECT * FROM test_table2");

                while (res2.next()) {
                    System.out.println("Column 1: "+res2.getInt(1));
                    System.out.println("Column 2: "+res2.getInt(2));
                }

                txn.commit();
            }
            catch (Exception ex) {
                ex.printStackTrace();
                System.exit(0);
            }
        }
        catch (Exception sysEx) {
            sysEx.printStackTrace();
            System.exit(0);
        }
    }      
}

12.9.3. JBossTransactionsJTA の API ドキュメント

JBoss EAP 6 のトランザクションサブシステムの API ドキュメントは、次の場所で入手できます。
Red Hat JBoss Developer Studio を使用してアプリケーションを開発する場合は、API ドキュメンテーションは Help メニューに含まれています。

12.9.4. XA リカバリープロセスの制限

XA リカバリーには以下の制限があります。
トランザクションログが正常にコミットされたトランザクションから消去されないことがあります。
XAResource のコミットメソッドが正常に完了し、トランザクションをコミットした後、コーディネーターがログをアップデートできるようになる前に JBoss EAP サーバーがクラッシュした場合、サーバーの再起動時に以下の警告メッセージが表示されることがあります。
ARJUNA016037: Could not find new XAResource to use for recovering non-serializable XAResource XAResourceRecord
これは、リカバリー時に JBoss トランザクションマネージャー はログのトランザクション参加者を確認し、コミットを再試行しようとするからです。最終的に、JBoss Transaction Manager はリソースがコミットされていると想定し、コミットを再試行しなくなります。このような場合、トランザクションはコミットされデータの損失はないため、警告を無視しても問題ありません。
警告を防ぐには、com.arjuna.ats.jta.xaAssumeRecoveryCompleteプロパティー値を true に設定します。このプロパティーは、登録された XAResourceRecovery インスタンスから新しい XAResource インスタンスが見つからないとチェックされます。true に設定すると、リカバリーで、以前のコミットの試行が成功したと見なされ、これ以上リカバリーを試行しなくてもインスタンスをログから削除できます。このプロパティーはグローバルであり、適切に使用しないと XAResource インスタンスがコミットされていない状態のままになるため、注意して使用する必要があります。
XAResource.prepare() の最後にサーバーがクラッシュすると、JTS トランザクションに対するロールバックは呼び出されません。
XAResource の完了後に JBoss EAP サーバーがクラッシュした場合prepare()メソッド呼び出しでは、参加しているすべての XAResources が準備済み状態でロックされ、サーバーの再起動時にその状態が維持されます。トランザクションがタイムアウトするか、DBA が手動でリソースをロールバックしてトランザクションをクリアするまで、トランザクションはロールバックされず、リソースはロックされたままになります。ログ。
周期リカバリーはコミットされたトランザクションで発生する可能性があります。
サーバーに過剰な負荷がかかっている場合、サーバーログには以下の警告メッセージとそれに続くスタックトレースが含まれる場合があります。
ARJUNA016027: Local XARecoveryModule.xaRecovery got XA exception XAException.XAER_NOTA: javax.transaction.xa.XAException
負荷が大きい場合、トランザクションにかかる処理時間が周期的リカバリープロセスのアクティビティーと重なることがあります。周期的リカバリープロセスは進行中のトランザクションを検出し、ロールバックを開始しようとしますが、トランザクションは完了するまで続行されます。周期的リカバリーはロールバックの開始に失敗し、ロールバックの失敗がサーバーログに記録されます。この問題の根本的な原因は、今後のリリースで修正される予定ですが、現時点では回避方法を使用できます。
を設定して、リカバリプロセスの 2 つのフェーズ間の間隔を増やします。com.arjuna.ats.jta.orphanSafetyIntervalプロパティーをデフォルト値の 10000 ミリ秒よりも高い値に設定します。40000 ミリ秒の値が推奨されます。これで問題が解決するわけではなく、発生する可能性が低くなり、警告メッセージがログに表示されることに注意してください。

第13章 Hibernate

13.1. Hibernate Core

Hibernate Core は、オブジェクト/リレーショナルマッピングライブラリーです。これは、Java クラスをデータベーステーブルにマッピングするためのフレームワークを提供し、アプリケーションがデータベースとの直接の対話を回避できるようにします。
詳細は、「Hibernate EntityManager」 および 「JPA について」 を参照してください。

13.2. Java 永続 API (JPA)

13.2.1. JPA について

Java Persistence API(JPA) は、Java プロジェクトで永続性を使用するための標準です。Java EE 6 アプリケーションは Java Persistence 2.0 仕様を使用し http://www.jcp.org/en/jsr/detail?id=317 ます。
Hibernate EntityManager は、仕様で定義されたプログラミングインターフェイスとライフサイクルルールを実装します。JBoss EAP 6 には完全な Java 永続ソリューションが提供されます。
JBoss EAP 6 は Java Persistence 2.0 仕様に 100% 準拠しています。また、Hibernate によってこの仕様に追加機能が提供されます。
JPA および JBoss EAP 6 の使用を開始するには、bean-validationgreeter、および kitchensink クイックスタートを参照してください。「クイックスタートにアクセスする」

13.2.2. Hibernate EntityManager

Hibernate EntityManager は、JPA2.0 仕様 で定義されたプログラミングインターフェイスとライフサイクルルールを実装します。JBoss EAP 6 には完全な Java 永続ソリューションが提供されます。
Java Persistence または Hibernate の詳細については、以下を参照してください。「JPA について」「Hibernate Core」

13.2.3. はじめに

13.2.3.1. Red Hat JBossDeveloperStudio で JPA プロジェクトを作成します

概要

この例では、Red Hat JBossDeveloperStudio で JPA プロジェクトを作成するために必要な手順について説明します。

手順13.1 Red Hat JBossDeveloperStudio で JPA プロジェクトを作成します

  1. Red Hat JBoss Developer Studio ウィンドウ +FileNewProject をクリックします。リストで JPA を見つけ、展開し、JPA Project を選択します。以下のダイアログが表示されます。
  2. プロジェクト名を入力します。
  3. Target runtime を選択します。使用可能なターゲットランタイムがない場合は、次の手順に従って新しいサーバーとランタイムを定義します。「Define New Server を使用して JBossEAP サーバーを追加します」
  4. JPA version (JPA バージョン)2.1 が選択されていることを確認します。
  5. Configuration (設定)Basic JPA Configuration (基本的な JPA 設定) を選択します。
  6. Finish をクリックします。
  7. 要求されたら、このタイプのプロジェクトを JPA パースペクティブウインドウに関連付けるかどうかを選択します。

13.2.3.2. Red Hat JBossDeveloperStudio で永続性設定ファイルを作成します

概要

このトピックでは、Red Hat JBossDeveloperStudio を使用して Java プロジェクトで persistence.xml ファイルを作成するプロセスについて説明します。

手順13.2 新しい永続性設定ファイルを作成および設定します。

  1. Red Hat JBossDeveloperStudio で EJB3.x プロジェクトを開きます。
  2. Project Explorer (プロジェクトエクスプローラー) パネルでプロジェクトルートディレクトリーを右クリックします。
  3. 新規その他... を選択します。
  4. XML フォルダーから XML File (XML ファイル) を選択し、Next (次へ) をクリックします。
  5. 親ディレクトリーとして ejbModule/META-INF フォルダーを選択します。
  6. ファイルの名前を persistence.xml と指定し、Next (次へ) をクリックします。
  7. Create XML file from an XML schema file (XML スキーマファイルから XML ファイルを作成) を選択し、Next (次へ) をクリックします。
  8. Select XML Catalog entry (XML カタログエントリーを選択) リストから http://java.sun.com/xml/ns/persistence/persistence_2.0.xsd を選択し、Next (次へ) をクリックします。
  9. Finish (完了) をクリックしてファイルを作成します。
結果:
persistence.xmlMETA-INF/ フォルダーに作成され、設定可能な状態になります。サンプルファイルはここにあります: 「例: 永続設定ファイル」

13.2.3.3. 例: 永続設定ファイル

例13.1 persistence.xml

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
   version="2.0">
   <persistence-unit name="example" transaction-type="JTA">
      <provider>org.hibernate.ejb.HibernatePersistence</provider>
      <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
      <mapping-file>ormap.xml</mapping-file>
      <jar-file>TestApp.jar</jar-file>
      <class>org.test.Test</class>
      <shared-cache-mode>NONE</shared-cache-mode>
      <validation-mode>CALLBACK</validation-mode>
      <properties>
         <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
         <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
      </properties>
   </persistence-unit>
</persistence>

13.2.3.4. Red Hat JBossDeveloperStudio で Hibernate 設定ファイルを作成します

概要

このトピックでは、Red Hat JBossDeveloperStudio を使用して Java プロジェクトで hibernate.cfg.xml ファイルを作成するプロセスについて説明します。

手順13.3 新しい Hibernate 設定ファイルを作成する

  1. Red Hat JBossDeveloperStudio で Java プロジェクトを開きます。
  2. Project Explorer (プロジェクトエクスプローラー) パネルでプロジェクトルートディレクトリーを右クリックします。
  3. 新規その他... を選択します。
  4. Hibernate フォルダーから Hibernate 設定ファイル を選択し、次へ をクリックします。
  5. src/ ディレクトリーを選択し、次へ をクリックします。
  6. 以下を設定します。
    • セッションファクトリー名
    • データベース方言
    • Driver class
    • 接続 URL
    • ユーザ名
    • パスワード
  7. Finish (完了) をクリックしてファイルを作成します。
結果:
hibernate.cfg.xmlsrc/ フォルダーに作成されました。サンプルファイルはここにあります:「Hibernate 設定ファイルの例」

13.2.3.5. Hibernate 設定ファイルの例

例13.2 hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

    <session-factory>

        <!-- Datasource Name -->
        <property name="connection.datasource">ExampleDS</property>

        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.H2Dialect</property>

        <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">thread</property>

        <!-- Disable the second-level cache  -->
        <property name="cache.region.factory_class">org.hibernate.cache.NoCacheProvider</property>

        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>

        <!-- Update the database schema on startup -->
        <property name="hbm2ddl.auto">update</property>

        <mapping resource="org/hibernate/tutorial/domain/Event.hbm.xml"/>

    </session-factory>

</hibernate-configuration>

13.2.4. 設定

13.2.4.1. Hibernate 設定プロパティー

表13.1 HibernateJava プロパティー

プロパティー名 Description
hibernate.dialect
Hibernate org.hibernate. metaect.Dialect のクラス名。Hibernate が特定の関係データベース向けに最適化された SQL を生成できるようにします。
ほとんどの場合、Hibernate は JDBC ドライバーによって返される JDBC metadata に基づいて適切な org.hibernate. metaect.Dialect 実装を選択できます。
hibernate.show_sql
ブール値。すべての SQL ステートメントをコンソールに書き込みます。これは、ログカテゴリー org.hibernate.SQLdebug に設定する代わりになります。
hibernate.format_sql
ブール値。pretty print で、ログとコンソールに SQL を出力します。
hibernate.default_schema
生成された SQL で指定のスキーマ/テーブルスペースを持つ修飾されていないテーブル名。
hibernate.default_catalog
生成された SQL で指定のカタログと修飾されていないテーブル名を修飾します。
hibernate.session_factory_name
その org.hibernate.SessionFactory 作成後、JNDI でこの名前に自動的にバインドされます。たとえば、jndi/composite/name です。
hibernate.max_fetch_depth
単独の関連 (one-to-one、many-to-one) の外部結合フェッチツリーの最大深さを設定します。0 は、デフォルトの外部ジョインフェッチを無効にします。推奨の値は 0 から 3 の間です。
hibernate.default_batch_fetch_size
関連付けの Hibernate バッチフェッチのデフォルトサイズを設定します。推奨される値は 4816です。
hibernate.default_entity_mode
この SessionFactoryか ら開かれたすべてのセッションに対するエンティティー表現のデフォルトモードを設定します。値には dynamic-mapdom4jpojo が含まれます。
hibernate.order_updates
ブール値。Hibernate は、更新する製品のプライマリーキーの値で SQL 更新の順序を強制します。これにより、非常に同時になるシステムでは、トランザクションのデッドロックが少なくなります。
hibernate.generate_statistics
ブール値。有効にすると、Hibernate はパフォーマンスチューニングに役立つ統計を収集します。
hibernate.use_identifier_rollback
ブール値。有効な場合、オブジェクトが削除されると、生成された識別子プロパティーがデフォルト値にリセットされます。
hibernate.use_sql_comments
ブール値。有効にすると、Hibernate はデバッグを容易にするため、SQL 内でコメントを生成します。デフォルト値は false です。
hibernate.id.new_generator_mappings
ブール値。@GeneratedValue を使用する場合、このプロパティーには関係があります。これは、新しい IdentifierGenerator 実装が javax.persistence.GenerationType.AUTOjavax.persistence.GenerationType.TABLE および javax.persistence.GenerationType.SEQUENCE に使用されるかどうかを示します。デフォルト値は true です。
hibernate.ejb.naming_strategy
を選択しますorg.hibernate.cfg.NamingStrategyHibernateEntityManager を使用する場合の実装。このクラスは非推奨であり、このプロパティーは下位互換性のためにのみ提供されています。このプロパティーは、と一緒に使用しないでくださいhibernate.ejb.naming_strategy_delegator
アプリケーションが EntityManager を使用しない場合は、以下の手順に従って NamingStrategy: Hibernate Reference Documentation - Implementing a Naming Strategy を設定します。
hibernate.ejb.naming_strategy_delegator
指定しますorg.hibernate.cfg.naming.NamingStrategyDelegatorHibernateEntityManager を使用する場合のデータベースオブジェクトとスキーマ要素の実装。このプロパティーには、次の可能な値があります。
  • org.hibernate.cfg.naming.LegacyNamingStrategyDelegator: これはデフォルト値です。このクラスは非推奨であり、下位互換性のためにのみ提供されています。
  • org.hibernate.cfg.naming.ImprovedNamingStrategyDelegator: これが推奨値です。JPA 仕様に準拠したデフォルトのテーブル名と列名を生成します。これにより、エンティティー名と外部キークラス名の両方を指定できます。このクラスは、Java アノテーションまたは JPAXML 記述子を使用してマップされたエンティティーにのみ影響します。hbm.xml を使用してマップされたエンティティーは影響を受けませんが、
  • 必要に応じて、実装するカスタムクラスを設定できます org.hibernate.cfg.naming.ImprovedNamingStrategyDelegator
注記
このプロパティーは、と一緒に使用しないでくださいhibernate.ejb.naming_strategy。の一時的な代替品ですorg.hibernate.cfg.NamingStrategyその制限に対処するため。両方を置き換える Hibernate5.0 のより包括的なソリューションが計画されていますorg.hibernate.cfg.NamingStrategyorg.hibernate.cfg.naming.NamingStrategyDelegator
アプリケーションが EntityManager を使用しない場合は、以下の手順に従って NamingStrategy: Hibernate Reference Documentation - Implementing a Naming Strategy を設定します。
重要
hibernate.id.new_generator_mappings の場合、新しいアプリケーションでは、デフォルト値である true のままにしてください。Hibernate 3.3.x を使用した既存のアプリケーションは、シーケンスオブジェクトまたはテーブルベースのジェネレーターを使用し、後方互換性を維持するために false に変更する必要がある場合があります。

13.2.4.2. Hibernate JDBC および接続プロパティー

表13.2 プロパティー

プロパティー名 Description
hibernate.jdbc.fetch_size
JDBC フェッチサイズを決定するゼロ以外の値 ( Statement.setFetchSize()を呼び出します)。
hibernate.jdbc.batch_size
ゼロ以外の値は、Hibernate による JDBC2 バッチ更新の使用を有効にします。推奨される値は 5 から 30 の間です。
hibernate.jdbc.batch_versioned_data
ブール値。JDBC ドライバーが executeBatch() から正しい行数を返す場合は、このプロパティーを true に設定します。その後、Hibernate は、自動的にバージョン付けされたデータにバッチ処理を使用します。デフォルト値は false です。
hibernate.jdbc.factory_class
カスタムを選択 org.hibernate.jdbc.Batcher.ほとんどのアプリケーションでは、この設定プロパティーは必要ありません。
hibernate.jdbc.use_scrollable_resultset
ブール値。Hibernate による JDBC2 のスクロール可能な結果セットの使用を有効にします。このプロパティーは、ユーザー指定の JDBC 接続を使用する場合にのみ必要です。Hibernate は接続メタデータを使用します。
hibernate.jdbc.use_streams_for_binary
ブール値。これはシステムレベルのプロパティーです。binary または serializable を JDBC に書き込む際や、JDBC から読み込む際には、ストリームを使用します。
hibernate.jdbc.use_get_generated_keys
ブール値。JDBC3 の PreparedStatement.getGeneratedKeys() を使用して、挿入後にネイティブに生成されたキーを取得できます。JDBC3+ ドライバーおよび JRE1.4+ が必要です。JDBC ドライバーに、Hibernate 識別子ジェネレーターの問題がある場合は false に設定します。デフォルトでは、接続メタデータを使用してドライバー機能を判断しようとします。
hibernate.connection.provider_class
カスタムのクラス名 org.hibernate.connection.ConnectionProvider これは、Hibernate への JDBC 接続を提供します。
hibernate.connection.isolation
JDBC トランザクション分離レベルを設定します。Check java.sql.Connection ただし、ほとんどのデータベースはすべての分離レベルをサポートしているわけではなく、一部のデータベースは追加の非標準分離を定義していることに注意してください。標準値は 1、2、4、8 です。
hibernate.connection.autocommit
ブール値。このプロパティーの使用は推奨されません。JDBC プールされた接続の自動コミットを有効にします。
hibernate.connection.release_mode
Hibernate が JDBC 接続を解放するタイミングを指定します。デフォルトでは、明示的にセッションが閉じられるか、または切断されるまで JDBC 接続が保持されます。デフォルト値 auto は JTA および CMT トランザクションストラテジーに after_statement を選択し、JDBC トランザクションストラテジーに after_transaction を選択します。
使用可能な値は auto (デフォルト)、on_closeafter_transactionafter_statement です。
この設定は、SessionFactory.openSession によって返される Session にのみ影響します。SessionFactory.getCurrentSession から取得した Session の場合、使用するために設定された CurrentSessionContext 実装はその Session の接続リリースモードを制御します。
hibernate.connection.<propertyName>
JDBC プロパティーを <propertyName> から DriverManager.getConnection() に渡します。
hibernate.jndi.<propertyName>
<propertyName> プロパティーを InitialContextFactory に渡します。

13.2.4.3. Hibernate キャッシュプロパティー

表13.3 プロパティー

プロパティー名 説明
hibernate.cache.region.factory_class
カスタム CacheProvider のクラス名。
hibernate.cache.use_minimal_puts
ブール値。書き込みを最小限に抑えるために 2 次レベルのキャッシュ操作を最適化し、読み取りの頻度を上げます。この設定はクラスター化されたキャッシュで最も便利なもので、Hibernate3 ではクラスター化されたキャッシュ実装に対してデフォルトで有効になっています。
hibernate.cache.use_query_cache
ブール値。クエリーキャッシュを有効にします。個別のクエリーをキャッシュ可能に設定する必要があります。
hibernate.cache.use_second_level_cache
ブール値。<cache> マッピングを指定するクラスに対してデフォルトで有効になっている 2 次レベルのキャッシュを完全に無効にするために使用されます。
hibernate.cache.query_cache_factory
カスタム QueryCache インターフェイスのクラス名。デフォルト値はビルトインの StandardQueryCache です。
hibernate.cache.region_prefix
2 次キャッシュリージョン名に使用するプレフィックス。
hibernate.cache.use_structured_entries
ブール値。Hibernate が、よりヒューマンリーダブルな形式で、2 次レベルのキャッシュにデータを格納するように強制します。
hibernate.cache.default_cache_concurrency_strategy
@Cacheable または @Cache のいずれかが使用された場合に使用するデフォルトの org.hibernate.annotations.CacheConcurrencyStrategy の名前を付与するために使用される設定。@Cache(strategy="..") は、このデフォルトを上書きするのに使用されます。

13.2.4.4. Hibernate トランザクションプロパティー

表13.4 プロパティー

プロパティー名 説明
hibernate.transaction.factory_class
Hibernate Transaction API で使用するための TransactionFactory のクラス名。デフォルトは JDBCTransactionFactory
jta.UserTransaction
アプリケーションサーバーから JTA UserTransaction を取得するために JTATransactionFactory によって使用される JNDI 名。
hibernate.transaction.manager_lookup_class
TransactionManagerLookup のクラス名。これは、JVM レベルキャッシングが有効な場合や、JTA 環境で hilo ジェネレーターを使用する場合に必要です。
hibernate.transaction.flush_before_completion
ブール値。有効にすると、トランザクションの完了前のフェーズでセッションが自動的にフラッシュされます。組み込みおよび自動セッションコンテキスト管理が推奨されます。
hibernate.transaction.auto_close_session
ブール値。有効にすると、トランザクションの完了フェーズ中にセッションが自動的に閉じられます。組み込みおよび自動セッションコンテキスト管理が推奨されます。

13.2.4.5. その他の Hibernate プロパティー

表13.5 プロパティー

プロパティー名 説明
hibernate.current_session_context_class
「現在」の Session セッションのスコープ設定にカスタムストラテジーを指定します。値には、jtathreadmanagedcustom.Class が含まれます。
hibernate.query.factory_class
HQL パーサー実装 ( org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory または org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory) を選択します。
hibernate.query.substitutions
Hibernate クエリーのトークンから SQL トークン (トークンは関数またはリテラル名) にマップするために使用されます。たとえば、hqlLiteral=SQL_LITERAL, hqlFunction=SQLFUNC
hibernate.hbm2ddl.auto
SessionFactory の作成時にスキーマをデータベースに自動的に検証またはエクスポートします。Create-dropSessionFactory を明示的に閉じると、データベーススキーマがドロップされます。プロパティー値のオプションはvalidateupdatecreatecreate-drop です。
hibernate.hbm2ddl.import_files
SessionFactory の作成時に実行される SQL Mission ステートメントが含まれるオプションのファイルのコンマ区切りの名前です。これは、テストまたはデモンストレーションに役立ちます。たとえば、AIA ステートメントを追加すると、デプロイ時にデータベースが最小限のデータセットでデータが投入されます。値の例は /humans.sql,/dogs.sql です。
ファイルの順序は重要です。以下のファイルのステートメントの前に特定ファイルのステートメントが実行されるためです。これらのステートメントは、たとえば hibernate.hbm2ddl.autocreate or create-drop に設定されている場合にのみ実行されます。
hibernate.hbm2ddl.import_files_sql_extractor
カスタムのクラス名 ImportSqlCommandExtractor.デフォルトは、ビルトインの SingleLineSqlCommandExtractor です。これは、各インポートファイルから単一の SQL ステートメントを抽出する専用パーサーを実装する際に便利です。Hibernate は、複数の行 (各ステートメントの最後で必須のセミコロン) に散在する命令/コメントおよび引用符で囲まれた文字列をサポートする、複数の MultipleLinesSqlCommandExtractor も提供します。
hibernate.bytecode.use_reflection_optimizer
ブール値。これはシステムレベルのプロパティーで、hibernate.cfg.xml ファイルで設定することはできません。ランタイムの反映の代わりにバイトコード操作の使用を有効にします。リフレクションはトラブルシューティング時に役に立つことがあります。Hibernate には常に cglib または javassist のいずれかが必要です。
hibernate.bytecode.provider
javassist または cglib は、バイト操作エンジンとして使用できます。デフォルトは javassist です。プロパティー値は javassist または cglib のいずれかです

13.2.4.6. HibernateSQL ダイアレクト

重要
hibernate.dialect プロパティーは、アプリケーションデータベースの適切な org.hibernate. denialect.Dialect サブクラスに設定する必要があります。ダイアレクトが指定されている場合、Hibernate は他のプロパティーの一部に対して適切なデフォルトを使用します。これは、手動で指定する必要がないことを意味します。

表13.6 SQL Dialects (hibernate.dialect)

RDBMS ダイアレクト
DB2 org.hibernate.dialect.DB2Dialect
DB2 AS/400 org.hibernate.dialect.DB2400Dialect
DB2 OS390 org.hibernate.dialect.DB2390Dialect
Adobird org.hibernate.dialect.FirebirdDialect
FrontBase org.hibernate.dialect.FrontbaseDialect
H2 Database org.hibernate.dialect.H2Dialect
HypersonicSQL org.hibernate.dialect.HSQLDialect
Informix org.hibernate.dialect.InformixDialect
Ingres org.hibernate.dialect.IngresDialect
Interbase org.hibernate.dialect.InterbaseDialect
Mckoi SQL org.hibernate.dialect.MckoiDialect
Microsoft SQL Server 2000 org.hibernate.dialect.SQLServerDialect
Microsoft SQL Server 2005 org.hibernate.dialect.SQLServer2005Dialect
Microsoft SQL Server 2008 org.hibernate.dialect.SQLServer2008Dialect
Microsoft SQL Server 2012 org.hibernate.dialect.SQLServer2008Dialect
MySQL5 org.hibernate.dialect.MySQL5Dialect
InnoDB を使用した MySQL5 org.hibernate.dialect.MySQL5InnoDBDialect
MyISAM を使用した MySQL org.hibernate.dialect.MySQLMyISAMDialect
Oracle (すべてのバージョン) org.hibernate.dialect.OracleDialect
Oracle 9i org.hibernate.dialect.Oracle9iDialect
Oracle 10g org.hibernate.dialect.Oracle10gDialect
Oracle 11g org.hibernate.dialect.Oracle10gDialect
Pointbase org.hibernate.dialect.PointbaseDialect
PostgreSQL org.hibernate.dialect.PostgreSQLDialect
PostgreSQL 9.2 org.hibernate.dialect.PostgreSQL82Dialect
Postgres Plus Advanced Server org.hibernate.dialect.PostgresPlusDialect
Progress org.hibernate.dialect.ProgressDialect
SAP DB org.hibernate.dialect.SAPDBDialect
Sybase org.hibernate.dialect.SybaseASE15Dialect
Sybase 15.7 org.hibernate.dialect.SybaseASE157Dialect
Sybase Anywhere org.hibernate.dialect.SybaseAnywhereDialect

13.2.5. 2 次キャッシュ

13.2.5.1. 2 次キャッシュ

2 次キャッシュとは、アプリケーションセッション外部で永続化された情報を保持するローカルデータストアのことです。このキャッシュは永続プロバイダーにより管理され、アプリケーションとデータを分離することでランタイムを改善します。
JBoss EAP 6 では、以下の目的のためにキャッシュがサポートされます。
  • Web セッションのクラスタリング
  • ステートフルセッション Bean のクラスタリング
  • SSO クラスタリング
  • Hibernate 2 次キャッシュ
各キャッシュコンテナーは repl および dist キャッシュを定義します。これらのキャッシュは、ユーザーアプリケーションで直接使用しないでください。

13.2.5.2. Hibernate の 2 次キャッシュの設定

このトピックでは、Infinispan が Hibernate の第 2 レベルのキャッシュとして機能できるようにするための設定要件について説明します。

手順13.4 hibernate.cfg.xml ファイルを作成および編集します

  1. hibernate.cfg.xml ファイルを作成します

    デプロイメントのクラスパスに hibernate.cfg.xml を作成します。詳細については、を参照してください。「Red Hat JBossDeveloperStudio で Hibernate 設定ファイルを作成します」
  2. これらの XML 行をアプリケーションの hibernate.cfg.xml ファイルに追加します。XML は <session-factory> タグ内にある必要があります。
    <property name="hibernate.cache.use_second_level_cache">true</property>
    <property name="hibernate.cache.use_query_cache">true</property>
  3. hibernate.cfg.xml ファイルの <session-factory> セクションに次のいずれかを追加します。
    • Infinispan CacheManager が JNDI にバインドされている場合:

      <property name="hibernate.cache.region.factory_class">
          org.hibernate.cache.infinispan.JndiInfinispanRegionFactory
      </property>
      <property name="hibernate.cache.infinispan.cachemanager">
          java:CacheManager
      </property>
    • Infinispan CacheManager がスタンドアロンの場合:

      <property name="hibernate.cache.region.factory_class">
          org.hibernate.cache.infinispan.InfinispanRegionFactory
      </property>

結果

Infinispan は、Hibernate の第 2 レベルのキャッシュとして設定されます。

13.3. Hibernate アノテーション

13.3.1. Hibernate アノテーション

表13.7 Hibernate で定義されたアノテーション

Annotation Description
AccessType プロパティーアクセスタイプ。
すべて 複数のエンティティータイプを参照するトール関連付けを定義します。一致したエンティティータイプのマッチングは、メタデータの識別子コラムを使用して行われます。このようなマッピングはマージのみにする必要があります。
AnyMetaDef @Any および @ManyToAny メタデータを定義します。
AnyMedaDefs @Any および @ManyToAny のメタデータセットを定義します。エンティティーレベルまたはパッケージレベルで定義できます。
BatchSize SQL 読み込みのバッチサイズ。
Cache キャッシュストラテジーをルートエンティティーまたはコレクションに追加します。
Cascade 関連付けにカスケードストラテジーを適用します。
Check クラス、プロパティー、またはコレクションレベルで定義できる任意の SQL チェック制約。
Columns 列のアレイをサポートします。コンポーネントのユーザータイプマッピングに便利です。
ColumnTransformer 値をコラムから読み取り、コラムに書き込むために使用するカスタムの SQL 式。クエリーとともにオブジェクトの直接読み込み/保存に使用します。書き込み式には、値に対して 1 つの '?' プレースホルダーが必ず含まれている必要があります。
ColumnTransformers @ColumnTransformer の複数のアノテーション複数のコラムがこの動作を使用している場合に便利です。
DiscriminatorFormula ルートエンティティーに配置されるイデンティターの式。
DiscriminatorOptions Hibernate 固有の識別子プロパティーを表示するオプションのアノテーションです。
エンティティー Hibernate 機能でエンティティーを拡張します。
Fetch 指定の関連付けに使用されるフェッチストラテジーを定義します。
FetchProfile フェッチストラテジープロファイルを定義します。
FetchProfiles @FetchProfile の複数形のアノテーション。
フィルター フィルターをエンティティーまたはコレクションのターゲットエンティティーに追加します。
FilterDef フィルター定義。
FilterDefs フィルター定義の配列。
FilterJoinTable フィルターを結合テーブルコレクションに追加します。
FilterJoinTables 複数の @FilterJoinTable をコレクションに追加します。
フィルター 複数の @Filter を追加します。
Formula 大半の場所で、@Column の代わりとして使用するために使用されます。式は有効な SQL フラグメントである必要があります。
Generated このアノテーション付きプロパティーはデータベースによって生成されます。
GenericGenerator タイプ解除された方法で、あらゆる Hibernate generator を記述するジェネレーターアノテーション。
GenericGenerators 汎用ジェネレーター定義のアレイ。
Immutable
エンティティーまたはコレクションにイミュータブルとしてマークを付けます。アノテーションがないということは、要素が変更されたことを意味します。
イミュータブルなエンティティーはアプリケーションによって更新されない可能性があります。イミュータブルなエンティティーの更新は無視されますが、例外は発生しません。
@Immutable をコレクションに配置すると、コレクションがイミュータブルな状態になり、コレクションへの追加および削除は許可されません。この場合、HibernateException が発生します。
Index データベースインデックスを定義します。
JoinFormula 大半の場所で、@JoinColumn の代わりとして使用するために使用されます。式は有効な SQL フラグメントである必要があります。
LazyCollection コレクションのレイジーステータスを定義します。
LazyToOne ToOne 関連づけのレイジーステータスを定義します (OneToOne または ManyToOne)。
Loader Hibernate デフォルトの FIND メソッドを上書きします。
ManyToAny 異なるエンティティータイプを参照する ToMany 関連付けを定義します。一致したエンティティータイプのマッチングは、メタデータの識別子コラムを使用して行われます。このようなマッピングはマージのみにする必要があります。
MapKeyType 永続マップのキーのタイプを定義します。
MetaValue 特定のエンティティータイプに関連付けられた識別子の値を表します。
NamedNativeQueries NamedNativeQueries を拡張して、Hibernate NamedNativeQuery オブジェクトを保持します。
NamedNativeQuery Hibernate 機能を使用した NamedNativeQuery の拡張
NamedQueries NamedQuery を拡張して Hibernate NamedQuery オブジェクトを保持します。
NamedQuery Hibernate 機能を使用して NamedQuery を拡張します。
NaturalId プロパティーがエンティティーの純粋な ID の一部であることを指定します。
NotFound 要素が関連上に見つからない場合に行うアクション。
OnDelete コレクション、アレイ、および結合されたサブクラスの削除で使用するストラテジー。現在、セカンダリーテーブルの OnDelete はサポートされていません。
OptimisticLock アノテーションが付けられたプロパティーの変更によってエンティティーバージョンの増分がトリガーされるかどうか。アノテーションが存在しない場合は、プロパティーが楽観的ロックストラテジーに関与します (デフォルト)。
OptimisticLocking エンティティーに適用される楽観的ロックのスタイルを定義するために使用されます。階層では、ルートエンティティーでのみ有効です。
OrderBy SQL 順序付け (HQL の順序ではなく) を使用してコレクションを順序付けます。
ParamDef パラメーター定義。
パラメーター キー/値のパターン。
Parent プロパティーを所有者 (通常は所有するエンティティー) へのポインターとして参照します。
Persister カスタム永続機能を指定します。
Polymorphism ポリモーフィズム Hibernate のタイプを定義するために使用されます。
Proxy 特定のクラスのレイジーおよびプロキシー設定。
RowId Hibernate の ROWID マッピング機能のサポート。
Sort コレクションのソート (Java レベルのソート)。
Source Version および timestamp version プロパティーと併せてのオプションのアノテーションです。アノテーションの値で、タイムスタンプの生成先が決まります。
SQLDelete Hibernate デフォルトの DELETE メソッドを上書きします。
SQLDeleteAll Hibernate のデフォルト DELETE ALL メソッドを上書きします。
SQLInsert Hibernate のデフォルト INSERT INTO メソッドを上書きします。
SQLUpdate Hibernate デフォルトの UPDATE メソッドを上書きします。
Subselect イミュータブルで読み取り専用のエンティティーを指定の SQL サブ選択式にマッピングします。
Synchronization 自動フラッシュが正しく実行され、派生エンティティーに対するクエリーが古いデータを返さないようにします。大半は Subselect とともに使用されます。
テーブル プライマリーまたはセカンダリーのテーブルに情報を補完します。
Tables Table の複数形のアノテーション。
Target 明示的なターゲットを定義し、反映および汎用的な解決を回避します。
Tuplizer エンティティーまたはコンポーネントの tuplizer を定義します。
Tuplizers エンティティーまたはコンポーネントの一連の tuplizer を定義します。
タイプ Hibernate タイプ。
TypeDef Hibernate タイプ定義。
TypeDefs Hibernate タイプ定義の配列。
Where コレクションのエンティティーまたはターゲットエンティティーに追加する要素。レシピは SQL で記述されます。
WhereJoinTable コレクションジョインテーブルに追加する部分。レシピは SQL で記述されます。
備考
アノテーション「Entity」は非推奨となり、今後のリリースで削除される予定です。

13.4. Hibernate Query 言語

13.4.1. Hibernate Query 言語について

Hibernate クエリー言語 (HQL) と Java Persistence クエリー言語 (JPQL) はどちらも、SQL と性質が似ているオブジェクトモデルに焦点を当てたクエリー言語です。HQL は JPQL のスーパーセットです。HQL クエリーは常に有効な JPQL クエリーではありませんが、JPQL クエリーは常に有効な HQL クエリーです。
HQL および JPQL は両方とも、クエリー操作を実行するのに型が安全ではありません。条件クエリーは、クエリーにタイプセーフなアプローチを提供します。

13.4.2. HQL ステートメント

HQL では、SELECTUPDATEDELETE、および INSERT ステートメントを使用できます。HQL INSERT ステートメントには、JPQL に相当するものはありません。
重要
UPDATE または DELETE ステートメントがいつ実行されるかについては注意が必要です。

表13.8 HQL ステートメント

ステートメント Description
SELECT
HQL における SELECT ステートメントの BNF は以下のとおりです。
select_statement :: =
        [select_clause]
        from_clause
        [where_clause]
        [groupby_clause]
        [having_clause]
        [orderby_clause]
最も単純な HQLSELECT ステートメントの形式は次のとおりです。
from com.acme.Cat
UDPATE HQL の UPDATE ステートメントの BNF は JPQL と同じです。
DELETE HQL の DELETE ステートメントの BNF は JPQL と同じです。

13.4.3. INSERT ステートメントについて

HQL は、INSERT ステートメントを定義する機能を追加します。これと同等の JPQL はありません。HQLINSERT ステートメントの BNF は次のとおりです。
insert_statement ::= insert_clause select_statement

insert_clause ::= INSERT INTO entity_name (attribute_list)

attribute_list ::= state_field[, state_field ]*
tribute_list は、SQL INSERT ステートメントの column specification に似ています。マッピングされた継承に関連するエンティティーでは、名前付きエンティティーに直接定義された属性のみが attribute_list で使用できます。スーパークラスプロパティーは許可されておらず、サブクラスプロパティーは意味を成しません。つまり、INSERT ステートメントは本質的にはポリモーフィックではありません。
警告
select_statement には、有効な HQL 選択クエリーを使用できます。この場合、戻り値のタイプは挿入で想定されるタイプと一致する必要があります。現在、これは、チェックによるデータベースへの再参照を許可するのではなく、クエリーのコンパイル時に確認されます。これにより、equal ではなく equivalent である Hibernate タイプ間で問題が発生する可能性があります。たとえば、これは org.hibernate.type.DateType としてマップされた属性と org.hibernate.type.TimestampType として定義された属性の間でミスマッチの問題を引き起こす可能性があります。
id 属性には、insert ステートメントに 2 つのオプションを付与します。attribute_listid プロパティーを明示的に指定することができます。この場合、その値は、対応する select 式から取得されるか、または生成された値が使用される場合は attribute_list から省略されます。後者のオプションは、データベースで (in the database) で動作する ID ジェネレーターを使用している場合にのみ利用できます。メモリー内 (in memory) タイプジェネレーターでこのオプションを使用しようとすると、解析中に例外が発生します。
ロック属性の場合、insert ステートメントでは、以下のいずれかのオプションが再度提供されます。attribute_list に属性を指定できます。この場合、その値は対応する select 式から取得されます。あるいは、attribute_list から除外できます。その場合は、対応する select 式によって定義される seed value が使用されます。 org.hibernate.type.VersionType 使用されている。

例13.3 INSERT クエリーステートメント

String hqlInsert = "insert into DelinquentAccount (id, name) select c.id, c.name from Customer c where ...";
int createdEntities = s.createQuery( hqlInsert ).executeUpdate();

13.4.4. FROM 句について

FROM 句は、残りのクエリーで使用できるオブジェクトモデルタイプのスコープを定義します。また、残りのクエリーで使用できるすべての識別変数も定義します。

13.4.5. WITH 句について

HQL は、結合条件を修飾するために WITH 句を定義します。これは HQL に固有です。JPQL はこの機能を定義していません。

例13.4 条項 付き

select distinct c
from Customer c
    left join c.orders o
        with o.value > 5000.00
重要な違いは、生成された SQL では with 句 の条件が生成された SQL の on 句 一部になり、HQL/JPQL 条件が生成された SQL。この特定の例の違いは、おそらくそれほど重要ではありません。より複雑なクエリーでは 、with 句 が必要になる場合があります。
明示的な結合は、関連付けまたはコンポーネント/埋め込み属性を参照する場合があります。コンポーネント/埋め込み属性の場合、結合は論理的であり、物理 (SQL) 結合とは相関しません。

13.4.6. 一括更新、挿入、削除について

Hibernate では、Data Manipulation Language (DML) を使用して、Hibernate Query Language を介して、マップされたデータベースにへのデータの直接挿入、更新、および削除を一括で行うことができます。
警告
複数のオブジェクトまたは関係マッピングに違反し、オブジェクト状態に影響を与える可能性があります。オブジェクト状態は、基盤のデータベースで実行される操作によって、メモリー内オブジェクトの状態が影響を受けることはありません。インメモリーデータは、インメモリーデータが使用される場合は注意して使用する必要があります。
UPDATE および DELETE ステートメントの疑似構文は次のとおりです。(更新 | 削除)FROM?EntityName (WHERE where_conditions)?.
注記
FROM キーワードおよび WHERE Clause はオプションです。
UPDATE ステートメントまたは DELETE ステートメントの実行結果は、実際に影響を受ける (更新または削除される) 行数です。

例13.5 一括更新ステートメント

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

String hqlUpdate = "update Company set name = :newName where name = :oldName";
int updatedEntities = s.createQuery( hqlUpdate )
        .setString( "newName", newName )
        .setString( "oldName", oldName )
        .executeUpdate();
tx.commit();
session.close();

例13.6 一括削除ステートメント

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

String hqlDelete = "delete Company where name = :oldName";
int deletedEntities = s.createQuery( hqlDelete )
        .setString( "oldName", oldName )
        .executeUpdate();
tx.commit();
session.close();
Query.executeUpdate() メソッドによって返される int 値は、オペレーションの影響を受けた、データベース内のエンティティーの数を示します。
内部では、複数の SQL ステートメントを使用して、DML Update または Delete 更新リクエストまたは削除リクエストに応答して操作を実行する場合があります。これは、テーブルと、更新または削除が必要な結合テーブルの間に存在する関係が原因です。
たとえば、(上記の例のように) delete ステートメントを実行すると、oldName という名前の企業用の Company テーブルだけでなく、結合したテーブルに対しても削除が実行されます。したがって、社員テーブルと双方向の多対多リレーションシップを持つ会社テーブルでは、前述の例の実行が成功すると、対応する結合テーブル Company_Employee から 行が失われることになります。
上記の int deletedEntries 値には、この操作によって影響を受けるすべての行の数 (結合テーブルの行を含む) が含まれます。
INSERT ステートメントの疑似構文は次のとおりです 。INSERTINTOEntityNameproperties_listselect_statement
注記
INSERTINTO..のみSELECT...フォームがサポートされています。INSERTINTO ではありません..。VALUES...フォーム。

例13.7 一括挿入ステートメント

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

String hqlInsert = "insert into Account (id, name) select c.id, c.name from Customer c where ...";
int createdEntities = s.createQuery( hqlInsert )
        .executeUpdate();
tx.commit();
session.close();
SELECT ステートメントを使用して id 属性の値を指定しない場合、基礎となるデータベースが自動生成キーをサポートする限り、識別子が生成されます。この一括挿入操作の戻り値は、データベースで実際に作成されたエントリー数です。

13.4.7. コレクションメンバーの参照について

コレクション値の関連付けへの参照は、実際にはそのコレクションのを参照します。

例13.8 コレクションの参照

select c
from Customer c
    join c.orders o
    join o.lineItems l
    join l.product p
where o.status = 'pending'
  and p.status = 'backorder'

// alternate syntax
select c
from Customer c,
    in(c.orders) o,
    in(o.lineItems) l
    join l.product p
where o.status = 'pending'
  and p.status = 'backorder'
この例では、識別変数 o は実際には、Customer#orders 関連付けの要素タイプであるオブジェクトモデルタイプ Order を参照します。
この例では、IN 構文を使用してコレクションの関連付けジョインを指定する代替構文も示しています。両方の形式は同じです。アプリケーションの選択を選択するのは、単に好みの問題です。

13.4.8. 修飾パス式について

これまでは、コレクション値関連づけは、コレクションのを実際に参照していると言及されました。コレクションのタイプによっては、明示的な修飾式のセットも利用できます。

表13.9 修飾パス式

Description
VALUE
コレクション値を参照します。修飾子を指定しないのと同じです。意図を明示的に表示するのに役立ちます。いずれかのタイプのコレクションと値の参照に有効です。
INDEX
HQL ルールによると、これはマップとリストの両方で有効です。 javax.persistence.OrderColumn マップキーまたはリスト位置 (別名 OrderColumn 値) を参照するための注釈。ただし、JPQL はこれを List ケースで使用するために予約し、MAP ケースに KEY を追加します。JPA プロバイダーの移植性に関心のあるアプリケーションは、この区別を認識する必要があります。
KEY
Maps にのみ有効です。マップのキーを参照します。キー自体がエンティティーである場合は、さらに移動することができます。
ENTRY
Maps にのみ有効です。マップの論理を参照します java.util.Map.Entry タプル (キーと値の組み合わせ)。ENTRY はターミナルパスとしてのみ有効で、選択でのみ有効です。

例13.9 適格なコレクションの参照

// Product.images is a Map<String,String> : key = a name, value = file path

// select all the image file paths (the map value) for Product#123
select i
from Product p
    join p.images i
where p.id = 123

// same as above
select value(i)
from Product p
    join p.images i
where p.id = 123

// select all the image names (the map key) for Product#123
select key(i)
from Product p
    join p.images i
where p.id = 123

// select all the image names and file paths (the 'Map.Entry') for Product#123
select entry(i)
from Product p
    join p.images i
where p.id = 123

// total the value of the initial line items for all orders for a customer
select sum( li.amount )
from Customer c
        join c.orders o
        join o.lineItems li
where c.id = 123
  and index(li) = 1

13.4.9. スカラー関数について

HQL は、使用中の基盤のデータベースに関係なく利用可能な標準の関数を定義します。HQL は、ダイアレクトおよびアプリケーションで定義される追加の機能を理解することもできます。

13.4.10. HQL の標準化機能

以下の関数は、使用中の基盤のデータベースに関係なく HQL で利用できます。

表13.10 HQL の標準化機能

関数 説明
BIT_LENGTH
バイナリーデータの長さを返します。
CAST
SQL キャストを実行します。cast ターゲットは、使用する Hibernate マッピングタイプに名前を付ける必要があります。
EXTRACT
Datetime 値に対して SQL の抽出を実行します。抽出により、日時の一部 (たとえば、年) が抽出されます。以下の省略形式を参照してください。
SECOND
2 つ目を抽出するための省略された抽出形式。
MINUTE
分を抽出するための省略された抽出形式。
HOUR
時を抽出するための省略された抽出形式。
DAY
日を抽出するための省略された抽出形式。
MONTH
月を抽出するための省略された抽出形式。
YEAR
年を抽出するための省略された抽出形式。
STR
値を文字データとしてキャストするための省略形式。
アプリケーション開発者は、独自の機能のセットも提供します。これは、通常は、カスタムの SQL 関数、または SQL のスニペットのエイリアスを表します。このような関数宣言は、addSqlFunctionorg.hibernate.cfg.Configuration のメソッド

13.4.11. 連結操作

HQL は、連結 (CONCAT) 関数のサポートのほかに連結演算子を定義します。これは JPQL では定義されないため、移植可能なアプリケーションは使用しないでください。連結演算子は、SQL 連結演算子 (||) から取得されます。

例13.10 連結操作例

select 'Mr. ' || c.name.first || ' ' || c.name.last
from Customer c
where c.gender = Gender.MALE

13.4.12. 動的インスタンス化について

select 句でのみ有効な特定の式タイプがあります。Hibernate では、これを「動的なインスタンス化 (dynamic instantiation)」と呼びます。JPQL はこの機能の一部に対応しており、これを「コンストラクト式 (constructor expression)」と呼びます。

例13.11 動的インスタンス化の例 - コンストラクター

select new Family( mother, mate, offspr )
from DomesticCat as mother
    join mother.mate as mate
    left join mother.kittens as offspr
ここでは Object[] を扱うのではなく、クエリーの結果として返される型安全な java オブジェクトの値をラップします。クラス参照は完全修飾する必要があり、一致するコンストラクターが必要です。
ここのクラスはマッピングする必要はありません。エンティティーを表す場合、生成されるインスタンスは NEW 状態 (管理されない) で返されます。
これは JPQL もサポートします。HQL は、追加の「動的なインスタンス化」機能に対応しています。まず、クエリーはスカラー結果に対して Object[] ではなく List を返すように指定できます。

例13.12 動的インスタンス化の例 - リスト

select new list(mother, offspr, mate.name)
from DomesticCat as mother
    inner join mother.mate as mate
    left outer join mother.kittens as offspr
このクエリーの結果は List<Object[]> ではなく List<List> になります。
HQL は、マップでのスカラー結果のラッピングもサポートします。

例13.13 動的インスタンス化の例 - マップ

select new map( mother as mother, offspr as offspr, mate as mate )
from DomesticCat as mother
    inner join mother.mate as mate
    left outer join mother.kittens as offspr

select new map( max(c.bodyWeight) as max, min(c.bodyWeight) as min, count(*) as n )
from Cat cxt
このクエリーの結果は List<Object[]> ではなく List<Map<String,Object>> になります。マップのキーは、選択式に対して提供されたエイリアスによって定義されます。

13.4.13. HQL 述語について

述語は、where 句、having 句、検索 CASE 式の基礎を形成します。これらは式であり、通常は TRUE または FALSE に解決されます。ただし、NULL が関係するブール値比較は一般的に UNKNOWN に解決します。

HQL の述語

ヌルネス述語
null の値を確認してください。基本的な属性参照、エンティティーの参照、およびパラメーターに適用できます。さらに HQL を使用すると、コンポーネント/ 組み込み可能なタイプに適用できます。

例13.14 ヌルネスチェックの例

// select everyone with an associated address
select p
from Person p
where p.address is not null

// select everyone without an associated address
select p
from Person p
where p.address is null
述語と同様
文字列値に対して、同様の比較を実行します。構文は以下のとおりです。
like_expression ::=
   string_expression
   [NOT] LIKE pattern_value
   [ESCAPE escape_character]
セマンティクスは、式のような SQL のことに従います。paattern_value は、string_expression で一致を試みるパターンです。SQL と同様に、pattern_value では _ と % をワイルドカードとして使用できます。意味は同じです。_ は任意の 1 文字に一致します。% は任意の数の文字に一致します。
オプションの escape_character は、pattern_value の _ と % の特別な意味をエスケープするために使用されるエスケープ文字を指定するために使用されます。これは、_ または % のいずれかを含むパターンを検索する必要がある場合に便利です。

例13.15 述語の例のように

select p
from Person p
where p.name like '%Schmidt'

select p
from Person p
where p.name not like 'Jingleheimmer%'

// find any with name starting with "sp_"
select sp
from StoredProcedureMetadata sp
where sp.name like 'sp|_%' escape '|'
BETWEEN 演算子
SQL BETWEEN 式と同様です。値が 2 つの他の値の範囲内にあるかどうかの評価を実行します。すべてのオペランドは、同等の型を持つ必要があります。

例13.16 述語の例の間

select p
from Customer c
    join c.paymentHistory p
where c.id = 123
  and index(p) between 0 and 9

select c
from Customer c
where c.president.dateOfBirth
        between {d '1945-01-01'}
            and {d '1965-01-01'}

select o
from Order o
where o.total between 500 and 5000

select p
from Person p
where p.name between 'A' and 'E'

13.4.14. 関連比較について

比較には、等号の =、>、>=、<、<=、<> のいずれかが関係します。HQL は、<> と比べる比較演算子として != も定義します。オペランドは同じタイプである必要があります。

例13.17 関係比較の例

// numeric comparison
select c
from Customer c
where c.chiefExecutive.age < 30

// string comparison
select c
from Customer c
where c.name = 'Acme'

// datetime comparison
select c
from Customer c
where c.inceptionDate < {d '2000-01-01'}

// enum comparison
select c
from Customer c
where c.chiefExecutive.gender = com.acme.Gender.MALE

// boolean comparison
select c
from Customer c
where c.sendEmail = true

// entity type comparison
select p
from Payment p
where type(p) = WireTransferPayment

// entity value comparison
select c
from Customer c
where c.chiefExecutive = c.chiefTechnologist
また、比較には ALLANYSOME などの修飾子を含めることもできます。some および ANY は同義語です。
ALL 修飾子は、サブくエリーの結果のすべての値に対して比較が true の場合に true に解決します。これは、値が空の場合は false に解決します。

例13.18 ALL サブクエリー比較修飾子の例

// select all players that scored at least 3 points
// in every game.
select p
from Player p
where 3 > all (
   select spg.points
   from StatsPerGame spg
   where spg.player = p
)
ANY/SOME 修飾子は、サブクエリーの結果の値のいずれかの比較が true の場合に true に解決します。これは、値が空の場合は false に解決します。

13.4.15. IN 述語について

IN 述語は、特定の値が値の一覧にあることを確認します。構文は次のとおりです。
in_expression ::= single_valued_expression
            [NOT] IN single_valued_list

single_valued_list ::= constructor_expression |
            (subquery) |
            collection_valued_input_parameter

constructor_expression ::= (expression[, expression]*)
single_valued_expression のタイプと single_valued_list の個別の値は一致している必要があります。JPQL は、有効なタイプを文字列、数値、日付、時間、タイムスタンプ、および列挙タイプに制限します。JPQL では、single_valued_expression は以下のみを参照できます。
  • 「状態フィールド」(state fields) は、単純な属性の用語です。具体的には、関連付けおよびコンポーネント/組み込み属性が除外されます。
  • エンティティー型式。
HQL では、single_valued_expression はより幅広い式タイプを参照することができます。1 価の関連づけが許可されています。コンポーネント/組み込み属性も同様です。ただし、この機能は基盤のデータベースのタプルのサポートレベルまたは「ロー値のコンストラクター構文」 (row value constructor syntax) によって異なります。さらに、HQL では値のタイプは制限されませんが、アプリケーション開発者は、基盤のデータベースベンダーに基づいてサポートが制限される可能性があることに注意する必要があります。これは、通常 JPQL の制限のためです。
値の一覧は多数の異なるソースから取得できます。constructor_expression およびcollection_valued_input_parameter では、値の一覧は空にすることはできません。少なくとも 1 つの値が含まれている必要があります。

例13.19 述語の例では

select p
from Payment p
where type(p) in (CreditCardPayment, WireTransferPayment)

select c
from Customer c
where c.hqAddress.state in ('TX', 'OK', 'LA', 'NM')

select c
from Customer c
where c.hqAddress.state in ?

select c
from Customer c
where c.hqAddress.state in (
    select dm.state
    from DeliveryMetadata dm
    where dm.salesTax is not null
)

// Not JPQL compliant!
select c
from Customer c
where c.name in (
    ('John','Doe'),
    ('Jane','Doe')
)

// Not JPQL compliant!
select c
from Customer c
where c.chiefExecutive in (
    select p
    from Person p
    where ...
)

13.4.16. HQL の順序について

クエリーの結果を順序付けすることもできます。ORDER BY は、結果の順序付けに使用される選択した値を指定するために使用されます。順序単位で有効とみなされる式のタイプには、以下が含まれます。
  • ステートフィールド
  • コンポーネント/組み込み可能な属性
  • 算術演算、関数などのスカラー式。
  • 前の式タイプに対して select 句で宣言された識別変数。
HQL は、order-by 句で参照されるすべての値が select 句内で命名されることを必須としませんが、JPQL で必要になります。データベースの移植性を求めるアプリケーションは、すべてのデータベースが、選択節で参照されていない order-by 句での参照値に対応しているわけではないことに注意してください。
order-by の個々の式は、必要な順序を示すために ASC (昇順) または DESC (下記) で修飾できます。

例13.20 注文例

// legal because p.name is implicitly part of p
select p
from Person p
order by p.name

select c.id, sum( o.total ) as t
from Order o
    inner join o.customer c
group by c.id
order by t

13.5. Hibernate サービス

13.5.1. Hibernate サービスについて

サービスは、Hibernate を提供するクラスで、さまざまなタイプの機能のプラグ可能な実装を提供します。特に、特定のサービスコントラクトインターフェースの実装です。このインターフェースはサービスロールとして知られています。実装クラスはサービス実装として知られています。一般的に、ユーザーはすべての標準サービスロール (上書き) の代替の実装をプラグインできます。また、サービスロールのベースセット (拡張) 以外に追加のサービスを定義することもできます。

13.5.2. サービス契約について

サービスの基本的な要件は、org.hibernate.service.Service のマーカーインターフェースを実装することです。Hibernate は、基本的なタイプの安全のためにこの内部で使用します。
オプションとして、サービスは org.hibernate.service.spi.Startable および org.hibernate.service.spi.Stoppable インターフェースを実装し、開始および停止の通知を受信することもできます。別のオプションのサービスコントラクトは org.hibernate.service.spi.Manageable で、JMX 統合が有効になっていると、JMX でサービスが管理可能であるとマークされます。

13.5.3. サービス依存関係の種類

サービスは、次の 2 つのアプローチのいずれかを使用して、他のサービスへの依存関係を宣言できます。
@org.hibernate.service.spi.InjectService
単一のパラメーターを受け入れ、@InjectService でアノテーションが付けられたサービス実装クラスのメソッドは 、別のサービスの挿入を要求していると見なされます。
デフォルトでは、method パラメーターのタイプは、インジェクトされるサービスロールになることが想定されます。パラメーターのタイプがサービスロールと異なる場合は、InjectServiceserviceRole 属性を使用してロールに明示的な名前を付ける必要があります。
デフォルトでは、インジェクトされたサービスは必須とみなされ、名前付き依存サービスがないと、起動に失敗します。インジェクションするサービスがオプションの場合、InjectServicerequired 属性は false と宣言する必要があります (デフォルトは true)。
org.hibernate.service.spi.ServiceRegistryAwareService
次のアプローチは、単一の injectServices メソッドを宣言する、オプションのサービスインターフェース org.hibernate.service.spi.ServiceRegistryAwareService をサービスが実装するプルアプローチです。
Hibernate は起動時に、org.hibernate.service.ServiceRegistry 自体をこのインターフェースを実装するサービスに挿入します。その後、ServiceRegistry 参照を使用して必要な追加サービスを見つけることができます。

13.5.4. ServiceRegistry

13.5.4.1. ServiceRegistry について

central サービス API はサービス自体以外に、org.hibernate.service.ServiceRegistry インターフェースです。サービスレジストリーの主な目的は、サービスへのアクセスを保持し、管理し、提供することです。
サービスレジストリーは階層的です。あるレジストリーのサービスは、同じレジストリーのサービスや任意の親レジストリーに依存して使用できます。
org.hibernate.service.ServiceRegistryBuilder を使用して org.hibernate.service.ServiceRegistry インスタンスをビルドします。

例13.21 ServiceRegistryBuilder を使用して ServiceRegistry を作成します

ServiceRegistryBuilder registryBuilder = new ServiceRegistryBuilder( bootstrapServiceRegistry );
    ServiceRegistry serviceRegistry = registryBuilder.buildServiceRegistry();

13.5.5. カスタムサービス

13.5.5.1. カスタムサービスについて

org.hibernate.service.ServiceRegistry を構築すると、不変とみなされます。このサービス自体は再設定を受け入れる可能性がありますが、ここでの不変性はサービスの追加/置き換えを意味します。そのため、org.hibernate.service.ServiceRegistryBuilder で利用できる別のロールは、これから生成される org.hibernate.service.ServiceRegistry に含まれるサービスの調整を許可することです。
カスタムサービスについて org.hibernate.service.ServiceRegistryBuilder に指示する方法は 2 つあります。
  • org.hibernate.service.spi.BasicServiceInitiator クラスを実装し、サービスクラスのオンデマンド構築を制御し、addInitiator メソッドを使用して org.hibernate.service.ServiceRegistryBuilder に追加します。
  • サービスクラスをインスタンス化し、それを介して org.hibernate.service.ServiceRegistryBuilder に追加するだけです。addService方法。
サービスの追加アプローチまたはイニシエーターの追加アプローチのいずれかが、レジストリーの拡張 (新しいサービ出力ルの追加) およびサービスのオーバーライド (サービス実装の置き換え) に有効です。

例13.22 ServiceRegistryBuilder を使用して、既存のサービスをカスタムサービスに置き換える

   ServiceRegistryBuilder registryBuilder = new ServiceRegistryBuilder( bootstrapServiceRegistry );
   registryBuilder.addService( JdbcServices.class, new FakeJdbcService() ); 
   ServiceRegistry serviceRegistry = registryBuilder.buildServiceRegistry();


   public class FakeJdbcService implements JdbcServices{

       @Override
       public ConnectionProvider getConnectionProvider() {
           return null;
       }

       @Override
       public Dialect getDialect() {
           return null;
       }

       @Override
       public SqlStatementLogger getSqlStatementLogger() {
           return null;
       }

       @Override
       public SqlExceptionHelper getSqlExceptionHelper() {
           return null;
       }

       @Override
       public ExtractedDatabaseMetaData getExtractedMetaDataSupport() {
           return null;
       }

       @Override
       public LobCreator getLobCreator(LobCreationContext lobCreationContext) {
           return null;
       }

       @Override
       public ResultSetWrapper getResultSetWrapper() {
           return null;
       }
   }

13.5.6. ブートストラップレジストリー

13.5.6.1. Boot-strap レジストリーについて

boot-strap レジストリーは、ほとんどの機能を機能させるために絶対に利用できるようにする必要のあるサービスを保持します。ここでの主要なサービスは、ClassLoaderService です。これは最適な例です。設定ファイルを解決するにも、クラス読み込みサービス (リソース検索) へのアクセスが必要です。これは、通常の使用時の (親ではなく) ルートレジストリーです。
boot-strap レジストリーのインスタンスは、org.hibernate.service.BootstrapServiceRegistryBuilder クラスを使用して作成されます。

13.5.6.2. BootstrapServiceRegistryBuilder の使用

例13.23 BootstrapServiceRegistryBuilder の使用

BootstrapServiceRegistry bootstrapServiceRegistry = new BootstrapServiceRegistryBuilder()
        // pass in org.hibernate.integrator.spi.Integrator instances which are not
        // auto-discovered (for whatever reason) but which should be included
        .with( anExplicitIntegrator )
        // pass in a class loader that Hibernate should use to load application classes
        .with( anExplicitClassLoaderForApplicationClasses )
        // pass in a class loader that Hibernate should use to load resources
        .with( anExplicitClassLoaderForResources )
        // see BootstrapServiceRegistryBuilder for rest of available methods
        ...
        // finally, build the bootstrap registry with all the above options
        .build();

13.5.6.3. BootstrapRegistry サービス

org.hibernate.service.classloading.spi.ClassLoaderService
Hibernate はクラスローダーと対話する必要があります。ただし、Hibernate または任意のライブラリーと対話する方法は、アプリケーションをホストしているランタイム環境によって異なります。アプリケーションサーバー、OSGi コンテナー、およびその他のモジュラークラスローディングシステムでは、非常に特殊なクラスローディング要件が課せられています。このサービスは、この環境的な複雑性からの抽象化を Hibernate に提供します。また、同様に重要な点として、単一スワップ可能なコンポーネントでこれを実行します。
クラスローダーとの対話では、Hibernate には以下の機能が必要になります。
  • アプリケーションクラスを検索する機能
  • インテグレーションクラスを検索する機能
  • リソース (プロパティーファイル、xml ファイルなど) を見つける機能
  • java.util.ServiceLoader をロードする機能
注記
現在、アプリケーションクラスをロードする機能と、統合クラスをロードする機能が、サービス上の単一の load class 機能に統合されています。これは、今後のリリースで変更される可能性があります。
org.hibernate.integrator.spi.IntegratorService
アプリケーション、アドオン、およびその他のモジュールは Hibernate と統合する必要があります。前述の方法では、各モジュールの登録を調整するために、通常アプリケーションなどのコンポーネントが必要でした。この登録は、各モジュールのインテグレーターに代わって実施されました。
このサービスは、検出機能に重点を置いています。これは、によって提供される標準の Javajava.util.ServiceLoader 機能を活用します。 org.hibernate.service.classloading.spi.ClassLoaderService の実装を発見するために org.hibernate.integrator.spi.Integrator contract.
インテグレーターは、単に /META-INF/services/org.hibernate.integrator.spi.Integrator という名前のファイルを定義し、これをクラスパスで利用できるようにします。
このファイルは、java.util.ServiceLoader メカニズムによって使用されます。これは、1 行ずつ org.hibernate.integrator.spi.Integrator インターフェースを実装するクラスの完全修飾名を一覧表示します。

13.5.7. SessionFactory レジストリー

13.5.7.1. SessionFactory レジストリー

すべてのレジストリータイプのインスタンスを特定のレジストリータイプを対象とするものとして扱うことがベストプラクティスですが org.hibernate.SessionFactory、このグループのサービスのインスタンスは、明示的に単一に属します org.hibernate.SessionFactory.
相違点は、開始タイミングに関する事項です。通常、彼らはにアクセスする必要があります org.hibernate.SessionFactory 開始されます。この特別なレジストリーは org.hibernate.service.spi.SessionFactoryServiceRegistry

13.5.7.2. SessionFactory サービス

org.hibernate.event.service.spi.EventListenerRegistry

Description
イベントリスナーを管理するためのサービスです。
イニシエーター
org.hibernate.event.service.internal.EventListenerServiceInitiator
実装
org.hibernate.event.service.internal.EventListenerRegistryImpl

13.5.8. インテグレーター

13.5.8.1. インテグレーター

その org.hibernate.integrator.spi.Integrator 開発者が機能する SessionFactory を構築するプロセスにフックできるようにするための簡単な手段を提供することを目的としています。その org.hibernate.integrator.spi.Integrator インターフェイスは、対象となる 2 つのメソッドを定義します。integrate構築プロセスにフックすることができます。disintegrateシャットダウンする SessionFactory にフックすることができます。
注記
に定義されている 3 番目のメソッドがあります org.hibernate.integrator.spi.Integrator、のオーバーロードされた形式integrate受け入れる org.hibernate.metamodel.source.MetadataImplementor org.hibernate.cfg.Configuration の代わりに。このフォームは、5.0 で完了する予定の新しいメタモデルコードで使用することを目的としています。
IntegratorService で利用できる検出アプローチに加え、BootstrapServiceRegistry のビルド時にアプリケーションが手動でインテグレーター実装を登録できます。

13.5.8.2. インテグレーターのユースケース

の主な使用例 org.hibernate.integrator.spi.Integrator 現在、イベントリスナーの登録とサービスの提供を行っています (を参照)。 org.hibernate.integrator.spi.ServiceContributingIntegrator).5.0 では、オブジェクトモデルとリレーショナルモデル間のマッピングを記述するメタモデルを変更できるように拡張する予定です。

例13.24 イベントリスナーの登録

public class MyIntegrator implements org.hibernate.integrator.spi.Integrator {

    public void integrate(
            Configuration configuration,
            SessionFactoryImplementor sessionFactory,
            SessionFactoryServiceRegistry serviceRegistry) {
        // As you might expect, an EventListenerRegistry is the thing with which event listeners are registered  It is a
        // service so we look it up using the service registry
        final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService( EventListenerRegistry.class );

        // If you wish to have custom determination and handling of "duplicate" listeners, you would have to add an
        // implementation of the org.hibernate.event.service.spi.DuplicationStrategy contract like this
        eventListenerRegistry.addDuplicationStrategy( myDuplicationStrategy );

        // EventListenerRegistry defines 3 ways to register listeners:
        //     1) This form overrides any existing registrations with
        eventListenerRegistry.setListeners( EventType.AUTO_FLUSH, myCompleteSetOfListeners );
        //     2) This form adds the specified listener(s) to the beginning of the listener chain
        eventListenerRegistry.prependListeners( EventType.AUTO_FLUSH, myListenersToBeCalledFirst );
		//     3) This form adds the specified listener(s) to the end of the listener chain
        eventListenerRegistry.appendListeners( EventType.AUTO_FLUSH, myListenersToBeCalledLast ); 
    }
}

13.6. Bean Validation

13.6.1. Bean Validation

Bean Validation あるいは JavaBeans Validation は、Java オブジェクトのデータのバリデーションを行うモデルです。このモデルでは、組み込みのカスタムアノテーション制約を使い、アプリケーションデータの整合性を保ちます。この仕様は、に文書化されてい http://jcp.org/en/jsr/detail?id=303 ます。
Hibernate Validator は Bean Validation の JBoss EAP 6 実装です。また、JSR の参照実装です。
JBoss EAP 6 は、JSR 303-Bean Validation に 100% 準拠しています。また、Hibernate Validator によってこの仕様に追加機能が提供されます。
Bean Validation の使用を開始するには、以下を参照してください。bean-validationクイックスタートの例:「クイックスタートにアクセスする」

13.6.2. Hibernate Validator

Hibernate Validator は、JSR303-BeanValidation のリファレンス実装です。
Bean Validation は、Java オブジェクトデータを検証するためのモデルをユーザーに提供します。詳細は、「Bean Validation」 および 「バリデーション制約」 を参照してください。

13.6.3. バリデーション制約

13.6.3.1. バリデーション制約

バリデーション制約とは、フィールド、プロパティー、Bean などの Java 要素に適用するルールのことです。制約は通常、制限を設定する際に利用する一連の属性です。定義済みの制約がありますが、カスタムの制約も作成可能です。各制約は、アノテーション形式で表されます。
HibernateValidator の組み込みの検証制約は次のとおりです。 「Hibernate Validator の制約」
詳細は、「Hibernate Validator」 および 「Bean Validation」 を参照してください。

13.6.3.2. Red Hat JBossDeveloperStudio で制約アノテーションを作成する

概要

このタスクでは、Java アプリケーション内で使用するために Red Hat JBossDeveloperStudio で制約アノテーションを作成するプロセスについて説明します。

手順13.5 制約注釈を作成する

  1. Red Hat JBossDeveloperStudio で Java プロジェクトを開きます。
  2. データセットを作成する

    制約アノテーションには、許容値を定義するデータセットが必要です。
    1. プロジェクトエクスプローラ パネルでプロジェクトルートフォルダーを右クリックします。
    2. NewEnum 選択します。
    3. 次の要素を設定します。
      • パッケージ:
      • 名前:
    4. 追加... ボタンをクリックして、必要なインターフェイスを追加します。
    5. Finish (完了) をクリックしてファイルを作成します。
    6. データセットに値のセットを追加し、保存 をクリックします。

    例13.25 データセットの例

    package com.example;
    
    public enum CaseMode {
        UPPER,
        LOWER;
    }
    
  3. 注釈ファイルを作成する

    新しい Java クラスを作成します。
  4. 制約注釈を設定し、保存 をクリックします。

    例13.26 制約注釈ファイルの例

    package com.mycompany;
    
    import static java.lang.annotation.ElementType.*;
    import static java.lang.annotation.RetentionPolicy.*;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.Retention;
    import java.lang.annotation.Target;
    
    import javax.validation.Constraint;
    import javax.validation.Payload;
    
    @Target( { METHOD, FIELD, ANNOTATION_TYPE })
    @Retention(RUNTIME)
    @Constraint(validatedBy = CheckCaseValidator.class)
    @Documented
    public @interface CheckCase {
    
        String message() default "{com.mycompany.constraints.checkcase}";
    
        Class<?>[] groups() default {};
    
        Class<? extends Payload>[] payload() default {};
        
        CaseMode value();
    
    }
結果
可能な値のセットを含むカスタム制約アノテーションが作成され、Java プロジェクトで使用できるようになりました。

13.6.3.3. Hibernate Validator の制約

表13.11 組み込みの制約

Annotation に適用する ランタイムチェック Hibernate Metadata の影響
@Length(min=, max=) プロパティー (文字列) 文字列の長さが指定の範囲と一致するかを確認します。 カラムの長さを最大に設定します。
@Max(value=) プロパティー (数値または数値の文字列表現) 値が最大値以下であるかを確認します。 カラムに check 制約を追加します。
@Min(value=) プロパティー (数値または数値の文字列表現) 値が最小値以上であるかを確認します。 カラムに check 制約を追加します。
@NotNull プロパティー 値が null でないかを確認します。 カラムが null でないかを確認します。
@NotEmpty プロパティー 文字列が null あるいは空でないかを確認します。接続が null あるいは空でないかを確認します。 列が null ではありません (文字列の場合)。
@Past プロパティー (日付またはカレンダー) 過去の日付であるかを確認します。 カラムに check 制約を追加します。
@Future プロパティー (日付またはカレンダー) 未来の日付であるかを確認します。 なし。
@Pattern(regex="regexp", flag=) or @Patterns( {@Pattern(...)} ) プロパティー (文字列) プロパティーが一致フラグを指定して正規表現と一致するかどうかを確認します (java.util.regex.Pattern を参照)。 なし。
@Range(min=, max=) プロパティー (数値または数値の文字列表現) 値が最小値と最大値 (含まれている) の間にあるかどうかを確認します。 カラムに check 制約を追加します。
@Size(min=, max=) プロパティー (配列、コレクション、マップ) 要素のサイズが最小から最大 (含まれている) の間にあるかどうかを確認します。 なし。
@AssertFalse プロパティー メソッドが false と評価することを確認します (アノテーションでなくコードで制約が表現されている場合に便利です)。 なし。
@AssertTrue プロパティー メソッドが true と評価することを確認します (アノテーションでなくコードで制約が表現されている場合に便利です)。 なし。
@Valid プロパティー (オブジェクト) 紐付けされたオブジェクトに再帰的にバリデーションを実行します。オブジェクトがコレクションかアレイの場合は、要素は再帰的に検証されます。また、オブジェクトがマップの場合、値要素が再帰的に検証されます。 なし。
@Email プロパティー (文字列) 文字列がメールアドレスの仕様に準拠するかどうかを確認します。 なし。
@CreditCardNumber プロパティー (文字列) 文字列が正規の形式のクレジットカード番号であるかどうかを確認します (Luhn アルゴリズムの派生)。 なし。
@Digits(integerDigits=1) プロパティー (数値または数値の文字列表現) プロパティーが integerDigits までの整数部と、fractionalDigits までの小数部を持つ数字であるかを確認します。 カラムの精度とスケールを定義します。
@EAN プロパティー (文字列) 文字列が正しくフォーマットされた EAN あるいは UPC-A コードであるかを確認します。 なし。

13.6.4. 設定

13.6.4.1. 例: バリデーション設定ファイル

例13.27 validation.xml

<validation-config xmlns="http://jboss.org/xml/ns/javax/validation/configuration"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration">

    <default-provider>
        org.hibernate.validator.HibernateValidator
    </default-provider>
    <message-interpolator>
        org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator
    </message-interpolator>
    <constraint-validator-factory>
        org.hibernate.validator.engine.ConstraintValidatorFactoryImpl
    </constraint-validator-factory>
    
    <constraint-mapping>
        /constraints-example.xml
    </constraint-mapping>
    
    <property name="prop1">value1</property>
    <property name="prop2">value2</property>
</validation-config>

13.7. エンバーズ

13.7.1. Hibernate Envers について

Hibernate Enver は監査およびバージョン管理システムであり、JBoss EAP 6 に永続クラスへのこれまでの変更を追跡する手段を提供します。監査テーブルは @Audited アノテーションが付けられたエンティティーに対して作成されています。これは、エンティティーに加えられた変更の履歴が保存されます。その後、データを取得し、クエリーできます。
Envers では、開発者は以下を行うことができます。
  • JPA 仕様で定義されているすべてのマッピングの監査
  • JPA 仕様を拡張するすべての Hibernate マッピングの監査
  • ネイティブ Hibernate API を使用する、または、これによってマッピングされるエンティティーの監査
  • リビジョンエンティティーを使用した各リビジョンのデータのログ記録、また
  • 履歴データのクエリー

13.7.2. 永続クラスの監査について

永続クラスの監査は、JBoss EAP 6 で HibernateEnvers および@Audited注釈。アノテーションがクラスに適用されると、エンティティーの改訂履歴を保存するテーブルが作成されます。
クラスに変更が行われるたびに、エントリーが監査テーブルに追加されます。エントリーにはクラスへの変更が含まれ、リビジョン番号が指定されます。これは、変更をロールバックしたり、以前のリビジョンを表示したりできることを意味します。

13.7.3. 監査ストラテジー

13.7.3.1. 監査ストラテジーについて

監査ストラテジーは、監査情報の永続化、クエリー、および保存方法を定義します。Hibernate Evers には現在、以下の 2 つの監査ストラテジーがあります。
デフォルトの監査ストラテジー
このストラテジーは、開始リビジョンとともに監査データの保存を永続化します。監査されたテーブルで挿入、更新、削除される行ごとに、有効性の開始リビジョンとともに、監査テーブルに 1 つ以上の行を挿入します。
監査テーブルの行は、挿入後には更新されません。監査情報のクエリーはサブクエリーを使用して、監査テーブルの適用可能な行を選択します。これはスピードが遅く、インデックス作成が困難です。
有効性監査ストラテジー
このストラテジーは、監査上の開始リビジョンと最後のリビジョンを保存します。監査されたテーブルで挿入、更新、削除される行ごとに、有効性の開始リビジョンとともに、監査テーブルに 1 つ以上の行を挿入します。
同時に、以前の監査行 (利用可能な場合) の終了リビジョンフィールドは、このリビジョンに設定されます。監査情報のクエリーは、サブクエリーの代わりに、 between startend revision の間で使用できます。つまり、追加の更新により、監査情報の永続化は多少遅くなりますが、監査情報の取得はかなり速くなります。
これは、インデックスを追加して改善することもできます。
監査の詳細については、を参照してください。「永続クラスの監査について」。アプリケーションの監査戦略を設定するには、以下を参照してください。「監査ストラテジーの設定」

13.7.3.2. 監査ストラテジーの設定

概要

JBoss EAP 6 でサポートされる監査戦略には、デフォルトと妥当性の監査戦略の 2 つがあります。このタスクでは、アプリケーションの監査戦略を定義するために必要な手順について説明します。

手順13.6 監査戦略を定義する

  • を設定しますorg.hibernate.envers.audit_strategyアプリケーションの persistence.xml ファイルのプロパティー。プロパティーが persistence.xml ファイルで設定されていない場合は、デフォルトの監査ストラテジーが使用されます。

    例13.28 デフォルトの監査ストラテジーの設定

    <property name="org.hibernate.envers.audit_strategy" value="org.hibernate.envers.strategy.DefaultAuditStrategy"/>
    

    例13.29 有効性監査ストラテジーの設定

    <property name="org.hibernate.envers.audit_strategy" value="org.hibernate.envers.strategy.ValidityAuditStrategy"/>
    

13.7.4. エンティティー監査の開始

13.7.4.1. JPA エンティティーへの監査サポートの追加

JBoss EAP 6 は、エンティティー監査を使用します。「Hibernate Envers について」、永続クラスの履歴変更を追跡します。このトピックでは、JPA エンティティーの監査サポートの追加について説明します。

手順13.7 JPA エンティティーへの監査サポートの追加

  1. デプロイメントに適した利用可能な監査パラメーターを設定します: 「Envers パラメーターの設定」
  2. 監査する JPA エンティティーを開きます。
  3. をインポートしますorg.hibernate.envers.Auditedインターフェイス。
  4. 監査する各フィールドまたはプロパティーに @Audited アノテーションを適用するか、クラス全体に対して 1 度適用します。

    例13.30 2 つのフィールドを監査する

    import org.hibernate.envers.Audited;
    
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Column;
    
    @Entity
    public class Person {
        @Id
        @GeneratedValue
        private int id;
    
        @Audited
        private String name;
    
        private String surname;
    
        @ManyToOne
        @Audited
        private Address address;
    
        // add getters, setters, constructors, equals and hashCode here
    }
    

    例13.31 クラス全体を監査する

    import org.hibernate.envers.Audited;
    
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Column;
    
    @Entity
    @Audited
    public class Person {
        @Id
        @GeneratedValue
        private int id;
    
        private String name;
    
        private String surname;
    
        @ManyToOne
        private Address address;
    
        // add getters, setters, constructors, equals and hashCode here
    }
    

結果

JPA エンティティーは監査用に設定されています。履歴の変更を保存するために、Entity_AUD というテーブルが作成されます。

13.7.5. 設定

13.7.5.1. Envers パラメーターの設定

JBoss EAP 6 は About Hibernate Envers を介してエンティティー監査を使用して、永続クラスのこれまでの変更を追跡します。このトピックでは、使用可能な Envers パラメーターの設定について説明します。

手順13.8 Envers パラメーターの設定

  1. アプリケーションの persistence.xml ファイルを開きます。
  2. 必要に応じて Envers プロパティーを追加、削除、または設定します。利用可能なプロパティーのリストについては、を参照してください。「Envers 設定プロパティー」

例13.32 例: Envers パラメーター

<persistence-unit name="mypc">
  <description>Persistence Unit.</description>
  <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
  <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
  <properties>
    <property name="hibernate.hbm2ddl.auto" value="create-drop" />
    <property name="hibernate.show_sql" value="true" />
    <property name="hibernate.cache.use_second_level_cache"	value="true" />
    <property name="hibernate.cache.use_query_cache" value="true" />
    <property name="hibernate.generate_statistics" value="true" />
    <property name="org.hibernate.envers.versionsTableSuffix" value="_V" />
    <property name="org.hibernate.envers.revisionFieldName" value="ver_rev" />
  </properties>
</persistence-unit>
結果
アプリケーション内のすべての JPA エンティティーに対して監査が設定されています。

13.7.5.2. ランタイム時の監査の有効化または無効化

概要

このタスクでは、実行時にエンティティーバージョンの監査を有効/無効にするために必要な設定手順について説明します。

手順13.9 監査の有効化/無効化

  1. AuditEventListener クラスをサブクラス化します。
  2. Hibernate イベントで呼び出される以下のメソッドを上書きします。
    • onPostInsert
    • onPostUpdate
    • onPostDelete
    • onPreUpdateCollection
    • onPreRemoveCollection
    • onPostRecreateCollection
  3. イベントのリスナーとしてサブクラスを指定します。
  4. 変更を監査する必要があるかどうかを判断します。
  5. 変更を監査する必要がある場合には、スーパークラスに呼び出しを渡します。

13.7.5.3. 条件監査の設定

概要

Hibernate Envers は、一連のイベントリスナーを使用して、さまざまな Hibernate イベントに対する応答で監査データを永続化します。Envers jar がクラスパスにある場合、これらのリスナーは自動的に登録されます。このタスクでは、Envers イベントリスナーの一部をオーバーライドすることにより、条件付き監査を実装するために必要な手順について説明します。

手順13.10 条件監査の実装

  1. persistence.xml ファイルで hibernate.listeners.envers.autoRegister を false に設定します。
  2. 上書きされる各イベントリスナーをサブクラス化します。条件付き監査ロジックをサブクラスに配置し、監査を実行する必要がある場合は super メソッドを呼び出します。
  3. org.hibernate.envers.event.EnversIntegrator に類似した、org.hibernate.integrator.spi.Integrator のカスタム実装を作成します。デフォルトのクラスではなく、ステップ 2 で作成したイベントリスナーサブクラスを使用します。
  4. META-INF/services/org.hibernate.integrator.spi.Integrator ファイルを jar に追加します。このファイルには、インターフェースを実装するクラスの完全修飾名が含まれている必要があります。

結果

条件付き監査が設定され、デフォルトの Envers イベントリスナーがオーバーライドされます。

13.7.5.4. Envers 設定プロパティー

表13.12 エンティティーデータのバージョン管理設定パラメーター

プロパティー名 デフォルト値 説明
org.hibernate.envers.audit_table_prefix
監査されたエンティティーの名前の前に付加される文字列。監査情報を保持するエンティティーの名前を作成します。
org.hibernate.envers.audit_table_suffix
_AUD
監査されたエンティティーの名前に付加される文字列。監査情報を保持するエンティティーの名前を作成します。たとえば、テーブル名が Person のエンティティーが監査されると、Envers は、履歴データを格納する Person_AUD と呼ばれるテーブルを生成します。
org.hibernate.envers.revision_field_name
REV
改訂番号を保持する監査エンティティーのフィールド名。
org.hibernate.envers.revision_type_field_name
REVTYPE
改訂の種類を保持する監査エンティティーのフィールド名。可能なリビジョンの現在のタイプは、addmod、および del です。
org.hibernate.envers.revision_on_collection_change
true
このプロパティーは、所有の変更のない関係フィールドがある場合にリビジョンを生成するかどうかを決定します。これは、一対多数の関係のコレクションであるか、または一対一の関係で mappedBy 属性を使用するフィールドになります。
org.hibernate.envers.do_not_audit_optimistic_locking_field
true
true の場合、(@Version でアノテーション付けされた) 楽観的ロックに使用されるプロパティーは自動的に監査から除外されます。
org.hibernate.envers.store_data_at_delete
false
このプロパティーは、ID のみではなく、エンティティーデータを削除するときに、エンティティーデータをリビジョンに保存するかどうかを定義します。その他のすべてのプロパティーは null とマークされます。通常、データは最後から 2 番目のバージョンにあるため、これは必須ではありません。ただし時折、最後のリビジョンでアクセスすることが簡単で、より効率的になる場合があります。ただし、これは、削除前に含まれるエンティティーのデータが 2 回保存されることを意味します。
org.hibernate.envers.default_schema
null (通常のテーブルと同じ)
監査テーブルに使用されるデフォルトのスキーマ名。@AuditTable(schema="...") アノテーションを使用して上書き可能。これがない場合、スキーマは通常のテーブルのスキーマと同じになります。
org.hibernate.envers.default_catalog
null (通常のテーブルと同じ)
監査テーブルに使用するデフォルトのカタログ名。@AuditTable(catalog="...") アノテーションを使用して上書き可能。存在しない場合、カタログは通常のテーブルのカタログと同じになります。
org.hibernate.envers.audit_strategy
org.hibernate.envers.strategy.DefaultAuditStrategy
このプロパティーは、監査データの永続化時に使用する必要のある監査ストラテジーを定義します。デフォルトでは、エンティティーが変更されたリビジョンのみが保存されます。または、org.hibernate.envers.strategy.ValidityAuditStrategyでは、開始リビジョンと終了リビジョンの両方を保存します。これらを組み合わせて、監査行が有効であったタイミングを定義します。
org.hibernate.envers.audit_strategy_validity_end_rev_field_name
REVEND
監査エンティティーで終了リビジョン番号を保持するコラムの名前。このプロパティーは、妥当な監査ストラテジーが使用される場合にのみ有効です。
org.hibernate.envers.audit_strategy_validity_store_revend_timestamp
false
このプロパティーは、終了リビジョン自体に加えて、データが最後に有効であった終了リビジョンのタイムスタンプも保存すべきかどうかを定義します。これは、テーブルパーティションを使用して、リレーショナルデータベースから古い監査レコードをパージする場合に便利です。パーティショニングには、テーブルに存在するコラムが必要です。このプロパティーは ValidityAuditStrategy が使用される場合にのみ評価されます。
org.hibernate.envers.audit_strategy_validity_revend_timestamp_field_name
REVEND_TSTMP
データがまだ有効であった時点での終了リビジョンのタイムスタンプのコラム名。ValidityAuditStrategy が使用されている場合にのみ使用され、 org.hibernate.envers.audit_strategy_validity_store_revend_timestamptrue と評価されます。

13.7.6. クエリー

13.7.6.1. 監査情報を取得する

概要

Hibernate Enver は、クエリーを介して監査情報を取得する機能を提供します。このトピックでは、これらのクエリーの例を示します。

注記
監査されたデータでのクエリーは、関連する subselect を伴うため、多くの場合、live データに対するクエリーよりもはるかに遅くなります。

例13.33 所定リビジョンでのクラスのエンティティーのクエリー

このタイプのクエリーのエントリーポイントは以下の通りです。
AuditQuery query = getAuditReader()
    .createQuery()
    .forEntitiesAtRevision(MyEntity.class, revisionNumber);
制約は AuditEntity ファクトリークラスを使用して指定できます。以下のクエリーは、name プロパティーが John と同等のエンティティーのみを選択します。
query.add(AuditEntity.property("name").eq("John"));
以下のクエリーは、特定のエンティティーに関連するエンティティーのみを選択します。
query.add(AuditEntity.property("address").eq(relatedEntityInstance));
// or
query.add(AuditEntity.relatedId("address").eq(relatedEntityId));
その結果は、順序付け、制限でき、集計と予測 (グループ化を除く) セットを設定することができます。以下の例は、フルクエリーです。
List personsAtAddress = getAuditReader().createQuery()
    .forEntitiesAtRevision(Person.class, 12)
    .addOrder(AuditEntity.property("surname").desc())
    .add(AuditEntity.relatedId("address").eq(addressId))
    .setFirstResult(4)
    .setMaxResults(2)
    .getResultList();

例13.34 所定クラスエンティティーが変更されるクエリーリビジョン

このタイプのクエリーのエントリーポイントは以下の通りです。
AuditQuery query = getAuditReader().createQuery()
    .forRevisionsOfEntity(MyEntity.class, false, true);
このクエリーには、前述の例と同じように制約を追加できます。このクエリーには、追加の方法が考えられます。
AuditEntity.revisionNumber()
監査済みエンティティーが変更されたリビジョン番号の制約、展開、および順序を指定します。
AuditEntity.revisionProperty(propertyName)
監査済みエンティティーが変更されたリビジョンに対応する、リビジョンエンティティーのプロパティーに対する制約、調整および順序付けを指定します。
AuditEntity.revisionType()
リビジョンのタイプ (ADD、MOD、DEL) へのアクセスを提供します。
クエリー結果は必要に応じて調整できます。以下のクエリーは、エンティティーの最小のリビジョン番号を選択しますMyEntityクラス、entityIdリビジョン番号 42 以降、ID が変更されました:
Number revision = (Number) getAuditReader().createQuery()
    .forRevisionsOfEntity(MyEntity.class, false, true)
    .setProjection(AuditEntity.revisionNumber().min())
    .add(AuditEntity.id().eq(entityId))
    .add(AuditEntity.revisionNumber().gt(42))
    .getSingleResult();
リビジョンのクエリーは、プロパティーを最小限に抑えたり、最大値にしたりすることもできます。以下のクエリーは、特定のエンティティーの actualDate の値が指定の値よりも大きくなるリビジョンを選択しますが、可能な限り小さくなります。
Number revision = (Number) getAuditReader().createQuery()
    .forRevisionsOfEntity(MyEntity.class, false, true)
    // We are only interested in the first revision
    .setProjection(AuditEntity.revisionNumber().min())
    .add(AuditEntity.property("actualDate").minimize()
        .add(AuditEntity.property("actualDate").ge(givenDate))
        .add(AuditEntity.id().eq(givenEntityId)))
    .getSingleResult();
minimize() および maximize() のメソッドは基準を返します。これは、制約を追加でき、 maximized/minimized プロパティーを持つエンティティーによって満たされる必要があります。
クエリーの作成時に、2 つのブール値パラメーターが渡されます。
selectEntitiesOnly
このパラメーターは、明示的な子が設定されていない場合のみ有効です。
true の場合、クエリーの結果は、指定された制約を満たすリビジョンで変更されたエンティティーのリストになります。
false の場合、結果は 3 つの要素の配列のリストになります。最初の要素は変更されたエンティティーインスタンスになります。次は、リビジョンデータを含むエンティティーです。カスタムエンティティーが使用されていない場合、DefaultRevisionEntity のインスタンスになります。3 番目の要素アレイはリビジョンのタイプ (ADD、MOD、DEL) になります。
selectDeletedEntities
このパラメーターは、エンティティーが削除されたリビジョンを結果に含める必要があるかどうかを指定します。true の場合、エンティティーにはリビジョンタイプ DEL が指定され、id を除くすべてのフィールドの値は null になります。

例13.35 所定プロパティーを変更するエンティティーのクエリーの修正

以下のクエリーは、のすべてのリビジョンを返しますMyEntity指定された ID を使用します。actualDateプロパティーが変更されました。
AuditQuery query = getAuditReader().createQuery()
  .forRevisionsOfEntity(MyEntity.class, false, true)
  .add(AuditEntity.id().eq(id));
  .add(AuditEntity.property("actualDate").hasChanged())
ThehasChanged条件は、追加の基準と組み合わせることができます。以下のクエリーは、revisionNumber の生成時に MyEntity の水平スライスを返します。変更されたリビジョンに限定されますprop1、だがしかしprop2
AuditQuery query = getAuditReader().createQuery()
  .forEntitiesAtRevision(MyEntity.class, revisionNumber)
  .add(AuditEntity.property("prop1").hasChanged())
  .add(AuditEntity.property("prop2").hasNotChanged());
作成されたセットには、revisionNumber よりも少ない数字のリビジョンも含まれます。これは、このクエリーをすべてを返すと読み取ることができないことを意味しますMyEntitiesRevisionNumber で 変更 されましたprop1変更され、prop2手つかず。
以下のクエリーは、を使用してこの結果を返す方法を示しています。forEntitiesModifiedAtRevisionクエリー:
AuditQuery query = getAuditReader().createQuery()
  .forEntitiesModifiedAtRevision(MyEntity.class, revisionNumber)
  .add(AuditEntity.property("prop1").hasChanged())
  .add(AuditEntity.property("prop2").hasNotChanged());

例13.36 指定リビジョンでのクエリーエンティティーの変更

以下の例は、特定のリビジョンで変更されたエンティティーの基本クエリーを示しています。指定されたリビジョンで変更されたエンティティー名と対応する Java クラスを取得することができます。
Set<Pair<String, Class>> modifiedEntityTypes = getAuditReader()
    .getCrossTypeRevisionChangesReader().findEntityTypes(revisionNumber);
からもアクセスできる他のクエリーがいくつかあります org.hibernate.envers.CrossTypeRevisionChangesReader:
List<Object> findEntities(Number)
指定のリビジョンで変更された (追加、更新、削除された) すべての監査済みエンティティーのスナップショットを返します。n+1 SQL クエリーを実行します。n は、指定されたリビジョン内で変更された複数の異なるエンティティークラスです。
List<Object> findEntities(Number, RevisionType)
変更タイプでフィルターされた特定のリビジョンで変更 (追加、更新、または削除) されたすべての監査済みエンティティーのスナップショットを返します。n+1 SQL クエリーを実行します。n は、指定されたリビジョン内で変更された複数の異なるエンティティークラスです。
Map<RevisionType, List<Object>> findEntitiesGroupByRevisionType(Number)
変更操作 (追加、更新、削除など) ごとにグループ化されたエンティティースナップショットのリストを含むマップを返します。3n+1 SQL クエリーを実行します。n は、指定されたリビジョン内で変更された複数の異なるエンティティークラスです。

13.8. パフォーマンスチューニング

13.8.1. 他のバッチロードアルゴリズム

Hibernate では、join、select、subselect、および batch の 4 つののフェッチストラテジーのいずれかを使用して関連付けのデータを読み込むことができます。これら 4 つのストラテジーにおいて、バッチローディングでは、select フェッチの最適化ストラテジーであるため、これらのストラテジーの外で、パフォーマンスを大幅に向上させることができます。このストラテジーでは、Hibernate はプライマリーキーまたは外部キーのリストを指定して、単一の SELECT ステートメントでエンティティーインスタンスまたはコレクションのバッチを取得します。batch フェッチは、レイジー select フェッチストラテジーの最適化です。
batch フェッチの設定方法は、クラス当たりのレベルまたはコレクション当たりのレベルです。
  • クラス当たりのレベル
    Hibernate がクラス当たりのレベルでデータを読み込む場合は、クエリーの実行時にロードする関連付けのバッチサイズが必要になります。たとえば、ランタイム時に、セッションに 30 個のインスタンスの car オブジェクトがロードされているとします。各 car オブジェクトは owner オブジェクトに属します。すべての car オブジェクトを繰り返し処理し、所有者を要求する場合、lazy 読み込みでは、Hibernate は所有者ごとに 30 個の select ステートメントを発行します。これはパフォーマンスのボトルネックです。
    代わりに、Hibernate に対して、クエリーを経由する前に所有者の次のバッチのデータを事前に読み込むように指示することもできます。owner オブジェクトがクエリーされると、Hibernate は同じ SELECT ステートメントで多くのこれらのオブジェクトをクエリーします。
    事前にクエリーする owner オブジェクトの数は、設定時に指定された batch-size パラメーターによって異なります。
    <class name="owner" batch-size="10"></class>
    これにより、Hibernate は、後で必要と予想される 10 個以上の owner オブジェクトをクエリーするようになります。ユーザーがクエリーを実行するとownercar Aownercar Bバッチロードの一部としてすでにロードされている可能性があります。ユーザーがデータベースに移動 (および SELECT ステートメントを実行) する代わりに、実際に car Bowner が必要な場合は、現在のセッションから値を取得できます。
    batch-size パラメーターに加えて、Hibernate 4.2.0 ではバッチロードのパフォーマンスを強化する新しい設定項目が導入されました。設定アイテムは呼び出されますBatch Fetch Style設定であり、hibernate.batch_fetch_style パラメーターで指定されます。
    LEGACY、PADDED、DYNAMIC といった異なるバッチフェッチスタイルがサポートされています。使用するスタイルを指定するには、org.hibernate.cfg.AvailableSettings#BATCH_FETCH_STYLE
    • レガシー: レガシースタイルの読み込みでは、に基づいて事前に作成されたバッチサイズのセットArrayHelper.getBatchSizes(int)利用されます。バッチは、既存のバッチ可能な識別子の数からの次に小さな事前ビルドされたバッチサイズを使用してロードされます。
      上記の例を続けて、batch-size30 に設定すると、事前に作成されたバッチサイズは 30、15、10、9、8、7、..、1 になります。ロード 29 識別子のバッチ処理を試みると、15、10、および 4 のバッチが発生します。対応する SQL クエリーは 3 つあり、各クエリーはデータベースから 15、10、および 4 の所有者 (owner) を読み込みます。
    • PADDED - PADDED は、バッチローディングの LEGACY スタイルに似ています。依然として事前ビルドされたバッチサイズを使用していますが、次に大きなバッチサイズを使用し、追加の識別子プレースホルダーをパディングします。
      上記の例と同様に、30 個の owner オブジェクトを初期化する場合、データベースに対してクエリーが実行されるのは 1 つのみとなります。
      ただし、29 個の owner オブジェクトが初期化される場合でも、Hibernate は依然としてバッチサイズ 30 の SQL select ステートメントのみを実行し、識別子が連続する追加スペースがパディングされます。
    • Dynamic - バッチサイズの制限に準拠していますが、このスタイルのバッチロードは、実際に読み込まれるオブジェクト数を使用して SQL SELECT ステートメントを動的に構築します。
      たとえば、owner オブジェクトが 30 個で、最大バッチサイズが 30 の場合、30 個の owner オブジェクトを取得する呼び出しは、1 つの SQL SELECT ステートメントになります。35 個を取得する呼び出しは、バッチサイズ 30 と 5 の 2 つの SQL ステートメントになります。Hibernate は、必要な数である 5 を維持するために 第 2 の SQL ステートメントを動的に変更します。また、バッチサイズは制限の 30 のままに保持します。これは、PADDED バージョンとは異なります。第 2 の SQL は PADDED されません。LEGACY スタイルとは異なり、第 2 の SQL ステートメントには固定サイズがなく、次の SQL は動的に作成されます。
      クエリーが 30 個の識別子を下回る場合、このスタイルは要求された識別子の数のみを動的に読み込みます。
  • コレクション当たりのレベル
    Hibernate では、上記の各クラス当たりのセクションにリストされているバッチフェッチサイズとスタイルを採用するロードコレクションのバッチ処理も可能です。
    前のセクションで使用した例を戻すには、各 owner オブジェクトが所有するすべての car オブジェクトをロードする必要があることを考慮してください。10 個の owner オブジェクトが現行セッションでロードされ、すべての owner で 反復すると、10 個の SELECT ステートメントが生成されます (getCars() メソッドへの呼び出しごと)。Owner のマッピングで cars コレクションのバッチフェッチを有効にすると、Hibernate は以下のようにこれらのコレクションの事前フェッチを実行できます。
    <class name="Owner"><set name="cars" batch-size="5"></set></class>
    したがって、バッチサイズが 5 で、レガシーバッチスタイルを使用して 10 のコレクションをロードする場合、Hibernate は 2 つの SELECT ステートメントを実行し、それぞれが 5 のコレクションを取得することになります。

13.8.2. 変更不可のデータのオブジェクト参照の 2 次レベルのキャッシング

Hibernate は、パフォーマンスを改善するために自動的にデータをメモリーにキャッシュします。これは、特にほとんど変更されないデータに対して、必要なデータベースルックアップ回数を減らすインメモリーキャッシュによって実現されます。
Hibernate は以下の種類のキャッシュを維持します。(1 次キャッシュとも呼ばれる) プライマリーキャッシュは必須です。このキャッシュは現行セッションと関連付けられ、すべてのリクエストがそのセッションを通過する必要があります。セカンダリーキャッシュとも呼ばれる 2 次キャッシュは任意で、プライマリーキャッシュが最初に参照された後にのみ参照されます。
データは、最初にデータを状態アレイにアセンブルすることで 2 次キャッシュに保存されます。このアレイはディープコピーされ、そのディープコピーがキャッシュに配置されます。その逆は、キャッシュからの読み取りに対して行われます。これは、変更 (変更不能データ) が変更できないデータには適切に機能しますが、変更できないデータには効率的ではありません。
データのディープコピーは、メモリー使用量と処理速度に関する負荷のかかる操作です。大きなデータセットでは、メモリーと処理速度がパフォーマンス制限の要因となります。Hibernate では、変更不能なデータがコピーされるのではなく、参照されるように指定できます。Hibernate は、データセット全体をコピーする代わりに、キャッシュのデータへの参照を保管できるようになりました。
これは、設定設定の値を変更することで実行できますhibernate.cache.use_reference_entriestrue。デフォルトでは、hibernate.cache.use_reference_entriesに設定されていますfalse
いつhibernate.cache.use_reference_entriesに設定されていますtrue、関連付けのない不変のデータオブジェクトは、第 2 レベルのキャッシュにコピーされず、そのオブジェクトへの参照のみが保存されます。
警告
いつhibernate.cache.use_reference_entriesに設定されていますtrue、関連付けのある不変のデータオブジェクトは、引き続き第 2 レベルのキャッシュに深くコピーされます。

第15章 JAX-RSWeb サービス

15.1. JAX-RS について

JAX-RS は RESTful Web サービスの Java API です。これは、アノテーションを使用して REST を使用した Web サービスを構築することをサポートします。これらのアノテーションは、Java オブジェクトを Web リソースにマッピングするプロセスを簡素化します。この仕様は、に定義されてい http://www.jcp.org/en/jsr/detail?id=311 ます。
RESTEasy は、JAX-RS の JBoss EAP 6 実装です。また、この仕様に追加機能も提供します。
JBoss EAP 6 は JSR311-JAX-RS に準拠しています。
JAX-RS および JBoss EAP 6 の使用を開始するには、以下を参照してください。helloworld-rsjax-rs-client、とkitchensinkクイックスタート:「クイックスタートにアクセスする」

15.2. RESTEasy について

RESTEasy は、JAX-RSJavaAPI の移植可能な実装です。また、送信要求をリモートサーバーにマッピングするためのクライアント側フレームワーク (RESTEasy JAX-RS クライアントフレームワーク) などの追加機能を提供し、JAX-RS がクライアントまたはサーバー側の仕様として動作できるようにします。

15.3. RESTfulWeb サービスについて

RESTful Web サービスは、Web 上で API を公開するように設計されています。クライアントが予測可能な URL を使用してデータとリソースにアクセスできるようにすることで、従来の Web サービスよりも優れたパフォーマンス、スケーラビリティ、および柔軟性を提供することを目的としています。
RESTful サービスの JavaEnterpriseEdition6 仕様は JAX-RS です。JAX-RS の詳細については、を参照してください。「JAX-RS について」「RESTEasy について」

15.4. RESTEasy で定義された注釈

表15.1 JAX-RS/RESTEasy アノテーション

アノテーション 用途
ClientResponseType これは、応答タイプが返される RESTEasy クライアントインターフェイスに追加できる注釈です。
ContentEncoding アノテーション付きのアノテーションで適用する Content-Encoding を指定するメタアノテーション。
DecorateTypes サポートされているタイプを指定するには、DecoratorProcessor クラスに配置する必要があります。
Decorator デコレーションをトリガーする別のアノテーションに配置されるメタアノテーション。
Form これは、リクエストと要求の発信および受信を行うためにオブジェクトとして使用できます。
StringParameterUnmarshallerBinder 文字列ベースのアノテーションインジェクターに適用されるように StringParameterUnmarshaller をトリガーする別のアノテーションに配置されるメタアノテーション。
Cache 応答の Cache-Control ヘッダーを自動的に設定します。
NoCache nocache の Cache-Control 応答ヘッダーを設定します。
ServerCached この jax-rs メソッドへの応答をサーバーにキャッシュする必要があることを指定します。
ClientInterceptor インターセプターをクライアント側のインターセプターとして特定します。
DecoderPrecedence このインターセプターは、コンテンツエンコーディングデコーダーです。
EncoderPrecedence このインターセプターは、コンテンツエンコーディングエンコーダーです。
HeaderDecoratorPrecedence HeaderDecoratorPrecedence インターセプターは、応答 (サーバー上) または送信要求 (クライアント上) を特別なユーザー定義のヘッダーで装飾するため、常に最初に来る必要があります。
RedirectPrecedence PreProcessInterceptor に配置する必要があります。
SecurityPrecedence PreProcessInterceptor に配置する必要があります。
ServerInterceptor インターセプターをサーバー側のインターセプターとして特定します。
NoJackson Jackson プロバイダーをトリガーしない場合にクラス、パラメーター、フィールド、またはメソッドに配置します。
ImageWriterParams IIOImageProvider にパラメーターを渡すためにリソースクラスが使用できるアノテーション。
DoNotUseJAXBProvider このクラスまたはパラメーターは、JAXB MessageBodyReader/Writer を使用せず、代わりにタイプをマーシャリングするために使用するより具体的なプロバイダーがある場合に使用してください。
Formatted インデントと改行で XML 出力をフォーマットします。これは、JAXB Decorator です。
IgnoreMediaTypes タイプ、メソッド、パラメーター、またはフィールドにフィールドを置くと、特定のメディアタイプに対して JAXRS プロバイダーを使用しないように指示します。
Stylesheet XML スタイルシートヘッダーを指定します。
Wrapped これをメソッドまたはパラメーターに配置すると、指定のオブジェクトのコレクションまたは配列をマーシャリングまたはマーシャリング解除できます。
WrappedMap これは、JAXB オブジェクトのマップのマーシャリングまたはマーシャリング解除を行う場合は、メソッドまたはパラメーターに配置します。
XmlHeader 返されたドキュメントの XML ヘッダーを設定します。
BadgerFish A JSONConfig.
Mapped A JSONConfig.
XmlNsMap A JSONToXml.
MultipartForm これは、multipart/form-data mime タイプの受信/発進のオブジェクトとして使用できます。
PartType List または Map を multipart/* タイプとして書き出す場合は、Multipart プロバイダーと併用する必要があります。
XopWithMultipartRelated このアノテーションは、アノテーション付きのオブジェクト間の XOP メッセージの受信/送信 (multipart / 関連としてパッケージ化) の処理と生成に使用できます。
After 署名時に有効期限属性を追加するため、または検証のための古いチェックとして使用されます。
Signed DOSETA 仕様を使用して要求または応答の署名をトリガーするコンビニエンスアノテーション。
Verify 署名ヘッダーで指定された入力署名の検証。
Path これは、クラスまたはリソースメソッドに存在する必要があります。両方に存在する場合、リソースメソッドへの相対パスはクラスとメソッドの連結になります。
PathParam 変数 URI パスのフラグメントをメソッド呼び出しにマッピングできるようにします。
QueryParam URI クエリー文字列パラメーターまたは URL 形式のエンコードされたパラメーターをメソッド呼び出しにマップできるようにします。
CookieParam HTTP リクエスト cookie のクッキーまたはオブジェクト表現の値をメソッド呼び出しに指定できます。
DefaultValue HTTP リクエスト項目が存在しない場合にデフォルト値を定義するために、その他の @*Param アノテーションと組み合わせることができます。
Context javax.ws.rs.core.HttpHeaders、javax.ws.rs.core.UriInfo、javax.ws.rs.core.Request、javax.servlet.HttpServletRequest、javax.servlet.HttpServletResponse、javax.ws.rs.core.SecurityContext オブジェクトのインスタンスを指定できます。
Encoded クラス、メソッド、またはパラメーターで使用できます。デフォルトでは、@PathParam および @QueryParams はデコードされます。@Encoded アノテーションを追加すると、これらのパラメーターの値がエンコードされた形式で提供されます。

15.5. RESTEasy 設定

15.5.1. RESTEasy 設定パラメーター

表15.2 要素

オプション名 デフォルト値 説明
resteasy.servlet.mapping.prefix デフォルトなし Resteasy servlet-mapping の url パターンが /*ではない場合。
resteasy.scan false @Provider および JAX-RS リソースクラス (@Path、@GET、@POST など) の両方に対して WEB-INF/lib JARs および WEB-INF/classes を自動的にスキャンします。
resteasy.scan.providers false @Provider クラスをスキャンして登録します。
resteasy.scan.resources false JAX-RS リソースクラスのスキャン。
resteasy.providers デフォルトなし 登録する完全修飾 @Provider クラス名のコンマ区切りリスト。
resteasy.use.builtin.providers true デフォルトのビルトイン @Provider クラスを登録するかどうか。
resteasy.resources デフォルトなし 登録する完全修飾 JAX-RS リソースクラス名のコンマ区切りリスト。
resteasy.jndi.resources デフォルトなし JAX-RS リソースとして登録するオブジェクトを参照する JNDI 名のカンマ区切りリスト。
javax.ws.rs.Application デフォルトなし 仕様移植可能な方法でブートストラップする Application クラスの完全修飾名。
resteasy.media.type.mappings デフォルトなし ファイル名の拡張子 (例: .xml や txt) をメディアタイプにマッピングすることで、Accept ヘッダーの必要性を置き換えます。クライアントが Accept ヘッダーを使用して表示 (ブラウザーなど) を選択できない場合に使用されます。
resteasy.language.mappings デフォルトなし ファイル名の拡張子 (.en または .fr など) を言語にマッピングすることで、Accept-Language ヘッダーの必要性を置き換えます。クライアントが Accept-Language ヘッダーを使用して言語 (ブラウザーなど) を選択できない場合に使用されます。
resteasy.document.expand.entity.references false 外部エンティティーを展開するか、空の文字列に置き換えるか。JBoss EAP 6 では、このパラメーターのデフォルトは false であるため、空の文字列に置き換わります。
resteasy.document.secure.processing.feature true org.w3c.dom.Document ドキュメントとつの JAXB オブジェクト表現を処理する際にセキュリティー制約を課します。
resteasy.document.secure.disableDTDs true org.w3c.dom.Document ドキュメントおよび JAXB オブジェクトの表現を禁止します。
重要
サーブレット 3.0 コンテナーでは、resteasy.scan.* ファイルの web.xml 設定は無視され、すべての JAX-RS アノテーションが付けられたコンポーネントが自動的にスキャンされます。

15.6. JAX-RSWeb サービスセキュリティー

15.6.1. RESTEasy JAX-RS Web サービスのロールベースのセキュリティーの有効化

概要

RESTEasy は JAX-RS メソッドでの @RolesAllowed、@PermitAll、@DenyAll アノテーションに対応しています。ただし、デフォルトではこれらの注釈は認識されません。以下の手順に従って、web.xml ファイルを設定し、ロールベースのセキュリティーを有効にします。

警告
以下の RESTEasy パラメーターのデフォルト値を変更すると、RESTEasy アプリケーションが XXE 攻撃に対して潜在的に脆弱になる可能性があります。
  • resteasy.document.expand.entity.references
  • resteasy.document.secure.processing.feature
  • resteasy.document.secure.disableDTDs
これらのパラメーターの詳細については、を参照してください。「RESTEasy 設定パラメーター」
警告
アプリケーションが EJB を使用する場合は、ロールベースのセキュリティーをアクティベートしないでください。EJB コンテナーは RESTEasy ではなく機能を提供します。

手順15.1 RESTEasy JAX-RS Web サービスのロールベースのセキュリティーの有効化

  1. テキストエディターでアプリケーションの web.xml ファイルを開きます。
  2. 以下の <context-param> をファイルに、web-app 内に追加します。
    <context-param>
        <param-name>resteasy.role.based.security</param-name>
        <param-value>true</param-value>
    </context-param>
    
  3. <security-role> タグを使用して、RESTEasy JAX-RS WAR ファイル内で使用されるすべてのロールを宣言します。
    <security-role>
        <role-name>ROLE_NAME</role-name>
    </security-role>
    <security-role>
        <role-name>ROLE_NAME</role-name>
    </security-role>
  4. すべてのロールについて JAX-RS ランタイムによって処理されるすべての URL へのアクセスを承認します。
    <security-constraint>
        <web-resource-collection>
    	<web-resource-name>Resteasy</web-resource-name>
    	<url-pattern>/PATH</url-pattern>
        </web-resource-collection>
        <auth-constraint>
    	<role-name>ROLE_NAME</role-name>
    	<role-name>ROLE_NAME</role-name>
        </auth-constraint>
    </security-constraint>

結果

ロールベースのセキュリティーは、定義されたロールとともにアプリケーション内で有効にされています。

例15.1 例: ロールベースのセキュリティー設定

<web-app>

    <context-param>
	<param-name>resteasy.role.based.security</param-name>
	<param-value>true</param-value>
    </context-param>

    <servlet-mapping>
	<servlet-name>Resteasy</servlet-name>
	<url-pattern>/*</url-pattern>
    </servlet-mapping>

    <security-constraint>
	<web-resource-collection>
	    <web-resource-name>Resteasy</web-resource-name>
	    <url-pattern>/security</url-pattern>
	</web-resource-collection>
	<auth-constraint>
	    <role-name>admin</role-name>
	    <role-name>user</role-name>
	</auth-constraint>
    </security-constraint>

    <security-role>
	<role-name>admin</role-name>
    </security-role>
    <security-role>
	<role-name>user</role-name>
    </security-role>
    
</web-app>

15.6.2. アノテーションを使用して JAX-RSWeb サービスを保護する

概要

このトピックでは、サポートされているセキュリティーアノテーションを使用して JAX-RSWeb サービスを保護する手順について説明します。

手順15.2 サポートされているセキュリティーアノテーションを使用して JAX-RSWeb サービスを保護する

  1. ロールベースセキュリティーを有効化します。詳細は、「RESTEasy JAX-RS Web サービスのロールベースのセキュリティーの有効化」 を参照してください。
  2. JAX-RS Web サービスにセキュリティーアノテーションを追加します。RESTEasy は以下のアノテーションをサポートします。
    @RolesAllowed
    メソッドにアクセスできるロールを定義します。すべてのロールは web.xml ファイルで定義する必要があります。
    @PermitAll
    web.xml ファイルに定義されているすべてのロールがメソッドにアクセスできるようにします。
    @DenyAll
    メソッドへのすべてのアクセスを拒否します。

15.7. 例外処理

15.7.1. 例外マッパーを作成する

概要

例外マッパーは、出力された例外をキャッチし、特定の HTTP 応答を書き込むカスタムのアプリケーション提供コンポーネントです。

例15.2 例外マッパー

例外マッパーは、@ Provider アノテーションが付けられたクラスであり、ExceptionMapperインターフェイス。
例外マッパーの例を以下に示します。
@Provider
public class EJBExceptionMapper implements ExceptionMapper<javax.ejb.EJBException>
    {
    Response toResponse(EJBException exception) {
    return Response.status(500).build();
    }
}
例外マッパーを登録するには、web.xml ファイルのresteasy.providerscontext-param、またはプログラムで登録しますResteasyProviderFactoryクラス。

15.7.2. RESTEasy 内部で出力された例外

表15.3 例外リスト

例外 HTTP コード 説明
BadRequestException 400 正しくない要求。リクエストが適切にフォーマットされていなかったか、またはリクエスト入力の処理に問題がありました。
UnauthorizedException 401 承認されていません。RESTEasy のアノテーションベースのロールベースのセキュリティーを使用している場合には、セキュリティー例外が発生します。
InternalServerErrorException 500 内部サーバーエラー。
MethodNotAllowedException 405 リソースが呼び出した HTTP 操作を処理できる JAX-RS メソッドはありません。
NotAcceptableException 406 Accept ヘッダーに一覧表示されるメディアタイプを生成する JAX-RS メソッドはありません。
NotFoundException 404 リクエストパス/ リソースを提供する JAX-RS メソッドはありません。
ReaderException 400 から出力されたすべての例外MessageBodyReadersこの例外にラップされます。ない場合ExceptionMapperラップされた例外の場合、または例外がWebApplicationExceptionの場合、RESTEasy はデフォルトで 400 コードを返します。
WriterException 500 から出力されたすべての例外MessageBodyWritersこの例外にラップされます。ない場合ExceptionMapperラップされた例外の場合、または例外がWebApplicationExceptionの場合、RESTEasy はデフォルトで 400 コードを返します。
JAXBUnmarshalException 400 JAXB プロバイダー (XML および Jettison) は、読み取り時にこの例外を出力します。JAXBExceptions をラップしている可能性があります。このクラスは拡張しますReaderException
JAXBMarshalException 500 JAXB プロバイダー (XML および Jettison) は、書き込み時にこの例外を出力します。JAXBExceptions をラップしている可能性があります。このクラスは拡張しますWriterException
ApplicationException 該当なし アプリケーションコードから出力されたすべての例外をラップします。と同じように機能しますInvocationTargetException。ラップされた例外に対する ExceptionMapper がある場合は、要求の処理に使用されます。
失敗 該当なし 内部 RESTEasy エラー。ログに記録されない。
LoggableFailure 該当なし 内部 RESTEasy エラー。ログが記録されています。
DefaultOptionsMethodException 該当なし ユーザーが HTTP OPTIONS を呼び出しても、JAX-RS メソッドが呼び出されない場合、RESTEasy はこの例外を発生させてデフォルトの動作を提供します。

15.8. RESTEasy インターセプター

15.8.1. JAX-RS 呼び出しのインターセプト

概要

RESTEasy は JAX-RS 呼び出しをインターセプトし、インターセプターと呼ばれるリスナーのようなオブジェクトでそれらをルーティングできます。このトピックでは、4 種類のインターセプターについて説明します。

例15.3 MessageBodyReader/Writer インターセプター

MessageBodyReaderInterceptors と MessageBodyWriterInterceptors は、サーバー側またはクライアント側のいずれかで使用できます。それらには注釈が付けられています@Provider、およびいずれか@ServerInterceptorまた@ClientInterceptorRESTEasy がそれらをインターセプターリストに追加するかどうかを認識できるようにします。
これらのインターセプターは、MessageBodyReader.readFrom()またMessageBodyWriter.writeTo()。これらは、Output や Input ストリームをラップするために使用できます。
RESTEasy GZIP サポートには、デフォルトの出力ストリームと入力ストリームを作成して GzipOutputStream または GzipInputStream でオーバーライドするインターセプターがあり、gzip エンコードが機能します。また、クライアント側で応答または送信要求にヘッダーを追加するために使用することもできます。
public interface MessageBodyReaderInterceptor
  {
     Object read(MessageBodyReaderContext context) throws IOException, WebApplicationException;

  }

public interface MessageBodyWriterInterceptor
  {
     void write(MessageBodyWriterContext context) throws IOException, WebApplicationException;

  }
インターセプターと MessageBodyReader または Writer は、単一の大きな Java 呼び出しスタックで呼び出されます。MessageBodyReaderContext.proceed() またMessageBodyWriterContext.proceed()次のインターセプターに移動するために呼び出されます。呼び出すインターセプターがこれ以上ない場合は、readFrom()またwriteTo()MessageBodyReader または MessageBodyWriter のメソッド。このラッピングにより、オブジェクトは Reader や Writer に到達する前に変更でき、proceed() が返された後にクリーンアップされます。
以下の例は、ヘッダー値を応答に追加するサーバー側のインターセプターです。
@Provider
@ServerInterceptor
public class MyHeaderDecorator implements MessageBodyWriterInterceptor {

    public void write(MessageBodyWriterContext context) throws IOException, WebApplicationException
    {
       context.getHeaders().add("My-Header", "custom");
       context.proceed();
    }
}

例15.4 PreProcessInterceptor

PreProcessInterceptors は、JAX-RS リソースメソッドが呼び出されることが検出された後、実際の呼び出しが行われる前に実行されます。それらは @ServerInterceptor でアノテーションが付けられ、順番に実行されます。
これらのインターフェイスはサーバー上でのみ使用できます。これらは、セキュリティー機能を実装したり、Java 要求を処理したりするために使用できます。RESTEasy セキュリティーの実装では、このタイプのインターセプターを使用して、ユーザーが承認を渡さない場合に、要求が発生する前に要求を中止します。RESTEasy キャッシングフレームワークもこれを使用して、キャッシュされた応答を返し、メソッドが再度呼び出されないようにします。
public interface PreProcessInterceptor
    {
       ServerResponse preProcess(HttpRequest request, ResourceMethod method) throws Failure, WebApplicationException;
    }
の場合preProcess()メソッドが ServerResponse を返すと、基になる JAX-RS メソッドは呼び出されず、ランタイムは応答を処理してクライアントに戻ります。の場合preProcess()メソッドは ServerResponse を返さず、基礎となる JAX-RS メソッドが呼び出されます。

例15.5 PostProcessInterceptors

PostProcessInterceptors は、JAX-RS メソッドが呼び出された後、MessageBodyWriters が呼び出される前に実行されます。これらは、MessageBodyWriter が呼び出されない可能性があるときに応答ヘッダーを設定する必要がある場合に使用されます。
サーバー側でのみ使用できます。それらは何もラップせず、順番に呼び出されます。
public interface PostProcessInterceptor
  {
    void postProcess(ServerResponse response);
  }

例15.6 ClientExecutionInterceptors

ClientExecutionInterceptors は、クライアント側でのみ使用できます。これらは、サーバーに送信される HTTP 呼び出しをラップアラウンドします。それらには注釈を付ける必要があります@ClientInterceptor@Provider。これらのインターセプターは、MessageBodyWriter の後、および ClientRequest がクライアント側で構築された後に実行されます。
RESTEasy GZIP サポートは、ClientExecutionInterceptors を使用して、リクエストが送信される前に gzip、deflate を含むように Accept ヘッダーを設定します。RESTEasy クライアントキャッシュは、それを使用して、ネットワークを経由する前に、キャッシュにリソースが含まれているかどうかを確認します。
public interface ClientExecutionInterceptor
{
  ClientResponse execute(ClientExecutionContext ctx) throws Exception;
}

public interface ClientExecutionContext
{
  ClientRequest getRequest();

  ClientResponse proceed() throws Exception;
}

15.8.2. インターセプターを JAX-RS メソッドにバインドする

概要

登録されているすべてのインターセプターは、デフォルトですべての要求に対して呼び出されます。The AcceptedByMethodこの動作を微調整するためにインターフェイスを実装できます。

例15.7 バインディングインターセプターの例

RESTEasy は accept()を実装するインターセプターのメソッド AcceptedByMethodインターフェイス。メソッドが true を返す場合、インターセプターは JAX-RS メソッドのコールチェーンに追加されます。それ以外の場合は、そのメソッドでは無視されます。
以下の例では、 accept()@GET アノテーションが JAX-RS メソッドに存在するかどうかを判別します。そうである場合、インターセプターはメソッドの呼び出しチェーンに適用されます。
@Provider
@ServerInterceptor
public class MyHeaderDecorator implements MessageBodyWriterInterceptor, AcceptedByMethod {

    public boolean accept(Class declaring, Method method) {
       return method.isAnnotationPresent(GET.class);
    }

   public void write(MessageBodyWriterContext context) throws IOException, WebApplicationException
   {
      context.getHeaders().add("My-Header", "custom");
      context.proceed();
   }
}

15.8.3. インターセプターを登録する

概要

このトピックでは、RESTEasyJAX-RS インターセプターをアプリケーションに登録する方法について説明します。

手順15.3 インターセプターを登録する

  • インターセプターを登録するには、以下の web.xml ファイルにインターセプターをリストします。resteasy.providerscontext-param、またはクラスまたはオブジェクトとして返しますApplication.getClasses()またApplication.getSingletons()方法。

例15.8 web.xml ファイル にインターセプターをリストして登録します。

<context-param>
	<param-name>resteasy.providers</param-name>
	<param-value>my.app.CustomInterceptor</paramvalue>
</context-param>

例15.9 Application.getClasses () メソッドを使用したインターセプターの登録:

package org.jboss.resteasy.example;

import javax.ws.rs.core.Application;
import java.util.HashSet;
import java.util.Set;

public class MyApp extends Application {

  public java.util.Set<java.lang.Class<?>> getClasses() {
    Set<Class<?>> resources = new HashSet<Class<?>>();
    resources.add(MyResource.class);
    resources.add(MyProvider.class);
    return resources;
  }
}

例15.10 Application.getSingletons () メソッドを使用したインターセプターの登録:

package org.jboss.resteasy.example;

import javax.ws.rs.core.Application;
import java.util.HashSet;
import java.util.Set;

public class MyApp extends Application {

   protected Set<Object> singletons = new HashSet<Object>();

   public PubSubApplication() {
     singletons.add(new MyResource());
     singletons.add(new MyProvider());
   }
   
   @Override
   public Set<Object> getSingletons() {
     return singletons;
   }
}

15.8.4. インターセプター優先ファミリー

15.8.4.1. インターセプター優先ファミリーについて

概要

インターセプターは、呼び出される順序に敏感になる可能性があります。RESTEasy は、インターセプターをファミリーにグループ化して、順序付けを簡単にします。このリファレンストピックでは、組み込みのインターセプター優先順位ファミリーとそれぞれに関連付けられたインターセプターについて説明します。

5 つの事前定義されたファミリーがあります。これらは次の順序で呼び出されます。
セキュリティー
SECURITY インターセプターは通常 PreProcessInterceptors です。呼び出しが許可される前に実行する必要があるのは可能な限り少ないため、最初に呼び出されます。
HEADER_DECORATOR
HEADER_DECORATOR インターセプターは、応答または送信要求にヘッダーを追加します。追加されたヘッダーが他のインターセプターファミリーの動作に影響を与える可能性があるため、これらはセキュリティーインターセプターに従います。
エンコーダー
ENCODER インターセプターは OutputStream を変更します。たとえば、GZIP インターセプターは GZIPOutputStream を作成して、圧縮のために実際の OutputStream をラップします。
REDIRECT
REDIRECT インターセプターは、リクエストを再ルーティングして JAX-RS メソッドを完全にバイパスする可能性があるため、通常 PreProcessInterceptors で使用されます。
デコーダ
DECODER インターセプターは InputStream をラップします。たとえば、GZIP インターセプターデコーダーは InputStream を GzipInputStream インスタンスにラップします。
完全な型の安全性のために、便利な注釈がありますorg.jboss.resteasy.annotations.interceptionパッケージ:@DecoredPrecedence@EncoderPrecedence@HeaderDecoratorPrecedence@RedirectPrecedence@SecurityPrecedence。の代わりにこれらを使用してください@Precedence注釈。詳細は、「RESTEasy で定義された注釈」 を参照してください。

15.8.4.2. カスタムインターセプター優先順位ファミリーを定義する

概要

カスタム優先順位ファミリーを作成して、web.xml ファイルに登録できます。このトピックでは、インターセプター優先順位ファミリーを定義するために使用できるコンテキストパラメーターの例について説明します。

新しい優先順位ファミリーを定義するために使用できる 3 つのコンテキストパラメーターがあります。

例15.11 resteasy.append.interceptor.precedence

Theresteasy.append.interceptor.precedencecontext param は、新しい優先順位ファミリーをデフォルトの優先順位ファミリーリストに追加します。
<context-param>
    <param-name>resteasy.append.interceptor.precedence</param-name>
    <param-value>CUSTOM_PRECEDENCE_FAMILY</param-value>
</context-param>

例15.12 resteasy.interceptor.before.precedence

Theresteasy.interceptor.before.precedencecontext param は、カスタムファミリーが以前に実行されるデフォルトの優先順位ファミリーを定義します。パラメーター値は、':' で区切られた DEFAULT_PRECEDENCE_FAMILY/CUSTOM_PRECEDENCE_FAMILY の形式を取ります。
<context-param>
    <param-name>resteasy.interceptor.before.precedence</param-name>
    <param-value>DEFAULT_PRECEDENCE_FAMILY : CUSTOM_PRECEDENCE_FAMILY</param-value>
</context-param>

例15.13 resteasy.interceptor.after.precedence

Theresteasy.interceptor.after.precedencecontext param は、カスタムファミリーが実行されるデフォルトの優先ファミリーを定義します。パラメーター値は、: で区切られた DEFAULT_PRECEDENCE_FAMILY/CUSTOM_PRECEDENCE_FAMILY の形式を取ります。
<context-param>
    <param-name>resteasy.interceptor.after.precedence</param-name>
    <param-value>DEFAULT_PRECEDENCE_FAMILY : CUSTOM_PRECEDENCE_FAMILY</param-value>
</context-param>
優先順位ファミリーは、@Precedence アノテーションを使用してインターセプターに適用されます。デフォルトの優先ファミリーリストについては、以下を参照してください。「インターセプター優先ファミリーについて」

15.9. 文字列ベースの注釈

15.9.1. 文字列ベースの @*Param アノテーションをオブジェクトに変換する

@QueryParam、@MatrixParam、@HeaderParam、@PathParam、@FormParam を含む JAX-RS @*Param アノテーションは、raw HTTP リクエストで文字列として表されます。これらのタイプのインジェクトされたパラメーターは、それらのオブジェクトに valueOf(String) 静的メソッドまたは String パラメーターを取るコンストラクターがある場合に、オブジェクトに変換できます。
RESTEasy は 2 つの独自仕様を提供します@Providerどちらも持たないクラスのこの変換を処理するためのインターフェイスvalueOf(String)静的メソッド、または文字列コンストラクタ。

例15.14 StringConverter

StringConverter インターフェイスは、カスタム文字列マーシャリングを提供するために実装されています。これは、web.xml ファイルの resteasy.providerscontext-param に登録されています。ResteasyProviderFactory.addStringConverter () メソッドを呼び出して手動で登録することもできます。
以下の例は、StringConverter を使用する簡単な例です。
import org.jboss.resteasy.client.ProxyFactory;
import org.jboss.resteasy.spi.StringConverter;
import org.jboss.resteasy.test.BaseResourceTest;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import javax.ws.rs.HeaderParam;
import javax.ws.rs.MatrixParam;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.ext.Provider;

public class StringConverterTest extends BaseResourceTest
{
  public static class POJO
  {
     private String name;

     public String getName()
     {
	return name;
     }

     public void setName(String name)
     {
	this.name = name;
     }
  }

  @Provider
  public static class POJOConverter implements StringConverter<POJO>
  {
     public POJO fromString(String str)
     {
	System.out.println("FROM STRNG: " + str);
	POJO pojo = new POJO();
	pojo.setName(str);
	return pojo;
     }

     public String toString(POJO value)
     {
	return value.getName();
     }
  }

  @Path("/")
  public static class MyResource
  {
     @Path("{pojo}")
     @PUT
     public void put(@QueryParam("pojo")POJO q, @PathParam("pojo")POJO pp,
		     @MatrixParam("pojo")POJO mp, @HeaderParam("pojo")POJO hp)
     {
	Assert.assertEquals(q.getName(), "pojo");
	Assert.assertEquals(pp.getName(), "pojo");
	Assert.assertEquals(mp.getName(), "pojo");
	Assert.assertEquals(hp.getName(), "pojo");
     }
  }

  @Before
  public void setUp() throws Exception
  {
     dispatcher.getProviderFactory().addStringConverter(POJOConverter.class);
     dispatcher.getRegistry().addPerRequestResource(MyResource.class);
  }

  @Path("/")
  public static interface MyClient
  {
     @Path("{pojo}")
     @PUT
     void put(@QueryParam("pojo")POJO q, @PathParam("pojo")POJO pp,
	      @MatrixParam("pojo")POJO mp, @HeaderParam("pojo")POJO hp);
  }

  @Test
  public void testIt() throws Exception
  {
     MyClient client = ProxyFactory.create(MyClient.class, "http://localhost:8081");
     POJO pojo = new POJO();
     pojo.setName("pojo");
     client.put(pojo, pojo, pojo, pojo);
  }
}

例15.15 StringParameterUnmarshaller

TheStringParameterUnmarshallerインターフェイスは、挿入するパラメーターまたはフィールドに配置された注釈に敏感です。インジェクターごとに作成されます。setAnnotations () メソッドは、アンマーシャラーを初期化するために resteasy によって呼び出されます。
このインターフェイスは、インターフェイスを実装するプロバイダーを作成して登録することで追加できます。と呼ばれるメタアノテーションを使用してバインドすることもできます org.jboss.resteasy.annotations.StringsParameterUnmarshallerBinder
以下の例では、java.util.Dateベースの @PathParam。
public class StringParamUnmarshallerTest extends BaseResourceTest
{
   @Retention(RetentionPolicy.RUNTIME)
   @StringParameterUnmarshallerBinder(DateFormatter.class)
   public @interface DateFormat
   {
      String value();
   }

   public static class DateFormatter implements StringParameterUnmarshaller<Date>
   {
      private SimpleDateFormat formatter;

      public void setAnnotations(Annotation[] annotations)
      {
         DateFormat format = FindAnnotation.findAnnotation(annotations, DateFormat.class);
         formatter = new SimpleDateFormat(format.value());
      }

      public Date fromString(String str)
      {
         try
         {
            return formatter.parse(str);
         }
         catch (ParseException e)
         {
            throw new RuntimeException(e);
         }
      }
   }

   @Path("/datetest")
   public static class Service
   {
      @GET
      @Produces("text/plain")
      @Path("/{date}")
      public String get(@PathParam("date") @DateFormat("MM-dd-yyyy") Date date)
      {
         System.out.println(date);
         Calendar c = Calendar.getInstance();
         c.setTime(date);
         Assert.assertEquals(3, c.get(Calendar.MONTH));
         Assert.assertEquals(23, c.get(Calendar.DAY_OF_MONTH));
         Assert.assertEquals(1977, c.get(Calendar.YEAR));
         return date.toString();
      }
   }

   @BeforeClass
   public static void setup() throws Exception
   {
      addPerRequestResource(Service.class);
   }

   @Test
   public void testMe() throws Exception
   {
      ClientRequest request = new ClientRequest(generateURL("/datetest/04-23-1977"));
      System.out.println(request.getTarget(String.class));
   }
}
@DateFormat と呼ばれる新しいアノテーションを定義します。アノテーションは、DateFormater クラスへの参照を含むメタアノテーション StringParameterUnmarshallerBinder でアノテーションが付けられます。
Service.get () メソッドには @PathParam パラメーターがあり、これにも @DateFormat アノテーションが付けられています。@DateFormat を適用すると、DateFormatter のバインドがトリガーされます。これで、DateFormatter が実行され、パスパラメーターが get () メソッドの日付パラメーターにアンマーシャリングされます。

15.10. ファイル拡張子を設定する

15.10.1. web.xml ファイルのメディアタイプにファイル拡張子をマップします

概要

ブラウザーなどの一部のクライアントは、Accept および Accept-Language ヘッダーを使用して、表現メディアタイプまたは言語をネゴシエートできません。RESTEasy は、この問題に対処するために、ファイル名サフィックスをメディアタイプおよび言語にマップできます。次の手順に従って、web.xml ファイルでメディアタイプをファイル拡張子にマップします。

手順15.4 メディアタイプをファイル拡張子にマップする

  1. テキストエディターでアプリケーションの web.xml ファイルを開きます。
  2. context-param を追加しますresteasy.media.type.mappingsファイルに、内部web-appタグ:
    <context-param>
        <param-name>resteasy.media.type.mappings</param-name>
    </context-param>
    
  3. パラメーター値を設定します。マッピングはコンマ区切りのリストを形成します。各マッピングは、::

    例15.16 マッピングの例

    <context-param>
        <param-name>resteasy.media.type.mappings</param-name>
        <param-value>html : text/html, json : application/json, xml : application/xml</param-value>
    </context-param>
    

15.10.2. ファイル拡張子を web.xml ファイルの言語にマップする

概要

ブラウザーなどの一部のクライアントは、Accept および Accept-Language ヘッダーを使用して、表現メディアタイプまたは言語をネゴシエートできません。RESTEasy は、この問題に対処するために、ファイル名サフィックスをメディアタイプおよび言語にマップできます。以下の手順に従い、web.xml ファイルのファイル拡張子に言語をマッピングします。

手順15.5 ファイル拡張子を web.xml ファイルの言語にマップする

  1. テキストエディターでアプリケーションの web.xml ファイルを開きます。
  2. context-param を追加しますresteasy.language.mappingsファイルに、内部web-appタグ:
    <context-param>
        <param-name>resteasy.language.mappings</param-name>
    </context-param>
    
  3. パラメーター値を設定します。マッピングはコンマ区切りのリストを形成します。各マッピングは、::

    例15.17 マッピングの例

    <context-param>
        <param-name>resteasy.language.mappings</param-name>
        <param-value> en : en-US, es : es, fr : fr</param-name>
    </context-param>
    

15.10.3. RESTEasy がサポートするメディアタイプ

表15.4 メディアタイプ

メディアタイプ Java タイプ
application/*+xml, text/*+xml, application/*+json, application/*+fastinfoset, application/atom+* JaxB アノテーション付きクラス
application/*+xml, text/*+xml org.w3c.dom.Document
*/* java.lang.String
*/* java.io.InputStream
text/plain プリミティブ、java.lang.String、または String コンストラクターを持つタイプ、または入力用の静的 valueOf(String) メソ背戸、出力用の toOf() メソッド。
*/* javax.activation.DataSource
*/* byte[]
*/* java.io.File
application/x-www-form-urlencoded javax.ws.rs.core.MultivaluedMap

15.11. RESTEasy JavaScript API

15.11.1. RESTEasy JavaScript API について

RESTEasy は、AJAX 呼び出しを使用して JAX-RS 操作を呼び出す JavaScript API を生成できます。各 JAX-RS リソースクラスは、宣言するクラスまたはインターフェースと同じ名前の JavaScript オブジェクトを生成します。JavaScript オブジェクトには、各 JAX-RS メソッドがプロパティーとして含まれています。

例15.18 単純な JAX-RSJavaScriptAPI の例

@Path("foo")
public class Foo{
 @Path("{id}")
 @GET
 public String get(@QueryParam("order") String order, @HeaderParam("X-Foo") String header,
                   @MatrixParam("colour") String colour, @CookieParam("Foo-Cookie") String cookie){
  &
 }
 @POST
 public void post(String text){
 }
}
次のコードを使用して、JavaScript で以前の JAX-RSAPI を使用できます。
var text = Foo.get({order: 'desc', 'X-Foo': 'hello',
                    colour: 'blue', 'Foo-Cookie': 123987235444});
Foo.put({$entity: text});
各 JavaScript API メソッドは、任意のオブジェクトを単一のパラメーターとして取得します。ここでの各プロパティーは名前で識別される Cookie、ヘッダー、パス、クエリーまたはフォームパラメーター、または API パラメータープロパティーです。プロパティーはここで利用できます:「RESTEasy JavaScript API パラメーター」

15.11.2. RESTEasy JavaScript API サーブレットの有効化

概要

RESTEasyJavaScriptAPI はデフォルトでは有効になっていません。次の手順に従って、web.xml ファイルを使用して有効にします。

手順15.6 web.xml を編集して、RESTEasyJavaScriptAPI を有効にします

  1. テキストエディターでアプリケーションの web.xml ファイルを開きます。
  2. 次の設定をファイル内のweb-appタグ:
    <servlet>
        <servlet-name>RESTEasy JSAPI</servlet-name>
        <servlet-class>org.jboss.resteasy.jsapi.JSAPIServlet</servlet-class>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>RESTEasy JSAPI</servlet-name>
        <url-pattern>/URL</url-pattern>
    </servlet-mapping>

15.11.3. RESTEasy JavaScript API パラメーター

表15.5 パラメータープロパティー

プロパティー デフォルト値 説明
$entity   PUT、POST 要求として送信するエンティティー。
$contentType   Content-Type ヘッダーとして送信されるボディーエンティティーの MIME タイプ。@Consumes アノテーションで決定されます。
$accepts */* Accept ヘッダーとして送信される許可される MIME タイプ。@Provides アノテーションで決定されます。
$callback   非同期呼び出しの関数 (httpCode、xmlHttpRequest、value) に設定します。これがない場合、呼び出しは同期され、値を返します。
$apiURL   最後のスラッシュを含まない JAX-RS エンドポイントのベース URI に設定します。
$username   ユーザー名およびパスワードが設定されている場合は、要求のクレデンシャルに使用されます。
$password   ユーザー名およびパスワードが設定されている場合は、要求のクレデンシャルに使用されます。

15.11.4. JavaScriptAPI を使用して AJAX クエリーを作成する

概要

RESTEasy JavaScript API を使用すると、手動で要求を作成することができます。このトピックでは、この動作の例について説明します。

例15.19 REST オブジェクト

REST オブジェクトを使用して、RESTEasyJavaScriptAPI クライアントの動作をオーバーライドできます。
// Change the base URL used by the API:
REST.apiURL = "http://api.service.com";

// log everything in a div element
REST.log = function(text){
 jQuery("#log-div").append(text);
};
REST オブジェクトには以下の読み書きプロパティーが含まれます。
apiURL
デフォルトでは、JAX-RS ルート URL に設定されています。要求の作成時にすべての JavaScript クライアント API 機能によって使用されます。
log
log: RESTEasy クライアント API ログを受信するために function(string) に設定します。これは、クライアント API のデバッグ、およびそれらを確認できる場所のログの配置を行う場合に便利です。

例15.20 REST.Request クラス

REST.Request クラスを使用して、カスタムリクエストを作成できます。
var r = new REST.Request();
r.setURI("http://api.service.com/orders/23/json");
r.setMethod("PUT");
r.setContentType("application/json");
r.setEntity({id: "23"});
r.addMatrixParameter("JSESSIONID", "12309812378123");
r.execute(function(status, request, entity){
 log("Response is "+status);
});

15.11.5. rest.Request クラスメンバー

表15.6 rest.Request クラス

メンバー 説明
execute(callback) 現在のオブジェクトに設定されたすべての情報でリクエストを実行します。値はオプションの引数コールバックに渡され、返されません。
setAccepts(acceptHeader) Accept 要求ヘッダーを設定します。デフォルトは "" です。
setCredentials(username, password) 要求の認証情報を設定します。
setEntity(entity) リクエストエンティティーを設定します。
setContentType(contentTypeHeader) Content-Type リクエストヘッダーを設定します。
setURI(uri) 要求 URI を設定します。絶対 URI である必要があります。
setMethod(method) 要求メソッドを設定します。デフォルトは GET です。
setAsync(async) リクエストを非同期にするかどうかを制御します。デフォルトは true です。
addCookie(name, value) 要求の実行時に現在のドキュメントに指定の Cookie を設定します。これは、ブラウザーで永続化されます。
addQueryParameter(name, value) クエリーパラメーターを URI クエリー部分に追加します。
addMatrixParameter(name, value) リクエスト URI の最後のパスセグメントにマトリクスパラメーター (path パラメーター) を追加します。
addHeader(name, value) 要求ヘッダーを追加します。

15.12. RESTEasy Asynchronous Job Service

15.12.1. RESTEasy 非同期ジョブサービスについて

RESTEasy Asynchronous Job Service は、HTTP プロトコルに非同期動作を追加するように設計されています。HTTP は同期プロトコルですが、非同期呼び出しについてはかすかな考えがあります。HTTP 1.1 202 accepted は、サーバーが処理応答を受信し、承認したものの、処理が完了していないことを示します。Asynchronous Job Service はこれに基づいてビルドされます。
サービスを有効にするには、以下を参照してください。「非同期ジョブサービスを有効にする」。サービスの仕組みの例については、を参照してください。「RESTEasy の非同期ジョブを設定する」

15.12.2. 非同期ジョブサービスを有効にする

手順15.7 web.xml ファイルを変更します

  • Asynchronous Job Service は web.xml ファイルで有効化します。
    <context-param>
        <param-name>resteasy.async.job.service.enabled</param-name>
        <param-value>true</param-value>
    </context-param>
    

結果

非同期ジョブサービスが有効になりました。設定オプションについては、以下を参照してください。「非同期ジョブサービス設定パラメーター」

15.12.3. RESTEasy の非同期ジョブを設定する

概要

本トピックでは、RESTEasy を使用した非同期ジョブのクエリーパラメーターの例について説明します。

警告
ロールベースのセキュリティーは、ポータブルに実装できないため Asynchronous Job Service とは連携しません。Asynchronous Job Service を使用する場合は、代わりに web.xml ファイルでの XML 宣言を使用してアプリケーションセキュリティーを確立する必要があります。
重要
GET、DELETE、および PUT メソッドは非同期的に呼び出すことができますが、これらのメソッドの HTTP 1.1 コントラクトが破損します。これらの呼び出しによってリソースが複数回呼び出されると、その状態が変更されることはありませんが、各呼び出しで新しいジョブエントリーとしてサーバーの状態が変更されます。

例15.21 非同期パラメーター

asynch クエリーパラメーターは、バックグラウンドで呼び出しを実行するために使用されます。202 Accepted 応答が返されます。また、バックグラウンドメソッドの応答がある場所を指す URL が含まれる場所のヘッダーも返されます。
POST http://example.com/myservice?asynch=true
上記の例では、202Accepted 応答が返されます。また、バックグラウンドメソッドの応答がある場所を指す URL のある場所のヘッダーも返します。以下は場所ヘッダーの例です。
HTTP/1.1 202 Accepted
Location: http://example.com/asynch/jobs/3332334
URI は以下の形式になります。
/asynch/jobs/{job-id}?wait={millisconds}|nowait=true
この URL では、GET、POST、および DELETE 操作を実行できます。
  • ジョブが完了したら、GET は応答として呼び出される JAX-RS リソースメソッドを返します。ジョブが完了していない場合、この GET は 202Accepted 応答コードを返します。GET を呼び出してもジョブは削除されないため、複数回呼び出すことができます。
  • POST はジョブの応答を読み取り、完了するとジョブを削除します。
  • DELETE は、ジョブキューを手動でクリーンアップするために呼び出されます。
    注記
    ジョブキューが満杯になると、DELETE を呼び出すことなく、メモリーから最も古いジョブを自動的に無効にします。

例15.22 待つ/待つ

GET および POST 操作では、を使用して最大待機時間を定義できます。waitnowaitクエリーパラメーター。の場合waitパラメーターが指定されていない場合、操作はデフォルトでnowait=true、およびジョブが完了していない場合はまったく待機しません。Thewaitパラメーターはミリ秒単位で定義されます。
POST http://example.com/asynch/jobs/122?wait=3000

例15.23 一方向パラメーター

RESTEasy は、ファイアアンドフォーゲットジョブをサポートします。onewayクエリーパラメーター。
POST http://example.com/myservice?oneway=true
上記の例では、202 Accepted 応答が返されますが、ジョブは作成されません。

15.12.4. 非同期ジョブサービス設定パラメーター

概要

以下の表は、非同期ジョブサービスの設定可能な context-params の詳細を示しています。これらのパラメーターは web.xml ファイルで設定できます。

表15.7 設定パラメーター

Parameter 説明
resteasy.async.job.service.max.job.results メモリーに一度に保持できるジョブ結果の数。デフォルト値は 100 です。
resteasy.async.job.service.max.wait クライアントがそのジョブをクエリーする際のジョブの最大待機時間。デフォルト値は 300000. です。
resteasy.async.job.service.thread.pool.size ジョブを実行するバックグラウンドスレッドのスレッドプールサイズ。デフォルト値は 100 です。
resteasy.async.job.service.base.path ジョブ URI のベースパスを設定します。デフォルト値は /asynch/jobs です。

例15.24 非同期ジョブ設定の例

<web-app>
    <context-param>
        <param-name>resteasy.async.job.service.enabled</param-name>
        <param-value>true</param-value>
    </context-param>

    <context-param>
        <param-name>resteasy.async.job.service.max.job.results</param-name>
        <param-value>100</param-value>
    </context-param>
    <context-param>
        <param-name>resteasy.async.job.service.max.wait</param-name>
        <param-value>300000</param-value>
    </context-param>
    <context-param>
        <param-name>resteasy.async.job.service.thread.pool.size</param-name>
        <param-value>100</param-value>
    </context-param>
    <context-param>
        <param-name>resteasy.async.job.service.base.path</param-name>
        <param-value>/asynch/jobs</param-value>
    </context-param>

    <listener>
        <listener-class>
            org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
        </listener-class>
    </listener>

    <servlet>
        <servlet-name>Resteasy</servlet-name>
        <servlet-class>
            org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
        </servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>Resteasy</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

</web-app>

15.13. RESTEasy JAXB

15.13.1. JAXB デコレータを作成する

概要

RESTEasy の資料プロバイダーには、Marshaller および Un Marketplaceler インスタンスを切り離すプラグ可能な方法があります。Marshaller または Unmarshaller インスタンスのいずれかをトリガーできるアノテーションが作成されます。このトピックでは、RESTEasy を使用して JAXB デコレータを作成する手順について説明します。

手順15.8 RESTEasy を使用したデコレーターの作成

  1. Processor クラスを作成します。

    1. DecoratorProcessor<Target, Annotation> を実装するクラスを作成します。ターゲットは JAXB Marshaller または Unmarshallerクラスのいずれかになります。アノテーションは、ステップ 2 で作成されます。
    2. クラスに @DecorateTypes アノテーションを付け、デコレーターがデコレートする必要のある MIME タイプを宣言します。
    3. 内でプロパティーまたは値を設定します decorate関数。

    例15.25 例: Processor クラス

    import org.jboss.resteasy.core.interception.DecoratorProcessor;
    import org.jboss.resteasy.annotations.DecorateTypes;
    
    import javax.xml.bind.Marshaller;
    import javax.xml.bind.PropertyException;
    import javax.ws.rs.core.MediaType;
    import javax.ws.rs.Produces;
    import java.lang.annotation.Annotation;
    
    @DecorateTypes({"text/*+xml", "application/*+xml"})
    public class PrettyProcessor implements DecoratorProcessor<Marshaller, Pretty>
    {
        public Marshaller decorate(Marshaller target, Pretty annotation,
    	  Class type, Annotation[] annotations, MediaType mediaType)
        {
    	target.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        }
    }
    
  2. アノテーションを作成します。

    1. @Decorator アノテーションが付けられたカスタムインターフェースを作成します。
    2. @Decorator アノテーションのプロセッサーおよびターゲットを宣言します。プロセッサーは、ステップ 1 で作成されます。ターゲットは JAXB Marshaller または Unmarshallerクラスのいずれかになります。

    例15.26 アノテーションの例

    import org.jboss.resteasy.annotations.Decorator;
    
    @Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    @Decorator(processor = PrettyProcessor.class, target = Marshaller.class)
    public @interface Pretty {}
    
  3. 手順 2 で作成したアノテーションを関数に追加して、入力または出力のいずれかがマーシャリングされるときにデコレートされるようにします。

結果

JAXB デコレータは、JAX-RSWeb サービス内で作成および適用されています。

15.13.2. アイザーおよび XML プロバイダー

RESTEasy は、XML に対する JAXB プロバイダーのサポートを容易にします。

@XmlHeader および @Stylesheet

RESTEasy は、@org.jboss.resteasy.annotations.providers.jaxb.XmlHeader注釈。以下に例を示します。

@XmlRootElement
public static class Thing
{
   private String name;

   public String getName()
   {
      return name;
   }

   public void setName(String name)
   {
      this.name = name;
   }
}

@Path("/test")
public static class TestService
{

   @GET
   @Path("/header")
   @Produces("application/xml")
   @XmlHeader("<?xml-stylesheet type='text/xsl' href='${baseuri}foo.xsl' ?>")
   public Thing get()
   {
      Thing thing = new Thing();
      thing.setName("bill");
      return thing;
   }
}
The@XmlHeaderXML 出力に XML スタイルシートヘッダーがあることを確認します。

RESTEasy にはスタイルシートヘッダーの便利なアノテーションがあります。以下に例を示します。
@XmlRootElement
public static class Thing
{
   private String name;

   public String getName()
   {
      return name;
   }

   public void setName(String name)
   {
      this.name = name;
   }
}

@Path("/test")
public static class TestService
{

   @GET
   @Path("/stylesheet")
   @Produces("application/xml")
   @Stylesheet(type="text/css", href="${basepath}foo.xsl")
   @Junk
   public Thing getStyle()
   {
      Thing thing = new Thing();
      thing.setName("bill");
      return thing;
   }
}

15.13.3. JAXB および JSON プロバイダー

RESTEasy を使用すると、JAXB アノテーション付き POJO を JSON との間でマーシャリングできます。このプロバイダーは、このタスクを実行するために Jettison JSON ライブラリーをラップします。Jettison の詳細と、その仕組みについては、を参照し http://jettison.codehaus.org/ てください。
<dependency>
	<groupId>org.jboss.resteasy</groupId>
	<artifactId>resteasy-jettison-provider</artifactId>
	<version>${version.org.jboss.resteasy}</version>
	<scope>provided</scope>
</dependency>
Jettison には 2 つのマッピング形式があります。1 つは BadgerFish で、もう 1 つは Jettison にマップされたコンベンション形式です。マップされた規則がデフォルトです。JAXB + JSON プロバイダーと Jettison の統合の詳細については、以下を参照してください。 http://docs.jboss.org/resteasy/docs/2.3.7.Final/userguide/html_single/index.html

15.14. RESTEasy Atom サポート

15.14.1. AtomAPI とプロバイダーについて

RESTEasy Atom API およびプロバイダーは、RESTEasy が Atom を表すように定義する簡単なオブジェクトモデルです。API の主なクラスは org.jboss.resteasy.plugins.providers.atom パッケージにあります。RESTEasy は JAXB を使用して API のマーシャリングおよびマーシャリング解除に使用します。プロバイダーは JAXB ベースであり、XML を使用した Atom オブジェクトの送信に限定されません。RESTEasy が持つすべての JAXB プロバイダーは、JSON を含む Atom API およびプロバイダーによって再利用できます。API の詳細については、カスタマーサービスポータル から入手できる javadocs を参照してください。
import org.jboss.resteasy.plugins.providers.atom.Content;
import org.jboss.resteasy.plugins.providers.atom.Entry;
import org.jboss.resteasy.plugins.providers.atom.Feed;
import org.jboss.resteasy.plugins.providers.atom.Link;
import org.jboss.resteasy.plugins.providers.atom.Person;

@Path("atom")
public class MyAtomService
{

   @GET
   @Path("feed")
   @Produces("application/atom+xml")
   public Feed getFeed() throws URISyntaxException
   {
      Feed feed = new Feed();
      feed.setId(new URI("http://example.com/42"));
      feed.setTitle("My Feed");
      feed.setUpdated(new Date());
      Link link = new Link();
      link.setHref(new URI("http://localhost"));
      link.setRel("edit");
      feed.getLinks().add(link);
      feed.getAuthors().add(new Person("John Brown"));
      Entry entry = new Entry();
      entry.setTitle("Hello World");
      Content content = new Content();
      content.setType(MediaType.TEXT_HTML_TYPE);
      content.setText("Nothing much");
      entry.setContent(content);
      feed.getEntries().add(entry);
      return feed;
   }
}

15.14.2. Atom プロバイダーでの JAXB の使用

org.jboss.resteasy.plugins.providers.atom.Content クラスを使用すると、コンテンツのボディーであるアノテーション付きのオブジェクトのマーシャリングおよびマーシャリング解除できます。エントリーのコンテンツの本文として Customer オブジェクトが添付されたエントリーを送信する例を参照できます。
 
@XmlRootElement(namespace = "http://jboss.org/Customer")
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer
{
   @XmlElement
   private String name;

   public Customer()
   {
   }

   public Customer(String name)
   {
      this.name = name;
   }

   public String getName()
   {
      return name;
   }
}

@Path("atom")
public static class AtomServer
{
   @GET
   @Path("entry")
   @Produces("application/atom+xml")
   public Entry getEntry()
   {
      Entry entry = new Entry();
      entry.setTitle("Hello World");
      Content content = new Content();
      content.setJAXBObject(new Customer("bill"));
      entry.setContent(content);
      return entry;
   }
}
Content.setJAXBObject () メソッドは、適切にマーシャリングするために JavaJAXB オブジェクトに送り返すコンテンツオブジェクトを指定するために使用されます。XML とは異なるベース形式 (例: application/atom+json) を使用している場合、添付の Mission オブジェクトは同じ形式でマーシャリングされます。atom ドキュメントを入力として用意している場合は、Content.getJAXBObject(Class clazz) メソッドを使用して Content から正確な JAXB オブジェクトを抽出することもできます。これは、入力アトムドキュメントとコンテンツからの Customer オブジェクトの抽出の例です。
 
@Path("atom")
public static class AtomServer
{
   @PUT
   @Path("entry")
   @Produces("application/atom+xml")
   public void putCustomer(Entry entry)
   {
      Content content = entry.getContent();
      Customer cust = content.getJAXBObject(Customer.class);
   }
}

15.15. YAML プロバイダー

RESTEasy には、SnakeYAML ライブラリーを使用した YAML のサポートが同梱されています。YAML サポートを有効にするには、アプリケーションのプロジェクト pom ファイルに次の依存関係を挿入する必要があります。
<dependency>
	<groupId>org.jboss.resteasy</groupId>
	<artifactId>resteasy-yaml-provider</artifactId>
	<version>${version.org.jboss.resteasy}</version>
	<scope>provided</scope>
</dependency>

<dependency>
	<groupId>org.yaml</groupId>
	<artifactId>snakeyaml</artifactId>
	<version>${version.org.yaml.snakeyaml}</version>
</dependency>
YAML プロバイダーは以下の mime タイプを認識します。
  • text/x-yaml
  • text/yaml
  • application/x-yaml
次の例は、リソースメソッドで YAML を使用する方法を示しています。
import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;

 @Path("/yaml")
 public class YamlResource
 {

@GET
@Produces("text/x-yaml")
public MyObject getMyObject() {
   return createMyObject();
}
...
 }

15.16. EJB 統合

RESTEasy を EJB と統合するには、最初に EJB の公開されたインターフェイスを変更する必要があります。現在、RESTEasy には EJB との単純なポータブル統合しかないため、RESTEasywar ファイルも手動で設定する必要があります。
EJB を JAX-RS リソースとして機能させるには、SLSB に注釈を付ける必要があります。@Remoteまた@LocalJAX-RS アノテーションとのインターフェイス:
@Local
@Path("/Library")
public interface Library {
   @GET
   @Path("/books/{isbn}")
   public String getBook(@PathParam("isbn") String isbn);
}
@Stateless
public class LibraryBean implements Library {
...
}
次に、RESTEasy の web.xml ファイルで、を使用して EJB を RESTEasy に手動で登録する必要があります。 resteasy.jndi.resources <context-param>
<web-app>
   <display-name>Archetype Created Web Application</display-name>
   <context-param>
      <param-name>resteasy.jndi.resources</param-name>
      <param-value>LibraryBean/local</param-value>
   </context-param>
   <listener>
      <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
   </listener>
   <servlet>
      <servlet-name>Resteasy</servlet-name>
      <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
   </servlet>
   <servlet-mapping>
      <servlet-name>Resteasy</servlet-name>
      <url-pattern>/*</url-pattern>
   </servlet-mapping>
</web-app>

15.17. Jackson による JSON サポート

JSON 用の JettisonJAXB アダプターに加えて、RESTEasy は Jackson プロジェクトとの統合もサポートしています。Jackson を使用すると、JSON との間で Java オブジェクトをマーシャリングできます。これには、JavaBean ベースのモデルと JAXB のような API があります。
Jackson には独自の JAX-RS 統合が付属していますが、RESTEasy はそれを拡張します。プロジェクトに含めるには、次の Maven 依存関係をビルドに追加します。
<repository>
	<id>jboss</id>
	<url>>http://repository.jboss.org/nexus/content/groups/public/</url>
</repository>
...
<dependency>
	<groupId>org.jboss.resteasy</groupId>
	<artifactId>resteasy-jackson-provider</artifactId>
	<version>${version.org.jboss.resteasy}</version>
	<scope>provided</scope>
</dependency>
Jackson プロジェクトを介した JSON サポートの詳細については、を参照してください。 http://docs.jboss.org/resteasy/docs/2.3.7.Final/userguide/html_single/index.html

15.18. RESTEasy/Spring 統合

15.18.1. RESTEasy/Spring 統合

前提条件

  • アプリケーションに既存の JAX-WS サービスおよびクライアント設定を指定する必要があります。

手順15.9 RESTEasy/Spring 統合機能を有効にする

  • RESTEasy は Spring 3.0.x と統合します。
    Maven ユーザーは resteasy-spring アーティファクトを使用する必要があります。または、jar を JBoss EAP 6 のモジュールとして利用できます。
    RESTEasy には、Bean が BeanFactory によって作成されたときに JAX-RS アノテーションを処理する RESTEasy 固有の BeanPostProcessor を登録する独自の Spring ContextLoaderListener が付属しています。これは、RESTEasy が Bean クラスの @Provider および JAX-RS リソースアノテーションを自動的にスキャンして登録することを意味します。それらを JAX-RS リソースとして。

    例15.27 web.xml を編集します

    以下を web.xml ファイルに追加し、RESTEasy/Spring 統合機能を有効にします。
    <web-app>
    	<display-name>
    			Archetype Created Web Application
    	</display-name>
    	<listener>
       	<listener-class>
       		org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
      	</listener-class>
    	</listener>
    
    	<listener>
    	  <listener-class>
      	 		org.jboss.resteasy.plugins.spring.SpringContextLoaderListener
       	</listener-class>
    	</listener>
    
    	<servlet>
      	<servlet-name>Resteasy
      	</servlet-name>
      		<servlet-class>
      			org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
      		</servlet-class>
    	</servlet>
    
    	<servlet-mapping>
      	<servlet-name>
      		Resteasy
      	</servlet-name>
      	<url-pattern>/*</url-pattern>
    	</servlet-mapping>
    </web-app>
    
    
    SpringContextLoaderListener は、ResteasyBootstrap の後に宣言する必要があります。これは、初期化される ServletContext 属性を使用するためです。
RestEasy と Spring の統合の詳細については、を参照してください。 http://docs.jboss.org/resteasy/docs/2.3.7.Final/userguide/html_single/

第16章 JAX-WS Web Services

16.1. JAX-WSWeb サービスについて

XMLWeb サービス用の JavaAPI(JAX-WS) は、Java Enterprise Edition (EE) プラットフォームに含まれている API であり、Web サービスの作成に使用されます。Web サービスは、ネットワークを介して相互に通信するように設計されたアプリケーションであり、通常、XML またはその他の構造化テキスト形式で情報を交換します。Web サービスはプラットフォームに依存しません。典型的な JAX-WS アプリケーションは、クライアント/サーバーモデルを使用します。サーバーコンポーネントは、Web サービスエンドポイント と呼ばれます。
JAX-WS には、JAX-RS と呼ばれるプロトコルを使用する、より小さく単純な Web サービスに対応するものがあります。JAX-RS は、Representational State Transfer (REST) のプロトコルです。JAX-RS アプリケーションは通常軽量であり、通信は HTTP プロトコル自体のみに依存します。JAX-WS を使用すると、次のようなさまざまな Web サービス指向のプロトコルを簡単にサポートできます。WS-NotificationWS-AddressingWS-PolicyWS-Security、とWS-Trust。これらは、メッセージアーキテクチャーとメッセージ形式を定義する Simple Object Access Protocol (SOAP) と呼ばれる特殊な XML 言語を使用して通信します。
JAX-WS Web サービスには、特殊な XML ドキュメントタイプである Web サービス記述言語 (WSDL) で記述された、マシンで読み取り可能な操作の記述も含まれています。
Web サービスエンドポイントは、実装するクラスで設定されますWebServiceWebMethodインターフェイス。
Web サービスクライアントは、WSDL 定義から生成される スタブ と呼ばれるいくつかのクラスに依存するクライアントで設定されます。JBoss EAP 6 には、WSDL からクラスを生成するためのツールが含まれています。
JAX-WS Web サービスでは、Web サービスが提供するインターフェイスを記述するための正式な契約が確立されます。コントラクトは通常 WSDL で記述されますが、SOAP メッセージで記述される場合もあります。Web サービスのアーキテクチャーは通常、トランザクション、セキュリティー、メッセージング、調整などのビジネス要件に対応します。JBoss EAP 6 は、これらのビジネス上の懸念を処理するためのメカニズムを提供します。
Web サービス記述言語 (WSDL) は、Web サービスとそのアクセス方法を記述するために使用される XML ベースの言語です。Web サービス自体は、Java または別のプログラミング言語で記述されています。WSDL 定義は、インターフェイスへの参照、ポート定義、および他の Web サービスがネットワークを介して WSDL と対話する方法に関する指示で設定されています。Web サービスは、Simple Object Access Protocol (SOAP) を使用して相互に通信します。このタイプの Web サービスは、Representative State Transfer (REST) 設計原則を使用して構築された RESTfulWeb サービスとは対照的です。これらの RESTfulWeb サービスは WSDL または SOAP の使用を必要としませんが、他のサービスがそれらとどのように相互作用するかを定義するために HTTP プロトコル自体の構造に依存しています。
JBoss EAP 6 には JAX-WS Web Service エンドポイントデプロイのサポートが含まれています。このサポートは JBossWS によって提供されます。エンドポイント設定、ハンドラーチェーン、ハンドラーなどの Web サービスサブシステムの設定は、Web サービス サブシステムを介して提供されます。

実例

JBoss EAP クイックスタートには、完全に機能する JAX-WSWeb サービスアプリケーションがいくつか含まれています。これらの例は次のとおりです。

  • wsat-simple
  • wsba-coordinator-completion-simple
  • wsba-participant-completion-simple

16.2. Web サービスサブシステムを設定します

JBoss EAP 6 にデプロイされた Web サービスの動作を制御する Web サービスサブシステムでは、多くの設定オプションを使用できます。管理 CLI スクリプトの各要素を変更するコマンド (EAP_HOME/bin/jboss-cli.sh または EAP_HOME/bin/jboss-cli.bat) が提供されています。スタンドアロンサーバーのコマンドの /profile= default 部分を削除するか、default を設定するプロファイルの名前に置き換えます。

公開されたエンドポイントアドレス

エンドポイントで公開された WSDL コントラクトの <soap:address> 要素を書き換えることができます。この機能を使用して、各エンドポイントのクライアントにアドバタイズされるサーバーアドレスを制御できます。次の各オプション要素は、要件に合わせて変更できます。アクティブな WS 展開がある場合、これらの要素のいずれかを変更するには、サーバーをリロードする必要があります。

表16.1 公開されたエンドポイントアドレスの設定要素

要素 Description CLI コマンド
modify-wsdl-address
常に WSDL アドレスを変更するかどうか。true の場合、<soap:address> の内容は常に上書きされます。false の場合、<soap:address> のコンテンツは、有効な URL でない場合にのみ上書きされます。使用される値は、以下で説明する wsdl-hostwsdl-port、および wsdl-secure-port になります。
/profile=default/subsystem=webservices/:write-attribute(name=modify-wsdl-address,value=true)
wsdl-host
<soap:address> の書き換えに使用するホスト名/IP アドレス。wsdl-host が文字列 jbossws.undefined.host に設定されている場合、<soap:address> を書き換えるときにリクエスターのホストが使用されます。
/profile=default/subsystem=webservices/:write-attribute(name=wsdl-host,value=10.1.1.1)
wsdl-port SOAP アドレスの書き換えに使用される HTTP ポートを明示的に定義する整数。未定義の場合、HTTP ポートは、インストールされている HTTP コネクターのリストを照会することによって識別されます。
/profile=default/subsystem=webservices/:write-attribute(name=wsdl-port,value=8080)
wsdl-secure-port SOAP アドレスの書き換えに使用される HTTPS ポートを明示的に定義する整数。未定義の場合、HTTPS ポートは、インストールされている HTTPS コネクターのリストを照会することによって識別されます。
/profile=default/subsystem=webservices/:write-attribute(name=wsdl-secure-port,value=8443)

事前定義されたエンドポイント設定

エンドポイントの実装で参照できるエンドポイント設定を定義できます。これを使用する 1 つの方法は、アノテーションが付いた特定のエンドポイント設定でマークされた WS エンドポイントに特定のハンドラーを追加することです。@org.jboss.ws.api.annotation.EndpointConfig

JBoss EAP 6 にはデフォルトが含まれていますStandard-Endpoint-Config。カスタム設定の例、Recording-Endpoint-Config、も含まれています。これは、レコーディングハンドラーの例を提供します。TheStandard-Endpoint-Config他の設定に関連付けられていないエンドポイントに自動的に使用されます。
読むにはStandard-Endpoint-Config管理 CLI を使用して、次のコマンドを使用します。
/profile=default/subsystem=webservices/endpoint-config=Standard-Endpoint-Config/:read-resource(recursive=true,proxies=false,include-runtime=false,include-defaults=true)

エンドポイント設定

管理 API で endpoint-config と呼ばれるエンドポイント設定には、特定のエンドポイントに適用される pre-handler-chainpost-handler-chain、およびいくつかのプロパティーが含まれます。次のコマンドは、エンドポイント設定を読み取り、追加します。

例16.1 エンドポイント設定を読み取る

/profile=default/subsystem=webservices/endpoint-config=Recording-Endpoint-Config:read-resource

例16.2 エンドポイント設定を追加する

/profile=default/subsystem=webservices/endpoint-config=My-Endpoint-Config:add

ハンドラーチェーン

各エンドポイント設定は、PRE および POST ハンドラーチェーンに関連付けることができます。各ハンドラーチェーンには、JAXWS 準拠のハンドラーが含まれる場合があります。アウトバウンドメッセージの場合、PRE ハンドラーチェーンハンドラーは、@HandlerChain アノテーションなどの標準の JAX-WS を使用してエンドポイントにアタッチされたハンドラーの前に実行されます。POST ハンドラーチェーンハンドラーは、通常のエンドポイントハンドラーの後に実行されます。受信メッセージには、逆が適用されます。JAX-WS は XML ベースの Web サービスの標準 API で、で http://jcp.org/en/jsr/detail?id=224 説明されています。

ハンドラーチェーンには、チェーンの開始をトリガーするプロトコルを設定する protocol-bindings 属性を含めることもできます。

例16.3 ハンドラーチェーンを読む

/profile=default/subsystem=webservices/endpoint-config=Recording-Endpoint-Config/pre-handler-chain=recording-handlers:read-resource

例16.4 ハンドラーチェーンの追加

/profile=default/subsystem=webservices/endpoint-config=My-Endpoint-Config/post-handler-chain=my-handlers:add(protocol-bindings="##SOAP11_HTTP")

ハンドラー

JAXWS ハンドラーは、ハンドラーチェーン内の子要素 ハンドラー です。ハンドラーは、ハンドラークラスの完全修飾クラス名である クラス 属性を取ります。エンドポイントがデプロイされると、参照デプロイメントごとにそのクラスのインスタンスが作成されます。モジュールのデプロイメントクラ出力ダーまたはクラ出力ダーのいずれかorg.jboss.as.webservices.server.integrationハンドラークラスをロードできる必要があります。

例16.5 ハンドラーを読む

/profile=default/subsystem=webservices/endpoint-config=Recording-Endpoint-Config/pre-handler-chain=recording-handlers/handler=RecordingHandler:read-resource

例16.6 ハンドラーの追加

/profile=default/subsystem=webservices/endpoint-config=My-Endpoint-Config/post-handler-chain=my-handlers/handler=foo-handler:add(class="org.jboss.ws.common.invocation.RecordingServerHandler")

Web サービスランタイム情報

エンドポイント自体にクエリーを実行することで、Web コンテキストや WSDLURL などの Web サービスに関するランタイム情報を表示できます。* 文字を使用して、すべてのエンドポイントを一度に照会できます。次の例は、管理対象ドメイン内のサーバーとスタンドアロンサーバーの両方に対するコマンドを示しています。

例16.7 管理対象ドメイン内のサーバー上のすべての Web サービスエンドポイントに関するランタイム情報を表示する

このコマンドは、物理ホスト マスター でホストされ、管理対象ドメインで実行されている server-one という名前のサーバー上のすべてのエンドポイントに関する情報を表示します。
/host=master/server=server-one/deployment="*"/subsystem=webservices/endpoint="*":read-resource

例16.8 スタンドアロンサーバー上のすべての Web サービスエンドポイントに関するランタイム情報を表示する

このコマンドは、スタンドアロンサーバー上のすべての Web サービスエンドポイントに関する情報を表示します。
/deployment="*"/subsystem=webservices/endpoint="*":read-resource

例16.9 エンドポイント情報の例

以下は、架空の出力を表示する例です。
{
   "outcome" => "success",
   "result" => [{
       "address" => [
           ("deployment" => "jaxws-samples-handlerchain.war"),
           ("subsystem" => "webservices"),
           ("endpoint" => "jaxws-samples-handlerchain:TestService")
       ],
       "outcome" => "success",
       "result" => {
           "class" => "org.jboss.test.ws.jaxws.samples.handlerchain.EndpointImpl",
           "context" => "jaxws-samples-handlerchain",
           "name" => "TestService",
           "type" => "JAXWS_JSE",
           "wsdl-url" => "http://localhost:8080/jaxws-samples-handlerchain?wsdl"
       }
   }]
}

16.3. アプリケーションごとに HTTP タイムアウトを設定する

HTTP セッションタイムアウトは、指定した期間内にアクティビティーがないため、HTTP セッションが無効とみなされる期間を定義します。
HTTP セッションタイムアウトは、いくつかの場所で設定できます。優先順位の順に、これらは次のとおりです。
  • アプリケーション - アプリケーションの web.xml 設定ファイルで定義されています。
  • サーバー -default-session-timeout 属性を介して指定されます。
  • デフォルト - 30 分です。

手順16.1 アプリケーションごとに HTTP タイムアウトを設定する

  1. アプリケーションの WEB-INF/web.xml ファイルを編集します。
  2. 次の設定 XML をファイルに追加し、30 を目的のタイムアウト (分単位) に変更します。
    <session-config>
      <session-timeout>30</session-timeout>
    </session-config>
  3. WAR ファイルを変更した場合は、アプリケーションを再デプロイします。WAR ファイルを展開した場合、JBoss EAP はアプリケーションを自動的にアンデプロイして再デプロイするため、これ以上のアクションは必要ありません。

16.4. JAX-WS Web サービスエンドポイント

16.4.1. JAX-WS Web サービスエンドポイント

このトピックは、JAX-WSWeb サービスエンドポイントとそれに付随する概念の概要です。JAX-WS Web サービスエンドポイントは、Web サービスのサーバーコンポーネントです。クライアントおよび他の Web サービスは、Simple Object Access Protocol (SOAP) と呼ばれる XML 言語を使用して HTTP プロトコルを介して通信します。エンドポイント自体は JBoss EAP 6 コンテナーにデプロイされます。
WSDL 記述子は、次の 2 つの方法のいずれかで作成できます。
  1. WSDL 記述子は手動で記述できます。
  2. WSDL 記述子を自動的に作成する JAX-WS アノテーションを使用できます。これは、WSDL 記述子を作成するための最も一般的な方法です。
エンドポイント実装 Bean には JAX-WS アノテーションが付けられ、サーバーにデプロイされます。サーバーは、クライアント消費のために、抽象的なコントラクトを自動的に生成し、パブリッシュします。すべてのマーシャリングおよびアンマーシャリングは、Java Architecture for XML Binding (JAXB) サービスに委任されます。
エンドポイント自体は、POJO(Plain Old Java Object) または JavaEEWeb アプリケーションの場合があります。EJB3 ステートレスセッション Bean を使用してエンドポイントを公開することもできます。Web アーカイブ (WAR) ファイルにパッケージ化されます。Java Service Endpoint(JSE) と呼ばれるエンドポイントをパッケージ化する仕様は、にある JSR-181 で定義されてい http://jcp.org/aboutJava/communityprocess/mrel/jsr181/index2.html ます。

開発要件

Web サービスは、JAX-WS API および JSR 181: Web Services Metadata for the Java Platform 仕様の要件を満たす必要があります。有効な実装は、以下の要件を満たしている必要があります。

  • それは含まれていますjavax.jws.WebService注釈。
  • すべてのメソッドパラメーターとリターンタイプは、JAXB2.0 仕様の JSR-222 と互換性があります。詳細は、http://www.jcp.org/en/jsr/summary?id=222 を参照してください。

例16.10 例: POJO エンドポイント

@WebService
@SOAPBinding(style = SOAPBinding.Style.RPC)
public class JSEBean01
{
   @WebMethod
   public String echo(String input)
   {
      ...
   }
}

例16.11 例: Web サービスエンドポイント

<web-app ...>
  <servlet>
    <servlet-name>TestService</servlet-name>
    <servlet-class>org.jboss.test.ws.jaxws.samples.jsr181pojo.JSEBean01</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>TestService</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>
</web-app>


例16.12 EJB でのエンドポイントの公開

この EJB3 ステートレスセッション Bean は、リモートインターフェイス上およびエンドポイント操作として同じメソッドを公開します。
@Stateless
@Remote(EJB3RemoteInterface.class)
@RemoteBinding(jndiBinding = "/ejb3/EJB3EndpointInterface")

@WebService
@SOAPBinding(style = SOAPBinding.Style.RPC)
public class EJB3Bean01 implements EJB3RemoteInterface
{
   @WebMethod
   public String echo(String input)
   {
      ...
   }
}

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

JAX-WS サービスは通常 Java サービスエンドポイントインターフェース (SEI) を実装します。これは、WSDL ポートタイプから、直接またはアノテーションを使用してマッピングされる可能性があります。この SEI は、Java オブジェクトとその XML 表現の詳細を隠す高度な抽象化を提供します。ただし、サービスは XML メッセージレベルで動作する必要があることがあります。エンドポイントProviderインターフェイスは、この機能を実装する Web サービスに提供します。

エンドポイントの使用およびアクセス

Web サービスをデプロイしたら、WSDL を消費してアプリケーションの基盤となるコンポーネントのスタブを作成できます。その後、アプリケーションはエンドポイントにアクセスしてその作業を実行できます。

実例

JBoss EAP クイックスタートには、完全に機能する JAX-WSWeb サービスアプリケーションがいくつか含まれています。これらの例は次のとおりです。

  • wsat-simple
  • wsba-coordinator-completion-simple
  • wsba-participant-completion-simple

16.4.2. JAX-WSWeb サービスエンドポイントの作成とデプロイ

はじめに

このトピックでは、サーバー側コンポーネントである単純な JAX-WS サービスエンドポイントの開発について説明します。これは、JAX-WS クライアントからの要求に応答し、それ自体の WSDL 定義を公開します。JAX-WS サービスエンドポイントの詳細については、以下を参照してください。「JAX-WS Common API Reference」JBoss EAP 6 とともに配布される Javadoc 形式の API ドキュメントバンドル。

開発要件

Web サービスは、JAXWS API と Web Services メタデータ仕様の要件に http://www.jcp.org/en/jsr/summary?id=181 対応します。有効な実装は、以下の要件を満たしている必要があります。

  • それは含まれていますjavax.jws.WebService注釈。
  • すべてのメソッドパラメーターとリターンタイプは、JAXB2.0 仕様の JSR-222 と互換性があります。詳細は、http://www.jcp.org/en/jsr/summary?id=222 を参照してください。

例16.13 サービス実装の例


package org.jboss.test.ws.jaxws.samples.retail.profile;
 
import javax.ejb.Stateless;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.soap.SOAPBinding;
 
@Stateless                                                             
@WebService(                                                           
   name="ProfileMgmt",
   targetNamespace = "http://org.jboss.ws/samples/retail/profile",
   serviceName = "ProfileMgmtService")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)         
public class ProfileMgmtBean {
 
   @WebMethod                                                          
   public DiscountResponse getCustomerDiscount(DiscountRequest request) {
      return new DiscountResponse(request.getCustomer(), 10.00);
   }
}

例16.14 XML ペイロードの例

以下は、DiscountRequestによって使用されるクラスProfileMgmtBean前の例の Bean。アノテーションは詳細度のために含まれています。通常、これは JAXB デフォルトは妥当な設定であり、指定する必要はありません。

package org.jboss.test.ws.jaxws.samples.retail.profile;
 
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
 
import org.jboss.test.ws.jaxws.samples.retail.Customer;
 
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(
  name = "discountRequest",
  namespace="http://org.jboss.ws/samples/retail/profile",
  propOrder = { "customer" }
)
public class DiscountRequest {
 
   protected Customer customer;
 
   public DiscountRequest() {
   }
 
   public DiscountRequest(Customer customer) {
      this.customer = customer;
   }
 
   public Customer getCustomer() {
      return customer;
   }
 
   public void setCustomer(Customer value) {
      this.customer = value;
   }
 
}
より複雑なマッピングが可能です。詳細は、の JAXB API 仕様 https://jaxb.java.net/ を参照してください。

デプロイメントをパッケージ化する

実装クラスは JAR デプロイメントでラップされます。デプロイメントに必要なメタデータは、実装クラスとサービスエンドポイントインターフェース上のアノテーションから取得されます。管理 CLI または管理インターフェイスを使用して JAR をデプロイすると、HTTP エンドポイントが自動的に作成されます。

次のリストは、EJBWeb サービスの JAR デプロイメントの正しい構造の例を示しています。

例16.15 Web サービスデプロイメントの JAR 構造の例

[user@host ~]$ jar -tf jaxws-samples-retail.jar
org/jboss/test/ws/jaxws/samples/retail/profile/DiscountRequest.class
org/jboss/test/ws/jaxws/samples/retail/profile/DiscountResponse.class
org/jboss/test/ws/jaxws/samples/retail/profile/ObjectFactory.class
org/jboss/test/ws/jaxws/samples/retail/profile/ProfileMgmt.class
org/jboss/test/ws/jaxws/samples/retail/profile/ProfileMgmtBean.class
org/jboss/test/ws/jaxws/samples/retail/profile/ProfileMgmtService.class
org/jboss/test/ws/jaxws/samples/retail/profile/package-info.class

16.5. JAX-WS Web サービスクライアント

16.5.1. JAX-WS Web サービスの消費とアクセス

手動または JAX-WS アノテーションを使用して Web サービスエンドポイントを作成した後、その WSDL にアクセスできます。これを使用して、Web サービスと通信する基本的なクライアントアプリケーションを作成できます。パブリッシュされた WSDL から Java コードを生成するプロセスは、Web サービスを使用すると呼ばれます。これは以下の場合に発生します。
  1. クライアントアーティファクトの作成
  2. サービススタブの構成

クライアントアーティファクトの作成

クライアントアーティファクトを作成する前に、WSDL コントラクトを作成する必要があります。以下の WSDL コントラクトは、本トピックの残りの部分に記載の例に使用します。

以下の例は、ProfileMgmtService.wsdl ファイルにこの WSDL コントラクトがあることを前提としています。

例16.16 WSDL コントラクトの例


<definitions
    name='ProfileMgmtService'
    targetNamespace='http://org.jboss.ws/samples/retail/profile'
    xmlns='http://schemas.xmlsoap.org/wsdl/'
    xmlns:ns1='http://org.jboss.ws/samples/retail'
    xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/'
    xmlns:tns='http://org.jboss.ws/samples/retail/profile'
    xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
 
   <types>
 
      <xs:schema targetNamespace='http://org.jboss.ws/samples/retail'
                 version='1.0' xmlns:xs='http://www.w3.org/2001/XMLSchema'>
         <xs:complexType name='customer'>
            <xs:sequence>
               <xs:element minOccurs='0' name='creditCardDetails' type='xs:string'/>
               <xs:element minOccurs='0' name='firstName' type='xs:string'/>
               <xs:element minOccurs='0' name='lastName' type='xs:string'/>
            </xs:sequence>
         </xs:complexType>
      </xs:schema>
 
      <xs:schema
          targetNamespace='http://org.jboss.ws/samples/retail/profile'
          version='1.0'
          xmlns:ns1='http://org.jboss.ws/samples/retail'
          xmlns:tns='http://org.jboss.ws/samples/retail/profile'
          xmlns:xs='http://www.w3.org/2001/XMLSchema'>
 
         <xs:import namespace='http://org.jboss.ws/samples/retail'/>
         <xs:element name='getCustomerDiscount'
                     nillable='true' type='tns:discountRequest'/>
         <xs:element name='getCustomerDiscountResponse'
                     nillable='true' type='tns:discountResponse'/>
         <xs:complexType name='discountRequest'>
            <xs:sequence>
               <xs:element minOccurs='0' name='customer' type='ns1:customer'/>
 
            </xs:sequence>
         </xs:complexType>
         <xs:complexType name='discountResponse'>
            <xs:sequence>
               <xs:element minOccurs='0' name='customer' type='ns1:customer'/>
               <xs:element name='discount' type='xs:double'/>
            </xs:sequence>
         </xs:complexType>
      </xs:schema>
 
   </types>
 
   <message name='ProfileMgmt_getCustomerDiscount'>
      <part element='tns:getCustomerDiscount' name='getCustomerDiscount'/>
   </message>
   <message name='ProfileMgmt_getCustomerDiscountResponse'>
      <part element='tns:getCustomerDiscountResponse'
            name='getCustomerDiscountResponse'/>
   </message>
   <portType name='ProfileMgmt'>
      <operation name='getCustomerDiscount'
                 parameterOrder='getCustomerDiscount'>
 
         <input message='tns:ProfileMgmt_getCustomerDiscount'/>
         <output message='tns:ProfileMgmt_getCustomerDiscountResponse'/>
      </operation>
   </portType>
   <binding name='ProfileMgmtBinding' type='tns:ProfileMgmt'>
      <soap:binding style='document'
                    transport='http://schemas.xmlsoap.org/soap/http'/>
      <operation name='getCustomerDiscount'>
         <soap:operation soapAction=''/>
         <input>
 
            <soap:body use='literal'/>
         </input>
         <output>
            <soap:body use='literal'/>
         </output>
      </operation>
   </binding>
   <service name='ProfileMgmtService'>
      <port binding='tns:ProfileMgmtBinding' name='ProfileMgmtPort'>
 
         <soap:address
             location='SERVER:PORT/jaxws-samples-retail/ProfileMgmtBean'/>
      </port>
   </service>
</definitions>	

注記
JAX-WS アノテーションを使用して Web サービスのエンドポイントを作成すると、WSDL コントラクトは自動的に生成されます。その URL のみが必要になります。この URL は、エンドポイントがデプロイされた後、Web ベースの管理コンソールの ランタイム セクションの Web サービス セクションから取得できます。
Wsconsume.sh ツールまたは wsconsume.bat ツールは、抽象的なコントラクト (WSDL) を消費し、アノテーション付きの Java クラスと、これを定義するオプションのソースを生成するために使用されます。このコマンドは、JBoss EAP 6 インストールの EAP_HOME/bin/ ディレクトリーにあります。

例16.17 wsconsume.sh コマンドの構文

[user@host bin]$ ./wsconsume.sh --help
WSConsumeTask is a cmd line tool that generates portable JAX-WS artifacts from a WSDL file.

usage: org.jboss.ws.tools.cmd.WSConsume [options] <wsdl-url>

options: 
    -h, --help                  Show this help message
    -b, --binding=<file>        One or more JAX-WS or JAXB binding files 
    -k, --keep                  Keep/Generate Java source
    -c  --catalog=<file>        Oasis XML Catalog file for entity resolution
    -p  --package=<name>        The target package for generated source
    -w  --wsdlLocation=<loc>    Value to use for @WebService.wsdlLocation
    -o, --output=<directory>    The directory to put generated artifacts
    -s, --source=<directory>    The directory to put Java source
    -t, --target=<2.0|2.1|2.2>  The JAX-WS specification target
    -q, --quiet                 Be somewhat more quiet
    -v, --verbose               Show full exception stack traces
    -l, --load-consumer         Load the consumer and exit (debug utility)
    -e, --extension             Enable SOAP 1.2 binding extension
    -a, --additionalHeaders     Enable processing of implicit SOAP headers
    -n, --nocompile             Do not compile generated sources

以下のコマンドは、出力に一覧表示されている .java ファイルを ProfileMgmtService.wsdl ファイルから生成します。ソースは、-p スイッチで指定されたパッケージのディレクトリー構造を使用します。
[user@host bin]$  wsconsume.sh -k -p org.jboss.test.ws.jaxws.samples.retail.profile ProfileMgmtService.wsdl
output/org/jboss/test/ws/jaxws/samples/retail/profile/Customer.java
output/org/jboss/test/ws/jaxws/samples/retail/profile/DiscountRequest.java
output/org/jboss/test/ws/jaxws/samples/retail/profile/DiscountResponse.java
output/org/jboss/test/ws/jaxws/samples/retail/profile/ObjectFactory.java
output/org/jboss/test/ws/jaxws/samples/retail/profile/ProfileMgmt.java
output/org/jboss/test/ws/jaxws/samples/retail/profile/ProfileMgmtService.java
output/org/jboss/test/ws/jaxws/samples/retail/profile/package-info.java
output/org/jboss/test/ws/jaxws/samples/retail/profile/Customer.class
output/org/jboss/test/ws/jaxws/samples/retail/profile/DiscountRequest.class
output/org/jboss/test/ws/jaxws/samples/retail/profile/DiscountResponse.class
output/org/jboss/test/ws/jaxws/samples/retail/profile/ObjectFactory.class
output/org/jboss/test/ws/jaxws/samples/retail/profile/ProfileMgmt.class
output/org/jboss/test/ws/jaxws/samples/retail/profile/ProfileMgmtService.class
output/org/jboss/test/ws/jaxws/samples/retail/profile/package-info.class
.java ソースファイルとコンパイルされた .class ファイルはどちらも、コマンドを実行するディレクトリー内の output/ ディレクトリーに生成されます。

表16.2 wsconsume.sh で作成されるアーティファクトの説明

ファイル 説明
ProfileMgmt.java
サービスエンドポイントインターフェース。
Customer.java
カスタムデータタイプ。
Discount*.java
カスタムデータタイプ。
ObjectFactory.java
JAXB XML レジストリー。
package-info.java
JAXB パッケージのアノテーション。
ProfileMgmtService.java
サービスファクトリー。
wsconsume.sh コマンドは、すべてのカスタムデータタイプ (JAXB アノテーションが付けられたクラス)、サービスエンドポイントインターフェース、およびサービスファクトリークラスを生成します。これらのアーティファクトは、Web サービスクライアントの実装をビルドするために使用されます。

サービススタブの構成

Web サービスクライアントはサービススタブを使用して、リモート Web サービス呼び出しの詳細を抽象化します。クライアントアプリケーションの場合、WS の呼び出しは他のビジネスコンポーネントの呼び出しと同様になります。この場合、サービスエンドポイントインターフェースはビジネスインターフェースとして機能し、サービスファクトリークラスはサービススタブとしての構築に使用されません。

例16.18 サービススタブの構築とエンドポイントへのアクセス

以下の例では、まずは WSDL の場所とサービス名を使用してサービスファクトリーを作成します。次に、wsconsume.sh コマンドによって作成されたサービスエンドポイントインターフェイスを使用して、サービススタブを構築します。最後に、スタブは他のビジネスインターフェースと同様に使用できます。
エンドポイントの WSDLURL は、Web ベースの管理コンソールにあります。トップバーの ランタイム メニュー項目を選択してから、左側のペインの サブシステム の下にある Web サービス エントリーを選択します。属性 タブを表示して、展開の詳細を確認します。

import javax.xml.ws.Service;
[...]
Service service = Service.create(                                 
new URL("http://example.org/service?wsdl"),
new QName("MyService")
);
ProfileMgmt profileMgmt = service.getPort(ProfileMgmt.class);     
 
// Use the service stub in your application

16.5.2. JAX-WS クライアントアプリケーションの開発

このトピックでは、JAX-WSWeb サービスクライアント全般について説明します。クライアントは Java Enterprise Edition 6 コンテナーにデプロイされた JAX-WS エンドポイントと通信し、そこから要求を行います。以下のクラス、メソッド、およびその他の実装の詳細は、「JAX-WS Common API Reference」 および、JBoss EAP 6 に含まれる Javadocs バンドルの関連セクションを参照してください。

サービス

概要
AServiceWSDL サービスを表す抽象化です。WSDL サービスは、一連の関連ポートです。それぞれには、特定のプロトコルとエンドポイントアドレスに結合したポートタイプが含まれます。
通常、サービスの生成は、残りのコンポーネントのスタブが、既存の WSDL コントラクトから生成されると行われます。WSDL コントラクトは、デプロイされたエンドポイントの WSDL URL 経由で利用できます。または、EAP_HOME/bin/ ディレクトリーの wsprovide.sh コマンドを使用してエンドポイントソースから作成できます。
このタイプの使用は、static ユースケースと呼ばれます。この場合、コンポーネントのスタブのいずれかとして作成された Service クラスのインスタンスを作成します。
を使用して、サービスを手動で作成することもできます。Service.create方法。これは、dynamic ユースケースと呼ばれます。
用途
静的ユースケース
JAX-WS クライアントの static ユースケースでは、すでに WSDL コントラクトが存在することを前提としています。これは外部ツールで生成されるか、JAX-WS エンドポイントの作成時に適切な JAX-WS アノテーションを使用して生成される可能性があります。
コンポーネントスタブを生成するには、wsconsume.shまたwsconsume.batEAP_HOME/bin/ に含まれているスクリプト。このスクリプトは、WSDL URL またはファイルをパラメーターとして受け取り、ディレクトリーツリーで構造化された複数のファイルを生成します。を表すソースファイルとクラスファイルService名前が付けられていますCLASSNAME_Service.javaCLASSNAME_Service.class、それぞれ。
生成された実装クラスには、引数のないパブリックコンストラクターと、2 つの引数を持つコンストラクターがあります。2 つの引数は、WSDL の場所を表します (java.net.URL) およびサービス名 (ajavax.xml.namespace.QName) それぞれ。
引数なしのコンストラクターは最もよく使用されます。この場合、WSDL の場所とサービス名は WSDL にあるものです。これらは、から暗黙的に設定されます@WebServiceClient生成されたクラスを装飾するアノテーション。

例16.19 生成されたサービスクラスの例

@WebServiceClient(name="StockQuoteService", targetNamespace="http://example.com/stocks", wsdlLocation="http://example.com/stocks.wsdl")
public class StockQuoteService extends javax.xml.ws.Service
{
   public StockQuoteService()
   {
      super(new URL("http://example.com/stocks.wsdl"), new QName("http://example.com/stocks", "StockQuoteService"));
   }

   public StockQuoteService(String wsdlLocation, QName serviceName)
   {
      super(wsdlLocation, serviceName);
   }

   ...
}
動的ユースケース
動的の場合、スタブは自動的に生成されません。代わりに、Web サービスクライアントはService.create作成する方法Serviceインスタンス。以下のコードはこのプロセスを示しています。

例16.20 手動でサービスを作成する

URL wsdlLocation = new URL("http://example.org/my.wsdl");
QName serviceName = new QName("http://example.org/sample", "MyService");
Service service = Service.create(wsdlLocation, serviceName);

ハンドラー解決
JAX-WS は、handlers と呼ばれるメッセージ処理モジュールに柔軟なプラグインフレームワークを提供します。これらのハンドラーは JAX-WS ランタイムシステムの機能を拡張します。AServiceインスタンスはへのアクセスを提供しますHandlerResolverのペアを介してgetHandlerResolversetHandlerResolverサービスごと、ポートごと、またはプロトコルごとのバインディングに基づいて一連のハンドラーを設定できるメソッド。
いつServiceインスタンスはプロキシーまたはDispatchたとえば、現在サービスに登録されているハンドラーリゾルバーは、必要なハンドラーチェーンを作成します。に設定されたハンドラーリゾルバーへのその後の変更Serviceインスタンスは、以前に作成されたプロキシーのハンドラーに影響を与えません。Dispatchインスタンス。
エグゼキューター (Executor)
Service インスタンスは、java.util.concurrent.Executor。TheExecutorアプリケーションによって要求された非同期コールバックを呼び出します。ThesetExecutorgetExecutorの方法Service変更および取得できますExecutorサービス用に設定されています。

動的プロキシー

動的プロキシー は、次のいずれかを使用するクライアントプロキシーのインスタンスです。getPortで提供されるメソッドService。TheportNameサービスが使用する WSDL ポートの名前を指定します。TheserviceEndpointInterface作成された動的プロキシーインスタンスでサポートされるサービスエンドポイントインターフェイスを指定します。

例16.21 getPort Methods

public <T> T getPort(QName portName, Class<T> serviceEndpointInterface)
public <T> T getPort(Class<T> serviceEndpointInterface)
Service Endpoint Interface は通常 wsconsume.sh ツールを使用して生成されます。これは、WSDL を解析し、そこから Java クラスを作成します。
ポートを返す、タイプ指定されたメソッドも提供されます。これらのメソッドは、SEI を実装する動的プロキシーも返します。以下の例を参照してください。

例16.22 サービスのポートを返す

@WebServiceClient(name = "TestEndpointService", targetNamespace = "http://org.jboss.ws/wsref",
   wsdlLocation = "http://localhost.localdomain:8080/jaxws-samples-webserviceref?wsdl")

public class TestEndpointService extends Service
{
    ...

    public TestEndpointService(URL wsdlLocation, QName serviceName) {
        super(wsdlLocation, serviceName);
    }

    @WebEndpoint(name = "TestEndpointPort")
    public TestEndpoint getTestEndpointPort()
    {
        return (TestEndpoint)super.getPort(TESTENDPOINTPORT, TestEndpoint.class);
    }
}

@WebServiceRef

The@WebServiceRefアノテーションは、Web サービスへの参照を宣言します。これは、で定義される javax.annotation.Resource アノテーションで示されるリソースパターンに http://www.jcp.org/en/jsr/summary?id=250 従います。

のユースケース @WebServiceRef

  • これを使用して、生成されたタイプの参照を定義できますServiceクラス。この例では、type および value 要素はそれぞれ、生成された Service クラスタイプを参照します。さらに、リファンレンスタイプがアノテーションが適用されるフィールドまたはメソッド宣言によって推定される場合、type および value 要素にはデフォルト値の Object.classが設定されることがあります。これは必須ではありません。タイプを推定できない場合、type 要素がデフォルト以外の値を持つ必要があります。
  • これは、タイプが SEI のリファンレスを定義するのに使用できます。この場合、リファレンスのタイプが annotated フィールドまたは method 宣言から推測される場合、type 要素はデフォルト値で存在することがあります (ただし、必須ではありません)。ただし、value 要素は常に存在し、生成されたサービスクラスターイプを参照する必要があります。これは、javax.xml.ws.Service。ThewsdlLocation要素が存在する場合は、で指定された WSDL ロケーション情報をオーバーライドします。@WebService参照された生成されたサービスクラスのアノテーション。

    例16.23 @WebServiceRef 例:

    public class EJB3Client implements EJB3Remote
    {
       @WebServiceRef
       public TestEndpointService service4;
    
       @WebServiceRef
       public TestEndpoint port3;
    

Dispatch

XML Web サービスは、Java EE コンテナーおよびすべてのクライアントにデプロイされる、エンドポイント間の通信に XML メッセージを使用します。XML メッセージは、Simple Object Access Protocol (SOAP) と呼ばれる XML 言語を使用します。JAX-WS API は、エンドポイントとクライアントのメカニズムを提供し、各エンドポイントが SOAP メッセージを送受信できるようにします。マーシャリングは、Java オブジェクトを SOAP XML メッセージに変換するプロセスです。マーシャリング解除とは、SOAP XML メッセージを Java オブジェクトに変換するプロセスのことです。

変換の結果ではなく、raw SOAP メッセージ自体にアクセスする必要がある場合があります。TheDispatchクラスはこの機能を提供します。Dispatch は、以下の定数のいずれかによって識別される、2 つの使用モードのいずれかで動作します。
  • javax.xml.ws.Service.Mode.MESSAGE - このモードは、クライアントアプリケーションがプロトコル固有のメッセージ構造を直接操作するように指示します。SOAP プロトコルバインディングを使用すると、クライアントアプリケーションは SOAP メッセージで直接機能します。
  • javax.xml.ws.Service.Mode.PAYLOAD - このモードでは、クライアントはペイロード自体を操作します。たとえば、SOAP プロトコルバインディングと使用すると、クライアントアプリケーションは SOAP メッセージ全体ではなく SOAP ボディーのコンテンツで動作します。
Dispatch は低レベルの API で、クライアントはメッセージまたはペイロードを XML として構成する必要があります。これは、個別のプロトコルの標準と、メッセージまたはペイロード構造の詳細な知識とメッセージに忠実に従った状態を意味します。Dispatch は、メッセージの入出力または、任意のタイプのメッセージペイロードに対応した汎用クラスです。

例16.24 Dispatch 用途

Service service = Service.create(wsdlURL, serviceName);
Dispatch dispatch = service.createDispatch(portName, StreamSource.class, Mode.PAYLOAD);

String payload = "<ns1:ping xmlns:ns1='http://oneway.samples.jaxws.ws.test.jboss.org/'/>";
dispatch.invokeOneWay(new StreamSource(new StringReader(payload)));

payload = "<ns1:feedback xmlns:ns1='http://oneway.samples.jaxws.ws.test.jboss.org/'/>";
Source retObj = (Source)dispatch.invoke(new StreamSource(new StringReader(payload)));

非同期呼び出し

TheBindingProviderインターフェイスは、クライアントが使用できるプロトコルバインディングを提供するコンポーネントを表します。これはプロキシーによって実装され、Dispatchインターフェイス。

BindingProvider インスタンスは非同期操作機能を提供する場合があります。非同期操作の呼び出しは、BindingProvider呼び出し時のインスタンス。操作が完了しても、応答コンテキストは更新されません。代わりに、別の応答コンテキストが使用可能になりますResponseインターフェイス。

例16.25 非同期呼び出しの例

public void testInvokeAsync() throws Exception
{
   URL wsdlURL = new URL("http://" + getServerHost() + ":8080/jaxws-samples-asynchronous?wsdl");
   QName serviceName = new QName(targetNS, "TestEndpointService");
   Service service = Service.create(wsdlURL, serviceName);
   TestEndpoint port = service.getPort(TestEndpoint.class);
   Response response = port.echoAsync("Async");
   // access future
   String retStr = (String) response.get();
   assertEquals("Async", retStr);
}

@Oneway 呼び出し

@Oneway アノテーションは、指定の web メソッドが入力メッセージを取得し、出力メッセージを返しないことを示します。通常、@Oneway メソッドは、ビジネスメソッドの実行前に、制御のスレッドを呼び出しアプリケーションに戻します。

例16.26 例@Oneway呼び出し

@WebService (name="PingEndpoint")
@SOAPBinding(style = SOAPBinding.Style.RPC)
public class PingEndpointImpl
{
   private static String feedback;
  
   @WebMethod
   @Oneway
   public void ping()
   {
      log.info("ping");
      feedback = "ok";
   }
  
   @WebMethod
   public String feedback()
   {
      log.info("feedback");
      return feedback;
   }
}

タイムアウトの設定

2 種類のプロパティーが HTTP 接続のタイムアウトの動作と、メッセージの受信を待機しているクライアントのタイムアウトを制御します。最初はjavax.xml.ws.client.connectionTimeoutそして 2 番目はjavax.xml.ws.client.receiveTimeout。それぞれはミリ秒単位で示され、正しい構文を以下に示します。

例16.27 JAX-WS タイムアウト設定

public void testConfigureTimeout() throws Exception
{
   //Set timeout until a connection is established
   ((BindingProvider)port).getRequestContext().put("javax.xml.ws.client.connectionTimeout", "6000");

   //Set timeout until the response is received
   ((BindingProvider) port).getRequestContext().put("javax.xml.ws.client.receiveTimeout", "1000");

   port.echo("testTimeout");
}

16.6. JAX-WS 開発リファレンス

16.6.1. Web サービスアドレス指定を有効にする (WS-Addressing)

前提条件

  • アプリケーションに既存の JAX-WS サービスおよびクライアント設定を指定する必要があります。

手順16.2 クライアントコードに注釈を付けて更新する

  1. サービスエンドポイントに注釈を付ける

    追加します@Addressingアプリケーションのエンドポイントコードへの注釈。

    例16.28 @Addressing Annotation

    この例は、通常の JAX-WS エンドポイントを示しています。@Addressing注釈が追加されました。
    package org.jboss.test.ws.jaxws.samples.wsa;
     
    import javax.jws.WebService;
    import javax.xml.ws.soap.Addressing;
     
    @WebService
    (
       portName = "AddressingServicePort",
       serviceName = "AddressingService",
       wsdlLocation = "WEB-INF/wsdl/AddressingService.wsdl",
       targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/wsaddressing",
       endpointInterface = "org.jboss.test.ws.jaxws.samples.wsa.ServiceIface"
    )
    @Addressing(enabled=true, required=true)
    public class ServiceImpl implements ServiceIface
    {
       public String sayHello()
       {
          return "Hello World!";
       }
    }
  2. クライアントコードを更新する

    アプリケーションのクライアントコードを更新して、WS-Addressing を設定します。

    例16.29 WS-Addressing のクライアント設定

    この例は、WS-Addressing を設定するために更新された通常の JAX-WS クライアントを示しています。
    package org.jboss.test.ws.jaxws.samples.wsa;
     
    import java.net.URL;
    import javax.xml.namespace.QName;
    import javax.xml.ws.Service;
    import javax.xml.ws.soap.AddressingFeature;
     
    public final class AddressingTestCase
    {
       private final String serviceURL = 
           "http://localhost:8080/jaxws-samples-wsa/AddressingService";
       
       public static void main(String[] args) throws Exception
       {
          // construct proxy
          QName serviceName = 
              new QName("http://www.jboss.org/jbossws/ws-extensions/wsaddressing",
                        "AddressingService");
          URL wsdlURL = new URL(serviceURL + "?wsdl");
          Service service = Service.create(wsdlURL, serviceName);
          ServiceIface proxy = 
              (ServiceIface)service.getPort(ServiceIface.class,  
                                            new AddressingFeature());
          // invoke method
          proxy.sayHello();
       }
    }

結果

クライアントとエンドポイントは、WS-Addressing を使用して通信しています。

16.6.2. JAX-WS Common API Reference

JAX-WS の開発概念は、Web サービスのエンドポイントとクライアント間で共有されています。これには、ハンドラーフレームワーク、メッセージコンテキスト、および障害処理が含まれます。

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

ハンドラーフレームワークは、クライアントおよびエンドポイント (サーバーコンポーネント) の JAX-WS プロトコルバインディングによって実装されます。binding providers として知られるプロキシーおよび Dispatch インスタンスは、それぞれプロトコルバインディングを使用して抽象機能を特定のプロトコルにバインドします。

クライアントおよびサーバー側のハンドラーは、handler chain と呼ばれる順序付けされたリストに編成されます。ハンドラーチェーン内のハンドラーは、メッセージが送受信されるたびに呼び出されます。受信メッセージは、バインディングプロバイダーが処理する前にハンドラーによって処理されます。アウトバウンドメッセージは、バインディングプロバイダーが処理した後にハンドラーによって処理されます。
ハンドラーは、受信メッセージおよびアウトバウンドメッセージにアクセスして変更し、プロパティーのセットを管理するメソッドを提供するメッセージコンテキストで呼び出されます。メッセージコンテキストプロパティーは、ハンドラーとクライアントおよびサービスの実装間の通信だけでなく、個別のハンドラー間の通信を容易にします。異なるタイプのハンドラーは異なるタイプのメッセージコンテキストで呼び出されます。

メッセージハンドラーの種類

論理ハンドラー
Logical handlers は、メッセージコンテキストプロパティーおよびメッセージペイロードでのみ動作します。論理ハンドラーはプロトコルに依存しないため、メッセージのプロトコル固有の部分には影響がありません。論理ハンドラーはインターフェイスを実装しますjavax.xml.ws.handler.LogicalHandler
プロトコルハンドラー
Protocol handlers は、メッセージコンテキストプロパティーおよびプロトコル固有のメッセージで動作します。プロトコルハンドラーは特定のプロトコルに固有のもので、メッセージのプロトコル固有の側面にアクセスし、変更する可能性があります。プロトコルハンドラーは、から派生した任意のインターフェイスを実装しますjavax.xml.ws.handler.Handler except javax.xml.ws.handler.LogicalHandler
サービスエンドポイントハンドラー
サービスエンドポイントでは、ハンドラーは@HandlerChain注釈。ハンドラーチェーンファイルの場所は、絶対的なものにすることができますjava.net.URLexternalFormまたは、ソースファイルまたはクラスファイルからの相対パス。

例16.30 サービスエンドポイントハンドラーの例

@WebService
@HandlerChain(file = "jaxws-server-source-handlers.xml")
public class SOAPEndpointSourceImpl
{
   ...
}

サービスクライアントハンドラー
JAX-WS クライアントでは、ハンドラーはサービスエンドポイントの場合と同様に @HandlerChain アノテーションを使用するか、JAX-WS API を使用して動的に定義されます。

例16.31 API を使用したサービスクライアントハンドラーの定義

Service service = Service.create(wsdlURL, serviceName);
Endpoint port = (Endpoint)service.getPort(Endpoint.class);
     
BindingProvider bindingProvider = (BindingProvider)port;
List<Handler> handlerChain = new ArrayList<Handler>();
handlerChain.add(new LogHandler());
handlerChain.add(new AuthorizationHandler());
handlerChain.add(new RoutingHandler());
bindingProvider.getBinding().setHandlerChain(handlerChain);
への呼び出しsetHandlerChainメソッドが必要です。

メッセージコンテキスト

TheMessageContextinterface は、すべての JAX-WS メッセージコンテキストのスーパーインターフェイスです。これは、追加のメソッドと定数を使用して Map<String,Object> を拡張し、ハンドラーチェーンのハンドラーが処理関連の状態を共有できるようにするプロパティーセットを管理します。たとえば、ハンドラーは put メソッドを使用してプロパティーをメッセージコンテキストに挿入します。ハンドラーチェーン内の他の 1 つ以上のハンドラーは、その後、get方法。

プロパティーは APPLICATION または HANDLER としてスコープ指定されます。すべてのプロパティーは、特定のエンドポイントのメッセージ交換パターン (MEP) のインスタンスに対するすべてのハンドラーで利用できます。たとえば、論理ハンドラーがプロパティーをメッセージコンテキストに置いた場合、そのプロパティーは MEP インスタンスの実行中にチェーンの任意のプロトコルハンドラーでも利用できます。
注記
非同期メッセージ交換パターン (MEP) を使用すると、HTTP 接続レベルでメッセージを非同期に送受信できます。これを有効にするには、要求コンテキストに追加のプロパティーを設定します。
APPLICATION レベルでスコープ設定されているプロパティーは、クライアントアプリケーションおよびサービスエンドポイント実装でも利用可能になります。Thedefaultscopeプロパティーの場合は HANDLER です。
論理メッセージと SOAP メッセージは、異なるコンテキストを使用します。
論理メッセージコンテキスト
論理ハンドラーが呼び出されると、タイプのメッセージコンテキストを受け取りますLogicalMessageContextLogicalMessageContext 拡張しますMessageContextメッセージペイロードを取得および変更するメソッドを使用します。メッセージのプロトコル固有の側面へのアクセスは提供しません。プロトコルバインディングは、論理メッセージコンテキストを介して使用できるメッセージのコンポーネントを定義します。SOAP バインディングにデプロイされた論理ハンドラーは SOAP ボディーのコンテンツにアクセスできますが、SOAP ヘッダーにはアクセスできません。一方、XML/HTTP バインディングは論理ハンドラーがメッセージの XML ペイロード全体にアクセスできることを定義します。
SOAP メッセージコンテキスト
SOAP ハンドラーが呼び出されると、SOAPMessageContextSOAPMessageContext 拡張しますMessageContextSOAP メッセージペイロードを取得および変更するメソッドを使用します。

障害処理

アプリケーションが SOAPFaultException またはアプリケーション固有のユーザー例外をスローする可能性があります。後者の場合、必要な障害ラッパー Bean がデプロイメントに含まれていない場合は、ランタイム時に生成されます。

例16.32 障害処理の例

public void throwSoapFaultException()
{
   SOAPFactory factory = SOAPFactory.newInstance();
   SOAPFault fault = factory.createFault("this is a fault string!", new QName("http://foo", "FooCode"));
   fault.setFaultActor("mr.actor");
   fault.addDetail().addChildElement("test");
   throw new SOAPFaultException(fault);
}
public void throwApplicationException() throws UserException
{
   throw new UserException("validation", 123, "Some validation error");
}

JAX-WS アノテーション

JAX-WS API 経由で利用可能なアノテーションは JSR-224 で定義されています。これについては、を参照してください http://www.jcp.org/en/jsr/detail?id=224。これらの注釈はパッケージに含まれていますjavax.xml.ws

JWS API で利用可能なアノテーションは、にある JSR-181 で定義されてい http://www.jcp.org/en/jsr/detail?id=181 ます。これらの注釈はパッケージに含まれていますjavax.jws

第17章 WebSocket

17.1. WebSocket について

WebSocket プロトコルは、Web クライアントとサーバー間の双方向通信を提供します。クライアントとサーバー間の通信はイベントベースであるため、ポーリングベースの通信よりも処理が高速になり、帯域幅が小さくなります。WebSocket は、JavaScriptAPI を介して Web アプリケーションで使用できます。
最初に接続はクライアントとサーバー間で HTTP 接続として確立されます。その後、クライアントは Upgrade ヘッダーを使用して WebSocket 接続を要求します。同じ TCP/IP 接続上ではすべて全二重通信になり、データのオーバヘッドが最小化されます。各メッセージには不必要な HTTP ヘッダーコンテンツが含まれていないため、Websocket 通信で必要な帯域幅は小さくなります。その結果、通信パスのレイテンシーが低くなるため、リアルタイムの応答が必要なアプリケーションに適しています。
JBoss EAP 6 WebSocket 実装は、サーバーエンドポイントに対して完全な依存関係注入サポートを提供しますが、クライアントエンドポイントに対して CDI サービスを提供しません。CDI のサポートは、Java EE 6 プラットフォームで必要なサポートに限定されているため、エンドポイントのインターセプターなどの JavaEE7 の機能はサポートされていません。

17.2. WebSocket アプリケーションを作成する

WebSocket アプリケーションには以下のコンポーネントと設定変更が必要です。
  • Javaクライアントまたは WebSocket が有効になっている HTML クライアント。次の場所で HTML クライアントブラウザーのサポートを確認できます。 http://caniuse.com/websockets
  • WebSocket サーバーエンドポイントクラス。
  • WebSocket を有効にするように設定された jboss-web.xml ファイル。
  • WebSocket API で依存関係を宣言するために設定されたプロジェクト依存関係。
  • Red Hat JBoss Enterprise Application Platform サーバー設定ファイルの Web サブシステムで NIO2 コネクターを有効にします。
注記
WebSocket アプリケーションには、JavaRuntimeEnvironment バージョン 7 以降が必要です。そうしないと、WebSocket が有効になりません。

手順17.1 WebSocket アプリケーションの作成

以下は、WebSocket アプリケーションの簡単な例です。接続を開き、メッセージを送信し、接続を閉じるためのボタンを提供します。他の機能を実装したり、実際のアプリケーションで必要となるエラー処理を含むことはありません。
  1. JavaScript HTML クライアントを作成します。

    以下は WebSocket クライアントの例になります。この例には 3 つの JavaScript 関数が含まれています。
    • connect(): この関数は WebSocket URI を渡す WebSocket 接続を作成します。リソースの場所は、サーバーエンドポイントクラスに定義されたリソースと一致します。この関数は、WebSocket をインターセプトして処理しますonopenonmessageonerror、とonclose
    • sendMessage(): この関数はフォームに入力された名前を取得し、メッセージを作成します。 さらに、WebSocket.send() コマンドを使用してメッセージを送信します。
    • disconnect(): この関数は WebSocket.close () コマンドを発行します。
    • displayMessage(): この関数は、ページ上の表示メッセージを WebSocket エンドポイントメソッドによって返された値に設定します。
    • displayStatus(): この関数は、WebSocket 接続ステータスを表示します。
    l
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
        <head>
            <title>WebSocket: Say Hello</title>
            <link rel="stylesheet" type="text/css" href="resources/css/hello.css" />
            <script type="text/javascript">
                var websocket = null;
    
                function connect() {
                    var wsURI = 'ws://' + window.location.host + '/jboss-websocket-hello/websocket/helloName';
                    websocket = new WebSocket(wsURI);
    
                    websocket.onopen = function() {
                        displayStatus('Open');
                        document.getElementById('sayHello').disabled = false;
                        displayMessage('Connection is now open. Type a name and click Say Hello to send a message.');
                    };
                    websocket.onmessage = function(event) {
                        // log the event                
                        displayMessage('The response was received! ' + event.data, 'success');
                    };
                    websocket.onerror = function(event) {
                        // log the event
                        displayMessage('Error! ' + event.data, 'error');
                    };
                    websocket.onclose = function() {
                        displayStatus('Closed');
                        displayMessage('The connection was closed or timed out. Please click the Open Connection button to reconnect.');
                        document.getElementById('sayHello').disabled = true;
                    };
                }
    
                function disconnect() {
                    if (websocket !== null) {
                        websocket.close();
                        websocket = null;
                    }
                    message.setAttribute("class", "message");
                    message.value = 'WebSocket closed.';
                    // log the event
                }
    
                function sendMessage() {
                    if (websocket !== null) {
                        var content = document.getElementById('name').value;
                        websocket.send(content);
                    } else {
                        displayMessage('WebSocket connection is not established. Please click the Open Connection button.', 'error');
                    }
                }
    
                function displayMessage(data, style) {
                    var message = document.getElementById('hellomessage');
                    message.setAttribute("class", style);
                    message.value = data;
                }
    
                function displayStatus(status) {
                    var currentStatus = document.getElementById('currentstatus');
                    currentStatus.value = status;
                }
    
            </script>
        </head>
        <body>
    
            <div>
                <h1>Welcome to JBoss!</h1>
                <div>This is a simple example of a WebSocket implementation.</div>
                <div id="connect-container">
                    <div>
                        <fieldset>
                            <legend>Connect or disconnect using WebSocket :</legend>
                            <input type="button" id="connect" onclick="connect();" value="Open Connection" />
                            <input type="button" id="disconnect" onclick="disconnect();" value="Close Connection" />
                        </fieldset>
                    </div>
                    <div>
                        <fieldset>
                            <legend>Type your name below. then click the `Say Hello` button :</legend>
                            <input id="name" type="text" size="40" style="width: 40%"/>
                            <input type="button" id="sayHello" onclick="sendMessage();" value="Say Hello" disabled="disabled"/>
                        </fieldset>
                    </div>
                    <div>Current WebSocket Connection Status: <output id="currentstatus" class="message">Closed</output></div>
                    <div>
                        <output id="hellomessage" />
                    </div>
                </div>
            </div>
        </body>
    </html>
  2. WebSocket サーバーエンドポイントを作成します。

    以下の方法のいずれかを使用して WebSocket サーバーエンドポイントを作成できます。
    • Programmatic Endpoint: エンドポイントは Endpoint クラスを拡張します。
    • Annotated Endpoint: エンドポイントクラスはアノテーションを使用して WebSocket イベントと対話します。これは、プログラム的なエンドポイントよりも簡単にコーディングできます。
    以下のコード例では、アノテーション付きエンドポイントが使用され、以下のイベントが処理されます。
    • The@ServerEndpointアノテーションは、このクラスを WebSocket サーバーエンドポイントとして識別し、パスを指定します。
    • WebSocket 接続が開かれると @OnOpen アノテーションがトリガーされます。
    • The@OnMessageメッセージが WebSocket 接続に送信されると、注釈がトリガーされます。
    • WebSocket 接続が閉じられると、@OnClose アノテーションがトリガーされます。
    package org.jboss.as.quickstarts.websocket_hello;
    
    import javax.websocket.CloseReason;
    import javax.websocket.OnClose;
    import javax.websocket.OnMessage;
    import javax.websocket.OnOpen;
    import javax.websocket.Session;
    import javax.websocket.server.ServerEndpoint;
    
    @ServerEndpoint("/websocket/helloName")
    public class HelloName {
    
        @OnMessage
        public String sayHello(String name) {
            System.out.println("Say hello to '" + name + "'");
            return ("Hello" + name);    
        }
    
        @OnOpen
        public void helloOnOpen(Session session) {
            System.out.println("WebSocket opened: " + session.getId());
        }
        
        @OnClose
        public void helloOnClose(CloseReason reason) {
            System.out.println("Closing a WebSocket due to " + reason.getReasonPhrase());
        }
    }
    
  3. jboss-web.xml ファイルを設定します。

    を作成する必要があります<enable-websockets>アプリケーション WEB-INF/jboss-web.xml の要素を作成し、true に設定します。
    <?xml version="1.0" encoding="UTF-8"?>
    <!--Enable WebSockets -->
    <jboss-web>
       <enable-websockets>true</enable-websockets>
    </jboss-web>
  4. プロジェクト POM ファイルで WebSocket API の依存関係を宣言します。

    Maven を使用する場合は、プロジェクト pom.xml ファイルに以下の依存関係を追加します。
    <dependency>
      <groupId>org.jboss.spec.javax.websocket</groupId>
      <artifactId>jboss-websocket-api_1.0_spec</artifactId>
      <version>1.0.0.Final</version>
      <scope>provided</scope>
    </dependency>
    
  5. JBoss EAP サーバーを設定します。

    http を設定します<connector>サーバー設定ファイルの Web サブシステムで、NIO2 プロトコルを使用します。
    1. JBoss EAP サーバーを起動します。
    2. ご使用のオペレーティングシステム向けのコマンドを使用して、管理 CLI を起動します。
      Linux の場合
      EAP_HOME/bin/jboss-cli.sh --connect
      Windows の場合:
      EAP_HOME\bin\jboss-cli.bat --connect
    3. JBoss EAP サーバー設定ファイルの Web サブシステムでノンブロッキング JavaNIO2 コネクタープロトコルを有効にするには、次のコマンドを入力します。
      /subsystem=web/connector=http/:write-attribute(name=protocol,value=org.apache.coyote.http11.Http11NioProtocol)
      どちらのコマンドでも、次の結果が表示されます。
      {
          "outcome" => "success",
          "response-headers" => {
              "operation-requires-reload" => true,
              "process-state" => "reload-required"
          }
      }
    4. 設定を再ロードするようにサーバーに通知します。
      reload
      以下の結果が表示されるはずです。
      {
          "outcome" => "success",
          "result" => undefined
      }
      
    5. JBoss EAP サーバー設定ファイルへの変更を確認します。これで、Web サブシステムに http 用の次の XML が含まれるはずです。<connector>
      <subsystem xmlns="urn:jboss:domain:web:2.1" default-virtual-server="default-host" native="false">
          <connector name="http" protocol="org.apache.coyote.http11.Http11NioProtocol" scheme="http" socket-binding="http"/>
          <virtual-server name="default-host" enable-welcome-root="true">
          <alias name="localhost"/>
              <alias name="example.com"/>
          </virtual-server>
      </subsystem>

第18章 アプリケーションセキュリティー

18.1. 基本的な概念

18.1.1. 暗号化について

暗号化 とは、数学的なアルゴリズムを適用して機密情報をエンコードすることを言います。暗号化は、データ漏洩、システム停止、およびその他のリスクからインフラストラクチャーを保護するための基盤の 1 つです。
暗号化は、パスワードなどの単純な文字列データに適用できます。また、データ通信ストリームにも適用できます。たとえば、HTTPS プロトコルは、当事者間でデータを転送する前に、すべてのデータを暗号化します。ユーザーが SSH プロトコル (Secure Shell) を使用してあるサーバーから別のサーバーに接続する場合、すべての通信は暗号化された トンネル で送信されます。

18.1.2. セキュリティードメイン

セキュリティードメインは、JBoss EAP 6 セキュリティーサブシステムの一部です。すべてのセキュリティー設定は、管理対象ドメインのドメインコントローラー、またはスタンドアロンサーバーによって一元管理されるようになりました。
セキュリティードメインは、認証、承認、セキュリティーマッピング、および監査の設定で構成されます。これは 、Java 認証および承認サービス (JAAS) の 宣言型セキュリティーを実装します。
認証とは、ユーザーの身元を確認することです。セキュリティー用語では、このユーザーは プリンシパル と呼ばれます。認証と承認は異なりますが、含まれている認証モジュールの多くは承認も処理します。
承認 は、認証されたユーザーが、システムまたは操作の特定のリソースへアクセスできるパーミッションまたは特権を持っているかどうかをサーバーが判断するセキュリティーポリシーです。セキュリティー用語では、ロールとも呼ばれます。
セキュリティーマッピング とは、情報をアプリケーションに渡す前にプリンシパル、ロール、または属性から情報を追加、編集、削除する機能のことです。
監査マネージャーは、ユーザーが プロバイダーモジュール を設定して、セキュリティーイベントの報告方法を制御できるようにします。
セキュリティードメインを使用する場合は、アプリケーション自体から特定のセキュリティー設定をすべて削除できます。これにより、セキュリティーパラメーターを一元的に変更できます。このような設定構造を有効に活用できる一般的な例が、アプリケーションをテスト環境と本番環境の間で移動する処理です。

18.1.3. SSL 暗号化について

Secure Sockets Layer (SSL) は、2 つのシステム間のネットワークトラフィックを暗号化します。2 つのシステム間のトラフィックは、接続の ハンドシェイク フェーズ中に生成され、これら 2 つのシステムによってのみ認識される双方向キーを使用して暗号化されます。
SSL は、双方向暗号化キーを安全に交換するために、公開キーインフラストラクチャー (PKI) を利用します。これは、キーペア を利用する暗号化の方法です。キーペア は、個別のキーで一致する暗号化キー (公開鍵と秘密鍵) の 2 つで構成されます。公開鍵は第三者と共有でき、データの暗号化に使用されます。秘密鍵は機密に扱われて、公開鍵を使用して暗号化されたデータの復号化に使用されます。
クライアントが安全な接続を要求すると、安全な通信を開始する前にハンドシェイクフェーズが実行されます。SSL ハンドシェイクの間、サーバーはパブリックキーを証明書としてクライアントに渡します。証明書には、サーバーの識別情報 (URL)、サーバーのパブリックキー、および証明書を検証するデジタル署名が含まれます。その後、クライアントは証明書を検証し、証明書が信頼できるかどうかについて決定します。証明書を信頼できる場合、クライアントは SSL 接続の双方向暗号鍵を生成し、サーバーのパブリックキーを使用して暗号化し、サーバーに返送します。サーバーは、その秘密鍵を使用して双方向暗号化鍵を復号化し、この接続を使用した 2 台のマシン間でさらに通信する場合は、この双方向暗号化鍵を使用して暗号化されます。
警告
Red Hat は、影響するすべてのパッケージで TLSv1.1 または TLSv1.2 を利用するために SSL を明示的に無効化することを推奨しています。

18.1.4. 宣言型セキュリティーについて

宣言型セキュリティー は、コンテナーを使用してセキュリティーを管理することでアプリケーションコードからセキュリティーの懸念を分離する方法です。コンテナーはファイルパーミッション、またはユーザー、グループ、およびロールを基に承認システムを提供します。通常この方法は、アプリケーション自体にセキュリティーの責任をすべて与えるプログラムによるセキュリティーよりも優れています。
JBoss EAP 6 は、セキュリティードメインを介して宣言型セキュリティーを提供します。

18.2. アプリケーションにおけるロールベースのセキュリティー

18.2.1. アプリケーションセキュリティーについて

アプリケーションの保護は、すべてのアプリケーション開発者にとって多面的で重要な関心事です。JBoss EAP 6 は、以下の機能を含む、安全なアプリケーションを作成するために必要なすべてのツールを提供します。

18.2.2. 認証

認証とは、認証の対象を特定し、その識別情報の真正性を検証することを言います。最も一般的な認証メカニズムは、ユーザー名とパスワードの組み合わせです。他の一般的な認証メカニズムは、共有キー、スマートカード、または指紋を使用します。認証が成功した結果は、Java Enterprise Edition の宣言型セキュリティーの観点から、プリンシパルと呼ばれます。
JBoss EAP 6 は、プラグイン可能な認証モジュールのシステムを使用して、組織ですでに使用している認証システムとの柔軟性と統合を提供します。各セキュリティードメインには、1 つ以上の設定済み認証モジュールが含まれる場合があります。各モジュールには、その動作をカスタマイズするための追加の設定パラメーターが含まれています。認証サブシステムを設定する最も簡単な方法は、Web ベースの管理コンソール内です。
認証は承認と同じではありませんが、リンクされていることがよくあります。含まれている認証モジュールの多くは、承認も処理できます。

18.2.3. 認可について

承認は、ID に基づいてリソースへのアクセスを許可または拒否するためのメカニズムです。これは、プリンシパルに追加できる一連の宣言型セキュリティーロールとして実装されます。
JBoss EAP 6 は、モジュラーシステムを使用して認証を設定します。各セキュリティードメインには、1 つ以上の承認ポリシーが含まれる場合があります。各ポリシーには、その動作を定義する基本モジュールがあります。特定のフラグと属性を使用して設定されます。許可サブシステムを設定する最も簡単な方法は、Web ベースの管理コンソールを使用することです。
承認は認証とは異なり、通常は認証後に行われます。認証モジュールの多くは、承認も処理します。

18.2.4. セキュリティー監査

セキュリティー監査とは、ログへの書き込みなど、security サブシステム内で発生するイベントに対してトリガーするイベントのことです。監査方法は、認証、承認、およびセキュリティーマッピングの詳細とともにセキュリティードメインの一部として設定されます。
監査は、プロバイダーモジュール を使用します。含まれているものの 1 つを使用することも、独自に実装することもできます。

18.2.5. セキュリティーマッピング

セキュリティーマッピングを使用すると、認証または承認が実行された後、情報がアプリケーションに渡される前に認証情報と承認情報を組み合わせることができます。
プリンシパル (認証)、ロール (承認)、またはクレデンシャル (プリンシパルやロールでない属性) をマッピングすることが可能です。
ロールマッピングは、認証後にサブジェクトへロールを追加、置換、または削除するために使用されます。
プリンシパルマッピングは、認証後にプリンシパルを変更するために使用されます。
属性マッピングは、外部システムからの属性値をアプリケーションで使用するために変換したり、逆にそのような外部システムへ属性を変換したりするために使用されます。<remark>Bugzilla のフィードバックを反映済み</remark>

18.2.6. Java 認証および承認サービス (JAAS)

Java Authentication and Authorization Service (JAAS) は、ユーザー認証と認可のために設計された一連の Java パッケージからなるセキュリティー API です。この API は 標準の PAM (Pluggable Authentication Modules) フレームワークの Java 実装です。これは、Java Enterprise Edition アクセス制御アーキテクチャーを拡張して、ユーザーベースの許可をサポートします。
JBoss EAP 6 では、JAAS は宣言型のロールベースのセキュリティーのみを提供します。宣言型セキュリティーの詳細は、「宣言型セキュリティーについて」 を参照してください。
JAAS は、Kerberos や LDAP などの基盤となる認証テクノロジーから独立しています。アプリケーションを変更せずに、基盤となるセキュリティー構造を変更できます。JAAS 設定を変更するだけで済みます。

18.2.7. Java 認証および承認サービス (JAAS) について

JBoss EAP 6 のセキュリティーアーキテクチャーは、セキュリティー設定サブシステムと、アプリケーション内のいくつかの設定ファイルに含まれるアプリケーション固有のセキュリティー設定で設定されています。

ドメイン、サーバーグループ、およびサーバー固有の設定

サーバーグループ (管理対象ドメイン内) およびサーバー (スタンドアロンサーバー内) には、セキュリティードメインの設定が含まれます。セキュリティードメインには、認証、承認、マッピング、および監査モジュールの組み合わせに関する情報と、設定の詳細が含まれています。アプリケーションは、jboss-web.xml で、必要なセキュリティードメインを名前で指定します。

アプリケーション固有の設定

アプリケーション固有の設定は、次の 4 つのファイルの 1 つ以上で行われます。

表18.1 アプリケーション固有の設定ファイル

ファイル Description
ejb-jar.xml
アーカイブの META-INF ディレクトリーにある EnterpriseJavaBean (EJB) アプリケーションのデプロイメント記述子。ejb-jar.xml を使用して、アプリケーションレベルでロールを指定し、それらをプリンシパルにマップします。特定のメソッドとクラスを特定のロールに制限することもできます。また、セキュリティーに関係のない他の EJB 固有の設定にも使用されます。
web.xml
Java Enterprise Edition (EE)Web アプリケーションのデプロイメント記述子。web.xml を使用して、許可される HTTP リクエストのタイプを制限するなど、アプリケーションのリソースとトランスポートの制約を宣言します。このファイルで単純な Web ベースの認証を設定することもできます。また、セキュリティーに関係のない他のアプリケーション固有の設定にも使用されます。アプリケーションが認証と承認に使用するセキュリティードメインは、jboss-web.xml で定義されています。
jboss-ejb3.xml
ejb-jar.xml 記述子に対する JBoss 固有の拡張機能が含まれています。
jboss-web.xml
web.xml 記述子に対する JBoss 固有の拡張機能が含まれています。
注記
ejb-jar.xml および web.xml は、Java Enterprise Edition (Java EE) 仕様で定義されています。jboss-ejb3.xmlejb-jar.xml の JBoss 固有の拡張機能を提供し、jboss-web.xmlweb.xml の JBoss 固有の拡張機能を提供します。

18.2.8. アプリケーションでのセキュリティードメインの使用

概要

アプリケーションでセキュリティードメインを使用するには、最初にサーバーの設定でセキュリティードメインを定義してから、アプリケーションの展開記述子でアプリケーションに対してセキュリティードメインを有効にする必要があります。次に、それを使用する EJB に必要なアノテーションを追加する必要があります。このトピックでは、アプリケーションでセキュリティードメインを使用するために必要な手順について説明します。

警告
アプリケーションが、認証キャッシュを使用するセキュリティードメインの一部である場合、セキュリティードメインの他のアプリケーションもそのアプリケーションのユーザー認証を使用できます。

手順18.1 セキュリティードメインを使用するようアプリケーションを設定

  1. セキュリティードメインの定義

    サーバーの設定ファイルでセキュリティードメインを定義した後、アプリケーションの記述子ファイルでアプリケーションに対して有効にする必要があります。
    1. サーバーの設定ファイルへセキュリティードメインを設定

      セキュリティードメインは、サーバーの設定ファイルの セキュリティー サブシステムで設定されます。JBoss EAP 6 インスタンスが管理対象ドメインで実行されている場合、これは domain/configuration/domain.xml ファイルです。JBoss EAP 6 インスタンスがスタンドアロンサーバーとして実行されている場合、これは standalone/configuration/standalone.xml ファイルです。
      jboss-web-policy および jboss-ejb-policy セキュリティードメインは、JBoss EAP 6 でデフォルトで提供されます。次の XML の例は、サーバーの設定ファイルの セキュリティー サブシステムからコピーされたものです。
      Thecache-typeセキュリティードメインの属性は、認証チェックを高速化するためのキャッシュを指定します。許可される値は、デフォルト でキャッシュとして単純なマップを使用するか、infinispan で Infinispan キャッシュを使用します。
      <subsystem xmlns="urn:jboss:domain:security:1.2">
          <security-domains>
              <security-domain name="other" cache-type="default">
                  <authentication>
                      <login-module code="Remoting" flag="optional">
                          <module-option name="password-stacking" value="useFirstPass"/>
                      </login-module>
                      <login-module code="RealmDirect" flag="required">
                          <module-option name="password-stacking" value="useFirstPass"/>
                      </login-module>
                  </authentication>
              </security-domain>
              <security-domain name="jboss-web-policy" cache-type="default">
                  <authorization>
                      <policy-module code="Delegating" flag="required"/>
                  </authorization>
              </security-domain>
              <security-domain name="jboss-ejb-policy" cache-type="default">
                  <authorization>
                      <policy-module code="Delegating" flag="required"/>
                  </authorization>
              </security-domain>
          </security-domains>
      </subsystem>
      管理コンソールまたは CLI を使用して、追加のセキュリティードメインを必要に応じて設定できます。
    2. アプリケーションの記述子ファイルでのセキュリティードメインの有効化

      セキュリティードメインは、アプリケーションの WEB-INF/jboss-web.xml ファイルの <jboss-web> 要素の <security-domain> 子要素で指定されます。次の例では 、my-domain という名前のセキュリティードメインを設定します。
      <jboss-web>
          <security-domain>my-domain</security-domain>
      </jboss-web>
      これは、WEB-INF/jboss-web.xml 記述子で指定できる多くの設定の 1 つにすぎません。
  2. EJB への必要なアノテーションの追加

    @SecurityDomain および @RolesAllowed アノテーションを使用して、EJB でセキュリティーを設定します。次の EJB コード例は、ゲスト ロールのユーザーによる 他の セキュリティードメインへのアクセスを制限します。
    package example.ejb3;
    
    import java.security.Principal;
    
    import javax.annotation.Resource;
    import javax.annotation.security.RolesAllowed;
    import javax.ejb.SessionContext;
    import javax.ejb.Stateless;
    
    import org.jboss.ejb3.annotation.SecurityDomain;
    
    /**
     * Simple secured EJB using EJB security annotations
     * Allow access to "other" security domain by users in a "guest" role.
     */
    @Stateless
    @RolesAllowed({ "guest" })
    @SecurityDomain("other")
    public class SecuredEJB {
    
       // Inject the Session Context
       @Resource
       private SessionContext ctx;
    
       /**
        * Secured EJB method using security annotations
        */
       public String getSecurityInfo() {
          // Session context injected using the resource annotation
          Principal principal = ctx.getCallerPrincipal();
          return principal.toString();
       }
    }
    その他のコード例は、Red Hat カスタマーポータルより入手できる JBoss EAP 6 Quickstarts バンドルの ejb-security クイックスタートを参照してください。
    注記
    EJB のセキュリティードメインは、jboss-ejb3.xml デプロイメント記述子を使用して設定することもできます。詳細は、「jboss-ejb3.xml デプロイメント記述子の参照」 を参照してください。

手順18.2 EJB3Bean のカスタムプリンシパルにアクセスするように JBoss EAP 6 を設定します

  1. JAAS に従うように ApplicationRealm を設定します。
    <security-realm name="MyDomainRealm">
     <authentication>
       <jaas name="my-security-domain"/>
    </security-realm>
  2. カスタムプリンシパルを使用するように JAAS セキュリティードメインを設定します。
    <security-domain name="my-security-domain" cache-type="default">
       <authentication>
           <login-module code="UsersRoles" flag="required">
               <module-option name="usersProperties" value="file:///${jboss.server.config.dir}/users.properties"/>
               <module-option name="rolesProperties" value="file:///${jboss.server.config.dir}/roles.properties"/>
               <module-option name="principalClass" value="org.jboss.example.CustomPrincipalImpl"/>
           </login-module>
       </authentication>
    </security-domain>
  3. カスタムプリンシパルを JBoss モジュールとしてデプロイします。
  4. を設定しますorg.jboss.as.remotingモジュール (modules/org/jboss/as/remoteing/main/module.xml) は、カスタムプリンシパルを含むモジュールに依存します。
                
    <resources>
        <resource-root path="jboss-as-remoting-7.1.2.Final-redhat-1.jar"/>
        <!-- Insert resources here -->
    </resources>
    
    <dependencies>
        <module name="org.jboss.staxmapper"/>
        <module name="org.jboss.as.controller"/>
        <module name="org.jboss.as.domain-management"/>
        <module name="org.jboss.as.network"/>
        <module name="org.jboss.as.protocol"/>
        <module name="org.jboss.as.server"/>
        <module name="org.jboss.as.security" optional="true"/>
        <module name="org.jboss.as.threads"/>
        <module name="org.jboss.logging"/>
        <module name="org.jboss.modules"/>
        <module name="org.jboss.msc"/>        
        <module name="org.jboss.remoting3"/>
        <module name="org.jboss.sasl"/>
        <module name="org.jboss.threads"/>
        <module name="org.picketbox" optional="true"/>        
        <module name="javax.api" />
        <module name="org.jboss.example" />  <!--FIXME:  dependency on custom principal added here -->
    </dependencies>
  5. 使用するクライアントを設定するorg.jboss.ejb.client.namingjboss-ejb-client.properties ファイルは次のようになります。
    remote.connections=default
    endpoint.name=client-endpoint
    remote.connection.default.port=4447
    remote.connection.default.host=localhost
    remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
    remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
    # The following setting is required when deferring to JAAS
    remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT=false
    
    remote.connection.default.username=admin
    remote.connection.default.password=testing

18.2.9. サーブレットでロールベースのセキュリティーを使用する

サーブレットにセキュリティーを追加するには、各サーブレットを URL パターンにマップし、セキュリティーで保護する必要のある URL パターンにセキュリティー制約を作成します。セキュリティー上の制約により、URL へのアクセスがロールに制限されます。認証と承認は、WAR の jboss-web.xml で指定されたセキュリティードメインによって処理されます。

前提条件

サーブレットでロールベースのセキュリティーを使用する前に、アクセスの認証と承認に使用されるセキュリティードメインを JBoss EAP 6 コンテナーで設定する必要があります。

手順18.3 サーブレットにロールベースのセキュリティーを追加する

  1. サーブレットと URL パターンの間にマッピングを追加します。

    web.xml<servlet-mapping> 要素を使用して、個々のサーブレットを URL パターンにマップします。次の例では、DisplayOpResult というサーブレットを URL パターン /DisplayOpResult にマップします。
    <servlet-mapping>
        <servlet-name>DisplayOpResult</servlet-name>
        <url-pattern>/DisplayOpResult</url-pattern>
    </servlet-mapping>		
    
    
  2. URL パターンにセキュリティー制約を追加します。

    URL パターンをセキュリティー制約にマップするには、<security-constraint> を使用します。次の例では、URL パターン /DisplayOpResult からのアクセスを、ロール eap_admin のプリンシパルがアクセスするように制限しています。ロールはセキュリティードメインに存在する必要があります。
    <security-constraint>
    	<display-name>Restrict access to role eap_admin</display-name>
    	<web-resource-collection>
    		<web-resource-name>Restrict access to role eap_admin</web-resource-name>
    		<url-pattern>/DisplayOpResult/*</url-pattern>
    	</web-resource-collection>
    	<auth-constraint>
    		<role-name>eap_admin</role-name>
    	</auth-constraint>	
    </security-constraint>	
    
    <security-role>
      <role-name>eap_admin</role-name>
    </security-role>
    
    
    <login-config>
        <auth-method>BASIC</auth-method>
    </login-config>
    
    
    認証方法を指定する必要があります。これは、BASIC、FORM、DIGEST、CLIENT-CERT、SPNEGO のいずれかになります。この例では、BASIC 認証を使用しています。
  3. WAR の jboss-web.xml でセキュリティードメインを指定します

    サーブレットを設定済みのセキュリティードメインに接続するために、セキュリティードメインを WAR の jboss-web.xml に追加します。これは、セキュリティー制約に対してプリンシパルを認証および承認する方法を知っています。次の例では、acme_domain というセキュリティードメインを使用しています。
    <jboss-web>
    	...
    	<security-domain>acme_domain</security-domain>
    	...
    </jboss-web>
    
    

例18.1 ロールベースのセキュリティーが設定された web.xml の例

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">

<display-name>Use Role-Based Security In Servlets</display-name>

<welcome-file-list>
  <welcome-file>/index.jsp</welcome-file>
</welcome-file-list>

<servlet-mapping>
    <servlet-name>DisplayOpResult</servlet-name>
    <url-pattern>/DisplayOpResult</url-pattern>
</servlet-mapping>

<security-constraint>
  <display-name>Restrict access to role eap_admin</display-name>
    <web-resource-collection>
      <web-resource-name>Restrict access to role eap_admin</web-resource-name>
      <url-pattern>/DisplayOpResult/*</url-pattern>
      </web-resource-collection>
      <auth-constraint>
        <role-name>eap_admin</role-name>
      </auth-constraint>
    </security-constraint>

    <security-role>
      <role-name>eap_admin</role-name>
    </security-role>

    <login-config>
        <auth-method>BASIC</auth-method>
    </login-config>

</web-app>

18.2.10. アプリケーションでサードパーティーの認証システムを使用する

サードパーティーのセキュリティーシステムを JBoss EAP 6 と統合できます。これらのタイプのシステムは通常、トークンベースです。外部システムは認証を実行し、リクエストヘッダーを介してトークンを Web アプリケーションに返します。これは、境界認証 と呼ばれることがよくあります。アプリケーションで境界認証を設定するには、カスタム認証バルブを追加します。サードパーティープロバイダーからのバルブがある場合は、それがクラスパスにあることを確認し、サードパーティー認証モジュールのドキュメントとともに、以下の例に従ってください。
注記
JBoss EAP 6 でバルブを設定する場所が変更されました。context.xml デプロイメント記述子はなくなりました。代わりに、バルブは jboss-web.xml 記述子で直接設定されます。context.xml は無視されるようになりました。

例18.2 基本認証バルブ

<jboss-web>
  <valve>
    <class-name>org.jboss.security.negotiation.NegotiationAuthenticator</class-name>
  </valve>
</jboss-web>
このバルブは、Kerberos ベースの SSO に使用されます。また、Web アプリケーションにサードパーティーのオーセンティケーターを指定するための最も単純なパターンも示しています。

例18.3 ヘッダー属性が設定されたカスタムバルブ

<jboss-web>
  <valve>
    <class-name>org.jboss.web.tomcat.security.GenericHeaderAuthenticator</class-name>
    <param>
      <param-name>httpHeaderForSSOAuth</param-name>
      <param-value>sm_ssoid,ct-remote-user,HTTP_OBLIX_UID</param-value>
    </param>
    <param>
      <param-name>sessionCookieForSSOAuth</param-name>
      <param-value>SMSESSION,CTSESSION,ObSSOCookie</param-value>
    </param>
  </valve>
</jboss-web>
この例は、バルブにカスタム属性を設定する方法を示しています。オーセンティケーターは、ヘッダー ID とセッションキーの存在を確認し、ユーザー名とパスワードの値として、セキュリティーレイヤーを駆動する JAAS フレームワークに渡します。ユーザー名とパスワードを処理し、サブジェクトに正しいロールを設定できるカスタム JAAS ログインモジュールが必要です。設定された値と一致するヘッダー値がない場合、通常のフォームベースの認証セマンティクスが適用されます。

カスタムオーセンティケーターの作成

独自のオーセンティケーターを作成することは、このドキュメントの範囲外です。ただし、例として次の Java コードが提供されています。

例18.4 GenericHeaderAuthenticator.java

/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2006, Red Hat Middleware LLC, and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
 
package org.jboss.web.tomcat.security;

import java.io.IOException;
import java.security.Principal;
import java.util.StringTokenizer;

import javax.management.JMException;
import javax.management.ObjectName;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.Realm;
import org.apache.catalina.Session;
import org.apache.catalina.authenticator.Constants;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.deploy.LoginConfig;
import org.jboss.logging.Logger;

import org.jboss.as.web.security.ExtendedFormAuthenticator;

/**
 * JBAS-2283: Provide custom header based authentication support
 * 
 * Header Authenticator that deals with userid from the request header Requires
 * two attributes configured on the Tomcat Service - one for the http header
 * denoting the authenticated identity and the other is the SESSION cookie
 * 
 * @author <a href="mailto:Anil.Saldhana@jboss.org">Anil Saldhana</a>
 * @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
 * @version $Revision$
 * @since Sep 11, 2006
 */
public class GenericHeaderAuthenticator extends ExtendedFormAuthenticator {
  protected static Logger log = Logger
      .getLogger(GenericHeaderAuthenticator.class);

  protected boolean trace = log.isTraceEnabled();

  // JBAS-4804: GenericHeaderAuthenticator injection of ssoid and
  // sessioncookie name.
  private String httpHeaderForSSOAuth = null;

  private String sessionCookieForSSOAuth = null;

  /**
   * <p>
   * Obtain the value of the <code>httpHeaderForSSOAuth</code> attribute. This
   * attribute is used to indicate the request header ids that have to be
   * checked in order to retrieve the SSO identity set by a third party
   * security system.
   * </p>
   * 
   * @return a <code>String</code> containing the value of the
   *         <code>httpHeaderForSSOAuth</code> attribute.
   */
  public String getHttpHeaderForSSOAuth() {
    return httpHeaderForSSOAuth;
  }

  /**
   * <p>
   * Set the value of the <code>httpHeaderForSSOAuth</code> attribute. This
   * attribute is used to indicate the request header ids that have to be
   * checked in order to retrieve the SSO identity set by a third party
   * security system.
   * </p>
   * 
   * @param httpHeaderForSSOAuth
   *            a <code>String</code> containing the value of the
   *            <code>httpHeaderForSSOAuth</code> attribute.
   */
  public void setHttpHeaderForSSOAuth(String httpHeaderForSSOAuth) {
    this.httpHeaderForSSOAuth = httpHeaderForSSOAuth;
  }

  /**
   * <p>
   * Obtain the value of the <code>sessionCookieForSSOAuth</code> attribute.
   * This attribute is used to indicate the names of the SSO cookies that may
   * be present in the request object.
   * </p>
   * 
   * @return a <code>String</code> containing the names (separated by a
   *         <code>','</code>) of the SSO cookies that may have been set by a
   *         third party security system in the request.
   */
  public String getSessionCookieForSSOAuth() {
    return sessionCookieForSSOAuth;
  }

  /**
   * <p>
   * Set the value of the <code>sessionCookieForSSOAuth</code> attribute. This
   * attribute is used to indicate the names of the SSO cookies that may be
   * present in the request object.
   * </p>
   * 
   * @param sessionCookieForSSOAuth
   *            a <code>String</code> containing the names (separated by a
   *            <code>','</code>) of the SSO cookies that may have been set by
   *            a third party security system in the request.
   */
  public void setSessionCookieForSSOAuth(String sessionCookieForSSOAuth) {
    this.sessionCookieForSSOAuth = sessionCookieForSSOAuth;
  }

  /**
   * <p>
   * Creates an instance of <code>GenericHeaderAuthenticator</code>.
   * </p>
   */
  public GenericHeaderAuthenticator() {
    super();
  }

  public boolean authenticate(Request request, HttpServletResponse response,
      LoginConfig config) throws IOException {
    log.trace("Authenticating user");

    Principal principal = request.getUserPrincipal();
    if (principal != null) {
      if (trace)
        log.trace("Already authenticated '" + principal.getName() + "'");
      return true;
    }

    Realm realm = context.getRealm();
    Session session = request.getSessionInternal(true);

    String username = getUserId(request);
    String password = getSessionCookie(request);

    // Check if there is sso id as well as sessionkey
    if (username == null || password == null) {
      log.trace("Username is null or password(sessionkey) is null:fallback to form auth");
      return super.authenticate(request, response, config);
    }
    principal = realm.authenticate(username, password);

    if (principal == null) {
      forwardToErrorPage(request, response, config);
      return false;
    }

    session.setNote(Constants.SESS_USERNAME_NOTE, username);
    session.setNote(Constants.SESS_PASSWORD_NOTE, password);
    request.setUserPrincipal(principal);

    register(request, response, principal, HttpServletRequest.FORM_AUTH,
        username, password);
    return true;
  }

  /**
   * Get the username from the request header
   * 
   * @param request
   * @return
   */
  protected String getUserId(Request request) {
    String ssoid = null;
    // We can have a comma-separated ids
    String ids = "";
    try {
      ids = this.getIdentityHeaderId();
    } catch (JMException e) {
      if (trace)
        log.trace("getUserId exception", e);
    }
    if (ids == null || ids.length() == 0)
      throw new IllegalStateException(
          "Http headers configuration in tomcat service missing");

    StringTokenizer st = new StringTokenizer(ids, ",");
    while (st.hasMoreTokens()) {
      ssoid = request.getHeader(st.nextToken());
      if (ssoid != null)
        break;
    }
    if (trace)
      log.trace("SSOID-" + ssoid);
    return ssoid;
  }

  /**
   * Obtain the session cookie from the request
   * 
   * @param request
   * @return
   */
  protected String getSessionCookie(Request request) {
    Cookie[] cookies = request.getCookies();
    log.trace("Cookies:" + cookies);
    int numCookies = cookies != null ? cookies.length : 0;

    // We can have comma-separated ids
    String ids = "";
    try {
      ids = this.getSessionCookieId();
      log.trace("Session Cookie Ids=" + ids);
    } catch (JMException e) {
      if (trace)
        log.trace("checkSessionCookie exception", e);
    }
    if (ids == null || ids.length() == 0)
      throw new IllegalStateException(
          "Session cookies configuration in tomcat service missing");

    StringTokenizer st = new StringTokenizer(ids, ",");
    while (st.hasMoreTokens()) {
      String cookieToken = st.nextToken();
      String val = getCookieValue(cookies, numCookies, cookieToken);
      if (val != null)
        return val;
    }
    if (trace)
      log.trace("Session Cookie not found");
    return null;
  }

  /**
   * Get the configured header identity id in the tomcat service
   * 
   * @return
   * @throws JMException
   */
  protected String getIdentityHeaderId() throws JMException {
    if (this.httpHeaderForSSOAuth != null)
      return this.httpHeaderForSSOAuth;
    return (String) mserver.getAttribute(new ObjectName(
        "jboss.web:service=WebServer"), "HttpHeaderForSSOAuth");
  }

  /**
   * Get the configured session cookie id in the tomcat service
   * 
   * @return
   * @throws JMException
   */
  protected String getSessionCookieId() throws JMException {
    if (this.sessionCookieForSSOAuth != null)
      return this.sessionCookieForSSOAuth;
    return (String) mserver.getAttribute(new ObjectName(
        "jboss.web:service=WebServer"), "SessionCookieForSSOAuth");
  }

  /**
   * Get the value of a cookie if the name matches the token
   * 
   * @param cookies
   *            array of cookies
   * @param numCookies
   *            number of cookies in the array
   * @param token
   *            Key
   * @return value of cookie
   */
  protected String getCookieValue(Cookie[] cookies, int numCookies,
      String token) {
    for (int i = 0; i < numCookies; i++) {
      Cookie cookie = cookies[i];
      log.trace("Matching cookieToken:" + token + " with cookie name="
          + cookie.getName());
      if (token.equals(cookie.getName())) {
        if (trace)
          log.trace("Cookie-" + token + " value=" + cookie.getValue());
        return cookie.getValue();
      }
    }
    return null;
  }
}

18.3. ログインモジュール

18.3.1. モジュールの使用

JBoss EAP 6 には、ほとんどのユーザー管理ニーズに適したいくつかのバンドルされたログインモジュールが含まれています。JBoss EAP 6 は、リレーショナルデータベース、LDAP サーバー、またはフラットファイルからユーザー情報を読み取ることができます。JBoss EAP 6 はこれらのコアログインモジュールの他に、高度なカスタマイズの必要性に対応する、ユーザー情報を提供するログインモジュールも提供します。
その他のログインモジュールとそのオプションについては、付録 A.1 を参照してください。

18.3.1.1. パスワードスタッキング

スタックでは複数のログインモジュールをチェーンでき、各ログインモジュールは認証中にクレデンシャルの検証とロールの割り当ての両方を提供します。これは多くのユースケースで機能しますが、クレデンシャルの検証とロールの割り当てが複数のユーザー管理ストアに分散されることがあります。
「Ldap ログインモジュール」 LDAP とリレーショナルデータベースを組み合わせて、ユーザーがどちらのシステムでも認証できるようにする方法について説明します。ユーザーは中央の LDAP サーバーで管理されますが、アプリケーション固有のロールはアプリケーションのリレーショナルデータベースに格納される場合を考えてみましょう。password-stacking モジュールオプションはこの関係をキャプチャーします。
パスワードスタッキングを使用するには、各ログインモジュールで設定する必要があります<module-option>使用するパスワードスタッキング 属性 FirstPass。パスワードスタッキングに設定した以前のモジュールがユーザーを認証した場合、他のすべてのスタッキングモジュールがユーザーによって認証されたこととなり、承認の手順でロールの提供のみを行います。
パスワードスタッキング オプションが useFirstPass に設定されている場合、このモジュールは最初にプロパティー名の下で共有ユーザー名とパスワードを検索しますjavax.security.auth.login.namejavax.security.auth.login.passwordログインモジュールの共有状態マップでそれぞれ。
これらのプロパティーが見つかった場合、プリンシパル名とパスワードとして使用されます。見つからない場合、プリンシパル名とパスワードはこのログインモジュールによって設定され、プロパティー名の下に保存されますjavax.security.auth.login.namejavax.security.auth.login.passwordそれぞれ。
注記
パスワードスタッキングを使用する場合は、すべてのモジュールが必要になるように設定します。これにより、すべてのモジュールが考慮され、承認プロセスにロールを公開することができるようになります。

例18.5 パスワードスタッキングサンプル

この管理 CLI の例は、パスワードスタッキングの使用方法を示しています。
/subsystem=security/security-domain=pwdStack/authentication=classic/login-module=Ldap:add( \
  code=Ldap, \
  flag=required, \
  module-options=[ \
    ("password-stacking"=>"useFirstPass"), \
    ... Ldap login module configuration
  ])
/subsystem=security/security-domain=pwdStack/authentication=classic/login-module=Database:add( \
  code=Database, \
  flag=required, \
  module-options=[ \
    ("password-stacking"=>"useFirstPass"), \
    ... Database login module configuration
  ])

18.3.1.2. パスワードのハッシュ化

ログインモジュールのほとんどは、クライアントが提供するパスワードをユーザー管理システムに保存されたパスワードと比較する必要があります。通常、これらのモジュールはプレーンテキストのパスワードを使用しますが、プレーンテキストのパスワードがサーバー側に保存されないようにするため、ハッシュ化されたパスワードをサポートするよう設定できます。
重要
Red Hat JBoss Enterprise Application Platform Common Criteria 認定リリースは、パスワードハッシュに SHA-256 のみをサポートします。

例18.6 パスワードのハッシュ化

以下は、認証されていないユーザーにプリンシパル名 nobody を割り当て、usersb64.properties ファイルに based64 でエンコードされた SHA-256 ハッシュのパスワードを含むログインモジュール設定です。usersb64.properties ファイルは、デプロイメントクラスパスの一部です。
/subsystem=security/security-domain=testUsersRoles:add
/subsystem=security/security-domain=testUsersRoles/authentication=classic:add
/subsystem=security/security-domain=testUsersRoles/authentication=classic/login-module=UsersRoles:add( \
  code=UsersRoles, \
  flag=required, \
  module-options=[ \
    ("usersProperties"=>"usersb64.properties"), \
    ("rolesProperties"=>"test-users-roles.properties"), \
    ("unauthenticatedIdentity"=>"nobody"), \
    ("hashAlgorithm"=>"SHA-256"), \
    ("hashEncoding"=>"base64") \
  ])
hashAlgorithm
パスワードをハッシュするために使用される java.security.MessageDigest アルゴリズムの名前。デフォルトがないため、ハッシュを有効にするには、このオプションを指定する必要があります。一般的な値は SHA-256SHA-1、および MD5 です。
hashEncoding
base64hexrfc2617 の 3 つのエンコーディングタイプのいずれかを指定する文字列。デフォルトは base64 です。
hashCharset
クリアテキストのパスワードをバイト配列に変換するために使用されるエンコーディング文字セット。プラットフォームのデフォルトエンコーディングがデフォルトです。
hashUserPassword
ユーザーが送信するパスワードにハッシュアルゴリズムを適用する必要があることを指定します。ハッシュ化されたユーザーパスワードは、ログインモジュール内の値と比較されます. これは、パスワードのハッシュです。デフォルトは true です。
hashStorePassword
サーバー側に保存されているパスワードにハッシュアルゴリズムを適用する必要があることを指定します。これは、ユーザーパスワードのハッシュと、比較対象のサーバーからの要求固有のトークンを送信するダイジェスト認証に使用されます。ハッシュアルゴリズム (ダイジェストの場合は rfc2617) を利用してサーバー側のハッシュを計算し、クライアントから送信されたハッシュ値と一致させる必要があります。
コードでパスワードを生成する必要がある場合、org.jboss.security.auth.spi.Util クラスは、指定されたエンコーディングを使用してパスワードをハッシュする静的ヘルパーメソッドを提供します。次の例では、base64 でエンコードされた MD5 ハッシュパスワードを生成します。
String hashedPassword = Util.createPasswordHash("SHA-256",
 Util.BASE64_ENCODING, null, null, "password");
OpenSSL は、コマンドラインでハッシュ化されたパスワードをすばやく生成するための代替方法を提供します。次の例では、base64 でエンコードされた SHA-256 ハッシュパスワードも生成されます。ここでは、プレーンテキストの パスワード (password) が OpenSSL ダイジェスト関数にパイプされ、次に別の OpenSSL 関数にパイプされて base64 エンコード形式に変換されます。
echo -n password | openssl dgst -sha256 -binary | openssl base64
どちらの場合も、パスワードのハッシュバージョンは同じです: XohImNooBHFR0OVvjcYpJ3NgPQ1qq73WKhHvch0VQtg=。この値は、上記の例ではセキュリティードメインで指定されたユーザーのプロパティーファイル (usersb64.properties) に保存する必要があります。

18.3.1.3. 認証されていない ID

すべての要求が認証形式で受信される訳ではありません。unauthenticatedIdentity は、認証情報を持たない要求に特定の ID (例: guest) を割り当てるログインモジュール設定オプションです。これを使用すると、保護されていないサーブレットは特定ロールを必要としない EJB でメソッドを呼び出すことができます。このようなプリンシパルには関連したロールがなく、セキュアでない EJB や、チェックされていないパーミッション制約と関連する EJB メソッドのみにアクセスできます。
  • unauthenticatedIdentity: これにより、認証情報を含まない要求に割り当てる必要があるプリンシパル名が定義されます。

18.3.1.4. Ldap ログインモジュール

Ldap ログインモジュールは、ライトウェイトディレクトリーアクセスプロトコル (LDAP) サーバーに対して認証を行う LoginModule 実装です。ユーザー名と資格情報が、Java Naming and Directory Interface (JNDI)LDAP プロバイダーを使用してアクセスできる LDAP サーバーに保管されている場合は、Ldap ログインモジュールを使用します。
AdvancedLDAP ログインモジュール
ユーザーが LDAP を SPNEGO 認証で使用する場合や、LDAP サーバーを使用中に認証フェーズの一部を省略する場合は、SPNEGO ログインモジュールとチェーンされた AdvancedLdap ログインモジュールの使用を検討するか、AdvancedLdap ログインモジュールのみの使用を検討してください。
識別名 (DN)
LDAP (Lightweight Directory Access Protocol) において、ディレクトリー内のオブジェクトを一意に特定する識別名。各識別名には、他のオブジェクトと区別するための一意名と場所が必要で、これには属性と値のペア (AVP) を使用します。AVP は、共通名、組織単位などの情報を定義します。LDAP に必要となる一意な文字列は、これらの値の組み合わせになります。
注記
このログインモジュールは、認証されていない ID とパスワードのスタッキングもサポートしています。
LDAP 接続情報は、JNDI 初期コンテキストの作成に使用される環境オブジェクトに渡される設定オプションとして提供されます。使用される標準 LDAP JNDI プロパティーには以下が含まれます。
java.naming.factory.initial
InitialContextFactory 実装クラス名。これは、デフォルトで SunLDAP プロバイダー実装 com.sun.jndi.ldap.LdapCtxFactory になります。
java.naming.provider.url
LDAP サーバーの LDAP URL。
java.naming.security.authentication
使用するセキュリティープロトコルレベル。使用可能な値には、nonesimplestrong が含まれます。プロパティーが定義されていない場合に、この動作はサービスプロバイダーによって決定されます。
java.naming.security.protocol
安全なアクセスに使用するトランスポートプロトコル。この設定オプションをサービスプロバイダーのタイプ (SSL など) に設定します。プロパティーが定義されていない場合に、この動作はサービスプロバイダーによって決定されます。
java.naming.security.principal
サービスへの呼び出し元を認証するためのプリンシパルの ID を指定します。これは、以下で説明されているように、その他のプロパティーから構築されます。
java.naming.security.credentials
サービスへの呼び出し元を認証するためのプリンシパルの資格情報を指定します。資格情報は、ハッシュ化されたパスワード、クリアテキストのパスワード、キー、または証明書の形式をとることができます。プロパティーが定義されていない場合に、この動作はサービスプロバイダーによって決定されます。
Ldap ログインモジュール設定オプションの詳細については、JBoss EAP の 『セキュリティーガイド』 の 『含まれる認証モジュール』 リファレンスを参照してください。
注記
特定のディレクトリースキーマ (Microsoft Active Directory など) では、ユーザーオブジェクトのロール属性は、単純な名前ではなく、ロールオブジェクトへの DN として格納されます。このスキーマタイプを使用する実装の場合、roleAttributeIsDNtrue に設定する必要があります。
ユーザー認証は、ログインモジュール設定オプションに基づいて LDAP サーバーに接続することで実行されます。LDAP サーバーへの接続は、このセクションで前述した LDAPJNDI プロパティーで設定される環境で InitialLdapContext を作成することによって行われます。
TheContext.SECURITY_PRINCIPALは、コールバックハンドラーと組み合わせて取得したユーザーの識別名に設定されます。principalDNPrefixprincipalDNSuffixオプション値、およびContext.SECURITY_CREDENTIALSプロパティーはそれぞれに設定されますStringパスワード。
認証が成功すると (InitialLdapContext インスタンスが作成されると)、検索属性がに設定された rolesCtxDN の場所で検索を実行することにより、ユーザーのロールが照会されます。roleAttributeNameuidAttributeNameオプション値。を呼び出すことによって名前が取得しているロール toString 検索結果セットのロール属性のメソッド。

例18.7 LDAP ログインモジュールセキュリティードメイン

この管理 CLI の例は、セキュリティードメイン認証設定でパラメーターを使用する方法を示しています。
/subsystem=security/security-domain=testLDAP:add(cache-type=default)
/subsystem=security/security-domain=testLDAP/authentication=classic:add
/subsystem=security/security-domain=testLDAP/authentication=classic/login-module=Ldap:add( \
  code=Ldap, \
  flag=required, \
  module-options=[ \
    ("java.naming.factory.initial"=>"com.sun.jndi.ldap.LdapCtxFactory"), \
    ("java.naming.provider.url"=>"ldap://ldaphost.jboss.org:1389/"), \
    ("java.naming.security.authentication"=>"simple"), \
    ("principalDNPrefix"=>"uid="), \
    ("principalDNSuffix"=>",ou=People,dc=jboss,dc=org"), \
    ("rolesCtxDN"=>"ou=Roles,dc=jboss,dc=org"), \
    ("uidAttributeID"=>"member"), \
    ("matchOnUserDN"=>true), \
    ("roleAttributeID"=>"cn"), \
    ("roleAttributeIsDN"=>false) \
  ])
java.naming.factory.initialjava.naming.factory.url、および java.naming.security オプションtestLDAPセキュリティードメインの設定は、次の条件を示しています。
  • SunLDAPJNDI プロバイダーの実装が使用されます
  • LDAP サーバーは、ポート 1389 のホスト ldaphost.jboss.org にあります。
  • LDAP サーバーへの接続には、LDAP の単純な認証方法が使用されます。
ログインモジュールは、認証しようとしているユーザーを表す識別名 (DN) を使用して LDAP サーバーに接続しようとします。この DN は、渡されたものから構築されますprincipalDNPrefix、ユーザーのユーザー名とprincipalDNSuffix上記のように。の例18.8「LDIF ファイルの例」、ユーザー名 jsmithuid = jsmith、ou = People、dc = jboss、dc=org に マップされます。
注記
この例では、LDAP サーバーがユーザーのエントリー (この例では デューク) の userPassword 属性を使用してユーザーを認証することを前提としています。ほとんどの LDAP サーバーはこのように動作しますが、LDAP サーバーが認証を異なる方法で処理する場合は、LDAP が実稼働環境の要件に従って設定されていることを確認する必要があります。
認証が成功すると、rolesCtxDN のサブツリー検索を実行して、認証の基になるロールが取得されます。uidAttributeIDユーザーと一致します。もしもmatchOnUserDNtrue の場合、検索はユーザーの完全な DN に基づいて行われます。それ以外の場合、検索は入力された実際のユーザー名に基づいて行われます。この例では、ou = Roles、dc = jboss、dc = org で、uid = jsmith、ou = People、dc = jboss、dc=org に 等しい メンバー 属性を持つエントリーを検索します。検索では、ロールエントリーの下に cn=JBossAdmin が見つかります。
検索では、で指定された属性が返されますroleAttributeIDオプション。この例では、属性は cn です。返される値は JBossAdmin になるため、jsmith ユーザーは JBossAdmin ロールに割り当てられます。
ローカル LDAP サーバーは、多くの場合、ID および認証サービスを提供しますが、承認サービスを使用することはできません。これは、アプリケーションのロールが常に LDAP グループに適切にマッピングされるとは限らず、LDAP 管理者は、中央の LDAP サーバーで外部のアプリケーション固有のデータを許可することをためらうことが多いためです。LDAP 認証モジュールは、データベースログインモジュールなどの別のログインモジュールとペアになっていることが多く、開発中のアプリケーションにより適したロールを提供できます。
このデータが動作するディレクトリーの構造を表す LDAP データ交換フォーマット (LDIF) ファイルを以下に示します。例18.8「LDIF ファイルの例」
LDAP データ交換形式 (LDIF)
LDAP ディレクトリーのコンテンツと更新要求を表すために使用されるプレーンテキストのデータ交換形式。ディレクトリーコンテンツは、オブジェクトまたは更新要求ごとに 1 つのレコードとして表されます。コンテンツは、追加、変更、削除、および名前変更のリクエストで設定されます。

例18.8 LDIF ファイルの例

dn: dc=jboss,dc=org
objectclass: top
objectclass: dcObject
objectclass: organization
dc: jboss
o: JBoss

dn: ou=People,dc=jboss,dc=org
objectclass: top
objectclass: organizationalUnit
ou: People

dn: uid=jsmith,ou=People,dc=jboss,dc=org
objectclass: top
objectclass: uidObject
objectclass: person
uid: jsmith
cn: John
sn: Smith
userPassword: theduke

dn: ou=Roles,dc=jboss,dc=org
objectclass: top
objectclass: organizationalUnit
ou: Roles

dn: cn=JBossAdmin,ou=Roles,dc=jboss,dc=org
objectclass: top
objectclass: groupOfNames
cn: JBossAdmin
member: uid=jsmith,ou=People,dc=jboss,dc=org
description: the JBossAdmin group

18.3.1.5. LdapExtended ログインモジュール

識別名 (DN)
LDAP (Lightweight Directory Access Protocol) において、ディレクトリー内のオブジェクトを一意に特定する識別名。各識別名には、他のオブジェクトと区別するための一意名と場所が必要で、これには属性と値のペア (AVP) を使用します。AVP は、共通名、組織単位などの情報を定義します。LDAP に必要となる一意な文字列は、これらの値の組み合わせになります。
LdapExtended (org.jboss.security.auth.spi.LdapExtLoginModule) ログインモジュールは、ユーザーと認証で関連ロールを検索します。ロールは再帰的にクエリーを行い、DN に従って階層的なロール構造を移動します。
LoginModule オプションには、JNDI プロバイダーがサポートする指定の LDAP によってオプションがサポートされるかどうかが含まれます。標準プロパティー名の例
  • Context.INITIAL_CONTEXT_FACTORY = "java.naming.factory.initial"
  • Context.SECURITY_PROTOCOL = "java.naming.security.protocol"
  • Context.PROVIDER_URL = "java.naming.provider.url"
  • Context.SECURITY_AUTHENTICATION = "java.naming.security.authentication"
  • Context.REFERRAL = "java.naming.referral"
ログインモジュールの実装ロジックは、次の順序に従います。
  1. 最初の LDAP サーバーバインドは、bindDNbindCredentialプロパティー。ThebindDN両方を検索する権限を持つユーザーですbaseCtxDNrolesCtxDNユーザーとロールのツリー。Theuser DN認証対象は、で指定されたフィルターを使用して照会されますbaseFilter財産。
  2. 結果としてuserDNを使用して LDAP サーバーにバインドすることで認証されますuserDNInitialLdapContext 環境としてContext.SECURITY_PRINCIPAL。TheContext.SECURITY_CREDENTIALSプロパティーは、コールバックハンドラーによって取得された文字列パスワードに設定されます。
  3. これが成功すると、rolesCtxDN、roleAttributeID、roleAttributeIsDN、roleNameAttributeID、および roleFilter オプションを使用して、関連付けられたユーザーロールが照会されます。
注記
AdvancedLdap ログインモジュールは、以下の点で LdapExtended ログインモジュールとは異なります。
  • トップレベルのロールは roleAttributeID のみに対してクエリーされ、roleNameAttributeID にはクエリーされません。
  • roleAttributeIsDN モジュールプロパティーが false に設定されている場合、recurseRoles モジュールオプションが true に設定されていても、再帰ロール検索は無効になります。
LdapExtended ログインモジュールオプションの詳細については、JBoss EAP の 『セキュリティーガイド』 の 『含まれる認証モジュール』 リファレンスを参照してください。

図18.1 LDAP 構造の例

LDAP 構造の例

例18.9 例 2LDAP 設定

version: 1
dn: o=example2,dc=jboss,dc=org
objectClass: top
objectClass: organization
o: example2

dn: ou=People,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: organizationalUnit
ou: People

dn: uid=jduke,ou=People,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: uidObject
objectClass: person
objectClass: inetOrgPerson
cn: Java Duke
employeeNumber: judke-123
sn: Duke
uid: jduke
userPassword:: dGhlZHVrZQ==

dn: uid=jduke2,ou=People,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: uidObject
objectClass: person
objectClass: inetOrgPerson
cn: Java Duke2
employeeNumber: judke2-123
sn: Duke2
uid: jduke2
userPassword:: dGhlZHVrZTI=

dn: ou=Roles,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: organizationalUnit
ou: Roles

dn: uid=jduke,ou=Roles,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: groupUserEx
memberOf: cn=Echo,ou=Roles,o=example2,dc=jboss,dc=org
memberOf: cn=TheDuke,ou=Roles,o=example2,dc=jboss,dc=org
uid: jduke

dn: uid=jduke2,ou=Roles,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: groupUserEx
memberOf: cn=Echo2,ou=Roles,o=example2,dc=jboss,dc=org
memberOf: cn=TheDuke2,ou=Roles,o=example2,dc=jboss,dc=org
uid: jduke2

dn: cn=Echo,ou=Roles,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: groupOfNames
cn: Echo
description: the echo role
member: uid=jduke,ou=People,dc=jboss,dc=org

dn: cn=TheDuke,ou=Roles,o=example2,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: TheDuke
description: the duke role
member: uid=jduke,ou=People,o=example2,dc=jboss,dc=org

dn: cn=Echo2,ou=Roles,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: groupOfNames
cn: Echo2
description: the Echo2 role
member: uid=jduke2,ou=People,dc=jboss,dc=org

dn: cn=TheDuke2,ou=Roles,o=example2,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: TheDuke2
description: the duke2 role
member: uid=jduke2,ou=People,o=example2,dc=jboss,dc=org

dn: cn=JBossAdmin,ou=Roles,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: groupOfNames
cn: JBossAdmin
description: the JBossAdmin group
member: uid=jduke,ou=People,dc=jboss,dc=org
この LDAP 構造の例のモジュール設定は、次の管理 CLI コマンドで概説されています。

/subsystem=security/security-domain=testLdapExample2/authentication=classic/login-module=LdapExtended:add( \
  code=LdapExtended, \
  flag=required, \
  module-options=[ \
    ("java.naming.factory.initial"=>"com.sun.jndi.ldap.LdapCtxFactory"), \
    ("java.naming.provider.url"=>"ldap://ldaphost.jboss.org"), \
    ("java.naming.security.authentication"=>"simple"), \
    ("bindDN"=>"cn=Root,dc=jboss,dc=org"), \
    ("bindCredential"=>"secret1"), \
    ("baseCtxDN"=>"ou=People,o=example2,dc=jboss,dc=org"), \
    ("baseFilter"=>"(uid={0})"), \
    ("rolesCtxDN"=>"ou=Roles,o=example2,dc=jboss,dc=org"), \
    ("roleFilter"=>"(uid={0})"), \
    ("roleAttributeIsDN"=>"true"), \
    ("roleAttributeID"=>"memberOf"), \
    ("roleNameAttributeID"=>"cn") \
  ])

例18.10 例 3LDAP 設定


dn: o=example3,dc=jboss,dc=org
objectclass: top
objectclass: organization
o: example3

dn: ou=People,o=example3,dc=jboss,dc=org
objectclass: top
objectclass: organizationalUnit
ou: People

dn: uid=jduke,ou=People,o=example3,dc=jboss,dc=org
objectclass: top
objectclass: uidObject
objectclass: person
objectClass: inetOrgPerson
uid: jduke
employeeNumber: judke-123
cn: Java Duke
sn: Duke
userPassword: theduke

dn: ou=Roles,o=example3,dc=jboss,dc=org
objectClass: top
objectClass: organizationalUnit
ou: Roles

dn: uid=jduke,ou=Roles,o=example3,dc=jboss,dc=org
objectClass: top
objectClass: groupUserEx
memberOf: cn=Echo,ou=Roles,o=example3,dc=jboss,dc=org
memberOf: cn=TheDuke,ou=Roles,o=example3,dc=jboss,dc=org
uid: jduke

dn: cn=Echo,ou=Roles,o=example3,dc=jboss,dc=org
objectClass: top
objectClass: groupOfNames
cn: Echo
description: the JBossAdmin group
member: uid=jduke,ou=People,o=example3,dc=jboss,dc=org

dn: cn=TheDuke,ou=Roles,o=example3,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: TheDuke
member: uid=jduke,ou=People,o=example3,dc=jboss,dc=org

この LDAP 構造の例のモジュール設定は、次の管理 CLI コマンドで概説されています。

/subsystem=security/security-domain=testLdapExample3/authentication=classic/login-module=LdapExtended:add( \
  code=LdapExtended, \
  flag=required, \
  module-options=[ \
    ("java.naming.factory.initial"=>"com.sun.jndi.ldap.LdapCtxFactory"), \
    ("java.naming.provider.url"=>"ldap://ldaphost.jboss.org"), \
    ("java.naming.security.authentication"=>"simple"), \
    ("bindDN"=>"cn=Root,dc=jboss,dc=org"), \
    ("bindCredential"=>"secret1"), \
    ("baseCtxDN"=>"ou=People,o=example3,dc=jboss,dc=org"), \
    ("baseFilter"=>"(cn={0})"), \
    ("rolesCtxDN"=>"ou=Roles,o=example3,dc=jboss,dc=org"), \
    ("roleFilter"=>"(member={1})"), \
    ("roleAttributeID"=>"cn") \
  ])

例18.11 例 4LDAP 設定


dn: o=example4,dc=jboss,dc=org
objectclass: top
objectclass: organization
o: example4

dn: ou=People,o=example4,dc=jboss,dc=org
objectclass: top
objectclass: organizationalUnit
ou: People

dn: uid=jduke,ou=People,o=example4,dc=jboss,dc=org
objectClass: top
objectClass: uidObject
objectClass: person
objectClass: inetOrgPerson
cn: Java Duke
employeeNumber: jduke-123
sn: Duke
uid: jduke
userPassword:: dGhlZHVrZQ==

dn: ou=Roles,o=example4,dc=jboss,dc=org
objectClass: top
objectClass: organizationalUnit
ou: Roles

dn: cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: RG1
member: cn=empty

dn: cn=RG2,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: RG2
member: cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org
member: uid=jduke,ou=People,o=example4,dc=jboss,dc=org

dn: cn=RG3,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: RG3
member: cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org

dn: cn=R1,ou=Roles,o=example4,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: R1
member: cn=RG2,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org

dn: cn=R2,ou=Roles,o=example4,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: R2
member: cn=RG2,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org

dn: cn=R3,ou=Roles,o=example4,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: R3
member: cn=RG2,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org
member: cn=RG3,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org

dn: cn=R4,ou=Roles,o=example4,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: R4
member: cn=RG3,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org

dn: cn=R5,ou=Roles,o=example4,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: R5
member: cn=RG3,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org
member: uid=jduke,ou=People,o=example4,dc=jboss,dc=org
この LDAP 構造体の例のモジュール設定は、コードサンプルで概説されています。

/subsystem=security/security-domain=testLdapExample4/authentication=classic/login-module=LdapExtended:add( \
  code=LdapExtended, \
  flag=required, \
  module-options=[ \
    ("java.naming.factory.initial"=>"com.sun.jndi.ldap.LdapCtxFactory"), \
    ("java.naming.provider.url"=>"ldap://ldaphost.jboss.org"), \
    ("java.naming.security.authentication"=>"simple"), \
    ("bindDN"=>"cn=Root,dc=jboss,dc=org"), \
    ("bindCredential"=>"secret1"), \
    ("baseCtxDN"=>"ou=People,o=example4,dc=jboss,dc=org"), \
    ("baseFilter"=>"(cn={0})"), \
    ("rolesCtxDN"=>"ou=Roles,o=example4,dc=jboss,dc=org"), \
    ("roleFilter"=>"(member={1})"), \
    ("roleRecursion"=>"1"), \
    ("roleAttributeID"=>"memberOf") \
  ])

例18.12 デフォルトの Active Directory 設定

以下の例は、デフォルトの Active Directory 設定を示しています。
Active Directory の設定によっては、通常のポート 389 ではなく、ポート 3268 でグローバルカタログを検索する必要がある場合があります。これは、Active Directory フォレストに複数のドメインが含まれる場合によく見られます。

/subsystem=security/security-domain=AD_Default/authentication=classic/login-module=LdapExtended:add( \
  code=LdapExtended, \
  flag=required, \
  module-options=[ \
    ("java.naming.provider.url"=>"ldap://ldaphost.jboss.org"), \
    ("bindDN"=>"JBOSS\searchuser"), \
    ("bindCredential"=>"password"), \
    ("baseCtxDN"=>"CN=Users,DC=jboss,DC=org"), \
    ("baseFilter"=>"(sAMAccountName={0})"), \
    ("rolesCtxDN"=>"CN=Users,DC=jboss,DC=org"), \
    ("roleFilter"=>"(sAMAccountName={0})"), \
    ("roleAttributeID"=>"memberOf"), \
    ("roleAttributeIsDN"=>"true"), \
    ("roleNameAttributeID"=>"cn"), \
    ("searchScope"=>"ONELEVEL_SCOPE"), \
    ("allowEmptyPasswords"=>"false") \
  ])

例18.13 再帰的なロール Active Directory の設定

以下の例では、Active Directory 内で再帰的なロール検索を実装します。この例と、デフォルトの Active Directory の例の主な違いは、ユーザーの DN を使用してメンバー属性を検索するためにロール検索が置き換えられている点です。ログインモジュールは、ロールの DN を使用して、グループがメンバーとなっているグループを検索します。

/subsystem=security/security-domain=AD_Recursive/authentication=classic/login-module=LdapExtended:add( \
  code=LdapExtended, \
  flag=required, \
  module-options=[ \
    ("java.naming.provider.url"=>"ldap://ldaphost.jboss.org"), \
    ("java.naming.referral"=>"follow"), \
    ("bindDN"=>"JBOSS\searchuser"), \
    ("bindCredential"=>"password"), \
    ("baseCtxDN"=>"CN=Users,DC=jboss,DC=org"), \
    ("baseFilter"=>"(sAMAccountName={0})"), \
    ("rolesCtxDN"=>"CN=Users,DC=jboss,DC=org"), \
    ("roleFilter"=>"(member={1})"), \
    ("roleAttributeID"=>"cn"), \
    ("roleAttributeIsDN"=>"false"), \
    ("roleRecursion"=>"2"), \
    ("searchScope"=>"ONELEVEL_SCOPE"), \
    ("allowEmptyPasswords"=>"false") \
  ])

18.3.1.6. UsersRoles ログインモジュール

UsersRoles ログインモジュールは、Java プロパティーファイルからロードされる複数のユーザーおよびユーザーロールをサポートする簡単なログインモジュールです。デフォルトの username-to-password マッピングファイル名は users.properties で、デフォルトの username-to-roles マッピングファイル名は roles.propertiesです。
UsersRoles ログインモジュールオプションの詳細については、JBoss EAP の 『セキュリティーガイド』 の 『含まれる認証モジュール』 リファレンスを参照してください。
このログインモジュールは、パスワードスタッキング、パスワードハッシュ、および認証されていないアイデンティティーをサポートします。
プロパティーファイルは、initialize メソッドスレッドコンテキストローダーを使用して初期化中にロードされます。つまり、これらのファイルは Jakarta EE デプロイメントのクラスパス (WAR アーカイブの WEB-INF/classes フォルダーなど) またはサーバークラスパスの任意のディレクトリーに配置できます。このログインモジュールの主な目的は、アプリケーションとともにデプロイされたプロパティーファイルを使用して複数のユーザーおよびロールのセキュリティー設定を簡単にテストすることです。

例18.14 UsersRoles ログインモジュール

/subsystem=security/security-domain=ejb3-sampleapp/authentication=classic/login-module=UsersRoles:add( \
  code=UsersRoles, \
  flag=required, \
  module-options=[ \
    ("usersProperties"=>"ejb3-sampleapp-users.properties"), \
    ("rolesProperties"=>"ejb3-sampleapp-roles.properties") \
  ])
例18.14「UsersRoles ログインモジュール」ejb3-sampleapp-users.properties ファイルは username = password 形式を使用し、各ユーザーエントリーは別々の行にあります。
username1=password1
username2=password2
...
で参照され ている ejb3-sampleapp-roles.properties ファイル例18.14「UsersRoles ログインモジュール」パターン username=role1、role2 を 使用し、オプションのグループ名の値を指定します。以下に例を示します。
username1=role1,role2,...
username1.RoleGroup1=role3,role4,...
username2=role1,role3,...
Theuser name.XXXejb3-sampleapp-roles.properties に存在するプロパティー名パターンは、プロパティー名の XXX 部分がグループ名である特定の名前付きロールグループにユーザー名ロールを割り当てるために使用されます。Theuser name=...form はの略語ですuser name.Roles=...、ここで、Roles グループ名は、JBossAuthorizationManager がユーザーの権限を定義するロールを含むことを期待する標準名です。
以下は、jduke ユーザー名の同等の定義です。
jduke=TheDuke,AnimatedCharacter
jduke.Roles=TheDuke,AnimatedCharacter

18.3.1.7. Database ログインモジュール

Database ログインモジュールは、認証とロールマッピングをサポートする JDBC (Java Database Connectivity) ベースのログインモジュールです。ユーザー名、パスワード、およびロール情報がリレーショナルデータベースに保存されている場合は、このログインモジュールを使用してください。
注記
このモジュールは、パスワードスタッキング、パスワードハッシュ、および認証されていないアイデンティティーをサポートします。
データベース ログインモジュールは、次の 2 つの論理テーブルに基づいています。
Table Principals(PrincipalID text, Password text)
Table Roles(PrincipalID text, Role text, RoleGroup text)
Principals テーブルはユーザー PrincipalID を有効なパスワードに関連付けます。また、Roles テーブルはユーザー PrincipalID をそのロールセットに関連付けます。ユーザーパーミッションに使用されるロールは、RolesRoleGroup コラムの値を持つ行に含まれる必要があります。
テーブルは論理であるため、ログインモジュールが使用する SQL クエリーを指定できます。唯一の要件として、java.sql.ResultSet は前述の Principals および Roles と同じ論理構造を持ちます。テーブル名およびコラムの実際の名前は、コラムのインデックスに基づいてアクセスされるため、関係ありません。
この概念を明確化するために、すでに宣言されているようにPrincipals および Roles という 2 つのテーブルがあるデータベースを検討してください。以下のステートメントは、以下のデータをテーブルに追加します。
  • Principals テーブルの echoman というパワスワードを持つ PrincipalID java
  • Roles テーブルの RolesRoleGroupEcho という名前のロールを持つ PrincipalID java
  • Roles テーブルの CallerPrincipalRoleGroupcaller_java という名前のロールを持つ PrincipalID java
INSERT INTO Principals VALUES('java', 'echoman')
INSERT INTO Roles VALUES('java', 'Echo', 'Roles')
INSERT INTO Roles VALUES('java', 'caller_java', 'CallerPrincipal')
データベースログインモジュールオプションの詳細については、JBoss EAP の 『セキュリティーガイド』 の 『含まれる認証モジュール』 リファレンスを参照してください。
データベースログインモジュール の設定例は、次のように設定できます。
CREATE TABLE Users(username VARCHAR(64) PRIMARY KEY, passwd VARCHAR(64))
CREATE TABLE UserRoles(username VARCHAR(64), role VARCHAR(32))
セキュリティードメインの対応するログインモジュール設定:
/subsystem=security/security-domain=testDB/authentication=classic/login-module=Database:add( \
  code=Database, \
  flag=required, \
  module-options=[ \
    ("dsJndiName"=>"java:/MyDatabaseDS"), \
    ("principalsQuery"=>"select passwd from Users where username=?"), \
    ("rolesQuery"=>"select role, 'Roles' from UserRoles where username=?") \
  ])

18.3.1.8. Certificate ログインモジュール

Certificate ログインモジュールは、X509 証明書を基にユーザーを認証します。このログインモジュールの典型的なユースケースが、web 層の CLIENT-CERT 認証です。
証明書ログインモジュールは認証のみを実行するため、セキュアな web または EJB コンポーネントへのアクセスを完全に定義するには、承認ロールを取得できる他のログインモジュールと組み合わせる必要があります。このログインモジュールの 2 つのサブクラスである CertRolesLoginModule および DatabaseCertLoginModule は動作を拡張し、プロパティーファイルまたはデータベースから承認ロールを取得します。
証明書 ログインモジュールオプションの詳細については、JBoss EAP の 『セキュリティーガイド』 の 『含まれる認証モジュール』 リファレンスを参照してください。
証明書 ログインモジュールには、ユーザー検証を実行するための KeyStore が必要です。これは、次の設定フラグメントに示すように、リンクされたセキュリティードメインの JSSE 設定から取得されます。
/subsystem=security/security-domain=trust-domain:add
/subsystem=security/security-domain=trust-domain/jsse=classic:add( \
  truststore={ \
    password=>pass1234, \
    url=>/home/jbosseap/trusted-clients.jks \
  })

/subsystem=security/security-domain=testCert:add
/subsystem=security/security-domain=testCert/authentication=classic:add
/subsystem=security/security-domain=testCert/authentication=classic/login-module=Certificate:add( \
  code=Certificate, \
  flag=required, \
  module-options=[ \
    ("securityDomain"=>"trust-domain"), \
  ])

手順18.4 証明書とロールベースの承認による安全な Web アプリケーション

この手順では、クライアント証明書とロールベースの承認を使用して、user-app.war などの Web アプリケーションを保護する方法について説明します。この例では、CertificateRoles ログインモジュールが認証と承認に使用されています。trusted-clients.keystoreapp-roles.properties の両方に、クライアント証明書に関連付けられたプリンシパルにマップするエントリーが必要です。
デフォルトでは、プリンシパルは、で指定された DN などのクライアント証明書の識別名を使用して作成されます。例18.15「証明書の例」
  1. リソースとロールを宣言する

    web.xml を変更して、認証と承認に使用できる許可されたロールとセキュリティードメインとともに、保護するリソースを宣言します。
    
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
            version="3.0">
    
            <security-constraint>
                    <web-resource-collection>
                            <web-resource-name>Protect App</web-resource-name>
                            <url-pattern>/*</url-pattern>
                    </web-resource-collection>
                    <auth-constraint>
                            <role-name>Admin</role-name>
                    </auth-constraint>
            </security-constraint>
    
            <login-config>
                    <auth-method>CLIENT-CERT</auth-method>
                    <realm-name>Secured area</realm-name>
            </login-config>
    
            <security-role>
                    <role-name>Admin</role-name>
            </security-role>
    </web-app>
    
    
  2. セキュリティードメインを指定する

    jboss-web.xml ファイルで、必要なセキュリティードメインを指定します。
    
    <jboss-web>
      <security-domain>app-sec-domain</security-domain>
    </jboss-web>
    
    
  3. ログインモジュールの設定

    管理 CLI を使用して、指定した app-sec-domain ドメインのログインモジュール設定を定義します。
    [
    /subsystem=security/security-domain=trust-domain:add
    /subsystem=security/security-domain=trust-domain/jsse=classic:add( \
      truststore={ \
        password=>pass1234, \
        url=>/home/jbosseap/trusted-clients.jks \
      })
    
    /subsystem=security/security-domain=app-sec-domain:add
    /subsystem=security/security-domain=app-sec-domain/authentication=classic:add
    /subsystem=security/security-domain=app-sec-domain/authentication=classic/login-module=CertificateRoles:add( \
      code=CertificateRoles, \
      flag=required, \
      module-options=[ \
        ("securityDomain"=>"trust-domain"), \
        ("rolesProperties"=>"app-roles.properties") \
      ])
    

例18.15 証明書の例

[conf]$ keytool -printcert -file valid-client-cert.crt
Owner: CN=valid-client, OU=Security QE, OU=JBoss, O=Red Hat, C=CZ
Issuer: CN=EAP Certification Authority, OU=Security QE, OU=JBoss, O=Red Hat, C=CZ
Serial number: 2
Valid from: Mon Mar 24 18:21:55 CET 2014 until: Tue Mar 24 18:21:55 CET 2015
Certificate fingerprints:
         MD5:  0C:54:AE:6E:29:ED:E4:EF:46:B5:14:30:F2:E0:2A:CB
         SHA1: D6:FB:19:E7:11:28:6C:DE:01:F2:92:2F:22:EF:BB:5D:BF:73:25:3D
         SHA256: CD:B7:B1:72:A3:02:42:55:A3:1C:30:E1:A6:F0:20:B0:2C:0F:23:4F:7A:8E:2F:2D:FA:AF:55:3E:A7:9B:2B:F4
         Signature algorithm name: SHA1withRSA
         Version: 3
trusted-clients.keystore には、次の証明書が必要です。例18.15「証明書の例」CN = valid-client、OU = Security QE、OU = JBoss、O = Red Hat、C=CZ のエイリアスで保存されます。app-roles.properties には同じエントリーが必要です。DN には通常区切り文字として扱われる文字が含まれているため、以下に示すように、円記号 (' \ ') を使用して問題のある文字をエスケープする必要があります。
# A sample app-roles.properties file
CN\=valid-client,\ OU\=Security\ QE,\ OU\=JBoss,\ O\=Red\ Hat,\ C\=CZ

18.3.1.9. Identity ログインモジュール

Identity ログインモジュールは、ハードコードされたユーザー名をモジュールに対して認証されたサブジェクトに関連付ける簡単なログインモジュールです。このモジュールは、principal のオプションによって指定された名前を使用して SimplePrincipal インスタンスを作成します。
注記
このモジュールは、パスワードのスタッキングをサポートしています。
このログインモジュールは、サービスに固定 ID を提供する必要がある場合や、開発環境で特定のプリンシパルおよび関連付けられたロールに関連付けられたセキュリティーをテストする場合に役立ちます。
Identity ログインモジュールオプションの詳細については、JBoss EAP の 『セキュリティーガイド』 の 『含まれる認証モジュール』 リファレンスを参照してください。
セキュリティードメイン設定の例を以下に説明します。すべてのユーザーを jduke という名前のプリンシパルとして認証し、TheDuke のロール名と AnimatedCharacter: を割り当てます。
/subsystem=security/security-domain=testIdentity:add
/subsystem=security/security-domain=testIdentity/authentication=classic:add
/subsystem=security/security-domain=testIdentity/authentication=classic/login-module=Identity:add( \
  code=Identity, \
  flag=required, \
  module-options=[ \
    ("principal"=>"jduke"), \
    ("roles"=>"TheDuke,AnimatedCharacter") \
  ])

18.3.1.10. RunAs ログインモジュール

RunAS ログインモジュールは、認証のログインフェーズの間に run as ロールをスタックにプッシュするヘルパーモジュールです。ログインフェーズ後、コミットまたはアボートフェーズで run as ロールをスタックからポップします。
このログインモジュールの目的は、セキュアな EJB にアクセスするログインモジュールなど、セキュアなリソースにアクセスして認証を実行する必要のあるその他のログインモジュールにロールを提供することです。RunAs ログインモジュールは、run as ロールの構築が必要なログインモジュールよりも先に設定する必要があります。
RunAs ログインモジュールオプションの詳細については、JBoss EAP の 『セキュリティーガイド』 の 『含まれる認証モジュール』 リファレンスを参照してください。
18.3.1.10.1. RunAsIdentity の作成
JBoss EAP 6 が EJB メソッドへのアクセスを保護するには、メソッド呼び出しが行われるときにユーザーの ID がわかっている必要があります。
サーバー内のユーザーの ID は、javax.security.auth.Subject インスタンスまたは org.jboss.security.RunAsIdentity インスタンスのいずれかで表されます。これらのクラスは両方とも、ID を表す 1 つ以上のプリンシパルと、ID が所有するロールのリストを格納します。javax.security.auth.Subject の場合、資格情報のリストも保存されます。
の中に<assembly-descriptor>ejb-jar.xml デプロイメント記述子のセクションでは、ユーザーがさまざまな EJB メソッドにアクセスするために必要な 1 つ以上のロールを指定します。これらのリストを比較すると、ユーザーが EJB メソッドにアクセスするために必要なロールの 1 つを持っているかどうかがわかります。

例18.16 org.jboss.security.RunAsIdentity Creation

ejb-jar.xml ファイルで、<security-identity>要素と<run-as><session> 要素の子として定義されたロール。
<session>
   ...
   <security-identity>
      <run-as>
         <role-name>Admin</role-name>
      </run-as>
   </security-identity>
   ...
</session>
この宣言は、AdminRunAsIdentity ロールを作成する必要があることを示しています。
管理者 ロールのプリンシパルに名前を付けるには、jboss-ejb3.xml ファイルで <run-as-principal> 要素を定義します。

<jboss:ejb-jar
        xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:jboss="http://www.jboss.com/xml/ns/javaee"
        xmlns:s="urn:security:1.1"
        version="3.1" impl-version="2.0">
    <assembly-descriptor>
        <s:security>
            <ejb-name>WhoAmIBean</ejb-name>
            <s:run-as-principal>John</s:run-as-principal>
        </s:security>
    </assembly-descriptor>
</jboss:ejb-jar>

ejb-jar.xml ファイルの <security-identity> 要素と jboss-ejb3.xml ファイルの <security> 要素の両方がデプロイメント時に解析されます。<run-as> ロール名と <run-as-principal> 名は、org.jboss.metadata.ejb.spec.SecurityIdentityMetaData クラスに保存されます。

例18.17 RunAsIdentity への複数のロールの割り当て

jboss-ejb3.xml デプロイメント記述子 <assembly-descriptor> エレメントグループのプリンシパルにロールをマッピングすることにより、RunAsIdentity により多くのロールを割り当てることができます。

<jboss:ejb-jar xmlns:sr="urn:security-role"
        ...>
        <assembly-descriptor>
            ...
                <sr:security-role>
                        <sr:role-name>Support</sr:role-name>
                        <sr:principal-name>John</sr:principal-name>
                        <sr:principal-name>Jill</sr:principal-name>
                        <sr:principal-name>Tony</sr:principal-name>
                </sr:security-role>
        </assembly-descriptor>
</jboss:ejb-jar>

例18.16「org.jboss.security.RunAsIdentity Creation」ジョン<run-as-principal> が作成されました。この例の設定では、サポート ロールを追加することにより、管理者 ロールを拡張します。新しいロールには、最初に定義されたプリンシパル John を含む追加のプリンシパルが含まれます。
ejb-jar.xml ファイルと jboss-ejb3.xml ファイルの両方の <security-role> 要素は、デプロイメント時に解析されます。<role-name> および <principal-name> データは、org.jboss.metadata.ejb.spec.SecurityIdentityMetaData クラスに保存されます。

18.3.1.11. Client ログインモジュール

Client ログインモジュール (org.jboss.security.ClientLoginModule) は、呼び出し元のアイデンティティーとクレデンシャルの確立時に JBoss クライアントによって使用される LoginModule の実装です。新しい SecurityContext を作成してプリンシパルとクレデンシャルに割り当て、SecurityContextThreadLocal セキュリティーコンテキストに設定します。
Client ログインモジュールは、クライアントが現在のスレッドの呼び出し元を確立するために唯一サポートされるログインモジュールです。セキュリティー環境が JBoss EJB security サブシステムを使用するよう透過的に設定されていない EJB クライアントとして動作するサーバー環境とスタンドアロンクライアントアプリケーションは、Client ログインモジュールを使用する必要があります。
このログインモジュールは認証を行わない点に注意してください。サーバー上の後続の認証のために、提供されたログイン情報をサーバー EJB 呼び出しレイヤーにコピーすることもほとんどありません。ユーザーのクライアント側認証を実行する必要がある場合は、クライアント ログインモジュールに加えて別のログインモジュールを設定する必要があります。
クライアントログインモジュールオプションの詳細については、JBoss EAP の 『セキュリティーガイド』 の 『含まれる認証モジュール』 リファレンスを参照してください。

18.3.1.12. SPNEGO ログインモジュール

SPNEGO ログインモジュール (org.jboss.security.negotiation.spnego.SPNEGOLoginModule) は、KDC で呼び出し元のアイデンティティーとクレデンシャルを確立する LoginModule の実装です。モジュールは、SPNEGO、Simple、および Protected GSSAPI Negotiation メカニズムを実装し、JBoss Negotiation プロジェクトの一部です。この認証を AdvancedLdap ログインモジュールとチェーンされた設定で使用すると、LDAP サーバーと連携できます。
SPNEGO ログインモジュールオプションの詳細については、JBoss EAP の 『セキュリティーガイド』 の 『含まれる認証モジュール』 リファレンスを参照してください。
JBoss Negotiation モジュールは、デプロイされたアプリケーションの標準の依存関係として含まれていません。を使用するにはSPNEGOまたAdvancedLdapプロジェクトのログインモジュールでは、META-INF/jboss-deployment-structure.xml デプロイメント記述子ファイルを編集して、依存関係を手動で追加する必要があります。

例18.18 JBossNegotiationModule を依存関係として追加する


<jboss-deployment-structure>
  <deployment>
    <dependencies>
      <module name="org.jboss.security.negotiation" />
    </dependencies>
  </deployment>
</jboss-deployment-structure>

18.3.1.13. RoleMapping ログインモジュール

RoleMapping ログインモジュールは、1 つ以上の宣言的ロールへの認証プロセスの最終結果となるロールのマッピングをサポートします。たとえば、ユーザー A のロールが ldapAdmin と testAdmin で、web.xml または ejb-jar.xml ファイルで定義されたアクセスの宣言的ロールは admin であると認証プロセスによって判断された場合、このログインモジュールは admin ロールを A にマップします。
RoleMapping ログインモジュールオプションの詳細については、JBoss EAP の 『セキュリティーガイド』 の 『含まれる認証モジュール』 リファレンスを参照してください。
RoleMapping ログインモジュールは、以前マップされたロールのマッピングを変更するため、ログインモジュール設定でオプションのモジュールとして定義する必要があります。

例18.19 マップされたロールの定義

/subsystem=security/security-domain=test-domain-2/:add
/subsystem=security/security-domain=test-domain-2/authentication=classic:add
/subsystem=security/security-domain=test-domain-2/authentication=classic/login-module=test-2-lm/:add(\
flag=required,\
code=UsersRoles,\
module-options=[("usersProperties"=>"users.properties"),("rolesProperties"=>"roles.properties")]\
)
/subsystem=security/security-domain=test-domain-2/authentication=classic/login-module=test2-map/:add(\
flag=optional,\
code=RoleMapping,\
module-options=[("rolesProperties"=>"rolesMapping-roles.properties")]\
)
同じ結果を達成する別の例ですが、マッピングモジュールを使用しています。これは、ロールマッピングの推奨される方法です。

例18.20 マップされたロールを定義するための好ましい方法

/subsystem=security/security-domain=test-domain-2/:add
/subsystem=security/security-domain=test-domain-2/authentication=classic:add
/subsystem=security/security-domain=test-domain-2/authentication=classic/login-module=test-2-lm/:add(\
flag=required,\
code=UsersRoles,\
module-options=[("usersProperties"=>"users.properties"),("rolesProperties"=>"roles.properties")]\
)
/subsystem=security/security-domain=test-domain-2/mapping=classic/mapping-module=test2-map/:add(\
code=PropertiesRoles,type=role,\
module-options=[("rolesProperties"=>"rolesMapping-roles.properties")]\
)

例18.21 RoleMappingLoginModule によって使用されるプロパティーファイル

ldapAdmin=admin, testAdmin
認証されたサブジェクトにロール ldapAdmin が含まれている場合、ロール admin および testAdmin は、認証されたサブジェクトに追加されるか、認証されたサブジェクトに置き換えられます。replaceRoleプロパティー値。

18.3.1.14. bindCredential モジュールオプション

bindCredential モジュールオプションは、DN の資格情報を保存するために使用され、複数のログインおよびマッピングモジュールで使用できます。パスワードを取得するには、いくつかの方法があります。

管理 CLI コマンドのプレーンテキスト。
のパスワードbindCredentialモジュールは、管理 CLI コマンドでプレーンテキストで提供できます。例: ("bindCredential"=>"secret1").セキュリティー上の理由から、パスワードは JBoss EAP ボールトメカニズムを使用して暗号化する必要があります。
外部コマンドを使用します。
外部コマンドの出力からパスワードを取得するには、次の形式を使用します{EXT}...どこ...外部コマンドです。コマンド出力の最初の行がパスワードとして使用されます。
パフォーマンスを向上させるために、{EXTC[:expiration_in_millis]}バリアントは、指定されたミリ秒数の間パスワードをキャッシュします。デフォルトでは、キャッシュされたパスワードは期限切れになりません。値 0 (ゼロ) が指定されている場合、キャッシュされた資格情報は期限切れになりません。
TheEXTCバリアントは、LdapExtendedログインモジュール。

例18.22 外部コマンドからパスワードを取得する

{EXT}cat /mysecretpasswordfile

例18.23 外部ファイルからパスワードを取得し、500 ミリ秒キャッシュします

{EXTC:500}cat /mysecretpasswordfile

18.3.2. カスタムモジュール

EAP セキュリティーフレームワークにバンドルされているログインモジュールがセキュリティー環境で機能しない場合は、独自のカスタムログインモジュール実装を作成できます。AuthenticationManager は、Subject プリンシパルの特定の使用パターンを必要とします。AuthenticationManager と動作するログインモジュールを作成するには、JAAS Subject クラスの情報ストレージ機能と、これらの機能の想定される使用方法を完全に理解する必要があります。
このセクションでは、この要件を検証し、カスタムログインモジュールの実装に役立つ 2 つの抽象ベース LoginModule 実装を紹介します。
次の方法を使用して、サブジェクト に関連付けられたセキュリティー情報を取得できます。
java.util.Set getPrincipals()
java.util.Set getPrincipals(java.lang.Class c)
java.util.Set getPrivateCredentials()
java.util.Set getPrivateCredentials(java.lang.Class c)
java.util.Set getPublicCredentials()
java.util.Set getPublicCredentials(java.lang.Class c)
サブジェクト ID とロールについては、EAP が最も論理的な選択肢を選択しました 。getPrincipals () および getPrincipals (java.lang.Class) を介して取得されたプリンシパルセットです。使用パターンは次のとおりです。
  • ユーザー ID(たとえば、ユーザー名、社会保障番号、従業員 ID) は、サブジェクトプリンシパル セットに java.security.Principal オブジェクトとして格納されます。ユーザー ID を表す プリンシパル の実装は、プリンシパルの名前に基づいて比較と同等性を確立する必要があります。適切な実装は、org.jboss.security.SimplePrincipal クラスとして利用できます。他の プリンシパル インスタンスは、必要に応じて サブジェクトプリンシパル セットに追加できます。
  • 割り当てられたユーザーロールも プリンシパル セットに保存され、java.security.acl.Group インスタンスを使用して名前付きロールセットにグループ化されます。Group インターフェイスは、Principal および/または Group のコレクションを定義し、java.security.Principal のサブインターフェイスです。
  • サブジェクト には、任意の数のロールセットを割り当てることができます。
  • EAP セキュリティーフレームワークは、RolesCallerPrincipal という名前の 2 つのよく知られたロールセットを使用します。
    • ロール グループは、サブジェクト が認証されたアプリケーションドメインで知られている名前付きロールの プリンシパル のコレクションです。このロールセットは、EJBContext.isCallerInRole (String) などのメソッドによって使用されます。EJB は、このメソッドを使用して、現在の呼び出し元が指定されたアプリケーションドメインロールに属しているかどうかを確認できます。メソッド権限チェックを実行するセキュリティーインターセプタロジックも、このロールセットを使用します。
    • CallerPrincipalグループ は、アプリケーションドメインのユーザーに割り当てられた単一の プリンシパル ID で設定されます。EJBContext.getCallerPrincipal () メソッドは、CallerPrincipal を使用して、アプリケーションドメインが操作環境 ID からアプリケーションに適したユーザー ID にマップできるようにします。サブジェクトCallerPrincipalGroup がない 場合、アプリケーション ID は運用環境 ID と同じです。

18.3.2.1. サブジェクト使用パターンのサポート

で説明されている サブジェクト の使用パターンの正しい実装を簡素化するため「カスタムモジュール」、EAP には、認証された サブジェクト に正しい サブジェクト の使用を強制するテンプレートパターンを入力するログインモジュールが含まれています。

AbstractServerLoginModule

2 つの中で最も一般的なのは、org.jboss.security.auth.spi.AbstractServerLoginModule クラスです。

これは、javax.security.auth.spi.LoginModule インターフェイスの実装を提供し、運用環境のセキュリティーインフラストラクチャーに固有の主要なタスクのための抽象的なメソッドを提供します。クラスの重要な詳細は、例18.24「AbstractServerLoginModule クラスの一部」。JavaDoc コメントは、サブクラスの責任について詳しく説明しています。
重要
loginOk インスタンス変数は極めて重要です。ログインが成功した場合は true に設定する必要があり、ログインメソッドをオーバーライドするサブクラスでは false に設定する必要があります。この変数が正しく設定されていない場合、commit メソッドはサブジェクトを正しく更新しません。
ログインフェーズの結果を追跡することで、ログインモジュールを制御フラグと一緒にチェーンできます。これらの制御フラグは、認証プロセスの一部としてログインモジュールが成功する必要はありません。

例18.24 AbstractServerLoginModule クラスの一部

package org.jboss.security.auth.spi;
/**
 *  This class implements the common functionality required for a JAAS
 *  server-side LoginModule and implements the PicketBox standard
 *  Subject usage pattern of storing identities and roles. Subclass
 *  this module to create your own custom LoginModule and override the
 *  login(), getRoleSets(), and getIdentity() methods.
 */
public abstract class AbstractServerLoginModule
    implements javax.security.auth.spi.LoginModule
{
    protected Subject subject;
    protected CallbackHandler callbackHandler;
    protected Map sharedState;
    protected Map options;
    protected Logger log;

    /** Flag indicating if the shared credential should be used */
    protected boolean useFirstPass;
    /** 
     * Flag indicating if the login phase succeeded. Subclasses that
     * override the login method must set this to true on successful
     * completion of login
     */
    protected boolean loginOk;
                
    // ...
    /**
     * Initialize the login module. This stores the subject,
     * callbackHandler and sharedState and options for the login
     * session. Subclasses should override if they need to process
     * their own options. A call to super.initialize(...)  must be
     * made in the case of an override.
     *
     * <p>
     * The options are checked for the  <em>password-stacking</em> parameter.
     * If this is set to "useFirstPass", the login identity will be taken from the
     * <code>javax.security.auth.login.name</code> value of the sharedState map,
     * and the proof of identity from the
     * <code>javax.security.auth.login.password</code> value of the sharedState map.
     *
     * @param subject the Subject to update after a successful login.
     * @param callbackHandler the CallbackHandler that will be used to obtain the
     * the user identity and credentials.
     * @param sharedState a Map shared between all configured login module instances
     * @param options the parameters passed to the login module.
     */
    public void initialize(Subject subject,
                           CallbackHandler callbackHandler,
                           Map sharedState,
                           Map options)
    {
        // ...
    }
    

    /**
     *  Looks for javax.security.auth.login.name and
     *  javax.security.auth.login.password values in the sharedState
     *  map if the useFirstPass option was true and returns true if
     *  they exist. If they do not or are null this method returns
     *  false.  
     *  Note that subclasses that override the login method
     *  must set the loginOk var to true if the login succeeds in
     *  order for the commit phase to populate the Subject. This
     *  implementation sets loginOk to true if the login() method
     *  returns true, otherwise, it sets loginOk to false.
     */
    public boolean login() 
        throws LoginException
    {
        // ...
    }
    
    /**
     *  Overridden by subclasses to return the Principal that
     *  corresponds to the user primary identity.
     */
    abstract protected Principal getIdentity();
                
    /**
     *  Overridden by subclasses to return the Groups that correspond
     *  to the role sets assigned to the user. Subclasses should
     *  create at least a Group named "Roles" that contains the roles
     *  assigned to the user.  A second common group is
     *  "CallerPrincipal," which provides the application identity of
     *  the user rather than the security domain identity.
     * 
     *  @return Group[] containing the sets of roles
     */
    abstract protected Group[] getRoleSets() throws LoginException;
}

UsernamePasswordLoginModule

カスタムログインモジュールに適した 2 番目の抽象ベースログインモジュールは、org.jboss.security.auth.spi.UsernamePasswordLoginModule です。

このログインモジュールは、文字列ベースのユーザー名をユーザー ID として、char パスワードを認証資格情報として適用することにより、カスタムログインモジュールの実装をさらに簡素化します。また、匿名ユーザー (null のユーザー名とパスワードで示される) のロールのないプリンシパルへのマッピングもサポートします。クラスの重要な詳細は、次のクラスフラグメントで強調表示されています。JavaDoc コメントは、サブクラスの責任について詳しく説明しています。

例18.25 UsernamePasswordLoginModule クラスの一部

package org.jboss.security.auth.spi;

/**
 *  An abstract subclass of AbstractServerLoginModule that imposes a
 *  an identity == String username, credentials == String password
 *  view on the login process. Subclasses override the
 *  getUsersPassword() and getUsersRoles() methods to return the
 *  expected password and roles for the user.
 */
public abstract class UsernamePasswordLoginModule
    extends AbstractServerLoginModule
{
    /** The login identity */
    private Principal identity;
    /** The proof of login identity */
    private char[] credential;
    /** The principal to use when a null username and password are seen */
    private Principal unauthenticatedIdentity;

    /**
     * The message digest algorithm used to hash passwords. If null then
     * plain passwords will be used. */
    private String hashAlgorithm = null;

    /**
     *  The name of the charset/encoding to use when converting the
     * password String to a byte array. Default is the platform's
     * default encoding.
     */
     private String hashCharset = null;

    /** The string encoding format to use. Defaults to base64. */
    private String hashEncoding = null;
                
    // ...
                
    /** 
     *  Override the superclass method to look for an
     *  unauthenticatedIdentity property. This method first invokes
     *  the super version.
     *
     *  @param options,
     *  @option unauthenticatedIdentity: the name of the principal to
     *  assign and authenticate when a null username and password are
     *  seen.
     */
    public void initialize(Subject subject,
                           CallbackHandler callbackHandler,
                           Map sharedState,
                           Map options)
    {
        super.initialize(subject, callbackHandler, sharedState,
                         options);
        // Check for unauthenticatedIdentity option.
        Object option = options.get("unauthenticatedIdentity");
        String name = (String) option;
        if (name != null) {
            unauthenticatedIdentity = new SimplePrincipal(name);
        }
    }
                
    // ...
                
    /**
     *  A hook that allows subclasses to change the validation of the
     *  input password against the expected password. This version
     *  checks that neither inputPassword or expectedPassword are null
     *  and that inputPassword.equals(expectedPassword) is true;
     *
     *  @return true if the inputPassword is valid, false otherwise.
     */
    protected boolean validatePassword(String inputPassword,
                                       String expectedPassword)
    {
        if (inputPassword == null || expectedPassword == null) {
            return false;
        }
        return inputPassword.equals(expectedPassword);
    }
    
    /**
     *  Get the expected password for the current username available
     * via the getUsername() method. This is called from within the
     * login() method after the CallbackHandler has returned the
     * username and candidate password.
     *
     * @return the valid password String
     */
    abstract protected String getUsersPassword()
        throws LoginException;
}

ログインモジュールのサブクラス化

AbstractServerLoginModuleUsernamePasswordLoginModule のサブクラスの選択は、ログインモジュールを作成する認証テクノロジーで文字列ベースのユーザー名と資格情報を使用できるかどうかに基づいています。文字列ベースのセマンティクスが有効な場合は、UsernamePasswordLoginModule をサブクラス化し、そうでない場合は、AbstractServerLoginModule をサブクラス化します。

サブクラス化の手順

カスタムログインモジュールが実行する必要のある手順は、選択した基本ログインモジュールクラスによって異なります。セキュリティーインフラストラクチャーと統合するカスタムログインモジュールを作成するときは、AbstractServerLoginModule または UsernamePasswordLoginModule をサブクラス化して、ログインモジュールが EAP セキュリティーマネージャーが期待する形式で認証された プリンシパル 情報を提供するようにする必要があります。

AbstractServerLoginModule をサブクラス化するときは、以下をオーバーライドする必要があります。
  • void initialize (Subject、CallbackHandler、Map、Map): 解析するカスタムオプションがある場合。
  • boolean login (): 認証アクティビティーを実行します。ログインが成功した場合は loginOk インスタンス変数を true に設定し、失敗した場合は false に設定してください。
  • Principal getIdentity (): log () ステップによって認証されたユーザーの Principal オブジェクトを返します。
  • Group getRoleSets (): login () 中に認証された プリンシパル に割り当てられたロールを含む Roles という名前の グループ を少なくとも 1 つ返します。2 番目の共通 グループCallerPrincipal という名前で、セキュリティードメイン ID ではなくユーザーのアプリケーション ID を提供します。
UsernamePasswordLoginModule をサブクラス化するときは、以下をオーバーライドする必要があります。
  • void initialize (Subject、CallbackHandler、Map、Map): 解析するカスタムオプションがある場合。
  • Group getRoleSets (): login () 中に認証された プリンシパル に割り当てられたロールを含む Roles という名前の グループ を少なくとも 1 つ返します。2 番目の共通 グループCallerPrincipal という名前で、セキュリティードメイン ID ではなくユーザーのアプリケーション ID を提供します。
  • String getUsersPassword (): getUsername () メソッドを介して使用可能な現在のユーザー名の予想されるパスワードを返します。getUsersPassword () メソッドは、callbackhandler がユーザー名と候補パスワードを返した後、login () 内から呼び出されます。

18.3.2.2. カスタム LoginModule の例

次の情報は、UsernamePasswordLoginModule を拡張し、JNDI ルックアップからユーザーのパスワードとロール名を取得するカスタムログインモジュールの例を作成するのに役立ちます。
このセクションの最後に、password/<username> という形式の名前 (<username> は現在のユーザー) を使用してコンテキストを検索すると、ユーザーのパスワードを返すカスタム JNDI コンテキストログインモジュールを作成します。認証されている)。同様に、roles/<username> の形式を検索すると、要求されたユーザーのロールが返されます。の例18.26「JndiUserAndPassLoginModule Custom Login Module」JndiUserAndPassLoginModule カスタムログインモジュールのソースコードです。
これは JBossUsernamePasswordLoginModule を拡張するため、JndiUserAndPassLoginModule は JNDI ストアからユーザーのパスワードとロールを取得することに注意してください。JndiUserAndPassLoginModule は、JAASLoginModule 操作と相互作用しません。

例18.26 JndiUserAndPassLoginModule Custom Login Module

package org.jboss.book.security.ex2;
                    
import java.security.acl.Group;
import java.util.Map;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginException;
import org.jboss.logging.Logger;
import org.jboss.security.SimpleGroup;
import org.jboss.security.SimplePrincipal;
import org.jboss.security.auth.spi.UsernamePasswordLoginModule;
/**
 * An example custom login module that obtains passwords and roles for a user from a JNDI lookup.
 * 
 * @author Scott.Stark@jboss.org
 */
public class JndiUserAndPassLoginModule extends UsernamePasswordLoginModule {
  /** The JNDI name to the context that handles the password/username lookup */
  private String userPathPrefix;
  /** The JNDI name to the context that handles the roles/username lookup */
  private String rolesPathPrefix;
  private static Logger log = Logger.getLogger(JndiUserAndPassLoginModule.class);
  /**
   * Override to obtain the userPathPrefix and rolesPathPrefix options.
   */
  @Override
  public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
    super.initialize(subject, callbackHandler, sharedState, options);
    userPathPrefix = (String) options.get("userPathPrefix");
    rolesPathPrefix = (String) options.get("rolesPathPrefix");
  }
  /**
   * Get the roles the current user belongs to by querying the rolesPathPrefix + '/' + super.getUsername() JNDI location.
   */
  @Override
  protected Group[] getRoleSets() throws LoginException {
    try {
      InitialContext ctx = new InitialContext();
      String rolesPath = rolesPathPrefix + '/' + super.getUsername();
      String[] roles = (String[]) ctx.lookup(rolesPath);
      Group[] groups = { new SimpleGroup("Roles") };
      log.info("Getting roles for user=" + super.getUsername());
      for (int r = 0; r < roles.length; r++) {
        SimplePrincipal role = new SimplePrincipal(roles[r]);
        log.info("Found role=" + roles[r]);
        groups[0].addMember(role);
      }
      return groups;
    } catch (NamingException e) {
      log.error("Failed to obtain groups for user=" + super.getUsername(), e);
      throw new LoginException(e.toString(true));
    }
  }
  /**
   * Get the password of the current user by querying the userPathPrefix + '/' + super.getUsername() JNDI location.
   */
  @Override
  protected String getUsersPassword() throws LoginException {
    try {
      InitialContext ctx = new InitialContext();
      String userPath = userPathPrefix + '/' + super.getUsername();
      log.info("Getting password for user=" + super.getUsername());
      String passwd = (String) ctx.lookup(userPath);
      log.info("Found password=" + passwd);
      return passwd;
    } catch (NamingException e) {
      log.error("Failed to obtain password for user=" + super.getUsername(), e);
      throw new LoginException(e.toString(true));
    }
  }
}

例18.27 セキュリティーの定義 - 新しく作成されたカスタムログインモジュールを使用した ex2 セキュリティードメイン

/subsystem=security/security-domain=security-ex2/:add
/subsystem=security/security-domain=security-ex2/authentication=classic:add
/subsystem=security/security-domain=security-ex2/authentication=classic/login-module=ex2/:add(\
flag=required,\
code=org.jboss.book.security.ex2.JndiUserAndPassLoginModule,\
module-options=[("userPathPrefix"=>"/security/store/password"),\
("rolesPathPrefix"=>"/security/store/roles")]\
)

ユーザーのサーバー側認証に JndiUserAndPassLoginModule カスタムログインモジュールを使用するかどうかは、セキュリティードメインの例のログイン設定によって決まります。EJB JAR META-INF/jboss-ejb3.xml 記述子は、セキュリティードメインを設定します。Web アプリケーションの場合、これは WEB-INF/jboss-web.xml ファイルの一部です。

例18.28 jboss-ejb3.xml の

<?xml version="1.0"?>
<jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:s="urn:security" version="3.1" impl-version="2.0">
  <assembly-descriptor>
    <s:security>
      <ejb-name>*</ejb-name>
      <s:security-domain>security-ex2</s:security-domain>
    </s:security>
  </assembly-descriptor>
</jboss:ejb-jar>

例18.29 jboss-web.xml example

<?xml version="1.0"?>
<jboss-web>
    <security-domain>security-ex2</security-domain>
</jboss-web>

18.4. EJB アプリケーションセキュリティー

18.4.1. セキュリティーアイデンティティー

18.4.1.1. EJB セキュリティーアイデンティティー

EJB は、他のコンポーネントでメソッドを呼び出す際に使用するアイデンティティーを指定できます。これは、EJB セキュリティーアイデンティティー で、呼び出しアイデンティティーとも呼ばれます。
デフォルトでは、EJB は独自の呼び出し元アイデンティティーを使用します。アイデンティティーは、特定のセキュリティーロールに設定することもできます。特定のセキュリティーロールの使用は、セグメント化されたセキュリティーモデルを構築する場合に便利です。たとえば、内部 EJB のみへのコンポーネントセットへのアクセスを制限します。

18.4.1.2. EJB のセキュリティーアイデンティティーの設定

EJB のセキュリティーアイデンティティーは、セキュリティー設定の <security-identity> タグで指定します。
デフォルトでは、<security-identity> タグが存在しない場合、EJB 自身の呼び出し元 ID が使用されます。

例18.30 EJB のセキュリティーアイデンティティーの呼び出し元と同じ値への設定

この例では、EJB によって作成されたメソッド呼び出しのセキュリティーアイデンティティーを、現在の呼び出し元のアイデンティティーと同じに設定します。<security-identity> 要素の宣言を指定しない場合は、この動作がデフォルトになります。
<ejb-jar>
  <enterprise-beans>
	 <session>
		<ejb-name>ASessionBean</ejb-name>
		<!-- ... -->
		<security-identity>
		  <use-caller-identity/>
		</security-identity>
	 </session>
	 <!-- ... -->
  </enterprise-beans>
</ejb-jar>

例18.31 EJB のセキュリティーアイデンティティーの特定のロールへの設定

セキュリティーアイデンティティーを特定のロールに設定するには、<security-identity> タグ内の <run-as><role-name> タグを使用します。
<ejb-jar>
  <enterprise-beans>
	 <session>
		<ejb-name>RunAsBean</ejb-name>
		<!-- ... -->
		<security-identity>
		  <run-as>
			 <description>A private internal role</description>
			 <role-name>InternalRole</role-name>
		  </run-as>
		</security-identity>
	 </session>
  </enterprise-beans>
  <!-- ... -->
</ejb-jar>
デフォルトでは、<run-as> を使用すると、anonymous という名前のプリンシパルが発信呼び出しに割り当てられます。異なるプリンシパルを割り当てるには、<run-as-principal> を使用します。
<session>
    <ejb-name>RunAsBean</ejb-name>
    <security-identity>
        <run-as-principal>internal</run-as-principal>
    </security-identity>
</session>
サーブレットでのセキュリティー ID の指定
また、servlet 要素内に <run-as> および <run-as-principal> 要素を使用することもできます。

18.4.2. EJB メソッドパーミッション

18.4.2.1. EJB メソッドパーミッションについて

EJB はメソッドへのアクセスを特定のセキュリティーロールに制限できます。
EJB <method-permission> 要素の宣言は、EJB のインターフェイスメソッドを呼び出すことができるロールを指定します。以下の組み合わせのパーミッションを指定できます。
  • 名前付き EJB のすべてのホームおよびコンポーネントインターフェースメソッド
  • 名前付き EJB のホームまたはコンポーネントインターフェースの指定メソッド
  • オーバーロード名を持つ一連のメソッドに指定されたメソッド

18.4.2.2. EJB メソッドパーミッションの使用

概要

<method-permission> 要素は、<method> 要素で定義される EJB メソッドへのアクセスを許可される論理ロールを定義します。複数の例は、XML の構文を示しています。複数のメソッドパーミッションステートメントが存在する可能性があり、それらのステートメントには累積的影響があります。<method-permission> 要素は、<ejb-jar> 記述子の <assembly-descriptor> 要素の子です。

XML 構文は、EJB メソッドパーミッションのアノテーションを使用する代わりになります。

例18.32 ロールに対する EJB の全メソッドへのアクセスの許可

<method-permission>
  <description>The employee and temp-employee roles may access any method
  of the EmployeeService bean </description>
  <role-name>employee</role-name>
  <role-name>temp-employee</role-name>
  <method>
    <ejb-name>EmployeeService</ejb-name>
    <method-name>*</method-name>
  </method>
</method-permission>

例18.33 ロールが EJB の特定のメソッドにのみアクセスできるようにし、渡すことができるメソッドパラメーターを制限します。

<method-permission>
  <description>The employee role may access the findByPrimaryKey,
  getEmployeeInfo, and the updateEmployeeInfo(String) method of
  the AcmePayroll bean </description>
  <role-name>employee</role-name>
  <method>
	<ejb-name>AcmePayroll</ejb-name>
	<method-name>findByPrimaryKey</method-name>
  </method>
  <method>
	<ejb-name>AcmePayroll</ejb-name>
	<method-name>getEmployeeInfo</method-name>
  </method>
  <method>
	<ejb-name>AcmePayroll</ejb-name>
	<method-name>updateEmployeeInfo</method-name>
	<method-params>
	  <method-param>java.lang.String</method-param>
	</method-params>
  </method>
</method-permission>

例18.34 任意の認証されたユーザーによる EJB のメソッドへのアクセスの許可

<unchecked/> 要素を使用すると、認証されたユーザーが指定されたメソッドを使用できます。
<method-permission>
  <description>Any authenticated user may access any method of the
  EmployeeServiceHelp bean</description>
  <unchecked/>
  <method>
	<ejb-name>EmployeeServiceHelp</ejb-name>
	<method-name>*</method-name>
  </method>
</method-permission>

例18.35 特定の EJB メソッドの使用を完全に除外します

<exclude-list>
  <description>No fireTheCTO methods of the EmployeeFiring bean may be
  used in this deployment</description>
  <method>
	<ejb-name>EmployeeFiring</ejb-name>
	<method-name>fireTheCTO</method-name>
  </method>
</exclude-list>

例18.36 複数の <method-permission> ブロックを含む完全な <assembly-descriptor>

<ejb-jar>
    <assembly-descriptor>
        <method-permission>
            <description>The employee and temp-employee roles may access any
                method of the EmployeeService bean </description>
            <role-name>employee</role-name>
            <role-name>temp-employee</role-name>
            <method>
                <ejb-name>EmployeeService</ejb-name>
                <method-name>*</method-name>
            </method>
        </method-permission>
        <method-permission>
            <description>The employee role may access the findByPrimaryKey,
                getEmployeeInfo, and the updateEmployeeInfo(String) method of
                the AcmePayroll bean </description>
            <role-name>employee</role-name>
            <method>
                <ejb-name>AcmePayroll</ejb-name>
                <method-name>findByPrimaryKey</method-name>
            </method>
            <method>
                <ejb-name>AcmePayroll</ejb-name>
                <method-name>getEmployeeInfo</method-name>
            </method>
            <method>
                <ejb-name>AcmePayroll</ejb-name>
                <method-name>updateEmployeeInfo</method-name>
                <method-params>
                    <method-param>java.lang.String</method-param>
                </method-params>
            </method>
        </method-permission>
        <method-permission>
            <description>The admin role may access any method of the
                EmployeeServiceAdmin bean </description>
            <role-name>admin</role-name>
            <method>
                <ejb-name>EmployeeServiceAdmin</ejb-name>
                <method-name>*</method-name>
            </method>
        </method-permission>
        <method-permission>
            <description>Any authenticated user may access any method of the
                EmployeeServiceHelp bean</description>
            <unchecked/>
            <method>
                <ejb-name>EmployeeServiceHelp</ejb-name>
                <method-name>*</method-name>
            </method>
        </method-permission>
        <exclude-list>
            <description>No fireTheCTO methods of the EmployeeFiring bean may be
                used in this deployment</description>
            <method>
                <ejb-name>EmployeeFiring</ejb-name>
                <method-name>fireTheCTO</method-name>
            </method>
        </exclude-list>
    </assembly-descriptor>
</ejb-jar>

18.4.3. EJB セキュリティーアノテーション

18.4.3.1. EJB セキュリティーアノテーションについて

EJB javax.annotation.security アノテーションは JSR-250 で定義されます。
EJB はセキュリティーアノテーションを使用してセキュリティーに関する情報をデプロイヤーに渡します。これらの型には次のようなものがあります。
@DeclareRoles
利用可能なロールを宣言します。
@RunAs
コンポーネントの伝播セキュリティーアイデンティティーを設定します。

18.4.3.2. EJB セキュリティーアノテーションの使用

概要

XML 記述子またはアノテーションのいずれかを使用して、Enterprise JavaBean (EJB) でメソッドを呼び出すことのできるセキュリティーロールを制御できます。XML 記述子の使用については、「EJB メソッドパーミッションの使用」 を参照してください。

デプロイメント記述子に明示的に指定されるメソッドの値はすべて、アノテーションの値を上書きします。メソッドの値がデプロイメント記述子で指定されていない場合は、アノテーションを使用して設定された値が使用されます。上書きの粒度は、方法ごとに決定されます。

EJB のセキュリティーパーミッションを制御するアノテーション

@DeclareRoles
@DeclareRoles を使用して、パーミッションをチェックするセキュリティーロールを定義します。@DeclareRoles がない場合、一覧は @RolesAllowed アノテーションから自動的にビルドされます。ロールの設定に関する詳細は、『Java EE 6 チュートリアルSpecifying Authorized Users by Declaring Security Roles を参照してください。
@RolesAllowed, @PermitAll, @DenyAll
使用する@RolesAllowed1 つまたは複数のメソッドへのアクセスが許可されているロールを一覧表示します。使用する@PermitAllまた@DenyAll1 つまたは複数のメソッドの使用からすべてのロールを許可または拒否します。アノテーションメソッドのパーミッション設定に関する詳細は、『Java EE 6 チュートリアルSpecifying Authorized Users by Declaring Security Roles を参照してください。
@RunAs
@RunAs を使用して、アノテーション付きのメソッドから呼び出しを行うときにメソッドが使用するロールを指定します。アノテーションを使用してセキュリティーアイデンティティーを伝播する方法は、『Java EE 6 チュートリアルPropagating a Security Identity (Run-As) を参照してください。

例18.37 セキュリティー注釈の例

@Stateless
@RolesAllowed({"admin"})
@SecurityDomain("other")
public class WelcomeEJB implements Welcome {
	@PermitAll
	public String WelcomeEveryone(String msg) {
		return "Welcome to " + msg;
	}
	@RunAs("tempemployee")
	public String GoodBye(String msg) {
	    return "Goodbye, " + msg;
	}
	public String GoodbyeAdmin(String msg) {
		return "See you later, " + msg;
	}
}
このコードでは、すべてのロールがメソッドにアクセスできますWelcomeEveryone。TheGoodByeメソッドはを使用しますtempemployee電話をかけるときのロール。のみadminロールはメソッドにアクセスできますGoodbyeAdmin、およびセキュリティーアノテーションのないその他のメソッド。

18.4.4. EJB へのリモートアクセス

18.4.4.1. リモートメソッドアクセスについて

JBoss Remoting は、EJB、JMX MBean、およびその他の同様のサービスへのリモートアクセスを提供するフレームワークです。SSL の有無にかかわらず、次のトランスポートタイプ内で機能します。

サポートされているトランスポートタイプ

  • ソケット/セキュアソケット
  • RMI/RMI over SSL
  • HTTP / HTTPS
  • サーブレット/セキュアサーブレット
  • Bisocket/Secure Bisocket
警告
Red Hat は、影響するすべてのパッケージで TLSv1.1 または TLSv1.2 を利用するために SSL を明示的に無効化することを推奨しています。
JBoss Remoting は、マルチキャストまたは JNDI を介した自動検出も提供します。
これは、JBoss EAP 6 内の多くのサブシステムで使用され、複数の異なるトランスポートメカニズムを介してクライアントがリモートで呼び出すことができるサービスを設計、実装、およびデプロイすることもできます。また、JBoss EAP 6 の既存のサービスにアクセスすることもできます。

データマーシャリング

リモーティングシステムは、データマーシャリングおよびアンマーシャリングサービスも提供します。データマーシャリングとは、ネットワークとプラットフォームの境界を越えてデータを安全に移動し、別のシステムがデータに対して作業を実行できるようにする機能を指します。その後、作業は元のシステムに送り返され、ローカルで処理されたかのように動作します。

アーキテクチャーの概要

Remoting を使用するクライアントアプリケーションを設計するときは、URL タイプ形式の単純な文字列である InvokerLocator と呼ばれる特別なタイプのリソースロケーターを使用するようにアプリケーションを設定することにより、サーバーと通信するようにアプリケーションに指示します。サーバーは、リモーティング サブシステムの一部として設定されている コネクター でリモートリソースの要求をリッスンします。コネクター は、設定された ServerInvocationHandler に要求を渡します。各 ServerInvocationHandler はメソッドを実装しますinvoke(InvocationRequest)、リクエストの処理方法を知っています。

JBoss Remoting フレームワークには、クライアント側とサーバー側で相互にミラーリングする 3 つのレイヤーが含まれています。

JBossRemotingFramework レイヤー

  • ユーザーは外層と対話します。クライアント側では、外層はClientクラス。呼び出し要求を送信します。サーバー側では、ユーザーによって実装され、呼び出し要求を受け取るのは InvocationHandler です。
  • トランスポートは、呼び出し側レイヤーによって制御されます。
  • 最下層には、データ形式をワイヤ形式に変換するマーシャラーとアンマーシャラーが含まれています。

18.4.4.2. コールバックのリモート処理について

リモーティングクライアントがサーバーに情報を要求すると、サーバーがブロックして応答するのを待つことができますが、これは多くの場合、理想的な動作ではありません。クライアントがサーバー上の非同期イベントをリッスンし、サーバーが要求を終了するのを待っている間、他の作業を続行できるようにするために、アプリケーションは、サーバーが終了したときに通知を送信するようにサーバーに要求できます。これはコールバックと呼ばれます。あるクライアントは、別のクライアントに代わって生成された非同期イベントのリスナーとして自分自身を追加することもできます。コールバックの受信方法には、プルコールバックまたはプッシュコールバックの 2 つの異なる選択肢があります。クライアントはプルコールバックを同期的にチェックしますが、プッシュコールバックを受動的にリッスンします。
本質的に、コールバックはサーバーが送信することによって機能しますInvocationRequestクライアントに。サーバー側のコードは、コールバックが同期であるか非同期であるかに関係なく、同じように機能します。クライアントだけが違いを知る必要があります。サーバーの InvocationRequest はresponseObjectクライアントに。これは、クライアントが要求したペイロードです。これは、リクエストまたはイベント通知への直接の応答である可能性があります。
サーバーは、m_listeners物体。サーバーハンドラーに追加されたすべてのリスナーのリストが含まれています。TheServerInvocationHandlerインターフェイスには、このリストを管理できるメソッドが含まれています。
クライアントは、プルコールバックとプッシュコールバックをさまざまな方法で処理します。いずれの場合も、コールバックハンドラーを実装する必要があります。コールバックハンドラーはインターフェイスの実装ですorg.jboss.remoting.InvokerCallbackHandler、コールバックデータを処理します。コールバックハンドラーを実装した後、プルコールバックのリスナーとして自分自身を追加するか、プッシュコールバックのコールバックサーバーを実装します。

コールバックをプル

プルコールバックの場合、クライアントは、を使用してサーバーのリスナーのリストに自分自身を追加します。Client.addListener()方法。次に、コールバックデータの同期配信のためにサーバーを定期的にポーリングします。このポーリングは、Client.getCallbacks()

プッシュコールバック

プッシュコールバックでは、クライアントアプリケーションが独自の InvocationHandler を実行する必要があります。これを行うには、クライアント自体で Remoting サービスを実行する必要があります。これは、コールバックサーバー と呼ばれます。コールバックサーバーは着信要求を非同期で受け入れ、要求者 (この場合はサーバー) のためにそれらを処理します。クライアントのコールバックサーバーをメインサーバーに登録するには、コールバックサーバーのInvokerLocatorの 2 番目の引数としてaddListener方法。

18.4.4.3. リモーティングサーバー検出について

リモーティングサーバーとクライアントは、JNDI またはマルチキャストを使用して相互に自動的に検出できます。Remoting Detector がクライアントとサーバーの両方に追加され、NetworkRegistry がクライアントに追加されます。
サーバー側の Detector は、定期的に InvokerRegistry をスキャンし、作成したすべてのサーバー呼び出し元をプルします。この情報を使用して、各サーバー呼び出し元がサポートするロケーターとサブシステムを含む検出メッセージを公開します。このメッセージは、マルチキャストブロードキャストまたは JNDI サーバーへのバインディングを介して公開されます。
クライアント側では、Detector はマルチキャストメッセージを受信するか、定期的に JNDI サーバーをポーリングして検出メッセージを取得します。検出器は、検出メッセージが新しく検出されたリモートサーバーに対するものであることに気付いた場合、それを NetworkRegistry に登録します。また、サーバーが使用できなくなったことを検出すると、Detector は NetworkRegistry を更新します。

18.4.4.4. リモーティングサブシステムを設定する

概要

JBoss Remoting には、3 つのトップレベルの設定可能な要素があります。ワーカースレッドプール、1 つ以上のコネクター、および一連のローカルおよびリモート接続 URI です。このトピックでは、設定可能な各項目の説明、各項目を設定する方法の CLI コマンドの例、および完全に設定されたサブシステムの XML の例を示します。この設定はサーバーにのみ適用されます。独自のアプリケーションにカスタムコネクターを使用する場合を除き、Remoting のサブシステムの設定は必要でないことがほとんどです。EJB などの、リモーティングクライアントとして動作するアプリケーションには特定のコネクターに接続するための別の設定が必要になります。

注記
Remoting サブシステムの設定は、Web ベースの管理コンソールには公開されませんが、コマンドラインベースの管理 CLI から完全に設定できます。XML を手動で編集することはお勧めしません。

CLI コマンドの適応

CLI コマンドは、デフォルト のプロファイルを設定するときに、管理対象ドメイン用に作成されます。別のプロファイルを設定するには、その名前に置き換えます。スタンドアロンサーバーの場合、コマンドの /profile=default 部分を省略します。

リモーティングサブシステム外の設定

リモーティング サブシステムの外部にあるいくつかの設定の側面があります。

ネットワークインターフェース
リモーティング サブシステムで使用されるネットワークインターフェイスは、domain/configuration/domain.xml または standalone/configuration/standalone.xml で定義されている パブリック インターフェイスです。
<interfaces>
   <interface name="management"/>
   <interface name="public"/>
   <interface name="unsecure"/>
</interfaces>        

パブリック インターフェイスのホストごとの定義は、domain.xml または standalone.xml と同じディレクトリーの host.xml で定義されます。このインターフェイスは、他のいくつかのサブシステムでも使用されます。変更するときは注意してください。
<interfaces>
   <interface name="management">
      <inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
   </interface>
   <interface name="public">
      <inet-address value="${jboss.bind.address:127.0.0.1}"/>
   </interface>
   <interface name="unsecure">
      <!-- Used for IIOP sockets in the standard configuration.
         To secure JacORB you need to setup SSL -->
      <inet-address value="${jboss.bind.address.unsecure:127.0.0.1}"/>
   </interface>
</interfaces>             

socket-binding
remoting サブシステムによって使用されるデフォルトのソケットバインディングは TCP ポート 4447 にバインドされます。これを変更する必要がある場合の詳細は、ソケットバインディングとソケットバインディンググループに関するドキュメントを参照してください。
ソケットバインディングおよびソケットバインディンググループに関する情報は、JBoss EAP の 『管理および設定ガイド』 の 『ソケットバインディンググループ』 の章にあります。 https://access.redhat.com/documentation/ja-jp/red_hat_jboss_enterprise_application_platform/?version=6.4
EJB の リモーティングコネクター参照
EJB サブシステムにはリモートメソッド呼び出しに対するリモーティングコネクターへの参照が含まれています。デフォルト設定は次のとおりです。
<remote connector-ref="remoting-connector" thread-pool-name="default"/>            

セキュアなトランスポート設定
リモーティングトランスポートはクライアントの要求があれば StartTLS を使用してセキュアな接続 (HTTPS、Secure Servlet など) を使用します。セキュアな接続とセキュアでない接続の両方で同じソケットバインディング (ネットワークポート) が使用されるため、サーバー側に追加の設定をする必要はありません。クライアントは必要に応じてセキュアなトランスポートまたはセキュアでないトランスポートを要求します。EJB、ORB、JMS プロバイダーなどのリモーティングを使用する JBoss EAP 6 のコンポーネントはデフォルトでセキュアなインターフェイスを使用します。
警告:StartTLS のセキュリティーに関する考慮事項
StartTLS はクライアントの要求があればセキュアな接続を有効にしますが、セキュアでない接続がデフォルトになります。本質的に、StartTLS は攻撃者がクライアントの要求を妨害し、要求を編集してセキュアでない接続を要求する中間者 攻撃の対象になりやすい欠点があります。セキュアでない接続が適切なフォールバックである場合を除き、実際にはクライアントがセキュアな接続を取得できなかったときに適切に失敗するよう記述する必要があります。

ワーカースレッドプール

ワーカースレッドプールは、Remoting コネクターを介して入ってくる作業を処理するために使用できるスレッドのグループです。これは単一の要素 <worker-thread-pool> であり、いくつかの属性を取ります。ネットワークタイムアウトが発生した場合、スレッドが不足した場合、またはメモリー使用量を制限する必要がある場合は、これらの属性を調整してください。具体的な推奨事項は、特定の状況によって異なります。詳細は Red Hat グローバルサポートサービスまでお問い合わせください。

表18.2 ワーカースレッドプールの属性

属性 説明 CLI コマンド
読み取りスレッド
リモーティングワーカーに対して作成する読み取りスレッドの数。デフォルトは1です。
/profile=default/subsystem=remoting/:write-attribute(name=worker-read-threads,value=1)
write-threads
リモーティングワーカーに作成する書き込みスレッドの数。デフォルトは1です。
/profile=default/subsystem=remoting/:write-attribute(name=worker-write-threads,value=1)
task-keepalive
コアでないリモーティングワーカーのタスクスレッドにキープアライブを使用する期間 (ミリ秒単位)。デフォルトは 60 です。
/profile=default/subsystem=remoting/:write-attribute(name=worker-task-keepalive,value=60)
task-max-threads
リモーティングワーカーのタスクスレッドプールに対するスレッドの最大数。デフォルトは 16 です。
/profile=default/subsystem=remoting/:write-attribute(name=worker-task-max-threads,value=16)
task-core-threads
リモーティングワーカーのタスクスレッドプールに対するコアスレッドの数。デフォルトは 4 です。
/profile=default/subsystem=remoting/:write-attribute(name=worker-task-core-threads,value=4)
task-limit
許可するリモーティングワーカータスクの最大数。 この数を超えるリモーティングワーカータスクは拒否されます。デフォルトは 16384 です。
/profile=default/subsystem=remoting/:write-attribute(name=worker-task-limit,value=16384)

コネクター

コネクターは主な Remoting 設定要素です。複数のコネクターを設定できます。それぞれは、いくつかのサブ要素といくつかの可能な属性を持つ要素 <connector> 要素で設定されています。デフォルトのコネクターは複数の JBoss EAP 6 サブシステムによって使用されます。カスタムコネクターの要素や属性の設定はアプリケーションによって異なるため、詳細は Red Hat グローバルサポートサービスまでご連絡ください。

表18.3 コネクターの属性

属性 説明 CLI コマンド
socket-binding このコネクターに使用するソケットバインディングの名前。
/profile = default/subsystem = remoteing/connectedor = remoteing-connector/:write-attribute (name = socket-binding、value = remoteing)
authentication-provider
このコネクターで使用するコンテナー用 Java 認証サービスプロバイダーインターフェイス (JASPIC) モジュール。モジュールはクラスパスに含まれている必要があります。
/profile = default/subsystem = remoteing/connectedor = remoteing-connector/:write-attribute (name = authentication-provider、value = myProvider)
security-realm
任意。アプリケーションのユーザー、パスワード、およびロールを含むセキュリティーレルム。EJB または Web アプリケーションは、セキュリティーレルムに対して認証できます。ApplicationRealm は、デフォルトの JBoss EAP 6 インストールで使用できます。
/profile = default/subsystem = remoteing/connectedor = remoteing-connector/:write-attribute (name = security-realm、value = ApplicationRealm)

表18.4 コネクター要素

属性 説明 CLI コマンド
sasl
Simple Authentication and Security Layer (SASL) 認証メカニズムの囲み要素
該当なし
properties
1 つ以上の <property> 要素が含まれ、それぞれに name 属性とオプションの value 属性があります。
/profile = default/subsystem = remoteing/connectedor = remoteing-connector/property = myProp/:add (value = myPropValue)

送信接続

3 つのタイプのアウトバウンド接続を指定することができます。

  • STF へのアウトバウンド接続
  • ソケットなどのローカルリソースに接続するローカルアウトバウンド接続
  • リモートリソースに接続し、セキュリティーレルムを使用して認証を行うリモートアウトバウンド接続
すべてのアウトバウンド接続は、<outbound-connections> 要素で囲まれています。これらの各接続タイプは、outbound-socket-binding-ref 属性を取ります。アウトバウンド接続は uri 属性を取ります。リモートアウトバウンド接続は、オプションの ユーザー名セキュリティーレルム 属性を使用して承認に使用します。

表18.5 アウトバウンド接続要素

属性 説明 CLI コマンド
outbound-connection 一般的なアウトバウンド接続。
/profile = default/subsystem = remoting/outbound-connection = my-connection/:add (uri = http://my-connection)
local-outbound-connection 暗黙の local://URI スキームを使用したアウトバウンド接続。
/profile = default/subsystem = remoteing/local-outbound-connection = my-connection/:add (outbound-socket-binding-ref = remoteing2)
remote-outbound-connection
セキュリティーレルムで基本/ダイジェスト認証を使用する、remote://URI スキームのアウトバウンド接続。
/profile = default/subsystem = remoteing/remote-outbound-connection = my-connection/:add (outbound-socket-binding-ref = remoteing、username = myUser、security-realm = ApplicationRealm)

SASL 要素

SASL 子要素を定義する前に、最初の SASL 要素を作成する必要があります。以下のコマンドを使用します。

/profile=default/subsystem=remoting/connector=remoting-connector/security=sasl:add
SASL 要素の子要素について、次の表で説明します。

表18.6 SASL 子要素

属性 説明 CLI コマンド
include-mechanisms
SASL メカニズムのリストである value 属性が含まれています。
/profile=default/subsystem=remoting/connector=remoting-connector/security=sasl:write-attribute(name=include-mechanisms,value=["DIGEST","PLAIN","GSSAPI"])
qop
優先度の高い順に、SASL の保護品質値のリストである value 属性が含まれています。
/profile=default/subsystem=remoting/connector=remoting-connector/security=sasl:write-attribute(name=qop,value=["auth"])
strength
優先度の高い順に、SASL 暗号強度値のリストである value 属性が含まれています。
/profile=default/subsystem=remoting/connector=remoting-connector/security=sasl:write-attribute(name=strength,value=["medium"])
reuse-session
ブール値である value 属性が含まれています。true の場合、セッションの再利用を試みます。
/profile=default/subsystem=remoting/connector=remoting-connector/security=sasl:write-attribute(name=reuse-session,value=false)
server-auth
ブール値である value 属性が含まれています。true の場合、サーバーはクライアントに対して認証を行います。
/profile=default/subsystem=remoting/connector=remoting-connector/security=sasl:write-attribute(name=server-auth,value=false)
policy
以下の要素を 0 個以上含む囲み要素。それぞれが単一の を取ります。
  • Forward-Secrecy – Forward Secrecy を実装するためにメカニズムが必要かどうか (1 つのセッションに割り込むと、将来のセッションに割り込むための情報が自動的に提供されません)
  • 非アクティブ–非辞書攻撃の影響を受けやすいメカニズムが許可されているかどうか。false の値は許可し、true は拒否します。
  • no-anonymous –匿名ログインを受け入れるメカニズムが許可されているかどうか。false の値は許可し、true は拒否します。
  • 辞書なし–パッシブ辞書攻撃の影響を受けやすいメカニズムが許可されているかどうか。false の値は許可し、true は拒否します。
  • no-plain-text –単純なプレーンパッシブ攻撃の影響を受けやすいメカニズムが許可されているかどうか。false の値は許可し、true は拒否します。
  • pass-credentials –クライアントの資格情報を渡すメカニズムが許可されているかどうか。
/profile=default/subsystem=remoting/connector=remoting-connector/security=sasl/sasl-policy=policy:add
/profile=default/subsystem=remoting/connector=remoting-connector/security=sasl/sasl-policy=policy:write-attribute(name=forward-secrecy,value=true)
/profile=default/subsystem=remoting/connector=remoting-connector/security=sasl/sasl-policy=policy:write-attribute(name=no-active,value=false)
/profile=default/subsystem=remoting/connector=remoting-connector/security=sasl/sasl-policy=policy:write-attribute(name=no-anonymous,value=false)
/profile=default/subsystem=remoting/connector=remoting-connector/security=sasl/sasl-policy=policy:write-attribute(name=no-dictionary,value=true)
/profile=default/subsystem=remoting/connector=remoting-connector/security=sasl/sasl-policy=policy:write-attribute(name=no-plain-text,value=false)
/profile=default/subsystem=remoting/connector=remoting-connector/security=sasl/sasl-policy=policy:write-attribute(name=pass-credentials,value=true)
properties
1 つ以上の <property> 要素が含まれ、それぞれに name 属性とオプションの value 属性があります。
/profile=default/subsystem=remoting/connector=remoting-connector/security=sasl/property=myprop:add(value=1)
/profile=default/subsystem=remoting/connector=remoting-connector/security=sasl/property=myprop2:add(value=2)

例18.38 設定例

この例は、JBoss EAP 6 に同梱されているデフォルトのリモーティングサブシステムを示しています。
<subsystem xmlns="urn:jboss:domain:remoting:1.1">
    <connector name="remoting-connector" socket-binding="remoting" security-realm="ApplicationRealm"/>
</subsystem>    

この例には多くの仮想値が含まれており、前に説明した要素と属性をコンテキストに入れるために提示されています。
<subsystem xmlns="urn:jboss:domain:remoting:1.1">
    <worker-thread-pool read-threads="1" task-keepalive="60" task-max-threads="16" task-core-thread="4" task-limit="16384" write-threads="1" />
    <connector name="remoting-connector" socket-binding="remoting" security-realm="ApplicationRealm">
        <sasl>
            <include-mechanisms value="GSSAPI PLAIN DIGEST-MD5" />
            <qop value="auth" />
            <strength value="medium" />
            <reuse-session value="false" />
            <server-auth value="false" />
            <policy>
                <forward-secrecy value="true" />
                <no-active value="false" />
                <no-anonymous value="false" />
                <no-dictionary value="true" />
                <no-plain-text value="false" />
                <pass-credentials value="true" />
            </policy>
            <properties>
                <property name="myprop1" value="1" />
                <property name="myprop2" value="2" />
            </properties>
        </sasl>
        <authentication-provider name="myprovider" />
        <properties>
            <property name="myprop3" value="propValue" />
        </properties>
    </connector>
    <outbound-connections>
        <outbound-connection name="my-outbound-connection" uri="http://myhost:7777/"/>
        <remote-outbound-connection name="my-remote-connection" outbound-socket-binding-ref="my-remote-socket" username="myUser" security-realm="ApplicationRealm"/>
        <local-outbound-connection name="myLocalConnection" outbound-socket-binding-ref="my-outbound-socket"/>
    </outbound-connections>
</subsystem>    

まだ文書化されていない設定の側面

  • JNDI およびマルチキャスト自動検出

18.4.4.5. リモート EJB クライアントでのセキュリティーレルムの使用

EJB をリモートで呼び出すクライアントにセキュリティーを追加する方法として、セキュリティーレルムを使用することができます。セキュリティーレルムは、ユーザー名/パスワードのペアとユーザー名/ロールのペアの単純なデータベースです。この用語は Web コンテナーのコンテキストでも使用され、意味が若干異なります。
EJB に対してセキュリティーレルムに存在する特定のユーザー名/パスワードのペアを認証するには、以下の手順に従います。
  • 新しいセキュリティーレルムをドメインコントローラーまたはスタンドアロンサーバーに追加します。
  • アプリケーションのクラスパスにある jboss-ejb-client.properties ファイルに以下のパラメーターを追加します。この例では、接続がファイル内の他のパラメーターによって default として参照されていることを前提としています。
    remote.connection.default.username=appuser
    remote.connection.default.password=apppassword
    
  • 新しいセキュリティーレルムを使用するドメインまたはスタンドアロンサーバーでカスタムリモーティングコネクターを作成します。
  • カスタムリモーティングコネクターでプロファイルを使用するよう設定されたサーバーグループに EJB を追加します。または管理対象ドメインを使用していない場合はスタンドアロンサーバーに EJB をデプロイします。

18.4.4.6. 新しいセキュリティーレルムの追加

  1. 管理 CLI を実行します。

    jboss-cli.sh または jboss-cli.bat コマンドを起動して、サーバーに接続します。
  2. 新しいセキュリティーレルム自体を作成します。

    以下のコマンドを実行し、ドメインコントローラーまたはスタンドアロンサーバーに MyDomainRealm という名前の新しいセキュリティーレルムを作成します。
    ドメインインスタンスの場合は、以下のコマンドを使用します。
    /host=master/core-service=management/security-realm=MyDomainRealm:add()
    スタンドアロンインスタンスの場合には、以下のコマンドを使用します。
    /core-service=management/security-realm=MyDomainRealm:add()
  3. 新規ロールに関する情報を格納するプロパティーファイルへの参照を作成します。

    以下のコマンドを実行して、新しいロールに関連するプロパティーが含まれる myfile.properties ファイルへのポインターを作成します。
    注記
    新しく作成されたプロパティーファイルは、含まれる add-user.sh および add-user.bat スクリプトでは管理されません。外部で管理する必要があります。
    ドメインインスタンスの場合は、以下のコマンドを使用します。
    /host=master/core-service=management/security-realm=MyDomainRealm/authentication=properties:add(path=myfile.properties)
    スタンドアロンインスタンスの場合には、以下のコマンドを使用します。
    /core-service=management/security-realm=MyDomainRealm/authentication=properties:add(path=myfile.properties)

結果

新しいセキュリティーレルムが作成されます。この新しいレルムにユーザーおよびロールを追加すると、情報はデフォルトのセキュリティーレルムとは別のファイルに保存されます。この新しいファイルは、独自のアプリケーションまたは手順を使用して管理できます。

18.4.4.7. セキュリティーレルムへのユーザーの追加

  1. add-user.sh または add-user.bat コマンドを実行します。

    ターミナルを開き、EAP_HOME/bin/ ディレクトリーに移動します。Red Hat Enterprise Linux またはその他の UNIX と同様のオペレーティングシステムを使用している場合には、add-user.sh を実行します。Microsoft Windows Server を実行している場合は、add-user.bat を実行します。
  2. 管理ユーザーまたはアプリケーションユーザーを追加するかどうかを選択します。

    この手順では、b と入力してアプリケーションユーザーを追加します。
  3. ユーザーを追加するレルムを選択します。

    デフォルトでは、利用可能なレルムは ApplicationRealm のみです。カスタムレルムを追加した場合は、代わりにその名前を入力できます。
  4. プロンプトが表示されたら、ユーザー名、パスワード、およびロールを入力します。

    プロンプトが表示されたら、希望のユーザー名、パスワード、および任意のロールを入力します。yes を入力して選択を確認するか、no と入力して変更をキャンセルします。変更は、セキュリティーレルムの各プロパティーファイルに書き込まれます。

18.4.4.8. SSL 暗号化を使用したリモート EJB アクセス

デフォルトでは、EJB2 および EJB3 Bean の Remote Method Invocation (RMI) のネットワークトラフィックは暗号化されません。暗号化が必要なインスタンスでは、クライアントとサーバー間の接続を暗号化する Secure Sockets Layer (SSL) を使用できます。また、SSL を使用すると、ファイアウォールの設定に応じて、ネットワークトラフィックが一部のファイアウォールを通過できるようになります。
警告
Red Hat は、影響するすべてのパッケージで TLSv1.1 または TLSv1.2 を利用するために SSL を明示的に無効化することを推奨しています。

18.5. JAX-RS アプリケーションセキュリティー

18.5.1. RESTEasy JAX-RS Web サービスのロールベースのセキュリティーの有効化

概要

RESTEasy は JAX-RS メソッドでの @RolesAllowed、@PermitAll、@DenyAll アノテーションに対応しています。ただし、デフォルトではこれらの注釈は認識されません。以下の手順に従って、web.xml ファイルを設定し、ロールベースのセキュリティーを有効にします。

警告
以下の RESTEasy パラメーターのデフォルト値を変更すると、RESTEasy アプリケーションが XXE 攻撃に対して潜在的に脆弱になる可能性があります。
  • resteasy.document.expand.entity.references
  • resteasy.document.secure.processing.feature
  • resteasy.document.secure.disableDTDs
これらのパラメーターの詳細については、を参照してください。「RESTEasy 設定パラメーター」
警告
アプリケーションが EJB を使用する場合は、ロールベースのセキュリティーをアクティベートしないでください。EJB コンテナーは RESTEasy ではなく機能を提供します。

手順18.5 RESTEasy JAX-RS Web サービスのロールベースのセキュリティーの有効化

  1. テキストエディターでアプリケーションの web.xml ファイルを開きます。
  2. 以下の <context-param> をファイルに、web-app 内に追加します。
    <context-param>
        <param-name>resteasy.role.based.security</param-name>
        <param-value>true</param-value>
    </context-param>
    
  3. <security-role> タグを使用して、RESTEasy JAX-RS WAR ファイル内で使用されるすべてのロールを宣言します。
    <security-role>
        <role-name>ROLE_NAME</role-name>
    </security-role>
    <security-role>
        <role-name>ROLE_NAME</role-name>
    </security-role>
  4. すべてのロールについて JAX-RS ランタイムによって処理されるすべての URL へのアクセスを承認します。
    <security-constraint>
        <web-resource-collection>
    	<web-resource-name>Resteasy</web-resource-name>
    	<url-pattern>/PATH</url-pattern>
        </web-resource-collection>
        <auth-constraint>
    	<role-name>ROLE_NAME</role-name>
    	<role-name>ROLE_NAME</role-name>
        </auth-constraint>
    </security-constraint>

結果

ロールベースのセキュリティーは、定義されたロールとともにアプリケーション内で有効にされています。

例18.39 例: ロールベースのセキュリティー設定

<web-app>

    <context-param>
	<param-name>resteasy.role.based.security</param-name>
	<param-value>true</param-value>
    </context-param>

    <servlet-mapping>
	<servlet-name>Resteasy</servlet-name>
	<url-pattern>/*</url-pattern>
    </servlet-mapping>

    <security-constraint>
	<web-resource-collection>
	    <web-resource-name>Resteasy</web-resource-name>
	    <url-pattern>/security</url-pattern>
	</web-resource-collection>
	<auth-constraint>
	    <role-name>admin</role-name>
	    <role-name>user</role-name>
	</auth-constraint>
    </security-constraint>

    <security-role>
	<role-name>admin</role-name>
    </security-role>
    <security-role>
	<role-name>user</role-name>
    </security-role>
    
</web-app>

18.5.2. アノテーションを使用して JAX-RSWeb サービスを保護する

概要

このトピックでは、サポートされているセキュリティーアノテーションを使用して JAX-RSWeb サービスを保護する手順について説明します。

手順18.6 サポートされているセキュリティーアノテーションを使用して JAX-RSWeb サービスを保護する

  1. ロールベースセキュリティーを有効化します。詳細は、「RESTEasy JAX-RS Web サービスのロールベースのセキュリティーの有効化」 を参照してください。
  2. JAX-RS Web サービスにセキュリティーアノテーションを追加します。RESTEasy は以下のアノテーションをサポートします。
    @RolesAllowed
    メソッドにアクセスできるロールを定義します。すべてのロールは web.xml ファイルで定義する必要があります。
    @PermitAll
    web.xml ファイルに定義されているすべてのロールがメソッドにアクセスできるようにします。
    @DenyAll
    メソッドへのすべてのアクセスを拒否します。

18.6. 機密性の高い文字列のパスワード vault

18.6.1. パスワード vault システム

JBoss EAP および関連するアプリケーションの設定には、ユーザー名とパスワードなどの機密情報が必要になります。
Password Vault は、パスワード情報をマスクして暗号化されたキーストアに保存する機能を提供します。暗号化されたキーストアの参照を管理 CLI コマンドまたはアプリケーションに含めることができます。パスワード vault は Java キーストアをストレージメカニズムとして使用します。パスワード vault はストレージとキーストレージの 2 つで構成されます。Java キーストアは、Vault ストレージで機密文字列を暗号化または復号化するために使用されるキーを保存するために使用されます。

18.6.2. パスワード Vault の設定と使用

パスワード Vault で提供されるマスクされたキーストアパスワード機能は、JBoss EAP サーバーに保存されているパスワード Vault からマスクされたキーストアパスワードを取得するオプションを提供します。パスワード vault は Java キーストアをストレージメカニズムとして使用します。

手順18.7 パスワード Vault の設定および使用に関する基本的な手順

  1. Java キーストアを設定し、パスワード暗号化用のキーを格納します。
    キーストアの作成は、「機密性が高い文字列を格納する Java キーストアの作成」 を参照してください。。
  2. パスワード vault を初期化します。
    パスワードのマスキングとパスワード Vault の初期化については、「パスワード vault の初期化」 を参照してください。
  3. パスワード Vault に機密文字列を保存します。
    機密文字列をパスワード Vault に保存する方法については、「パスワード Vault に Sensitive 文字列を保存します。」 を参照してください。
  4. パスワード vault を使用するように JBoss EAP 6 を設定します。
    パスワード Vault を使用するように JBoss EAP 6 を設定する方法については、「パスワード vault を使用するよう JBoss EAP 6 を設定」 を参照してください。カスタム実装については、「パスワード Vault のカスタム実装を使用するよう JBoss EAP 6 を設定」 を参照してください
    注記
    暗号化した機密文字列を設定で使用する方法は、「暗号化した機密文字列を設定で使用」 を参照してください。
    アプリケーションで暗号化した機密文字列を使用する方法は、「アプリケーションで暗号化した機密文字列の使用」 を参照してください。
    パスワード Vault で機密文字列を確認するには、「機密文字列がパスワード vault 内にあるかどうかを確認します。」 を参照してください。
    パスワード Vault から機密文字列を削除するには、「パスワード vault からの機密文字列の削除」 を参照してください。

18.6.3. 外部ソースからのキーストアパスワードの取得

Vault 設定で EXT、EXTC、CMD、CMDC、または CLASS メソッドを使用して、Java キーストアのパスワードを取得することもできます。
<vault-option name="KEYSTORE_PASSWORD" value="[here]"
この方法を以下で説明します。
  • これは、そのまま使えるコマンドを参照します。ここでの {EXT}... は、実際のコマンドです。例:{EXT}/usr/bin/getmypassword --section 1 --query company/usr/bin/getmypassword を実行すると、パスワードを標準出力に表示し、Security Vault のキーストアのパスワードとして使用します。この例では --section 1 と --query company のオプションを使用しています。
  • {EXTC[:expiration_in_millis]}...: 実際のコマンドを参照します。ここでの、... は、プラットフォームコマンドを実行するために Runtime.exec(String) メソッドに渡される、実際のコマンドラインです。コマンド出力の最初の行がパスワードとして使用されます。EXTC バリアントは expiration_in_millis ミリ秒のパスワードをキャッシュします。デフォルトのキャッシュ有効期限は 0 (ゼロ) です。これは、キャッシュ内のアイテムが期限切れにならないことを意味します。例:{EXTC:120000}/usr/bin/getmypassword --section 1 --query company/usr/bin/getmypassword の出力がキャッシュに含まれているかどうかを確認します。出力が含まれている場合はそれを使用します。出力がない場合は、コマンドを実行してこれをキャッシュに出力して使用します。この例では、キャッシュは 2 分 (120000 ミリ秒) で期限切れになります。
  • {CMD}... or {CMDC[:expiration_in_millis]}...: 一般的なコマンドは 「,」 (コンマ) で区切られた文字列です。最初の部分は実際のコマンドで、追加の部分はパラメーターを表します。コンマにバックスラッシュを付けることで、パラメーターの一部として維持することができます。例: {CMD}/usr/bin/getmypassword,--section,1,--query,company
  • {CLASS[@jboss_module_spec]}classname[:ctorargs]: [:ctorargs] は、クラス名から : (コロン) によって区切られるオプションの文字列です。これは、クラス名 ctor に渡されます。ctorargs は文字列のコンマ区切りの一覧です。例: {CLASS@org.test.passwd}org.test.passwd.ExternamPassworProvider.この例では、org.test.passwd モジュールからの org.test.passwd.ExternamPassworProvider クラスを読み込んで、 toCharArray() メソッドを使用し、パスワードを取得します。toCharArray() が利用できない場合は toString() メソッドを使用します。org.test.passwd.ExternamPassworProvider クラスにはデフォルトのコンストラクターが必要です。

18.6.4. 機密性が高い文字列を格納する Java キーストアの作成

前提条件

  • Java Runtime Environment (JRE) によって提供される keytool ユーティリティー。このファイルへのパスを見つけます。Red Hat Enterprise Linux では、/usr/bin/keytool です。
警告
JCEKS キーストアの実装は Java のベンダーによって異なるため、使用する Java development kit と同じベンダーの keytool ユーティリティーを使用してキーストアを生成する必要があります。
別のベンダーの Java 開発キットで実行されている JBoss EAP インスタンスで、あるベンダーの Java 開発キットの keytool によって生成されたキーストアを使用すると、次の例外が発生します。
java.io.IOException: com.sun.crypto.provider.SealedObjectForKeyProtector

手順18.8 Java キーストアの設定

  1. キーストアと他の暗号化された情報を格納するディレクトリーを作成します。

    キーストアと他の重要な情報を格納するディレクトリーを作成します。この手順では、ディレクトリーは EAP_HOME/vault/ と想定します。このディレクトリーには機密情報が含まれるため、アクセスは、一部のユーザーに制限する必要があります。JBoss EAP を実行しているユーザーアカウントには少なくとも読み書き込みアクセスが必要です。
  2. keytool ユーティリティーで使用するパラメーターを決定します。

    以下のパラメーターの値を決めます。
    alias
    エイリアスは、vault やキーストアに保存されている他のデータの一意識別子です。エイリアスは大文字と小文字を区別しません。
    storetype
    ストアタイプはキーストアのタイプを指定します。値は、jceks が推奨されます。
    keyalg
    暗号化に使用するアルゴリズム。JRE とオペレーティングシステムのドキュメントを使用して、他にどの選択肢が利用できるかを確認してください。
    keysize
    暗号化キーのサイズは、ブルートフォースでの暗号解除の難易度に影響します。適切な値の詳細は、keytool ユーティリティーとともに配布されるドキュメントを参照してください。
    storepass
    storepass の値は、キーストアに対する認証に使用されるパスワードであるため、鍵を読み取ることができます。パスワードは 6 文字以上である必要があります。パスワードは、キーストアへのアクセス時に入力する必要があります。このパラメーターを省略すると、コマンドの実行時に入力を求められます。
    keypass
    keypass の値は、特定のキーにアクセスするために使用されるパスワードで、storepass パラメーターの値と一致する必要があります。
    validity
    validity の値は、鍵が有効になる期間 (日数) です。
    keystore
    keystore の値は、keystore の値が格納される予定のファイルパスおよびファイル名です。キーストアファイルは、データが最初に追加されると作成されます。
    正しいファイルパス区切り文字が使用されていることを確認します。Red Hat Enterprise Linux および同様のオペレーティングシステムの場合は / (フォワードスラッシュ)、Microsoft Windows Server の場合は \ (バックスラッシュ) を使用します。
    Keytool ユーティリティーには、その他の多くのオプションがあります。詳細は、JRE またはオペレーティングシステムのドキュメントを参照してください。
  3. keytool コマンドを実行します。

    オペレーティングシステムのコマンドラインインターフェイスを開き、収集した情報を使用して keytool ユーティリティーを実行します。

例18.40 Java キーストアの作成

$ keytool -genseckey -alias vault -storetype jceks -keyalg AES -keysize 128 -storepass vault22 -keypass vault22 -validity 730 -keystore EAP_HOME/vault/vault.keystore

結果

この場合、キーストアはファイルは EAP_HOME/vault/vault.keystore に作成されています。JBoss EAP では、パスワードなどの暗号化された文字列を保存するために使用されるエイリアス vault とともに単一のキーを保存します。

18.6.5. パスワード vault の初期化

概要

パスワード vault は、各パラメーターの値を入力するように求められる対話的な方法、またはすべてのパラメーターの値がコマンドラインで指定される非対話的な方法で初期化できます。それぞれの方法で同じ結果が得られるため、どちらの方法を選択してもかまいません。

どちらの方法を使用する場合でも、次のリストを参照してください。

パラメーター値

keystore URL (KEYSTORE_URL)
キーストアファイルのファイルシステムパスまたは URI。この例では、EAP_HOME/vault/vault.keystore を使用します。
キーストアパスワード (KEYSTORE_PASSWORD)
キーストアのアクセスに使用されるパスワード。
Salt (SALT)
Salt 値は、キーストアの内容を暗号化するために、iteration count (反復カウント) とともに使用される 8 文字のランダムな文字列です。
keystore Alias (KEYSTORE_ALIAS)
キーストア認識されているエイリアス。
Iteration Count (ITERATION_COUNT)
暗号化アルゴリズムの実行回数。
Directory to store encrypted files (ENC_FILE_DIR)
暗号化したファイルを保存するパス。これは通常、パスワード vault を含むディレクトリーです。
暗号化されたすべての情報をキーストアと同じ場所に格納することは便利ですが、必須ではありません。このディレクトリーには、制限のあるユーザーのみがアクセスできるようにする必要があります。JBoss EAP を実行しているユーザーアカウントには少なくとも読み書き込みアクセスが必要です。「機密性が高い文字列を格納する Java キーストアの作成」 を実行した場合は、キーストアは EAP_HOME/vault/ というディレクトリーにあります。
注記
ディレクトリー名の後にはバックスラッシュまたはスラッシュが必要です。正しいファイルパス区切り文字が使用されていることを確認します。Red Hat Enterprise Linux および同様のオペレーティングシステムの場合は / (フォワードスラッシュ)、Microsoft Windows Server の場合は \ (バックスラッシュ) を使用します。
Vault Block (VAULT_BLOCK)
パスワード vault でこのブロックに与えられる名前。分かりやすい値を選択してください。
Attribute (ATTRIBUTE)
保存される属性に与えられる名前。分かりやすい値を選択してください。たとえば、データソースに関する名前を選択できます。
Security Attribute (SEC-ATTR)
パスワード vault に保存されているパスワード。

手順18.9 パスワード vault コマンドを対話式に実行します。

各パラメーターの値の入力を求めるように設定する場合は、このメソッドを使用します。
  1. パスワード vault コマンドをインタラクティブに起動します。

    オペレーティングシステムのコマンドラインインターフェイスを起動し、EAP_HOME/bin/vault.sh (Red Hat Enterprise Linux および同様のオペレーティングシステム) または EAP_HOME\bin\vault.bat (Microsoft Windows Server 上) を実行します。新しい対話セッションを開始するには、0 (ゼロ) と入力します。
  2. 要求パラメーターを入力します。

    プロンプトに従って必要なパラメーターを入力します。
  3. マスクされたパスワード情報をメモします。

    マスクされたパスワード、salt、iteration count (反復数) は、標準出力に出力されます。安全な場所にそれらを書き留めておきます。これらのエントリーは、パスワード Vault に追加する必要があります。キーストアファイルおよびこの値にアクセスすると、攻撃者はパスワード Vault の機密情報にアクセスできるようになります。
  4. 対話式コンソールを終了します。

    3 と入力して、対話式コンソールを終了します。

例18.41 パスワード vault コマンドの対話式実行

Please enter a Digit::   0: Start Interactive Session  1: Remove Interactive Session  2: Exit
0
Starting an interactive session
Enter directory to store encrypted files:EAP_HOME/vault/                        
Enter Keystore URL:EAP_HOME/vault/vault.keystore
Enter Keystore password: vault22
Enter Keystore password again: vault22
Values match
Enter 8 character salt:1234abcd
Enter iteration count as a number (Eg: 44):120
Enter Keystore Alias:vault
Initializing Vault
Oct 17, 2014 12:58:11 PM org.picketbox.plugins.vault.PicketBoxSecurityVault init
INFO: PBOX000361: Default Security Vault Implementation Initialized and Ready
Vault Configuration in AS7 config file:
********************************************
...
</extensions>
<vault>
  <vault-option name="KEYSTORE_URL" value="EAP_HOME/vault/vault.keystore"/>
  <vault-option name="KEYSTORE_PASSWORD" value="MASK-5dOaAVafCSd"/>
  <vault-option name="KEYSTORE_ALIAS" value="vault"/>
  <vault-option name="SALT" value="1234abcd"/>
  <vault-option name="ITERATION_COUNT" value="120"/>
  <vault-option name="ENC_FILE_DIR" value="EAP_HOME/vault/"/>
</vault><management> ...
********************************************
Vault is initialized and ready for use
Handshake with Vault complete

手順18.10 パスワード Vault コマンドの自動実行

すべてのパラメーターの値を一度に指定する場合は、このメソッドを使用してください。
  • オペレーティングシステムのコマンドラインインターフェイスを起動し、パスワード Vault コマンドを実行します。を参照してくださいパラメーター値リスト、プレースホルダーの値を好みの値に置き換えます。
    Red Hat Enterprise Linux または同様のオペレーティングシステムでは EAP_HOME/bin/vault.sh、Microsoft Windows Server では EAP_HOME\bin\vault.bat を使用します。
    vault.sh --keystore KEYSTORE_URL --keystore-password KEYSTORE_PASSWORD --alias KEYSTORE_ALIAS --vault-block VAULT_BLOCK --attribute ATTRIBUTE --sec-attr SEC-ATTR --enc-dir ENC_FILE_DIR --iteration ITERATION_COUNT --salt SALT

    例18.42 パスワード Vault コマンドの自動実行

    vault.sh --keystore EAP_HOME/vault/vault.keystore --keystore-password vault22 --alias vault --vault-block vb --attribute password --sec-attr 0penS3sam3 --enc-dir EAP_HOME/vault/ --iteration 120 --salt 1234abcd
    コマンド出力
    =========================================================================
    
      JBoss Vault
    
      JBOSS_HOME: EAP_HOME
    
      JAVA: java
    
    =========================================================================
    
    Oct 17, 2014 2:23:43 PM org.picketbox.plugins.vault.PicketBoxSecurityVault init
    INFO: PBOX000361: Default Security Vault Implementation Initialized and Ready
    Secured attribute value has been stored in vault. 
    Please make note of the following:
    ********************************************
    Vault Block:vb
    Attribute Name:password
    Configuration should be done as follows:
    VAULT::vb::password::1
    ********************************************
    Vault Configuration in AS7 config file:
    ********************************************
    ...
    </extensions>
    <vault>
      <vault-option name="KEYSTORE_URL" value="EAP_HOME/vault/vault.keystore"/>
      <vault-option name="KEYSTORE_PASSWORD" value="MASK-5dOaAVafCSd"/>
      <vault-option name="KEYSTORE_ALIAS" value="vault"/>
      <vault-option name="SALT" value="1234abcd"/>
      <vault-option name="ITERATION_COUNT" value="120"/>
      <vault-option name="ENC_FILE_DIR" value="EAP_HOME/vault/"/>
    </vault><management> ...
    ********************************************
    

結果

キーストアパスワードは、設定ファイルおよびデプロイメントで使用するためにマスクされています。さらに、vault は初期化され、使用できる状態になります。

18.6.6. パスワード vault を使用するよう JBoss EAP 6 を設定

概要

設定ファイルにあるパスワードや機密性の高いその他の属性をマスキングする前に、これらを保存し復号化するパスワード vault を JBoss EAP 6 が認識するようにする必要があります。

手順18.11 パスワード Vault の有効化

  • 「パスワード vault の初期化」 の管理 CLI コマンドを実行し、プレースホルダーの値をパスワード Vault コマンドの出力からの値に置き換えます。。
    注記
    Microsoft Windows Server を使用する場合は、通常 1 つを使用するファイルパスで 2 つの円記号 ( \\) を使用します。例: C:\\data\\vault\\vault.keystoreこれは、単一のバックスラッシュ (\) が文字エスケープに使用されるためです。
    /core-service=vault:add(vault-options=[("KEYSTORE_URL" => "PATH_TO_KEYSTORE"), ("KEYSTORE_PASSWORD" => "MASKED_PASSWORD"), ("KEYSTORE_ALIAS" => "ALIAS"), ("SALT" => "SALT"),("ITERATION_COUNT" => "ITERATION_COUNT"), ("ENC_FILE_DIR" => "ENC_FILE_DIR")])

例18.43 パスワード Vault の有効化

/core-service=vault:add(vault-options=[("KEYSTORE_URL" => "EAP_HOME/vault/vault.keystore"), ("KEYSTORE_PASSWORD" => "MASK-5dOaAVafCSd"), ("KEYSTORE_ALIAS" => "vault"), ("SALT" => "1234abcd"),("ITERATION_COUNT" => "120"), ("ENC_FILE_DIR" => "EAP_HOME/vault/")])

結果

JBoss EAP 6 が、パスワード Vault に保存されている、マスクされた文字列を復号化するように設定されました。パスワード Vault に文字列を追加して設定で使用するには、「パスワード Vault に Sensitive 文字列を保存します。」を参照してください。

18.6.7. パスワード Vault のカスタム実装を使用するよう JBoss EAP 6 を設定

概要

独自の SecurityVault 実装を使用して、設定ファイルのパスワードや機密性の高いその他の属性をマスクできます。

手順18.12 パスワード vault のカスタム実装の使用

  1. SecurityVault インターフェイスを実装するクラスを作成します。
  2. 直前の手順からクラスを含むモジュールを作成し、インターフェイスが SecurityVaultorg.picketbox で依存関係を指定します。
  3. 以下の属性を用いて vault 要素を追加して、JBoss EAP サーバー設定でカスタムのパスワード vault を有効にします。
    code
    SecurityVault を実装するクラスの完全修飾名。
    module
    カスタムクラスが含まれるモジュールの名前。
    オプションで vault-options パラメーターを使用して、パスワード Vault のカスタムクラスを初期化できます。

    例18.44 vault-options パラメーターを使用したカスタムクラスの初期化

    /core-service=vault:add(code="custom.vault.implementation.CustomSecurityVault", module="custom.vault.module", vault-options=[("KEYSTORE_URL" => "PATH_TO_KEYSTORE"), ("KEYSTORE_PASSWORD" => "MASKED_PASSWORD"), ("KEYSTORE_ALIAS" => "ALIAS"), ("SALT" => "SALT"),("ITERATION_COUNT" => "ITERATION_COUNT"), ("ENC_FILE_DIR" => "ENC_FILE_DIR")])

結果

パスワード vault のカスタム実装を使用して、マスクされた文字列が復号化されるよう JBoss EAP 6 が設定されます。

18.6.8. パスワード Vault に Sensitive 文字列を保存します。

概要

プレーンテキストの設定ファイルにパスワードやその他の機密文字列を含めると、セキュリティーリスクが伴います。セキュリティー上の理由からも、これらの文字列はパスワード vault に保存します。パスワード vault では、これらの文字列は、マスク化した形式で設定ファイル、管理 CLI コマンド、およびアプリケーションで参照できます。

パスワード vault は、各パラメーターの値を入力するように求められる対話的な方法、またはすべてのパラメーターの値がコマンドラインで指定される非対話的な方法で保存できます。それぞれの方法で同じ結果が得られるため、どちらの方法を選択してもかまいません。すべてのパラメーターの説明については、「パスワード vault の初期化」 を参照してください。

手順18.13 対話式での機密文字列の保存

各パラメーターの値の入力を求めるように設定する場合は、このメソッドを使用します。
  1. PasswordVault コマンドを実行します

    オペレーティングシステムのコマンドラインインターフェイスを起動し、パスワード Vault コマンドを実行します。Red Hat Enterprise Linux または同様のオペレーティングシステムでは EAP_HOME/bin/vault.sh、Microsoft Windows Server では EAP_HOME\bin\vault.bat を使用します。新しい対話セッションを開始するには、0 (ゼロ) と入力します。
  2. PasswordVault に関するプロンプトパラメーターを入力します

    プロンプトに従って必要な認証パラメーターを入力します。これらの値は、パスワード vault の作成時に提供された値と一致している必要があります。
    注記
    キーストアパスワードは、マスク形式ではなく、プレーンテキスト形式で指定する必要があります。
  3. 機密文字列に関するパラメーター入力を行います。

    機密文字列の保存を開始する場合は 0 (ゼロ) を入力します。プロンプトに従って必要なパラメーターを入力します。
  4. マスクされた文字列についての情報を書き留めておきます。

    メッセージは標準出力に出力され、vault ブロック、属性名、マスクされた文字列、設定の文字列の使用に関するアドバイスが表示します。この情報は、安全な場所にメモしておいてください。出力例を以下に示します。
    Vault Block:ds_Example1
    Attribute Name:password
    Configuration should be done as follows:
    VAULT::ds_Example1::password::1
    
  5. 対話式コンソールを終了します。

    3 と入力して、対話式コンソールを終了します。

例18.45 対話式での機密文字列の保存

=========================================================================

  JBoss Vault

  JBOSS_HOME: EAP_HOME/jboss-eap-6.4

  JAVA: java

=========================================================================

**********************************
****  JBoss Vault  ***************
**********************************
Please enter a Digit::   0: Start Interactive Session  1: Remove Interactive Session  2: Exit
0
Starting an interactive session
Enter directory to store encrypted files:11:18:46,086 INFO  [org.jboss.security] (management-handler-thread - 4) PBOX0                                                                  
Enter directory to store encrypted files:EAP_HOME/vault/ 
Enter Keystore URL:EAP_HOME/vault/vault.keystore
Enter Keystore password: 
Enter Keystore password again: 
Values match
Enter 8 character salt:1234abcd
Enter iteration count as a number (Eg: 44):120
Enter Keystore Alias:vault
Initializing Vault
Oct 21, 2014 11:20:49 AM org.picketbox.plugins.vault.PicketBoxSecurityVault init
INFO: PBOX000361: Default Security Vault Implementation Initialized and Ready
Vault Configuration in AS7 config file:
********************************************
...
</extensions>
<vault>
  <vault-option name="KEYSTORE_URL" value="EAP_HOME/vault/vault.keystore"/>
  <vault-option name="KEYSTORE_PASSWORD" value="MASK-5dOaAVafCSd"/>
  <vault-option name="KEYSTORE_ALIAS" value="vault"/>
  <vault-option name="SALT" value="1234abcd"/>
  <vault-option name="ITERATION_COUNT" value="120"/>
  <vault-option name="ENC_FILE_DIR" value="EAP_HOME/vault/"/>
</vault><management> ...
********************************************
Vault is initialized and ready for use
Handshake with Vault complete
Please enter a Digit::   0: Store a secured attribute  1: Check whether a secured attribute exists  2: Remove secured attribute  3: Exit
0
Task: Store a secured attribute
Please enter secured attribute value (such as password):
Please enter secured attribute value (such as password) again: 
Values match
Enter Vault Block:ds_Example1
Enter Attribute Name:password
Secured attribute value has been stored in vault. 
Please make note of the following:
********************************************
Vault Block:ds_Example1
Attribute Name:password
Configuration should be done as follows:
VAULT::ds_Example1::password::1
********************************************
Please enter a Digit::   0: Store a secured attribute  1: Check whether a secured attribute exists  2: Remove secured attribute  3: Exit

手順18.14 機密性の高い文字列の非対話式保存

すべてのパラメーターの値を一度に指定する場合は、このメソッドを使用してください。
  1. オペレーティングシステムのコマンドラインインターフェイスを起動し、パスワード Vault コマンドを実行します。Red Hat Enterprise Linux または同様のオペレーティングシステムでは EAP_HOME/bin/vault.sh、Microsoft Windows Server では EAP_HOME\bin\vault.bat を使用します。
    プレースホルダーの値を独自の値に置き換えます。パラメーター KEYSTORE_URLKEYSTORE_PASSWORD、および KEYSTORE_ALIAS の値は、パスワード vault の作成時に提供された値と一致している必要があります。
    注記
    キーストアパスワードは、マスク形式ではなく、プレーンテキスト形式で指定する必要があります。
    EAP_HOME/bin/vault.sh --keystore KEYSTORE_URL --keystore-password KEYSTORE_PASSWORD --alias KEYSTORE_ALIAS --vault-block VAULT_BLOCK --attribute ATTRIBUTE --sec-attr SEC-ATTR --enc-dir ENC_FILE_DIR --iteration ITERATION_COUNT --salt SALT
  2. マスクされた文字列についての情報を書き留めておきます。

    メッセージは標準出力に出力され、vault ブロック、属性名、マスクされた文字列、設定の文字列の使用に関するアドバイスが表示します。この情報は、安全な場所にメモしておいてください。出力例を以下に示します。
    Vault Block:vb
    Attribute Name:password
    Configuration should be done as follows:
    VAULT::vb::password::1
    

例18.46 パスワード Vault コマンドの自動実行

EAP_HOME/bin/vault.sh --keystore EAP_HOME/vault/vault.keystore --keystore-password vault22 --alias vault --vault-block vb --attribute password --sec-attr 0penS3sam3 --enc-dir EAP_HOME/vault/ --iteration 120 --salt 1234abcd
コマンド出力
=========================================================================

  JBoss Vault

  JBOSS_HOME: EAP_HOME

  JAVA: java

=========================================================================

Oct 22, 2014 9:24:43 AM org.picketbox.plugins.vault.PicketBoxSecurityVault init
INFO: PBOX000361: Default Security Vault Implementation Initialized and Ready
Secured attribute value has been stored in vault. 
Please make note of the following:
********************************************
Vault Block:vb
Attribute Name:password
Configuration should be done as follows:
VAULT::vb::password::1
********************************************
Vault Configuration in AS7 config file:
********************************************
...
</extensions>
<vault>
  <vault-option name="KEYSTORE_URL" value="EAP_HOME/vault/vault.keystore"/>
  <vault-option name="KEYSTORE_PASSWORD" value="vault22"/>
  <vault-option name="KEYSTORE_ALIAS" value="vault"/>
  <vault-option name="SALT" value="1234abcd"/>
  <vault-option name="ITERATION_COUNT" value="120"/>
  <vault-option name="ENC_FILE_DIR" value="EAP_HOME/vault/vault/"/>
</vault><management> ...
********************************************

結果

これで機密文字列が PasswordVault に保存され、設定ファイル、管理 CLI コマンド、およびアプリケーションでマスクされた形式で使用できるようになりました。

18.6.9. 暗号化した機密文字列を設定で使用

暗号化されている機密文字列は、マスクされた形式で設定ファイルまたは管理 CLI コマンド内で使用でき、式の指定も可能です。
特定のサブシステム内で式が許可されているかどうかを確認するには、そのサブシステムに対して以下の管理 CLI コマンドを実行します。
注記
管理対象ドメインのコマンドに、プレフィックス /host=HOST_NAME を追加します。
/core-service=SUBSYSTEM:read-resource-description(recursive=true)

例18.47 管理サブシステム内のすべてのリソースの説明を一覧表示します

/core-service=management:read-resource-description(recursive=true)
このコマンドの実行の出力から、expressions-allowed パラメーターの値を探します。これが 当てはまる 場合は、このサブシステムの設定内で式を使用できます。
以下の構文を使用して、プレーンテキスト文字列をマスクされたフォームに置き換えます。
${VAULT::VAULT_BLOCK::ATTRIBUTE_NAME::MASKED_STRING}

例18.48 マスクされたフォームでのパスワードを使用したデータソース定義

この例では、ボールトブロックは ds_ExampleDS であり、属性は パスワードです
...
  <subsystem xmlns="urn:jboss:domain:datasources:1.0">
    <datasources>
      <datasource jndi-name="java:jboss/datasources/ExampleDS" enabled="true" use-java-context="true" pool-name="H2DS">
        <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1</connection-url>
        <driver>h2</driver>
        <pool></pool>
        <security>
          <user-name>sa</user-name>
          <password>${VAULT::ds_ExampleDS::password::1}</password>
        </security>
      </datasource>
      <drivers>
         <driver name="h2" module="com.h2database.h2">
            <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
         </driver>
      </drivers>
    </datasources>
  </subsystem>
...

18.6.10. アプリケーションで暗号化した機密文字列の使用

パスワード vault に保存されている暗号化された文字列は、アプリケーションのソースコードで使用できます。

例18.49 vault されたパスワードを使用するサーブレット

この例は、サーブレットのソースコードの抜粋です。これは、プレーンテキストのパスワードではなく、データソース定義でのマスクされたパスワードの使用を示しています。プレーンテキストバージョンはコメントアウトされているため、違いがわかります。
/*@DataSourceDefinition(
        name = "java:jboss/datasources/LoginDS",
        user = "sa",
        password = "sa",
        className = "org.h2.jdbcx.JdbcDataSource",
        url = "jdbc:h2:tcp://localhost/mem:test"
)*/
@DataSourceDefinition(
        name = "java:jboss/datasources/LoginDS",
        user = "sa",
        password = "VAULT::DS::thePass::1",
        className = "org.h2.jdbcx.JdbcDataSource",
        url = "jdbc:h2:tcp://localhost/mem:test"
)

18.6.11. 機密文字列がパスワード vault 内にあるかどうかを確認します。

概要

パスワード vault に機密文字列を保存または使用する前に、その文字列がすでに保存されているかどうかを確認すると便利です。

このチェックは、ユーザーに各パラメーターの値の入力を求める対話形式または、コマンドラインですべてのパラメーターの値が提供される非対話形式のいずれかで実行できます。それぞれの方法で同じ結果が得られるため、どちらの方法を選択してもかまいません。

手順18.15 対話式での機密文字列の確認

各パラメーターの値の入力を求めるように設定する場合は、このメソッドを使用します。
  1. PasswordVault コマンドを実行します

    オペレーティングシステムのコマンドラインインターフェイスを起動し、パスワード Vault コマンドを実行します。Red Hat Enterprise Linux または同様のオペレーティングシステムでは EAP_HOME/bin/vault.sh、Microsoft Windows Server では EAP_HOME\bin\vault.bat を使用します。新しい対話セッションを開始するには、0 (ゼロ) と入力します。
  2. PasswordVault に関するプロンプトパラメーターを入力します

    プロンプトに従って必要な認証パラメーターを入力します。これらの値は、パスワード vault の作成時に提供された値と一致している必要があります。
    注記
    キーストアパスワードは、マスク形式ではなく、プレーンテキスト形式で指定する必要があります。
  3. 1 を入力してセキュリティー保護された属性が存在するかどうかを確認します。
  4. 機密文字列を保存する vault ブロックの名前を入力します。
  5. チェックする機密文字列の名前を入力します。

結果

機密文字列が指定された vault ブロックに保存されている場合は、以下のような確認メッセージが表示されます。

A value exists for (VAULT_BLOCK, ATTRIBUTE)
機密文字列が指定ブロックに保存されていない場合は、以下のようなメッセージが出力されます。
No value has been store for (VAULT_BLOCK, ATTRIBUTE)

例18.50 対話式での機密文字列の確認

=========================================================================

  JBoss Vault

  JBOSS_HOME: EAP_HOME

  JAVA: java

=========================================================================

**********************************
****  JBoss Vault  ***************
**********************************
Please enter a Digit::   0: Start Interactive Session  1: Remove Interactive Session  2: Exit
0
Starting an interactive session
Enter directory to store encrypted files:EAP_HOME/vault
Enter Keystore URL:EAP_HOME/vault/vault.keystore
Enter Keystore password:
Enter Keystore password again:
Values match
Enter 8 character salt:1234abcd
Enter iteration count as a number (Eg: 44):120
Enter Keystore Alias:vault
Initializing Vault
Oct 22, 2014 12:53:56 PM org.picketbox.plugins.vault.PicketBoxSecurityVault init
INFO: PBOX000361: Default Security Vault Implementation Initialized and Ready
Vault Configuration in AS7 config file:
********************************************
...
</extensions>
<vault>
  <vault-option name="KEYSTORE_URL" value="EAP_HOME/vault/vault.keystore"/>
  <vault-option name="KEYSTORE_PASSWORD" value="MASK-5dOaAVafCSd"/>
  <vault-option name="KEYSTORE_ALIAS" value="vault"/>
  <vault-option name="SALT" value="1234abcd"/>
  <vault-option name="ITERATION_COUNT" value="120"/>
  <vault-option name="ENC_FILE_DIR" value="EAP_HOME/vault/"/>
</vault><management> ...
********************************************
Vault is initialized and ready for use
Handshake with Vault complete
Please enter a Digit::   0: Store a secured attribute  1: Check whether a secured attribute exists  2: Remove secured attribute  3: Exit
1
Task: Verify whether a secured attribute exists
Enter Vault Block:vb
Enter Attribute Name:password
A value exists for (vb, password)
Please enter a Digit::   0: Store a secured attribute  1: Check whether a secured attribute exists  2: Remove secured attribute  3: Exit

手順18.16 機密性の高い文字列の非対話式チェック

すべてのパラメーターの値を一度に指定する場合は、このメソッドを使用してください。すべてのパラメーターの説明については、「パスワード vault の初期化」 を参照してください。
  • オペレーティングシステムのコマンドラインインターフェイスを起動し、パスワード Vault コマンドを実行します。Red Hat Enterprise Linux または同様のオペレーティングシステムでは EAP_HOME/bin/vault.sh、Microsoft Windows Server では EAP_HOME\bin\vault.bat を使用します。
    プレースホルダーの値を独自の値に置き換えます。パラメーター KEYSTORE_URLKEYSTORE_PASSWORD-password、および KEYSTORE_ALIAS の値は、パスワード vault の作成時に提供された値と一致している必要があります。
    注記
    キーストアパスワードは、マスク形式ではなく、プレーンテキスト形式で指定する必要があります。
    EAP_HOME/bin/vault.sh --keystore KEYSTORE_URL --keystore-password KEYSTORE_PASSWORD --alias KEYSTORE_ALIAS --check-sec-attr --vault-block VAULT_BLOCK --attribute ATTRIBUTE --enc-dir ENC_FILE_DIR --iteration ITERATION_COUNT --salt SALT

結果

機密文字列が指定された vault ブロックに保存されると、以下のメッセージが出力されます。

Password already exists.
値が指定のブロックに保存されていない場合は、以下のメッセージが表示されます。
Password doesn't exist.

18.6.12. パスワード vault からの機密文字列の削除

概要

セキュリティー上の理由から、機密文字列が不要になった場合は、パスワード vault から削除することが推奨されます。たとえば、アプリケーションの使用を停止する場合、データソース定義で使用される機密文字列を同時に削除する必要があります。

前提条件

パスワード vault から機密文字列を削除するには、JBoss EAP の設定で使用されるかどうかを確認します。これを行う 1 つの方法は、grep ユーティリティーを使用して、マスクされた文字列のインスタンスの設定ファイルを検索することです。Red Hat Enterprise Linux (および同様のオペレーティングシステム) では、grep はデフォルトでインストールされますが、Microsoft Windows の場合は手動でインストールする必要があります。

パスワード Vault ユーティリティーには、対話型と非対話型の 2 つのモードがあります。対話型モードでは、各パラメーターの値の入力を求められます。非対話型モードでは、1 つのコマンドですべてのパラメーターの値を指定する必要があります。

手順18.17 対話式での機密文字列の削除

各パラメーターの値の入力を求めるように設定する場合は、このメソッドを使用します。
  1. PasswordVault コマンドを実行します

    オペレーティングシステムのコマンドラインインターフェイスを起動し、EAP_HOME/bin/vault.sh (Red Hat Enterprise Linux および同様のオペレーティングシステム) または EAP_HOME\bin\vault.bat (Microsoft Windows Server 上) を実行します。新しい対話セッションを開始するには、0 (ゼロ) と入力します。
  2. 認証の詳細を提供する

    プロンプトに従って必要な認証パラメーターを入力します。これらの値は、パスワード vault の作成時に提供された値と一致している必要があります。
    注記
    キーストアパスワードは、マスク形式ではなく、プレーンテキスト形式で指定する必要があります。
  3. 2 と入力して、セキュアな属性を削除する オプションを選択します。
  4. 機密文字列を保存する vault ブロックの名前を入力します。
  5. 削除する機密文字列の名前を入力します。

結果

機密文字列が正常に削除されると、以下のような確認メッセージが出力されます。

Secured attribute [VAULT_BLOCK::ATTRIBUTE] has been successfully removed from vault
機密文字列が削除されない場合は、以下のようなメッセージが表示されます。
Secured attribute [VAULT_BLOCK::ATTRIBUTE] was not removed from vault, check whether it exist

例18.51 対話式での機密文字列の削除

**********************************
****  JBoss Vault  ***************
**********************************
Please enter a Digit::   0: Start Interactive Session  1: Remove Interactive Session  2: Exit
0
Starting an interactive session
Enter directory to store encrypted files:EAP_HOME/vault/
Enter Keystore URL:EAP_HOME/vault/vault.keystore
Enter Keystore password: 
Enter Keystore password again: 
Values match
Enter 8 character salt:1234abcd
Enter iteration count as a number (Eg: 44):120
Enter Keystore Alias:vault
Initializing Vault
Dec 23, 2014 1:40:56 PM org.picketbox.plugins.vault.PicketBoxSecurityVault init
INFO: PBOX000361: Default Security Vault Implementation Initialized and Ready
Vault Configuration in configuration file:
********************************************
...
</extensions>
<vault>
  <vault-option name="KEYSTORE_URL" value="EAP_HOME/vault/vault.keystore"/>
  <vault-option name="KEYSTORE_PASSWORD" value="MASK-5dOaAVafCSd"/>
  <vault-option name="KEYSTORE_ALIAS" value="vault"/>
  <vault-option name="SALT" value="1234abcd"/>
  <vault-option name="ITERATION_COUNT" value="120"/>
  <vault-option name="ENC_FILE_DIR" value="EAP_HOME/vault/"/>
</vault><management> ...
********************************************
Vault is initialized and ready for use
Handshake with Vault complete
Please enter a Digit::  0: Store a secured attribute  1: Check whether a secured attribute exists  2: Remove secured attribute  3: Exit
2
Task: Remove secured attribute
Enter Vault Block:craft
Enter Attribute Name:password
Secured attribute [craft::password] has been successfully removed from vault

手順18.18 機密性の高い文字列の非対話式削除

すべてのパラメーターの値を一度に指定する場合は、このメソッドを使用してください。すべてのパラメーターの説明については、「パスワード vault の初期化」 を参照してください。
  • オペレーティングシステムのコマンドラインインターフェイスを起動し、パスワード Vault コマンドを実行します。Red Hat Enterprise Linux または同様のオペレーティングシステムでは EAP_HOME/bin/vault.sh、Microsoft Windows Server では EAP_HOME\bin\vault.bat を使用します。
    プレースホルダーの値を独自の値に置き換えます。パラメーター KEYSTORE_URLKEYSTORE_PASSWORD、および KEYSTORE_ALIAS の値は、パスワード vault の作成時に提供された値と一致している必要があります。
    注記
    キーストアパスワードは、マスク形式ではなく、プレーンテキスト形式で指定する必要があります。
    EAP_HOME/bin/vault.sh --keystore KEYSTORE_URL --keystore-password KEYSTORE_PASSWORD --alias KEYSTORE_ALIAS --remove-sec-attr --vault-block VAULT_BLOCK --attribute ATTRIBUTE --enc-dir ENC_FILE_DIR --iteration ITERATION_COUNT --salt SALT

結果

機密文字列が正常に削除されると、以下のような確認メッセージが出力されます。

Secured attribute [VAULT_BLOCK::ATTRIBUTE] has been successfully removed from vault
機密文字列が削除されない場合は、以下のようなメッセージが表示されます。
Secured attribute [VAULT_BLOCK::ATTRIBUTE] was not removed from vault, check whether it exist

例18.52 機密性の高い文字列の非対話式削除

./vault.sh --keystore EAP_HOME/vault/vault.keystore --keystore-password vault22 --alias vault --remove-sec-attr --vault-block craft --attribute password --enc-dir ../vault/ --iteration 120 --salt 1234abcd
=========================================================================

  JBoss Vault

  JBOSS_HOME: EAP_HOME

  JAVA: java

=========================================================================

Dec 23, 2014 1:54:24 PM org.picketbox.plugins.vault.PicketBoxSecurityVault init
INFO: PBOX000361: Default Security Vault Implementation Initialized and Ready
Secured attribute [craft::password] has been successfully removed from vault

18.7. Java Authorization Contract for Containers (JACC)

18.7.1. JACC (Java Authorization Contract for Containers)

JACC (Java Authorization Contract for Containers) はコンテナーと承認サービスプロバイダー間のコントラクトを定義する規格であり、これによりコンテナーによって使用されるプロバイダーの実装が可能になります。これは JSR-115 で定義されています。これは、の Java Community Process Web サイトにあり http://jcp.org/en/jsr/detail?id=115 ます。これは、JavaEE バージョン 1.3 以降のコア JavaEnterprise Edition (Java EE) 仕様の一部です。
JBoss EAP 6 はセキュリティーサブシステムのセキュリティー機能内に JACC のサポートを実装します。

18.7.2. JACC (Java Authorization Contract for Containers) のセキュリティーの設定

JACC (Java Authorization Contract for Containers) を設定するには、適切なモジュールでセキュリティードメインを設定し、適切なパラメーターが含まれるよう jboss-web.xml を編集する必要があります。

セキュリティードメインへの JACC サポートの追加

セキュリティードメインに JACC サポートを追加するには、required フラグセットで JACC 承認ポリシーをセキュリティードメインの承認スタックへ追加します。以下は JACC サポートを持つセキュリティードメインの例です。ただし、セキュリティードメインは、XML で直接設定するのではなく、管理コンソールまたは管理 CLI で設定します。

<security-domain name="jacc" cache-type="default">
    <authentication>
        <login-module code="UsersRoles" flag="required">
        </login-module>
    </authentication>
    <authorization>
        <policy-module code="JACC" flag="required"/>
    </authorization>
</security-domain>

JACC を使用するよう Web アプリケーションを設定

jboss-web.xml ファイルは デプロイメントの WEB-INF/ ディレクトリーに存在し、Web コンテナーに対する追加の JBoss 固有の設定を格納し、上書きします。JACC が有効になっているセキュリティードメインを使用するには、<security-domain> 要素が含まれるようにし、さらに <use-jboss-authorization> 要素を true に設定する必要があります。次のアプリケーションは、上記の JACC セキュリティードメインを使用するように適切に設定されています。

<jboss-web>
    <security-domain>jacc</security-domain>
    <use-jboss-authorization>true</use-jboss-authorization>
</jboss-web>

JACC を使用するよう EJB アプリケーションを設定

セキュリティードメインと JACC を使用するよう EJB を設定する方法は Web アプリケーションの場合とは異なります。EJB の場合、ejb-jar.xml 記述子にてメソッドまたはメソッドのグループ上で メソッドパーミッション を宣言できます。<ejb-jar> 要素内では、すべての子 <method-permission> 要素に JACC ロールに関する情報が含まれます。詳細は、設定例を参照してください。EJBMethodPermission クラスは Java Enterprise Edition 6 API の一部であり、で http://docs.oracle.com/javaee/6/api/javax/security/jacc/EJBMethodPermission.html 説明されています。

例18.53 EJB の JACC メソッドパーミッション例

<ejb-jar>
  <assembly-descriptor>
    <method-permission>
      <description>The employee and temp-employee roles may access any method of the EmployeeService bean </description>
      <role-name>employee</role-name>
      <role-name>temp-employee</role-name>
      <method>
        <ejb-name>EmployeeService</ejb-name>
        <method-name>*</method-name>
      </method>
    </method-permission>
  </assembly-descriptor>
</ejb-jar>
Web アプリケーションと同様にセキュリティードメインを使用して EJB の認証および承認メカニズムを指定することも可能です。セキュリティードメインは <security> 子要素の jboss-ejb3.xml 記述子に宣言されます。セキュリティードメインの他に、EJB が実行されるプリンシパルを変更する <run-as-principal> を指定することもできます。

例18.54 EJB におけるセキュリティードメイン宣言の例

<ejb-jar> 
	<assembly-descriptor>
		<security>
  		<ejb-name>*</ejb-name>
  		<security-domain>myDomain</security-domain>
  		<run-as-principal>myPrincipal</run-as-principal>
		</security>
 	</assembly-descriptor>
</ejb-jar>

18.8. JASPI (Java Authentication SPI for Containers)

18.8.1. JASPI (Java Authentication SPI for Containers) のセキュリティー

Java Authentication SPI for Containers (JASPI または JASPIC) は Java アプリケーションのプラグ可能なインターフェースであり、Java Community Process の JSR-196 に定義されています。JACC は、Java コミュニティープロセスの JSR-196 で定義されています。仕様の詳細は、http://www.jcp.org/en/jsr/detail?id=196 を参照してください。

18.8.2. JASPI (Java Authentication SPI for Containers) のセキュリティーの設定

JASPI プロバイダーに対して認証するには、セキュリティードメインに <authentication-jaspi> 要素を追加します。設定は標準的な認証モジュールと似ていますが、ログインモジュール要素は <login-module-stack> 要素で囲まれています。設定の構成は次のとおりです。

例18.55 authentication-jaspi 要素の構造

<authentication-jaspi>
	<login-module-stack name="...">
	  <login-module code="..." flag="...">
	    <module-option name="..." value="..."/>
	  </login-module>
	</login-module-stack>
	<auth-module code="..." login-module-stack-ref="...">
	  <module-option name="..." value="..."/>
	</auth-module>
</authentication-jaspi>

ログインモジュール自体は標準的な認証モジュールと全く同じように設定されます。
Web ベースの管理コンソールは JASPI 認証モジュールの設定を公開しないため、設定を EAP_HOME/domain/configuration/domain.xml または EAP_HOME/standalone/configuration/standalone.xml に直接追加する前に、JBoss EAP 6 を完全に停止する必要があります。。

第19章 シングルサインオン (SSO)

19.1. Web アプリケーションのシングルサインオン (SSO) について

概要

シングルサインオン (SSO) を使用すると、1 つのリソースへの認証により、他のリソースへのアクセスを暗黙的に許可できます。

クラスター化および非クラスター化 SSO

非クラスターか SSO は、同じ仮想ホストでアプリケーションへの承認情報の共有を制限します。また、ホストに障害が発生した場合の回復性はありません。クラスター化された SSO データは、複数のホスト内のアプリケーション間で共有でき、フェイルオーバーに対して回復力があります。さらに、クラスター化された SSO はロードバランサーからリクエストを受信できます。

SSO のしくみ

リソースが保護されていない場合、ユーザーは認証をまったく要求されません。ユーザーが保護されたリソースにアクセスする場合、ユーザーは認証する必要があります。

承認に成功した後、ユーザーに関連するロールが保存され、関連する他のリソースすべての承認に使用されます。
ユーザーがアプリケーションからログアウトした場合、またはアプリケーションがプログラムでセッションを無効にした場合、永続化された認証データはすべて削除され、プロセスが最初からやり直されます。
他のセッションがまだ有効である場合、セッションタイムアウトによって SSO セッションが無効になることはありません。

19.2. Web アプリケーションのクラスター化されたシングルサインオン (SSO) について

シングルサインオン (SSO) は、ユーザーが単一の Web アプリケーションに対して認証する機能であり、認証が成功すると、アプリケーションごとにプロンプトを表示しなくても、他の複数のアプリケーションに対して正常に認証されます。クラスター化された SSO は、認証情報をクラスター化されたキャッシュに保存します。これにより、複数の異なるサーバー上のアプリケーションが情報を共有できるようになり、ホストの 1 つの障害に対して情報の回復力も高まります。
サポートされている SSO メカニズムの一部 (Kerberos、PicketLink SAML など) は、正しく機能するためにバルブを必要とします。バルブはサーブレットフィルターと同様の機能を備えていますが、コンテナー管理認証の前に処理されます。Web アプリケーションのバルブは、jboss-web.xml デプロイメント記述子で定義できます。

19.3. 適切な SSO 実装を選択する

JBoss EAP 6 は、Java Enterprise Edition (EE) アプリケーションを実行します。これは、Web アプリケーション、EJB アプリケーション、Web サービス、またはその他のタイプの場合があります。シングルサインオン (SSO) を使用すると、これらのアプリケーション間でセキュリティーコンテキストと ID 情報を伝達できます。いくつかの SSO ソリューションが利用可能ですが、適切なソリューションの選択は要件によって異なります。
クラスター化された web アプリケーションとクラスター化された SSO には明らかな違いがある点に注意してください。クラスター化された web アプリケーションは、そのアプリケーションをホストするための負荷を分散するためにクラスターのノード全体で分散されます。分散可能とマークされている場合には、新しいセッションと既存セッションの変更はすべてクラスターの別のメンバーへレプリケートされます。アプリケーションは、web.xml デプロイメント記述子の <distributable/> タグを使用して、クラスターノード全体に分散できるものとしてマークされます。クラスター化された SSO は、アプリケーション自体がクラスター化されているかどうかに関わらず、セキュリティーコンテキストとアイデンティティー情報のレプリケーションを可能にします。これらのテクノロジーは一緒に使用できますが、別々の概念です。

Kerberos ベースのデスクトップ SSO

組織で既に MicrosoftActiveDirectory などの Kerberos ベースの認証および承認システムを使用している場合は、同じシステムを使用して、Active Directory で実行されているエンタープライズアプリケーションに対して透過的に認証できます。

非クラスター化 Web アプリケーション SSO

1 つのインスタンスで複数のアプリケーションを実行していて、それらのアプリケーションに対して SSO セッションレプリケーションを有効にする必要がある場合、非クラスター化 SSO が要件を満たします。

クラスター化された Web アプリケーション SSO

クラスター全体で単一のアプリケーションまたは複数のアプリケーションを実行していて、それらのアプリケーションの SSO セッションレプリケーションを有効にする必要がある場合、クラスター化された SSO は要件を満たします。

19.4. Web アプリケーションでシングルサインオン (SSO) を使用する

概要

シングルサインオン (SSO) 機能は、Web および Infinispan サブシステムによって提供されます。この手順を使用して、Web アプリケーションで SSO を設定します。

前提条件

  • 認証とアクセスを処理する設定済みのセキュリティードメイン。
  • Theinfinispanサブシステム。デフォルトでは、管理対象ドメインとスタンドアロンサーバーのすべてのプロファイルに存在します。
  • Thewebcache-containerおよび SSO レプリケートキャッシュ。初期設定ファイルにはすでにwebcache-container、および一部の設定には、SSO レプリケートされたキャッシュもすでに含まれています。次のコマンドを使用して、SSO レプリケートキャッシュを確認して有効にします。これらのコマンドはha管理対象ドメインのプロファイル。スタンドアロンサーバーの場合は、コマンドを変更して別のプロファイルを使用するか、コマンドの /profile=ha 部分を削除できます。

    例19.1 を確認してくださいwebキャッシュコンテナー

    上記のプロファイルと設定には、webデフォルトでは cache-container。次のコマンドを使用して、その存在を確認します。別のプロファイルを使用する場合は、ha の代わりにその名前に置き換えてください。
    /profile=ha/subsystem=infinispan/cache-container=web/:read-resource(recursive=false,proxies=false,include-runtime=false,include-defaults=true)
    結果が 成功 した場合、サブシステムが存在します。それ以外の場合は、追加する必要があります。

    例19.2 追加しますwebキャッシュコンテナー

    次の 3 つのコマンドを使用して、webcache-container を設定に追加します。プロファイルの名前、およびその他のパラメーターを必要に応じて変更します。ここでのパラメーターは、デフォルト設定で使用されるパラメーターです。
    /profile=ha/subsystem=infinispan/cache-container=web:add(aliases=["standard-session-cache"],default-cache="repl",module="org.jboss.as.clustering.web.infinispan")
    /profile=ha/subsystem=infinispan/cache-container=web/transport=TRANSPORT:add(lock-timeout=60000)
    /profile=ha/subsystem=infinispan/cache-container=web/replicated-cache=repl:add(mode="ASYNC",batching=true)

    例19.3 を確認してくださいSSOレプリケートされたキャッシュ

    次の管理 CLI コマンドを実行します。
    /profile=ha/subsystem=infinispan/cache-container=web/:read-resource(recursive=true,proxies=false,include-runtime=false,include-defaults=true)
    次のような出力を探します。 "sso" => {
    見つからない場合は、SSO レプリケートキャッシュが設定に存在しません。

    例19.4 追加しますSSOレプリケートされたキャッシュ

    /profile=ha/subsystem=infinispan/cache-container=web/replicated-cache=sso:add(mode="SYNC", batching=true)

管理対象ドメインのクラスター化された SSO を設定する

web サブシステムは SSO を使用するように設定する必要があります。次のコマンドは、default-host と呼ばれる仮想サーバーと cookie ドメイン domain.com で SSO を有効にします。キャッシュ名は sso であり、再認証は無効になっています。
/profile=ha/subsystem=web/virtual-server=default-host/sso=configuration:add(cache-container="web",cache-name="sso",reauthenticate="false",domain="domain.com")
SSO 情報を共有する各アプリケーションは、jboss-web.xml デプロイメント記述子で同じ <security-domain> を使用し、web.xml 設定ファイルで同じレルムを使用するように設定する必要があります。

スタンドアロンサーバーのクラスター化または非クラスター化 SSO の設定

設定、設定ssoサーバープロファイルの Web サブシステムの下。TheClusteredSingleSignOnバージョンは属性のときに使用されますcache-container存在する、そうでない場合は標準SingleSignOnクラスが使用されます。

例19.5 非クラスター化 SSO 設定の例

/subsystem=web/virtual-server=default-host/sso=configuration:add(reauthenticate="false")

セッションを無効にする

アプリケーションは、メソッドを呼び出すことにより、プログラムでセッションを無効にすることができますjavax.servlet.http.HttpSession.invalidate()

19.5. Kerberos について

Kerberos はクライアントサーバーアプリケーションのネットワーク認証プロトコルです。これは、秘密鍵の対称暗号を使用して、安全な方法でセキュアでないネットワーク全体で認証を可能にします。
Kerberos はチケットと呼ばれるセキュリティートークンを使用します。セキュアなサービスを利用するためには、ユーザーはネットワーク上のサーバーで動作するサービスである Ticket Granting Service (TGS) からチケットを入手する必要があります。チケットの取得後、同じネットワークで実行される別のサービスである認証サービス (AS) からサービスチケット (ST) を要求します。次に、ST を使用して、使用するサービスに対して認証します。TGS と AS は、ともに KDC (Key Distribution Center) と呼ばれる囲い込みサービスの内部で動作します。
Kerberos は、クライアントサーバーデスクトップ環境での使用を目的としているため、通常は web アプリケーションやシンクライアント環境では使用されません。しかし、デスクトップの認証に Kerberos システムをすでに使用しているため、web アプリケーション用のシステムを作成せずに、既存のシステムを再使用したい組織が多くあります。Kerberos は Microsoft Active Directory には欠かせない要素で、Red Hat Enterprise Linux 環境の多くでも使用されています。

19.6. SPNEGO について

SPNEGO (Simple and Protected GSS_API Negotiation Mechanism) は Web アプリケーションで使用するために Kerberos ベースのシングルサインオン環境を拡張するメカニズムを提供します。
web ブラウザーなどのクライアントコンピューター上のアプリケーションが web サーバーの保護されたページにアクセスしようとすると、サーバーは承認が必要であることを伝えます。その後、アプリケーションは Kerberos Key Distribution Center (KDC) にサービスチケットを要求します。チケットの取得後、アプリケーションはこのチケットをSPNEGO 向けにフォーマットされたリクエストにラップし、ブラウザーを介して web アプリケーションに返信します。デプロイされた web アプリケーションを実行している web コンテナーはリクエストをアンパックし、チケットを認証します。認証に成功するとアクセスが許可されます。
SPNEGO は、Red Hat Enterprise Linux に含まれる Kerberos サービスや Microsoft Active Directory には不可欠な Kerberos サーバーなど、全タイプの Kerberos プロバイダーと動作します。

19.7. Microsoft Active Directory について

Microsoft Active Directory (AD) は、Microsoft が開発したディレクトリーサービスで、Microsoft Windows ドメインでユーザーとコンピューターを認証します。Microsoft Windows Server の一部として含まれています。Microsoft Windows Server のコンピューターは、ドメインコントローラーと呼ばれます。Samba サービスを実行している Red Hat Enterprise Linux サーバーは、このタイプのネットワークのドメインコントローラーとしても機能します。
Active Directory は、共に動作する 3 つのコアテクノロジーに依存します。
  • ユーザー、コンピューター、パスワード、およびその他のリソースに関する情報を格納する軽量 Directory Access Protocol (LDAP)。
  • Kerberos: ネットワーク上でセキュアな認証を提供します。
  • ドメインネームサービス (DNS): ネットワーク上のコンピューターおよびその他のデバイスにおける IP アドレスとホスト名との間のマッピングを提供します。

19.8. Web アプリケーション用に Kerberos または MicrosoftActiveDirectory デスクトップ Active Directory を設定する

はじめに

Microsoft Active Directory などの組織の既存の Kerberos ベースの認証および承認インフラストラクチャーを使用して Web または EJB アプリケーションを認証するには、JBoss EAP 6 に組み込まれている JBoss ネゴシエーション機能を使用できます。Web アプリケーションを適切に設定した場合、デスクトップまたはネットワークへのログインが成功すれば、Web アプリケーションに対して透過的に認証できるため、追加のログインプロンプトは必要ありません。

プラットフォームの以前のバージョンとの違い

JBoss EAP 6 と、これまでのバージョンには顕著な違いがいくつかあります。

  • セキュリティードメインは、管理対象ドメインの各プロファイル、またはスタンドアロンサーバーごとに設定されます。これらはデプロイメント自体には含まれません。デプロイメントが使用するセキュリティードメインは、デプロイメントの jboss-web.xml ファイルまたは jboss-ejb3.xml ファイルで指定されます。
  • セキュリティープロパティーはセキュリティードメインの一部として設定されます。これらはデプロイメントには含まれません。
  • デプロイメントの一部としてオーセンティケーターをオーバーライドすることはできなくなりました。ただし、jboss-web.xml 記述子に NegotiationAuthenticator バルブを追加して、同じ効果を実現することができます。バルブを使用するには、<security-constraint> および <login-config> 要素を web.xml に定義する必要があります。これらの要素は、セキュアなリソースを決定するのに使用されます。しかし、選択した auth-method は jboss-web.xml の NegotiationAuthenticator バルブによって上書きされます。
  • セキュリティードメインの CODE 属性は、完全修飾クラス名ではなく、単純な名前を使用するようになりました。以下の表は、JBoss Negotiation に使用されるクラスとそれらのクラスとの間のマッピングを示しています。

表19.1 ログインモジュールコードとクラス名

簡単な名前 クラス名 目的
Kerberos
com.sun.security.auth.module.Krb5LoginModule
com.ibm.security.auth.module.Krb5LoginModule
Oracle JDK を使用する場合の Kerberos ログインモジュール
IBMJava 開発キットを使用する場合の Kerberos ログインモジュール
SPNEGO org.jboss.security.negotiation.spnego.SPNEGOLoginModule Web アプリケーションが Kerberos 認証サーバーに対して認証できるようにするメカニズム。
AdvancedLdap org.jboss.security.negotiation.AdvancedLdapLoginModule Microsoft Active Directory 以外の LDAP サーバーで使用されます。
AdvancedAdLdap org.jboss.security.negotiation.AdvancedADLoginModule Microsoft Active Directory LDAP サーバーで使用されます。

JBoss Negotiation Toolkit

JBoss Negotiation Toolkit は、から https://community.jboss.org/servlet/JiveServlet/download/16876-2-34629/jboss-negotiation-toolkit.war ダウンロードできるデバッグツールです。これは、アプリケーションを実稼働環境にデプロイする前に認証メカニズムのデバッグおよびテストに役立つ追加ツールとして提供されます。これはサポート対象のツールではありませんが、SPENEGO を web アプリケーションに対して設定するのは難しいこともあるため、大変便利なツールと言えます。

手順19.1 Web または EJB アプリケーションの SSO 認証を設定する

  1. サーバーの ID を表す 1 つのセキュリティードメインを設定します。必要に応じてシステムプロパティーを設定します。

    最初のセキュリティードメインは、コンテナー自体をディレクトリーサービスに対して認証します。実際のユーザーは関与しないため、ある種の静的ログインメカニズムを受け入れるログインモジュールを使用する必要があります。この例では静的プリンシパルを使用し、クレデンシャルが含まれるキータブファイルを参照します。
    XML コードはわかりやすくするためにここに示されていますが、セキュリティードメインを設定するには管理コンソールまたは管理 CLI を使用する必要があります。
    <security-domain name="host" cache-type="default">
       <authentication>
          <login-module code="Kerberos" flag="required">
             <module-option name="storeKey" value="true"/>
             <module-option name="useKeyTab" value="true"/>
             <module-option name="principal" value="host/testserver@MY_REALM"/>
             <module-option name="keyTab" value="/home/username/service.keytab"/>
             <module-option name="doNotPrompt" value="true"/>
             <module-option name="debug" value="false"/>
          </login-module>
       </authentication>
    </security-domain>
  2. 1 つまたは複数の Web アプリケーションを保護するために、2 番目のセキュリティードメインを設定します。必要に応じてシステムプロパティーを設定します。

    2 番目のセキュリティードメインは、Kerberos または SPNEGO 認証サーバーに対して個々のユーザーを認証するために使用されます。ユーザーを認証するために少なくとも 1 つのログインモジュールが必要であり、ユーザーに適用するロールを検索するために別のログインモジュールが必要です。次の XML コードは、SPNEGO セキュリティードメインの例を示しています。これには、ロールを個々のユーザーにマップするための承認モジュールが含まれています。認証サーバー自体でロールを検索するモジュールを使用することもできます。
    <security-domain name="SPNEGO" cache-type="default">
       <authentication>
          <!-- Check the username and password -->
          <login-module code="SPNEGO"  flag="requisite">
             <module-option name="password-stacking" value="useFirstPass"/>
             <module-option name="serverSecurityDomain" value="host"/>
          </login-module>
          <!-- Search for roles -->
          <login-module code="UsersRoles" flag="required">
             <module-option name="password-stacking" value="useFirstPass" />
             <module-option name="usersProperties" value="spnego-users.properties" />
             <module-option name="rolesProperties" value="spnego-roles.properties" />
          </login-module> 
       </authentication>
    </security-domain>
  3. web.xml で security-constraint と login-config を指定します

    web.xml 記述子には、セキュリティーの制約とログイン設定に関する情報が含まれています。以下は、それぞれの値の例です。
    <security-constraint>
       <display-name>Security Constraint on Conversation</display-name>
       <web-resource-collection>
          <web-resource-name>examplesWebApp</web-resource-name>
          <url-pattern>/*</url-pattern>
       </web-resource-collection>
       <auth-constraint>
       <role-name>RequiredRole</role-name>
       </auth-constraint>
    </security-constraint>
    
    <login-config>
       <auth-method>SPNEGO</auth-method>
       <realm-name>SPNEGO</realm-name>
    </login-config>
     
    <security-role>
       <description> role required to log in to the Application</description>
       <role-name>RequiredRole</role-name>
    </security-role>
  4. jboss-web.xml 記述子でセキュリティードメインおよびその他の設定を指定します。

    デプロイメントの jboss-web.xml 記述子でクライアント側のセキュリティードメイン (この例では 2 番目) の名前を指定して、このセキュリティードメインを使用するようにアプリケーションに指示します。
    オーセンティケーターを直接オーバーライドすることはできなくなりました。代わりに、必要に応じて、NegotiationAuthenticator をバルブとして jboss-web.xml 記述子に追加できます。<jacc-star-role-allow> を使用すると、アスタリスク (*) 文字を使用して複数のロール名と一致させることができます。これはオプションです。
    <jboss-web>
       <security-domain>SPNEGO</security-domain>
       <valve>
          <class-name>org.jboss.security.negotiation.NegotiationAuthenticator</class-name>
       </valve>
       <jacc-star-role-allow>true</jacc-star-role-allow>
    </jboss-web>
  5. アプリケーションの MANIFEST.MF に依存関係を追加して、ネゴシエーションクラスを見つけます。

    Web アプリケーションにはクラスへの依存が必要ですorg.jboss.security.negotiationJBoss Negotiation クラスを見つけるために、デプロイメントの META-INF/MANIFEST.MF マニフェストに追加されます。以下に、適切にフォーマットされたエントリーを示します。
    Manifest-Version: 1.0
    Build-Jdk: 1.6.0_24
    Dependencies: org.jboss.security.negotiation
    • 別の方法として、META-INF/jboss-deployment-structure.xml ファイルを編集して、アプリケーションに依存関係を追加します。
      <?xml version="1.0" encoding="UTF-8"?>
      <jboss-deployment-structure>
        <deployment>
          <dependencies>
      	<module name='org.jboss.security.negotiation'/>
          </dependencies>
        </deployment>
      </jboss-deployment-structure>
注記
セキュリティードメインで使用できる Kerberos ログインモジュールは 1 つだけです。

結果

Web アプリケーションは、Kerberos、Microsoft Active Directory、またはその他の SPNEGO 互換のディレクトリーサービスに対してクレデンシャルを受け入れて認証します。ユーザーがすでにディレクトリーサービスにログインしているシステムからアプリケーションを実行し、必要なロールがすでにユーザーに適用されている場合、Web アプリケーションは認証のプロンプトを表示せず、SSO 機能が実現されます。

19.9. SPNEGO フォールバックをフォーム認証に設定する

以下の手順に従って、フォーム認証への SPNEGO フォールバックを設定します。⁠

手順19.2 フォーム認証へのフォールバックを備えた SPNEGO セキュリティー

  1. SPNEGO を設定する

  2. web.xml の変更

    login-config 要素をアプリケーションに追加し、web.xml でログインページとエラーページを設定します。
    <login-config>
        <auth-method>SPNEGO</auth-method>
        <realm-name>SPNEGO</realm-name>
            <form-login-config>
                <form-login-page>/login.jsp</form-login-page>
                <form-error-page>/error.jsp</form-error-page>
            </form-login-config>
       </login-config>
    
  3. Web コンテンツを追加する

    login.html および error.html の参照を web.xml に追加します。これらのファイルは、form-login-config 設定で指定された場所の Web アプリケーションアーカイブに追加されます。詳細は、JBoss EAP6 の 『セキュリティーガイド』 の 『フォームベースの認証』 を有効にするセクションを参照してください。典型的な login.html は次のようになります。
    <html>
        <head>
            <title>Vault Form Authentication</title>
        </head>
        <body>
            <h1>Vault Login Page</h1>
            <p>   
            <form method="post" action="j_security_check">
            <table>
                <tr>
                    <td>Username</td><td>-</td>
                    <td><input type="text" name="j_username"></td>
                </tr>
                <tr>
                    <td>Password</td><td>-</td>
                    <td><input type="password" name="j_password"></td>
                </tr>
                <tr>
                    <td colspan="2"><input type="submit"></td>
                </tr>              
            </table>
            </form>
            </p> 
            <hr>
        </body>
    </html>
    
注記
FORM ロジックへのフォールバックは、SPNEGO(または NTLM) トークンが存在しない場合にのみ使用できます。その結果、ブラウザーが NTLM トークンを送信した場合、ログインフォームはブラウザーに表示されません。

19.10. SAMLWeb ブラウザーベースの SSO について

JBoss EAP の PicketLink は、フェデレーション ID ベースのサービスを実装するためのプラットフォームを提供します。これには、一元化された ID サービスとアプリケーション用の Single Sign-On (SSO) が含まれます。
SAML プロファイルは、HTTP/POST と HTTP/リダイレクトの両方のバインディングをサポートしており、一元化された ID サービスを使用して、アプリケーションの WebSSO を有効にします。SAMLv2 ベースの WebSSO のアーキテクチャーは、Identity Management のハブアンドスポークアーキテクチャーに従います。このアーキテクチャーでは、ID プロバイダー (IDP) が、すべてのアプリケーション (サービスプロバイダー) に対する ID およびロール情報の中央ソース (ハブ) として機能します。スポークはサービスプロバイダー (SP) です。
重要
1 つの HTTP クライアント (Web ブラウザー) が同じ IDP を指す複数の SP に接続する場合、IDP は異なる SP を区別しません。1 つのクライアントからのより多くの要求が同時に来る場合、IDP は SP からの最新の要求を処理し、認証されたユーザーに関する SAML アサーションを送り返します。これは、IDP からの SAML 応答が、このような場合に誤った SP に転送される可能性があることを意味します。古い SP に戻すには、ブラウザーに SPURL を再入力する必要があります。
注記
詳細については、『Red Hat JBoss Enterprise Application Platform 6.4 SAML V2 ドキュメントで SSO を設定する方法、』 および 『Red Hat JBoss Enterprise Application Platform6.4 セキュリティーアーキテクチャー』 ドキュメントの 『SAML を使用したブラウザーベースの SSO』 セクションを参照してください。

第20章 開発セキュリティーリファレンス

20.1. EJB セキュリティーパラメーターリファレンス

表20.1 EJB セキュリティーパラメーター要素

要素 Description
<security-identity>
EJB のセキュリティー ID に関連する子要素が含まれています。
<use-caller-identity />
EJB が呼び出し元と同じセキュリティー ID を使用することを示します。
<run-as>
<role-name> 要素が含まれています。
<run-as-principal>
存在する場合、発信コールに割り当てられたプリンシパルを示します。存在しない場合、発信コールは anonymous という名前のプリンシパルに割り当てられます。
<role-name>
EJB を実行するロールを指定します。
<description>
<role-name> で指定されたロールについて説明します
.

例20.1 セキュリティー ID の例

以下の ejb-jar.xml ファイルの例は、表20.1「EJB セキュリティーパラメーター要素」<session> 内でも使用できます。
<ejb-jar>
    <enterprise-beans>
        <session>
            <ejb-name>ASessionBean</ejb-name>
            <security-identity>
                <use-caller-identity/>
            </security-identity>
        </session>
        <session>
            <ejb-name>RunAsBean</ejb-name>
            <security-identity>
                <run-as>
                    <description>A private internal role</description>
                    <role-name>InternalRole</role-name>
                </run-as>
            </security-identity>
        </session>
		  <session>
			 <ejb-name>RunAsBean</ejb-name>
			 <security-identity>
				<run-as-principal>internal</run-as-principal>
			 </security-identity>
		  </session>
    </enterprise-beans>
</ejb-jar>
上記のパラメーターは、jboss-ejb3.xml ファイルに含めることもできます。jboss-ejb3.xml ファイルについては、「jboss-ejb3.xml デプロイメント記述子の参照」

第21章 設定リファレンス

21.1. jboss-web.xml 設定リファレンス

はじめに

jboss-web.xml および web.xml デプロイメント記述子は両方ともデプロイメントの WEB-INF ディレクトリーに配置されます。jboss-web.xml は、JBoss EAP の Web アプリケーションデプロイメント記述子であり、JBossWeb の追加機能のための追加の設定オプションが含まれています。この記述子を使用して、web.xml 記述子の設定をオーバーライドし、JBoss EAP 固有の設定を設定できます。

グローバルリソースの WAR 要件へのマッピング

使用可能な設定の多くは、アプリケーションの web.xml で設定された要件をローカルリソースにマップします。web.xml 設定の説明は、を参照してください http://docs.oracle.com/cd/E13222_01/wls/docs81/webapp/web_xml.html

たとえば、web.xmljdbc/MyDataSource が必要な場合、jboss-web.xml はこのニーズを満たすためにグローバルデータソース java:/DefaultDS をマップする場合があります。WAR は、グローバルデータソースを使用して、jdbc/MyDataSource の必要性を満たします。

表21.1 jboss-web.xml の一般的なトップレベル属性

属性 Description
servlet
サーブレット要素は、サーブレット固有のバインディングを指定します。
max-active-sessions
許可されるアクティブなセッションの最大数を決定します。セッションマネージャーによって管理されるセッションの数がこの値を超え、パッシベーション が有効になっている場合、設定された passivation-min-idle-time に 基づいて超過分がパッシベーションされます。
-1 に設定すると、制限がないことを意味します。
replication-config
Replication-config 要素は、jboss-web.xml ファイルでセッションレプリケーションを設定するために使用されます。
passivation-config
passivation-config 要素は、jboss-web.xml ファイルでセッションパッシベーションを設定するために使用されます。
distinct-name
個別の名前 要素は、Web アプリケーションの EJB3 の個別の名前を指定します。
data-source
web.xml に必要な データソース へのマッピング。
context-root アプリケーションのルートコンテキスト。デフォルト値は、.war 接尾辞のないデプロイメントの名前です。
virtual-host アプリケーションが要求を受け入れる HTTP 仮想ホストの名前。HTTP ホスト ヘッダーの内容を参照します。
アノテーション アプリケーションで使用される注釈について説明します。詳細は、<annotation> を参照してください。
listener アプリケーションで使用されるリスナーについて説明します。詳細は、<listener> を参照してください。
session-config この要素は、web.xml<session-config> 要素と同じ機能を果たし、互換性のためにのみ含まれています。
バルブ アプリケーションで使用されるバルブについて説明します。詳細は、<valve> を参照してください。
overlay アプリケーションに追加するオーバーレイの名前。
security-domain アプリケーションが使用するセキュリティードメインの名前。セキュリティードメイン自体は、Web ベースの管理コンソールまたは管理 CLI で設定されます。
security-role この要素は、web.xml<security-role> 要素と同じ機能を果たし、互換性のためにのみ含まれています。
jacc-star-role-allow
jacc-star-role-allow 要素は、jacc プロバイダーが許可をバイパスするかどうかを決定できるように、Web レイヤーの jacc 許可生成エージェントが WebResourcePermission 許可を生成する必要があるかどうかを指定します。
use-jboss-authorization この要素が存在し、大文字と小文字を区別しない値 true が含まれている場合、JBossWeb 認証スタックが使用されます。存在しないか、true ではない値が含まれている場合は、JavaEnterpriseEdition 仕様で指定されている許可メカニズムのみが使用されます。この要素は JBoss EAP 6 の新機能です。
disable-audit このブール要素を false に設定すると有効になり、true に設定すると Web 監査が無効になります。Web セキュリティー監査は JavaEE 仕様の一部ではありません。この要素は JBoss EAP 6 の新機能です。
disable-cross-context false の場合、アプリケーションは別のアプリケーションコンテキストを呼び出すことができます。デフォルトは true です。
enable-websockets jboss-web.xml でこの要素を true に設定して、Web アプリケーションで WebSocket アクセスを有効にするかどうかを指定します。
次の要素にはそれぞれ子要素があります。
<annotation>
アプリケーションで使用される注釈について説明します。次の表に、<annotation> の子要素を示します。

表21.2 注釈設定要素

属性 説明
class-name
注釈のクラスの名前
servlet-security
サーブレットのセキュリティーを表す @ServletSecurity などの要素。
run-as
実行情報を表す @RunAs などの要素。
multipart-config
multipart-config 情報を表す @MultiPart などの要素。
<listener>
リスナーについて説明します。次の表に、<listener> の子要素を示します。

表21.3 リスナー設定要素

属性 説明
class-name
リスナーのクラスの名前
listener-type
アプリケーションのコンテキストに追加するリスナーの種類を示す 条件 要素のリスト。有効な選択肢は次のとおりです。
CONTAINER
ContainerListener をコンテキストに追加します。
ライフサイクル
LifecycleListener をコンテキストに追加します。
SERVLET_INSTANCE
InstanceListener をコンテキストに追加します。
SERVLET_CONTAINER
WrapperListener をコンテキストに追加します。
SERVLET_LIFECYCLE
WrapperLifecycle をコンテキストに追加します。
module
リスナークラスを含むモジュールの名前。
param
パラメーター。<param-name><param-value> の 2 つの子要素が含まれます。
<valve>
アプリケーションのバルブについて説明します。に似ています<listener>、には class-name、module、および param 要素があります。

第22章 補足リファレンス

22.1. Java アーカイブの種類

JBoss EAP 6 は、いくつかの異なるタイプのアーカイブファイルを認識します。アーカイブファイルは、デプロイ可能なサービスとアプリケーションをパッケージ化するために使用されます。
一般に、アーカイブファイルは、特定のファイル拡張子と特定のディレクトリー構造を持つ Zip アーカイブです。Zip アーカイブがアプリケーションサーバーにデプロイされる前に抽出された場合、それは展開されたアーカイブと呼ばれます。その場合、ディレクトリー名には引き続きファイル拡張子が含まれ、ディレクトリー構造の要件が引き続き適用されます。

表22.1

アーカイブタイプ 範囲 目的 ディレクトリー構造の要件
Java アーカイブ .jar Java クラスライブラリーが含まれています。
META-INF/Manifest.mf ファイル (オプション)。どのクラスが メイン クラスであるかなどの情報を指定します。
Web アーカイブ .war
Java クラスとライブラリーに加えて、Java Server Pages (JSP) ファイル、サーブレット、および XML ファイルが含まれています。Web アーカイブのコンテンツは、Web アプリケーションとも呼ばれます。
WEB-INF/web.xml ファイル。これには、Web アプリケーションの構造に関する情報が含まれています。他のファイルも WEB-INF/ に存在する可能性があります。
リソースアダプターアーカイブ。 .rar
ディレクトリー構造は、JCA 仕様で指定されています。
Java コネクターアーキテクチャー (JCA) リソースアダプターが含まれています。コネクターとも呼ばれます。
エンタープライズアーカイブ .ear
Java Enterprise Edition (EE) によって使用され、1 つ以上のモジュールを単一のアーカイブにパッケージ化して、モジュールをアプリケーションサーバーに同時にデプロイできるようにします。Maven と Ant は、EAR アーカイブの構築に使用される最も一般的なツールです。
META-INF/ ディレクトリー。1 つ以上の XML デプロイメント記述子ファイルが含まれています。
次のタイプのモジュールのいずれか。
  • Web アーカイブ (WAR)。
  • プレーンオールド Java オブジェクト (POJO) を含む 1 つ以上の Java アーカイブ (JAR)。
  • 独自の META-INF/ ディレクトリーを含む 1 つ以上の EnterpriseJavaBean (EJB) モジュール。このディレクトリーには、デプロイされる永続クラスの記述子が含まれています。
  • 1 つ以上のリソースアーカイブ (RAR)。
サービスアーカイブ .sar
エンタープライズアーカイブに似ていますが、JBoss EAP に固有です。
jboss-service.xml または jboss-beans.xml ファイルを含む META-INF/ ディレクトリー。

付録A 改訂履歴

改訂履歴
改訂 6.4.0-48Thursday November 16 2017Red Hat Customer Content Services
Red Hat JBoss Enterprise Application Platform 6.4.0.GA Continuous Release