Red Hat Training

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

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

3.1. はじめに

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

JBoss EAP は、デプロイされたアプリケーションのクラスパスを制御するためにモジュール形式のクラスロードシステムを使用します。このシステムは、階層クラスローダーの従来のシステムよりも、柔軟性があり、より詳細に制御できます。開発者は、アプリケーションで利用可能なクラスに対して粒度の細かい制御を行い、アプリケーションサーバーで提供されるクラスを無視して独自のクラスを使用するようデプロイメントを設定できます。

モジュール形式のクラスローダーにより、すべての Java クラスはモジュールと呼ばれる論理グループに分けられます。各モジュールは、独自のクラスパスに追加されたモジュールからクラスを取得するために、他のモジュールの依存関係を定義できます。デプロイされた各 JAR および WAR ファイルはモジュールとして扱われるため、開発者はモジュール設定をアプリケーションに追加してアプリケーションのクラスパスの内容を制御できます。

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

JBoss EAP では、クラスローディングを行うために、デプロイメントはすべてモジュールとして処理されます。このようなデプロイメントは動的モジュールと呼ばれます。クラスローディングの動作はデプロイメントの種類によって異なります。

WAR デプロイメント
WAR デプロイメントは 1 つのモジュールとして考慮されます。WEB-INF/lib ディレクトリーのクラスは WEB-INF/classes ディレクトリーにあるクラスと同じように処理されます。WAR にパッケージされているクラスはすべて、同じクラスローダーでロードされます。
EAR デプロイメント

EAR デプロイメントは複数のモジュールで構成され、以下のルールに従って定義されます。

  1. EAR の lib/ ディレクトリーは親モジュールと呼ばれる 1 つのモジュールです。
  2. また、EAR 内の各 WAR デプロイメントは 1 つのモジュールです。
  3. 同様に、EAR 内の EJB JAR デプロイメントも 1 つのモジュールです。

EAR 内の WAR および JAR デプロイメントなどのサブデプロイメントモジュールは、自動的に親モジュールに依存しますが、サブデプロイメントモジュール同士が自動的に依存するわけではありません。これは、サブデプロイメントの分離 (subdeployment isolation) と呼ばれ、デプロイメントごとまたはアプリケーションサーバー全体で無効にすることができます。

サブデプロイメントモジュール間の明示的な依存関係は、他のモジュールと同じ方法で追加することが可能です。

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

JBoss EAP のモジュール形式クラスローダーは、優先順位を決定してクラスローディングの競合が発生しないようにします。

デプロイメントに、パッケージとクラスの完全なリストがデプロイメントごとおよび依存関係ごとに作成されます。このリストは、クラスローディングの優先順位のルールに従って順序付けされます。実行時にクラスをロードすると、クラスローダーはこのリストを検索し、最初に一致したものをロードします。こうすることで、デプロイメントクラスパス内の同じクラスやパッケージの複数のコピーが競合しないようになります。

クラスローダーは上から順にクラスをロードします。

  1. 暗黙的な依存関係: これらの依存関係 (JAVA EE API など) は JBoss EAP によって自動的に追加されます。これらの依存関係には一般的な機能や JBoss EAP によって提供される 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.4. jboss-deployment-structure.xml

jboss-deployment-structure.xml ファイルは JBoss EAP のオプションのデプロイメント記述子です。このデプロイメント記述子を使用すると、デプロイメントでクラスローディングを制御できます。

このデプロイメント記述子の XML スキーマは、EAP_HOME/docs/schema/jboss-deployment-structure-1_2.xsd 下の製品インストールディレクトリーにあります。

このデプロイメント記述子を使用して実行できる主なタスクは次のとおりです。

  • 明示的なモジュール依存関係を定義する。
  • 特定の暗黙的な依存関係がロードされないようにする。
  • デプロイメントのリソースより追加モジュールを定義する。
  • EAR デプロイメントのサブデプロイメント分離の挙動を変更する。
  • EAR のモジュールに追加のリソースルートを追加する。

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

明示的なモジュール依存関係をアプリケーションに追加すると、これらのモジュールのクラスをデプロイメント時にアプリケーションのクラスパスに追加することができます。

注記

JBoss EAP では、依存関係がデプロイメントに自動的に追加されます。詳細については、「暗黙的なモジュール依存関係」を参照してください。

