第6章 JBoss EAP クラスローディング
JBoss EAP は、デプロイされたアプリケーションのクラスパスを制御するためにモジュール形式のクラスロードシステムを使用します。このシステムは、階層クラスローダーの従来のシステムよりも、柔軟性があり、より詳細に制御できます。開発者は、アプリケーションで利用可能なクラスに対して粒度の細かい制御を行い、アプリケーションサーバーで提供されるクラスを無視して独自のクラスを使用するようデプロイメントを設定できます。
モジュール形式のクラスローダーにより、すべての Java クラスはモジュールと呼ばれる論理グループに分けられます。各モジュールは、独自のクラスパスに追加されたモジュールからクラスを取得するために、他のモジュールの依存関係を定義できます。デプロイされた各 JAR および WAR ファイルはモジュールとして扱われるため、開発者はモジュール設定をアプリケーションに追加してアプリケーションのクラスパスの内容を制御できます。
6.1. モジュール
モジュールは、クラスローディングおよび依存関係管理に使用されるクラスの論理グループです。JBoss EAP は、静的モジュールと動的モジュールの 2 つの種類のモジュールを識別します。この 2 つの種類のモジュールの主な違いは、パッケージ化方法です。
静的モジュール
静的モジュールは、アプリケーションサーバーの EAP_HOME/modules/
ディレクトリーで定義されます。各モジュールは EAP_HOME/modules/com/mysql/
のようにサブディレクトリーとして存在します。各モジュールには、module.xml
設定ファイルとすべての必要な JAR ファイルが含まれるスロットサブディレクトリー (デフォルトでは main
) が含まれます。アプリケーションサーバーにより提供される API は、Java EE API と他の API を含む静的モジュールとして提供されます。
例: MySQL JDBC ドライバー module.xml
ファイル
<?xml version="1.0" ?> <module xmlns="urn:jboss:module:1.1" name="com.mysql"> <resources> <resource-root path="mysql-connector-java-5.1.36-bin.jar"/> </resources> <dependencies> <module name="javax.api"/> <module name="javax.transaction.api"/> </dependencies> </module>
モジュール名 com.mysql
は、スロット名 main
を除くモジュールのディレクトリー構造と一致する必要があります。
カスタム静的モジュールの作成は、同じサードパーティーライブラリーを使用する同じサーバー上に多くのアプリケーションがデプロイされる場合に役立ちます。これらのライブラリーを各アプリケーションとバンドルする代わりに、管理者はこれらのライブラリーが含まれるモジュールを作成およびインストールできます。アプリケーションは、カスタム静的モジュールで明示的な依存関係を宣言できます。
JBoss EAP ディストリビューションで提供されるモジュールは、 EAP_HOME/modules
ディレクトリー内の system
ディレクトリーにあります。このため、サードパーティーによって提供されるモジュールから分離されます。また、JBoss EAP 上で使用する、Red Hat により提供されるすべての製品によって、system
ディレクトリー内にモジュールがインストールされます。
モジュールごとに 1 つのディレクトリーを使用して、カスタムモジュールが EAP_HOME/modules
ディレクトリーにインストールされるようにする必要があります。こうすると、同梱されたバージョンではなく、system
ディレクトリーに存在するカスタムバージョンのモジュールがロードされるようになります。これにより、ユーザー提供のモジュールがシステムモジュールよりも優先されます。
JBOSS_MODULEPATH
環境変数を使用して JBoss EAP がモジュールを検索する場所を変更する場合は、指定された場所の 1 つで system
サブディレクトリー構造を探します。system
構造は、JBOSS_MODULEPATH
で指定された場所のどこかに存在する必要があります。
JBoss EAP 7.1 より、module.xml
ファイルの resource-root path
要素で絶対パスを使用できるようになりました。これにより、リソースライブラリーを EAP_HOME/modules/
ディレクトリーに移動しなくてもリソースライブラリーにアクセスできるようになりました。
例: module.xml
ファイルの絶対パス
<?xml version="1.0" ?> <module xmlns="urn:jboss:module:1.1" name="oracle.jdbc"> <resources> <resource-root path="/home/redhat/test.jar"/> </resources> </module>
動的モジュール
動的モジュールは、各 JAR または WAR デプロイメント (または、EAR 内のサブデプロイメント) に対してアプリケーションサーバーによって作成およびロードされます。動的モジュールの名前は、デプロイされたアーカイブの名前に由来します。デプロイメントはモジュールとしてロードされるため、依存関係を設定し、他のデプロイメントで依存関係として使用することが可能です。
モジュールは必要な場合にのみロードされます。通常、モジュールは、明示的または暗黙的な依存関係があるアプリケーションがデプロイされる場合にのみロードされます。
6.2. モジュールの依存性
モジュール依存関係は、あるモジュールに他の 1 つまたは複数のモジュールのクラスが必要になるという宣言です。JBoss EAP がモジュールをロードするときに、モジュール形式のクラスローダーがモジュールの依存関係を解析し、各依存関係のクラスをクラスパスに追加します。指定の依存関係が見つからない場合、モジュールはロードできません。
モジュールとモジュール形式のクラスロードシステムに関する完全な詳細については、「モジュール」を参照してください。
JAR や WAR などのデプロイされたアプリケーションは動的モジュールとしてロードされ、依存関係を利用して JBoss EAP によって提供される API にアクセスします。
依存関係には明示的と暗黙的の 2 つのタイプがあります。
- 明示的な依存関係
-
明示的な依存関係は開発者が設定ファイルで宣言します。静的モジュールでは、依存関係を
module.xml
ファイルに宣言できます。動的モジュールでは、デプロイメントのMANIFEST.MF
またはjboss-deployment-structure.xml
デプロイメント記述子に依存関係を宣言できます。 - 暗黙的な依存関係
暗黙的な依存関係は、デプロイメントで特定の状態やメタデータが見つかったときに自動的に追加されます。JBoss EAP に同梱される Java EE 7 API は、デプロイメントで暗黙的な依存関係が検出されたときに追加されるモジュールの例になります。
jboss-deployment-structure.xml
デプロイメント記述子ファイルを使用して、特定の暗黙的な依存関係を除外するようデプロイメントを設定することも可能です。これは、JBoss EAP が暗黙的な依存関係として追加しようとする特定バージョンのライブラリーをアプリケーションがバンドルする場合に役に立つことがあります。
オプションの依存関係
明示的な依存関係は、オプションとして指定できます。オプションの依存関係をロードできなくても、モジュールのロードは失敗しません。ただし、依存関係は後で使用できるようになっても、モジュールのクラスパスには追加されません。依存関係はモジュールがロードされるときに利用可能である必要があります。
依存関係のエクスポート
モジュールのクラスパスには独自のクラスとその直接の依存関係のクラスのみが含まれます。モジュールは 1 つの依存関係の依存関係クラスにはアクセスできませんが、暗黙的な依存関係のエクスポートを指定できます。エクスポートされた依存関係は、エクスポートするモジュールに依存するモジュールへ提供されます。
たとえば、モジュール A はモジュール B に依存し、モジュール B はモジュール C に依存します。モジュール A はモジュール B のクラスにアクセスでき、モジュール B はモジュール C のクラスにアクセスできます。モジュール Aは以下のいずれかの条件を満たさない限り、モジュール C のクラスにアクセスできません。
- モジュール A が、モジュール C に対する明示的な依存関係を宣言する
- モジュール B がモジュール C の依存関係をエクスポートする
グローバルモジュール
グローバルモジュールは、JBoss EAP が各アプリケーションへの依存関係として提供するモジュールです。このモジュールをグローバルモジュールの JBoss EAP のリストへ追加すると、モジュールをグローバルモジュールにすることができます。モジュールへの変更は必要ありません。
詳細は「グローバルモジュールの定義」の項を参照してください。
6.3. カスタムモジュールの作成
カスタムの静的モジュールを追加して、JBoss EAP で実行しているデプロイメントがリソースを利用できるようにすることができます。モジュールは 手動 で作成するか、管理 CLI を使用して作成することができます。
モジュールの作成後、アプリケーションがリソースを使用できるようにするにはモジュールを依存関係として追加する必要があります。
カスタムモジュールの手動作成
カスタムモジュールを手動で作成するには、以下の手順に従います。
EAP_HOME/modules/
ディレクトリーに適切なディレクトリー構造を作成します。例: MySQL JDBC ドライバーディレクトリー構造の作成
$ cd EAP_HOME/modules/ $ mkdir -p com/mysql/main
JAR ファイルまたはその他必要なリソースを
main/
サブディレクトリーにコピーします。例: MySQL JDBC ドライバー JAR のコピー
$ cp /path/to/mysql-connector-java-5.1.36-bin.jar EAP_HOME/modules/com/mysql/main/
module.xml
ファイルをmain/
サブディレクトリーに作成し、そのファイルの適切なリソースおよび依存関係を指定します。例: MySQL JDBC ドライバー
module.xml
ファイル<?xml version="1.0" ?> <module xmlns="urn:jboss:module:1.1" name="com.mysql"> <resources> <resource-root path="mysql-connector-java-5.1.36-bin.jar"/> </resources> <dependencies> <module name="javax.api"/> <module name="javax.transaction.api"/> </dependencies> </module>
管理 CLI を使用したカスタムモジュールの作成
module add
管理 CLI コマンドを使用してカスタムモジュールを作成できます。
module
管理 CLI コマンドを使用したモジュールの追加および削除は、テクノロジープレビューとしてのみ提供されます。管理対象ドメインの場合や、リモートで管理 CLI へ接続する場合は、このコマンドは使用しないでください。本番環境ではモジュールを手作業で 追加 および 削除 してください。
テクノロジープレビューの機能は、Red Hat の本番環境のサービスレベルアグリーメント (SLA) ではサポートされず、機能的に完全ではないことがあるため、Red Hat は本番環境での使用は推奨しません。テクノロジープレビューの機能は、最新の技術をいち早く提供して、開発段階で機能のテストやフィードバックの収集を可能にするために提供されます。
テクノロジープレビュー機能のサポート範囲については、Red Hat カスタマーポータルの「テクノロジプレビュー機能のサポート範囲」を参照してください。
- JBoss EAP サーバーを起動します。
管理 CLI を起動しますが、稼働しているインスタンスへの接続に
--connect
または-c
引数を使用しないでください。$ EAP_HOME/bin/jboss-cli.sh
module add
管理 CLI コマンドを使用して新しいコアモジュールを追加します。module add --name=MODULE_NAME --resources=PATH_TO_RESOURCE --dependencies=DEPENDENCIES
例: MySQL モジュールの作成
module add --name=com.mysql --resources=/path/to/mysql-connector-java-5.1.36-bin.jar --dependencies=javax.api,javax.transaction.api
独自の
module.xml
ファイルの提供、外部モジュールディレクトリーの使用、モジュールの代替スロットの指定など、このコマンドのカスタマイズに使用できる引数については、「モジュールコマンド引数」を参照してください。また、module --help
を実行すると、このコマンドを使用したモジュールの追加および削除に関する詳細を表示することもできます。
モジュールを依存関係として追加
アプリケーションがこのモジュールのリソースにアクセスできるようにするには、モジュールを依存関係として追加する必要があります。
- デプロイメント記述子を使用してアプリケーション固有の依存関係を追加するには、『開発ガイド』の「デプロイメントへの明示的なモジュール依存関係の追加」を参照してください。
- モジュールを依存関係としてすべてのアプリケーションに追加する手順については「グローバルモジュールの定義 」の項を参照してください。
たとえば、以下の手順は複数のプロパティーファイルが含まれる JAR ファイルをモジュールとして追加し、グローバルモジュールを定義して、アプリケーションがこれらのプロパティーをロードできるようにします。
JAR ファイルをコアモジュールとして追加します。
module add --name=myprops --resources=/path/to/properties.jar
すべてのデプロイメントが使用できるようにするため、このモジュールをグローバルモジュールとして定義します。
/subsystem=ee:list-add(name=global-modules,value={name=myprops})
アプリケーションは、JAR 内に含まれるプロパティーファイルの 1 つからプロパティーを読み出すことができます。
Thread.currentThread().getContextClassLoader().getResource("my.properties");
6.4. カスタムモジュールの削除
カスタムモジュールは、手作業 または管理 CLI を使用して削除できます。
手作業によるカスタムモジュールの削除
モジュールを手作業で削除する前に、デプロイされたアプリケーションやサーバー設定 (データソースなど) がそのモジュールを必要としていないことを確認してください。
カスタムモジュールを削除するには、module.xml
ファイルと関連する JAR ファイルまたはその他のリソースが含まれる EAP_HOME/modules/
以下にあるモジュールのディレクトリーを削除します。たとえば、main
スロットのカスタム MySQL JDBC ドライバーモジュールを削除するには、 EAP_HOME/modules/com/mysql/main/
ディレクトリーを削除します。
管理 CLI を使用したカスタムモジュールの削除
module remove
管理 CLI コマンドを使用するとカスタムモジュールを削除できます。
module
管理 CLI コマンドを使用したモジュールの追加および削除は、テクノロジープレビューとしてのみ提供されます。管理対象ドメインの場合や、リモートで管理 CLI へ接続する場合は、このコマンドは使用しないでください。本番環境ではモジュールを手作業で 追加 および 削除 してください。
テクノロジープレビューの機能は、Red Hat の本番環境のサービスレベルアグリーメント (SLA) ではサポートされず、機能的に完全ではないことがあるため、Red Hat は本番環境での使用は推奨しません。テクノロジープレビューの機能は、最新の技術をいち早く提供して、開発段階で機能のテストやフィードバックの収集を可能にするために提供されます。
テクノロジープレビュー機能のサポート範囲については、Red Hat カスタマーポータルの「テクノロジプレビュー機能のサポート範囲」を参照してください。
- JBoss EAP サーバーを起動します。
管理 CLI を起動しますが、稼働しているインスタンスへの接続に
--connect
または-c
引数を使用しないでください。$ EAP_HOME/bin/jboss-cli.sh
module remove
管理 CLI コマンドを使用してカスタムモジュールを削除します。module remove --name=MODULE_NAME
-
削除するモジュールが
main
以外のスロットにある場合は、--slot
引数を使用します。
例: MySQL モジュールの削除
module remove --name=com.mysql
-
削除するモジュールが
module --help
を実行すると、このコマンドを使用したモジュールの追加および削除の詳細を表示できます。
6.5. グローバルモジュールの定義
モジュールを依存関係としてすべてのデプロイメントに追加する、グローバルモジュールのリストを定義できます。
グローバルモジュールとして設定するモジュールの名前を知っている必要があります。含まれるモジュールの完全リストと、それらのモジュールがサポートされるかどうかについては、Red Hat カスタマーポータルの「Red Hat JBoss Enterprise Application Platform 7 に含まれるモジュール」を参照してください。
以下の管理 CLI コマンドを使用してグローバルモジュールのリストを定義します。
/subsystem=ee:write-attribute(name=global-modules,value=[{name=MODULE_NAME_1},{name=MODULE_NAME_2}]
以下の管理 CLI コマンドを使用して、1 つのモジュールを既存のグローバルモジュールのリストに追加します。
/subsystem=ee:list-add(name=global-modules,value={name=MODULE_NAME})
管理コンソールを使用してグローバルモジュールを追加および削除することもできます。Configuration タブから EE サブシステムに移動し、Global Modules セクションを選択します。
6.6. サブデプロイメント分離の設定
エンタープライズアーカイブ (EAR) の各サブデプロイメントは、独自のクラスローダーを持つ動的モジュールです。サブデプロイメントは、EAR/lib
のクラスへのアクセスを提供する親モジュールの暗黙的な依存関係を常に持ちます。デフォルトでは、サブデプロイメントはその EAR 内にある他のサブデプロイメントのリソースにアクセスできます。
サブデプロイメントが他のサブデプロイメントに属するクラスにアクセスできないようにするには、JBoss EAP で厳格なサブデプロイメント分離を有効にします。この設定はすべてのデプロイメントに影響します。
すべてのデプロイメントを対象とするサブデプロイメントモジュール分離の有効化
サブデプロイメント分離は ee
サブシステムから管理コンソールまたは管理 CLI を使用して有効または無効にできます。デフォルトでは、サブデプロイメント分離は false に設定され、サブデプロイメントは EAR 内にある他のサブデプロイメントのリソースにアクセスできます。
以下の管理 CLI を使用して EAR サブデプロイメント分離を有効にします。
/subsystem=ee:write-attribute(name=ear-subdeployments-isolated,value=true)
EAR のサブデプロイメントは他のサブデプロイメントからリソースにアクセスできなくなります。
6.7. 外部 JBoss EAP モジュールディレクトリーの定義
JBoss EAP モジュールのデフォルトのディレクトリーは EAP_HOME/modules
です。JBOSS_MODULEPATH
変数を使用すると JBoss EAP モジュールの他のディレクトリーを指定できます。以下の手順に従って、JBoss EAP 起動設定ファイルでこの変数を設定します。
JBOSS_MODULEPATH
を JBoss EAP 起動設定ファイルで設定する代わりに、環境変数として設定することもできます。
起動設定ファイルを編集します。
-
スタンドアロンサーバーとして実行している場合は、
EAP_HOME/bin/standalone.conf
ファイル (Windows Server の場合はstandalone.conf.bat
) を編集します。 -
管理対象ドメインで実行している場合は、
EAP_HOME/bin/domain.conf
ファイル (Windows Server の場合はdomain.conf.bat
) を編集します。
-
スタンドアロンサーバーとして実行している場合は、
JBOSS_MODULEPATH
変数を設定します。例を以下に示します。JBOSS_MODULEPATH="/path/to/modules/directory/"
ディレクトリーのリストを指定するには、ディレクトリーのリストをコロン (
:
) で区切ります。注記Windows Server の場合、次の構文を使用して
JBOSS_MODULEPATH
変数を設定します。set "JBOSS_MODULEPATH /path/to/modules/directory/"
ディレクトリーのリストを指定するには、ディレクトリーのリストをセミコロン (
;
) で区切ります。
6.8. 動的モジュールの命名規則
JBoss EAP では、すべてのデプロイメントが、以下の規則に従って名前が付けられたモジュールとしてロードされます。
WAR および JAR ファイルのデプロイメントは次の形式で名前が付けられます。
deployment.DEPLOYMENT_NAME
たとえば、
inventory.war
とstore.jar
のモジュール名はそれぞれdeployment.inventory.war
とdeployment.store.jar
になります。エンタープライズアーカイブ (EAR) 内のサブデプロイメントは次の形式で名前が付けられます。
deployment.EAR_NAME.SUBDEPLOYMENT_NAME
たとえば、エンタープライズアーカイブ
accounts.ear
内にあるreports.war
のサブデプロイメントのモジュール名はdeployment.accounts.ear.reports.war
になります。