前提条件

  1. モジュールの依存関係を追加するソフトウェアプロジェクト。
  2. 依存関係として追加するモジュールの名前を知っている必要があります。JBoss EAP に含まれる静的モジュールのリストについては、「含まれるモジュール」を参照してください。モジュールが他のデプロイメントである場合は、JBoss EAP『設定ガイド』の「動的モジュールの命名規則」を参照してモジュール名を判断してください。

依存関係を設定するには、以下の 2 つの方法があります。

  • デプロイメントの MANIFEST.MF ファイルにエントリーを追加します。
  • jboss-deployment-structure.xml デプロイメント記述子にエントリーを追加します。

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

MANIFEST.MF ファイルの必要な依存関係エントリーを作成するよう Maven プロジェクトを設定できます。

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

    Dependencies: org.javassist, org.apache.velocity, org.antlr
    • 依存関係をオプションにするには、依存関係エントリーのモジュール名に optional を付けます。

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

      Dependencies: org.javassist, org.apache.velocity export
    • annotations フラグは、EJB インターセプターを宣言するときなど、アノテーションのスキャン中に処理する必要があるアノテーションがモジュールの依存関係に含まれる場合に必要になります。この設定を行わないと、モジュールに宣言された EJB インターセプターをデプロイメントで使用できません。アノテーションのスキャンが関係するその他の状況でも、この設定が必要になる場合があります。

      Dependencies: org.javassist, test.module annotations
    • デフォルトでは、依存関係の META-INF 内のアイテムにはアクセスできません。services 依存関係により META-INF/services のアイテムにアクセスできるようになり、モジュール内の services をロードできるようになります。

      Dependencies: org.javassist, org.hibernate services
    • beans.xml ファイルをスキャンし、生成される Bean をアプリケーションが利用できるようにするために、meta-inf 依存関係を使用できます。

      Dependencies: org.javassist, test.module meta-inf

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

  1. 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" />
    • 値が true のモジュールエントリーに optional 属性を追加することにより依存関係をオプションにすることができます。この属性のデフォルト値は false です。

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

      <module name="org.javassist" export="true" />
    • アノテーションのスキャン中に処理する必要があるアノテーションがモジュール依存関係に含まれる場合は、annotations フラグが使用されます。

      <module name="test.module" annotations="true" />
    • services 依存関係は、この依存関係にある services を使用するかどうか、およびどのように使用するかを指定します。デフォルト値は none です。この属性に import の値を指定することは、依存関係モジュールの META-INF/services パスを含むインポートフィルターリストの最後にフィルターを追加することと同じです。この属性に export の値を設定することは、エクスポートフィルターリストに対して同じアクションを実行することと同じです。

      <module name="org.hibernate" services="import" />
    • META-INF 依存関係は、この依存関係の META-INF エントリーを使用するかどうか、およびどのように使用するかを指定します。デフォルト値は none です。この属性に import の値を指定することは、依存関係モジュールの META-INF/** パスを含むインポートフィルターリストの最後にフィルターを追加することと同じです この属性に export の値を設定することは、エクスポートフィルターリストに対して同じアクションを実行することと同じです。

      <module name="test.module" meta-inf="import" />

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

Jandex インデックスの作成

annotations フラグを使用するには、モジュールに Jandex インデックスが含まれる必要があります。JBoss EAP 7.1 では、これは自動的に生成されます。ただし、このインデックスを手動で追加する場合は、後方互換性を確保するために、モジュールに追加する新しい「index JAR」を作成します。Jandex JAR を使用してインデックスをビルドした後、新しい JAR ファイルに挿入します。

Jandex インデックスの作成:

  1. インデックスを作成します。

    java -jar modules/system/layers/base/org/jboss/jandex/main/jandex-jandex-2.0.0.Final-redhat-1.jar $JAR_FILE
  2. 一時作業領域を作成します。

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

    mv $JAR_FILE.ifx /tmp/META-INF/jandex.idx
    1. オプション 1: インデックスを新しい JAR ファイルに含めます。

      jar cf index.jar -C /tmp META-INF/jandex.idx

      JAR をモジュールディレクトリーに置き、 module.xml を編集してリソースルートへ追加します。

    2. オプション 2: インデックスを既存の JAR に追加します。

      java -jar /modules/org/jboss/jandex/main/jandex-1.0.3.Final-redhat-1.jar -m $JAR_FILE
  4. アノテーションインデックスを使用するようモジュールインポートに指示し、アノテーションのスキャンでアノテーションを見つけられるようにします。

    1. オプション 1: MANIFEST.MF を使用してモジュールの依存関係を追加する場合は、annotations をモジュール名の後に追加します。例を以下に示します。

      Dependencies: test.module, other.module

      上記を以下に変更します。

      Dependencies: test.module annotations, other.module
    2. オプション 2: jboss-deployment-structure.xml を使用してモジュールの依存関係を追加する場合は、モジュールの依存関係に annotations="true" を追加します。

      注記

      静的モジュール内のクラスで定義されたアノテーション付き Java EE コンポーネントをアプリケーションで使用する場合は、アノテーションインデックスが必要です。JBoss EAP 7.1 では、静的モジュールのアノテーションインデックスは自動的に生成されるため、作成する必要がありません。ただし、MANIFEST.MF または jboss-deployment-structure.xml ファイルのいずれかに依存関係を追加して、アノテーションを使用するようモジュールインポートに指示する必要があります。

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

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

Maven を使用して MANIFEST.MF エントリーを生成する前に、以下のものが必要になります。

  • JAR、EJB、または WAR プラグイン (maven-jar-pluginmaven-ejb-plugin、または maven-war-plugin) のいずれかを使用している Maven プロジェクト。
  • プロジェクトのモジュール依存関係の名前を知っている必要があります。JBoss EAP に含まれる静的モジュールのリストについては、「含まれるモジュール」を参照してください。モジュールが他のデプロイメントである場合は、JBoss EAP『設定ガイド』の「動的モジュールの命名規則」を参照してモジュール名を判断してください。

モジュール依存関係が含まれる 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:single

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

    例: 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. モジュールが暗黙的にロードされないようにする

暗黙的な依存関係がロードされないようデプロイ可能なアプリケーションを設定できます。これは、アプリケーションサーバーにより提供される暗黙的な依存関係とは異なるバージョンのライブラリーやフレームワークがアプリケーションに含まれる場合に役に立つことがあります。

前提条件

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

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

  1. 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" />

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

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

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

サブシステムの除外は、サブシステムの削除と同じ効果がありますが、単一のデプロイメントにのみ適用されます。jboss-deployment-structure.xml 設定ファイルを編集することにより、デプロイメントからサブシステムを除外できます。

サブシステムの除外

  1. jboss-deployment-structure.xml ファイルを編集します。
  2. <deployment> タグ内に以下の XML を追加します。

    <exclude-subsystems>
      <subsystem name="SUBSYSTEM_NAME" />
    </exclude-subsystems>
  3. jboss-deployment-structure.xml ファイルを保存します。

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

例: 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 クラスを初期化する例になります。

Class<?> targetClass = Class.forName("com.myorg.util.TargetClass", true, CurrentClass.class.getClassLoader());

名前ですべてのリソースを検索

リソースの名前とパスが分かり、直接そのリソースをロードする場合は、標準的な Java Development Kit (JDK) の Class または ClassLoader API を使用するのが最良の方法です。

  • 単一のリソースをロードします。

    ご使用のクラスと同じディレクトリーまたはデプロイメントの他のクラスと同じディレクトリーにある単一のリソースをロードする場合は、Class.getResourceAsStream() メソッドを使用できます。

    InputStream inputStream = CurrentClass.class.getResourceAsStream("targetResourceName");
  • 単一リソースのインスタンスをすべてロードします。

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

    以下の例は、1 つのリソースのすべてのインスタンスをロードし、結果で処理を繰り返します。

    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() や他の関連するメソッドを使用する必要はありません。ストリームは非常に簡単に使用でき、ストリームを使用することにより、コードの複雑さが最小限に抑えられます。

  • クラスローダーからクラスファイルをロードします。

    クラスがすでにロードされている場合は、以下の構文を使用して、そのクラスに対応するクラスファイルをロードできます。

    InputStream inputStream = CurrentClass.class.getResourceAsStream(TargetClass.class.getSimpleName() + ".class");

    クラスがロードされていない場合は、クラスローダーを使用し、パスを変換する必要があります。

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

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

JBoss Modules ライブラリーは、すべてのデプロイメントリソースを繰り返し処理するために複数の API を提供します。JBoss Modules API の JavaDoc は http://docs.jboss.org/jbossmodules/1.3.0.Final/api/ にあります。これらの API を使用するには、以下の依存関係を MANIFEST.MF に追加する必要があります。

依存関係: org.jboss.modules

これらの API により柔軟性が向上しますが、直接パスを検索するよりもよりも動作がかなり遅くなることに注意してください。

ここでは、アプリケーションコードでプログラムを用いてリソースを繰り返す方法を説明します。

  • デプロイメント内およびすべてのインポート内のリソースをリストします。

    場合によっては、正確なパスでリソースを検索できないことがあります。たとえば、正確なパスがわからなかったり、指定のパスで複数のファイルをチェックする必要がある場合などです。このような場合、JBoss Modules ライブラリーはすべてのデプロイメントを繰り返し処理するための API を複数提供します。2 つのメソッドのいずれかを使用すると、デプロイメントでリソースを繰り返し処理できます。

    • 単一のモジュールで見つかったすべてのリソースを繰り返し処理します。

      ModuleClassLoader.iterateResources() メソッドは、このモジュールクラスローダー内のすべてのリソースを繰り返し処理します。このメソッドは、検索を開始するディレクトリーの名前と、サブディレクトリーで再帰的に処理するかどうかを指定するブール値の 2 つの引数を取ります。

      以下の例は、ModuleClassLoader の取得方法と、bin/ ディレクトリーにあるリソースのイテレーターの取得方法 (サブディレクトリーを再帰的に検索) を示しています。

      ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader();
      Iterator<Resource> mclResources = moduleClassLoader.iterateResources("bin",true);

      取得されたイテレーターは、一致した各リソースをチェックし、名前とサイズのクエリー (可能な場合) を行うために使用できます。また、読み取り可能ストリームを開いたり、リソースの URL を取得するために使用できます。

    • 単一のモジュールで見つかったすべてのリソースとインポートされたリソースを繰り返し処理します。

      Module.iterateResources() メソッドは、このモジュールクラスローダー内のすべてのリソース (モジュールにインポートされたリソースを含む) を繰り返し処理します。このメソッドは、前述のメソッドよりもはるかに大きなセットを返します。このメソッドには、特定パターンの結果を絞り込むフィルターとなる引数が必要になります。代わりに、PathFilters.acceptAll() を指定してセット全体を返すことも可能です。

      以下の例は、インポートを含む、このモジュールのリソースのセット全体を検索する方法を示しています。

      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() メソッドを使用しますが、追加のメソッドを使用して結果となるイテレーターをフィルターする必要があります。PathFilters.filtered() メソッドは、リソースイテレーターのフィルターされたビューを提供できます。PathFilters クラスには、さまざまな関数を実行するフィルターを作成する多くの静的メソッドが含まれています。これには、子パスや完全一致の検索、Ant 形式の「glob」パターンの一致などが含まれます。

  • リソースのフィルターに関する追加のコード例。

    以下の例は、異なる基準を基にしてリソースをフィルターする方法を示しています。

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

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

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

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

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

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

    例: デプロイメントおよびインポートで 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"));

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

    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 では、サブデプロイメントクラスローダーの分離がデフォルトで無効になるため、非 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> 要素が jboss-deployment-structure.xml ファイルに存在しない場合は追加し、内容が true になるようにします。

    <ear-subdeployments-isolated>true</ear-subdeployments-isolated>

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

3.7.4. エンタープライズアーカイブのサブデプロイメント間で共有するセッションの設定

JBoss EAP では、EAR に含まれる WAR モジュールサブデプロイメント間でセッションを共有するようエンタープライズアーカイブ (EAR) を設定する機能が提供されます。この機能はデフォルトで無効になり、EAR の META-INF/jboss-all.xml ファイルで明示的に有効にする必要があります。

重要

この機能は標準的サーブレット機能ではないため、この機能が有効な場合はアプリケーションを移植できないことがあります。

EAR 内の WAR 間で共有するセッションを有効にするには、EAR の META-INF/jboss-all.xmlshared-session-config 要素を宣言する必要があります。

例: META-INF/jboss-all.xml

<jboss umlns="urn:jboss:1.0">
  ...
  <shared-session-config xmlns="urn:jboss:shared-session-config:1.0">
  </shared-session-config>
  ...
</jboss>

shared-session-config 要素は、EAR 内のすべての WAR に対して共有セッションマネージャーを設定するために使用されます。shared-session-config 要素が存在する場合は、EAR 内のすべての WAR で同じセッションマネージャーが共有されます。ここで行われる変更は、EAR 内に含まれるすべての WAR に影響します。

3.7.4.1. 共有セッション設定オプションのリファレンス

例: META-INF/jboss-all.xml

<jboss umlns="urn:jboss:1.0">
    <shared-session-config xmlns="urn:jboss:shared-session-config:1.0">
        <max-active-sessions>10</max-active-sessions>
        <session-config>
            <session-timeout>0</session-timeout>
            <cookie-config>
                <name>JSESSIONID</name>
                <domain>domainName</domain>
                <path>/cookiePath</path>
                <comment>cookie comment</comment>
                <http-only>true</http-only>
                <secure>true</secure>
                <max-age>-1</max-age>
            </cookie-config>
            <tracking-mode>COOKIE</tracking-mode>
        </session-config>
        <replication-config>
            <cache-name>web</cache-name>
            <replication-granularity>SESSION</replication-granularity>
        </replication-config>
    </shared-session-config>
</jboss>

要素説明

shared-session-config

共有セッション設定のルート要素。この要素が META-INF/jboss-all.xml に存在しない場合は、EAR に含まれるすべてのデプロイ済み WAR で単一のセッションマネージャーが共有されます。

max-active-sessions

許可される最大セッション数。

session-config

EAR に含まれるすべてのデプロイ済み WAR に対するセッション設定パラメーターを含みます。

session-timeout

EAR に含まれるデプロイ済み WAR で作成されたすべてのセッションに対するデフォルトのセッションタイムアウト間隔を定義します。指定されたタイムアウトは、分単位の整数で表記する必要があります。タイムアウトが 0 またはそれよりも小さい値である場合は、コンテナーにより、セッションのデフォルトの動作がタイムアウトしなくなります。この要素が指定されない場合は、コンテナーでデフォルトのタイムアウト期間を設定する必要があります。

cookie-config

EAR に含まれるデプロイ済み WAR により作成されたセッション追跡クッキーを含みます。

name

EAR に含まれるデプロイ済み WAR により作成されたセッション追跡クッキーに割り当てられる名前。デフォルト値は JSESSIONID です。

domain

EAR に含まれるデプロイ済み WAR により作成されたセッション追跡クッキーに割り当てられるドメイン名。

path

EAR に含まれるデプロイ済み WAR により作成されたセッション追跡クッキーに割り当てられるパス。

comment

EAR に含まれるデプロイ済み WAR により作成されたセッション追跡クッキーに割り当てられるコメント。

http-only

EAR に含まれるデプロイ済みの WAR によって作成されたセッション追跡クッキーを HttpOnly とマークするかどうかを指定します。

secure

対応するセッションを開始したリクエストが HTTPS ではなくプレーン HTTP を使用している場合であっても、EAR に含まれるデプロイ済みの WAR によって作成されたセッション追跡クッキーをセキュアとマークするかどうかを指定します。

max-age

EAR に含まれるデプロイ済みの WAR によって作成されたセッション追跡クッキーに割り当てられる有効期間 (秒単位)。デフォルト値は -1 です。

tracking-mode

EAR に含まれるデプロイ済み WAR により作成されたセッションの追跡モードを定義します。

replication-config

HTTP セッションクラスタリング設定を含みます。

cache-name

このオプションは、クラスタリング専用です。セッションデータを格納する Infinispan コンテナーとキャッシュの名前を指定します。デフォルト値が明示的に設定されていない場合は、アプリケーションサーバーによってデフォルト値が決定されます。キャッシュコンテナー内で特定のキャッシュを使用するには、web.dist のように container.cache という形式 を使用します。名前が修飾されてない場合は、指定されたコンテナーのデフォルトのキャッシュが使用されます。

replication-granularity

このオプションはクラスタリング専用です。セッションレプリケーションの粒度を決定します。可能な値は SESSIONATTRIBUTE で、デフォルト値は SESSION です。

SESSION 粒度が使用される場合は、すべてのセッション属性がレプリケートされます (要求のスコープ内でいずれかのセッション属性が変更された場合)。このポリシーは、オブジェクト参照が複数のセッション属性で共有されるときに必要になります。ただし、セッション属性が非常に大きい場合や頻繁に変更されない場合は非効率になることがあります。これは、属性が変更されたかどうかに関係なく、すべての属性をレプリケートする必要があるためです。

ATTRIBUTE 粒度が使用される場合は、要求のスコープ内で変更された属性のみがレプリケートされます。オブジェクト参照が複数のセッション属性で共有される場合、このポリシーは適切ではありません。セッション属性が非常に大きい場合や頻繁に変更されない場合は SESSION よりも効率的になることがあります。

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

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

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

注記

少なくとも 1 つの JAR に TLD が含まれ、TLD が META-INF に含まれるようにします。

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

  1. 管理 CLI を使用して、JBoss EAP インスタンスへ接続し、以下のコマンドを実行して TLD JAR が含まれるカスタムモジュールを作成します。

    module add --name=MyTagLibs --resources=/path/to/TLDarchive.jar
    重要

    module 管理 CLI コマンドを使用したモジュールの追加および削除は、テクノロジープレビューとしてのみ提供されます。このコマンドは、管理対象ドメインでの使用や、リモートによる管理 CLI への接続時には適していません。本番環境では、モジュールを手作業で追加および削除する必要があります。詳細は、JBoss EAP『設定ガイド』の「カスタムモジュールの手動作成」および「手作業によるカスタムモジュールの削除」を参照してください。

    テクノロジープレビューの機能は、Red Hat の本番環境のサービスレベルアグリーメント (SLA) ではサポートされず、機能的に完全ではないことがあるため、Red Hat は本番環境での使用は推奨しません。テクノロジープレビューの機能は、最新の技術をいち早く提供して、開発段階で機能のテストやフィードバックの収集を可能にするために提供されます。

    テクノロジープレビュー機能のサポート範囲については、Red Hat カスタマーポータルの「テクノロジプレビュー機能のサポート範囲」を参照してください。

    TLD が依存関係を必要とするクラスとともにパッケージ化されている場合は、--dependencies オプションを使用して、カスタムモジュールの作成時にこれらの依存関係を指定するようにします。

    モジュールを作成するときに、システムのファイルシステム固有の区切り文字を使用して複数の JAR リソースを指定できます。

    • Linux の場合 - : 例、--resources=<path-to-jar>:<path-to-another-jar>
    • Windows の場合 - : 例、--resources=<path-to-jar>;<path-to-another-jar>

      注記
      --resources
      これは --module-xml を使用しない限り必要です。ファイルシステム固有のパス区切り文字 (たとえば、java.io.File.pathSeparatorChar) で区切られたファイルシステムパス (通常は JAR ファイル) をリストします。指定されたファイルは作成されたモジュールのディレクトリーにコピーされます。
      --resource-delimiter
      これは、リソース引数のオプションのユーザー定義パス区切り文字です。この引数が存在する場合、コマンドパーサーはファイルシステム固有のパス区切り文字の代わりにその値を使用します。これにより、modules コマンドをクロスプラットフォームのスクリプトで使用できるようになります。
  2. ご使用のアプリケーションで、デプロイメントへの明示的なモジュール依存関係の追加で説明されているいずれかの方法を使用して新しい MyTagLibs カスタムモジュールの依存関係を宣言します。
重要

依存関係を宣言するときは必ず META-INF もインポートしてください。たとえば、MANIFEST.MF の場合は以下のようになります。

Dependencies: com.MyTagLibs meta-inf

jboss-deployment-structure.xml の場合は、meta-inf 属性を使用してください。

3.9. クラスローディングの参照

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

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

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

依存関係を追加するサブシステム常に追加されるパッケージ依存関係条件的に追加されるパッケージ依存関係依存関係の追加を引き起こす条件

Application Client

  • org.omg.api
  • org.jboss.xnio
  

Batch

  • javax.batch.api
  • org.jberet.jberet-core
  • org.wildfly.jberet
  

Bean Validation

  • org.hibernate.validator
  • javax.validation.api
  

Core Server

  • javax.api
  • sun.jdk
  • org.jboss.vfs
  • ibm.jdk
  

DriverDependenciesProcessor

 
  • javax.transaction.api
 

EE

  • org.jboss.invocation (org.jboss.invocation.proxy.classloading を除く)
  • org.jboss.as.ee (org.jboss.as.ee.component.serialization、org.jboss.as.ee.concurrent、および org.jboss.as.ee.concurrent.handle を除く)
  • org.wildfly.naming
  • javax.annotation.api
  • javax.enterprise.concurrent.api
  • javax.interceptor.api
  • javax.json.api
  • javax.resource.api
  • javax.rmi.api
  • javax.xml.bind.api
  • javax.api
  • org.glassfish.javax.el
  • org.glassfish.javax.enterprise.concurrent
  

EJB 3

  • javax.ejb.api
  • javax.xml.rpc.api
  • org.jboss.ejb-client
  • org.jboss.iiop-client
  • org.jboss.as.ejb3
  • org.wildfly.iiop-openjdk
 

IIOP

  • org.omg.api
  • javax.rmi.api
  • javax.orb.api
  

JAX-RS (RESTEasy)

  • javax.xml.bind.api
  • javax.ws.rs.api
  • javax.json.api
  • org.jboss.resteasy.resteasy-atom-provider
  • org.jboss.resteasy.resteasy-crypto
  • org.jboss.resteasy.resteasy-validator-provider-11
  • org.jboss.resteasy.resteasy-jaxrs
  • org.jboss.resteasy.resteasy-jaxb-provider
  • org.jboss.resteasy.resteasy-jackson2-provider
  • org.jboss.resteasy.resteasy-jsapi
  • org.jboss.resteasy.resteasy-json-p-provider
  • org.jboss.resteasy.resteasy-multipart-provider
  • org.jboss.resteasy.resteasy-yaml-provider
  • org.codehaus.jackson.jackson-core-asl
  • org.jboss.resteasy.resteasy-cdi

デプロイメントに 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
  • org.jboss.as.jpa
  • org.jboss.as.jpa.spi
  • org.javassist

@PersistenceUnit または @PersistenceContext アノテーションが存在するか、デプロイメント記述子に <persistence-unit-ref> または <persistence-context-ref> 要素が存在すること。

JBoss EAP は永続プロバイダー名をモジュール名にマップします。persistence.xml ファイルで特定のプロバイダーに名前を付けると、適切なモジュールに対して依存関係が追加されます。これが希望の挙動ではない場合は、jboss-deployment-structure.xml を使用して除外できます。

JSF (Java Server Faces)

 
  • javax.faces.api
  • com.sun.jsf-impl
  • org.jboss.as.jsf
  • org.jboss.as.jsf-injection

EAR アプリケーションに追加されます。

値が trueorg.jboss.jbossfaces.WAR_BUNDLES_JSF_IMPLcontext-paramweb.xml ファイルで指定しない場合のみ WAR アプリケーションに追加されます。

JSR-77

  • javax.management.j2ee.api
  

Logging

  • org.jboss.logging
  • org.apache.commons.logging
  • org.apache.log4j
  • org.slf4j
  • org.jboss.logging.jul-to-slf4j-stub
  

Mail

  • javax.mail.api
  • javax.activation.api
  

Messaging

  • javax.jms.api
  • org.wildfly.extension.messaging-activemq
 

PicketLink Federation

 
  • org.picketlink
 

Pojo

  • org.jboss.as.pojo
  

SAR

 
  • org.jboss.modules
  • org.jboss.as.system-jmx
  • org.jboss.common-beans

jboss-service.xml を含む SAR アーカイブのデプロイメント。

Seam2

 
  • org.jboss.vfs

.

Security

  • org.picketbox
  • org.jboss.as.security
  • javax.security.jacc.api
  • javax.security.auth.message.api
  

ServiceActivator

 
  • org.jboss.msc
 

Transactions

  • javax.transaction.api
  • org.jboss.xts
  • org.jboss.jts
  • org.jboss.narayana.compensations
 

Undertow

  • javax.servlet.jstl.api
  • javax.servlet.api
  • javax.servlet.jsp.api
  • javax.websocket.api
  • io.undertow.core
  • io.undertow.servlet
  • io.undertow.jsp
  • io.undertow.websocket
  • io.undertow.js
  • org.wildfly.clustering.web.api
 

Web Services

  • javax.jws.api
  • javax.xml.soap.api
  • javax.xml.ws.api
  • org.jboss.ws.api
  • org.jboss.ws.spi

アプリケーションクライアントタイプでない場合は、条件付き依存関係が追加されます。

Weld (CDI)

  • javax.enterprise.api
  • javax.inject.api
  • javax.persistence.api
  • org.javassist
  • org.jboss.as.weld
  • org.jboss.weld.core
  • org.jboss.weld.probe
  • org.jboss.weld.api
  • org.jboss.weld.spi
  • org.hibernate.validator.cdi

デプロイメントに beans.xml ファイルが存在すること。

3.9.2. 含まれるモジュール

含まれるモジュールの完全なリストとこれらのモジュールがサポートされているかについては、Red Hat カスタマーポータルの「JBoss Enterprise Application Platform (EAP) 7 に含まれるモジュール 」を参照してください。