Jakarta Enterprise Beans アプリケーションの開発
Red Hat JBoss Enterprise Application Platform 用の Jakarta Enterprise Beans アプリケーションの開発およびデプロイを行う開発者および管理者の手順と情報。
概要
JBoss EAP ドキュメントへのフィードバック (英語のみ)
エラーを報告したり、ドキュメントを改善したりするには、Red Hat Jira アカウントにログインし、課題を送信してください。Red Hat Jira アカウントをお持ちでない場合は、アカウントを作成するように求められます。
手順
- このリンクをクリック してチケットを作成します。
- ドキュメント URL、セクション番号、課題の説明 を記入してください。
- Summary に課題の簡単な説明を入力します。
- Description に課題や機能拡張の詳細な説明を入力します。問題があるドキュメントのセクションへの URL を含めてください。
- Submit をクリックすると、課題が作成され、適切なドキュメントチームに転送されます。
多様性を受け入れるオープンソースの強化
Red Hat では、コード、ドキュメント、Web プロパティーにおける配慮に欠ける用語の置き換えに取り組んでいます。まずは、マスター (master)、スレーブ (slave)、ブラックリスト (blacklist)、ホワイトリスト (whitelist) の 4 つの用語の置き換えから始めます。この取り組みは膨大な作業を要するため、今後の複数のリリースで段階的に用語の置き換えを実施して参ります。詳細は、Red Hat CTO である Chris Wright のメッセージ をご覧ください。
第1章 はじめに
1.1. Jakarta Enterprise Bean の概要
Jakarta Enterprise Beans は、Enterprise Bean と呼ばれるサーバー側のコンポーネントを使用して、分散型のトランザクション型のセキュアな移植可能な Jakarta EE アプリケーションを開発するための API です。エンタープライズ Bean は、再利用を促すような分離方法でアプリケーションのビジネスロジックを実装します。Jakarta Enterprise Beans は Jakarta Enterprise Beans 3.2 仕様 に文書化されています。
1.2. Jakarta Enterprise Beans 3.2 機能セット
以下の Jakarta Enterprise Beans 3.2 機能は、JBoss EAP 7.3 以降のバージョンでサポートされます。
- セッション Bean
- メッセージ駆動 Bean
- Jakarta Enterprise Beans API グループ
- インターフェイスなしビュー
- ローカルインターフェイス
- リモートインターフェイス
- AutoClosable インターフェイス
- タイマーサービス
- 非同期呼び出し
- Jakarta Interceptors
- RMI/IIOP の相互運用性
- トランザクションサポート
- セキュリティー
- 組み込み API
以下の機能は JBoss EAP 7 ではサポートされなくなりました。
- EJB 2.1 エンティティー Bean クライアントビュー
- Bean 管理の永続性のあるエンティティー Bean
- コンテナー管理の永続性のあるエンティティー Bean
- EJB クエリー言語 (EJB QL)
- JAX-RPC ベースの Web サービス: エンドポイントおよびクライアントビュー
1.3. エンタープライズ Bean
Enterprise Bean は Java クラスとして記述され、適切な Jakarta Enterprise Beans アノテーションが付けられたアノテーションでアノテーションが付けられます。Jakarta EE アプリケーションの一部としてデプロイすることも、独自のアーカイブ (JAR ファイル) でアプリケーションサーバーにデプロイできます。アプリケーションサーバーは、各エンタープライズ bean のライフサイクルを管理し、セキュリティー、トランザクション、同時実行管理などのサービスを提供します。
また、エンタープライズ Bean は任意の数のビジネスインターフェイスを定義できます。ビジネスインターフェイスは、クライアントで利用できる Bean のメソッドの制御を強化し、リモート JVM で実行しているクライアントへのアクセスも許可します。
エンタープライズ Bean には、セッション Bean、メッセージ駆動 Beanエンティティー Bean の 3 つの Bean があります。
JBoss EAP はエンティティー Bean をサポートしません。
1.3.1. エンタープライズ Bean の作成
エンタープライズ Bean は、Java アーカイブ (JAR) ファイルにパッケージ化され、デプロイされます。エンタープライズ Bean JAR ファイルをアプリケーションサーバーにデプロイしたり、エンタープライズアーカイブ (EAR) ファイルに組み込み、そのアプリケーションでデプロイしたりできます。また、Web アプリケーションとともに Web アーカイブ (WAR) ファイルにエンタープライズ Bean をデプロイすることもできます。
1.4. エンタープライズ Bean のビジネスインターフェイス
Jakarta Enterprise Beans ビジネスインターフェイスは、Bean 開発者が作成する Java インターフェイスで、クライアントで利用可能なセッション Bean のパブリックメソッドの宣言を提供する 。セッション Bean は任意の数のインターフェイスを実装できます。なし ( no-interface bean) も含まれます。
ユーザーインターフェイスは、ローカルインターフェイスまたはリモートインターフェイスとして宣言できますが、両方に宣言することはできません。
Jakarta Enterprise Beans ローカルビジネスインターフェイス
Jakarta Enterprise Beans ローカルビジネスインターフェイスは、Bean とクライアントが同じ JVM にある場合に使用できるメソッドを宣言します。セッション Bean がローカルビジネスインターフェイスを実装すると、そのインターフェイスで宣言されたメソッドのみがクライアントで利用できます。
Jakarta Enterprise Beans リモートビジネスインターフェイス
Jakarta Enterprise Beans リモートビジネスインターフェイスは、リモートクライアントで使用できるメソッドを宣言します。リモートインターフェイスを実装するセッション Bean へのリモートアクセスは、Jakarta Enterprise Beans コンテナーにより自動的に提供されます。
リモートクライアントは、異なる JVM で実行されているクライアントです。また、デスクトップアプリケーションや、異なるアプリケーションサーバーにデプロイされた Web アプリケーション、サービス、およびエンタープライズ Bean を含めることができます。
ローカルクライアントは、リモートビジネスインタフェースで公開されるメソッドにアクセスできます。
Jakarta Enterprise Beans No-interface Beans
いずれのビジネスインターフェイスも実装しないセッション Bean は、インターフェイスなしの bean (no-interface bean) と呼ばれます。no-interface Bean のすべてのパブリックメソッドは、ローカルクライアントからアクセスできます。
また、ビジネスインターフェイスを実装するセッション Bean を作成して、no-interface ビューを公開することもできます。
1.5. レガシー EJB クライアントの互換性
JBoss EAP は、リモート Jakarta Enterprise Beans コンポーネントを呼び出すプライマリー API として Jakarta Enterprise Beans クライアントライブラリーを提供します。
JBoss EAP 7.1 より、以下の 2 つの Jakarta Enterprise Beans クライアントが同梱されるようになりました。
- Enterprise Beans クライアント: 通常の Enterprise Beans クライアントは完全に後方互換性がありません。
- レガシー EJB クライアント: レガシー EJB クライアントはバイナリー後方互換性を提供します。このレガシー EJB クライアントは、JBoss EAP 7.0 の EJB クライアントを使用して最初にコンパイルされたクライアントアプリケーションで実行できます。JBoss EAP 7.0 の EJB クライアントに存在していたすべての API は、JBoss EAP 7.4 のレガシー EJB クライアントにあります。
以下の Maven 依存関係を設定に含めると、レガシー EJB クライアントの互換性を使用できます。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jboss.eap</groupId>
<artifactId>wildfly-ejb-client-legacy-bom</artifactId>
<version>EAP_BOM_VERSION</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jboss-ejb-client-legacy</artifactId>
</dependency>
</dependencies>
JBoss EAP Maven リポジトリーで利用可能な EAP_BOM_VERSION を使用する必要があります。
第2章 エンタープライズ Bean プロジェクトの作成
2.1. Red Hat CodeReady Studio を使用した Jakarta Enterprise Beans アーカイブプロジェクトの作成
ここでは、Red Hat CodeReady Studio で Jakarta Enterprise Beans プロジェクトを作成する方法を説明します。
要件
JBoss EAP のサーバーランタイムおよびサーバーランタイムが Red Hat CodeReady Studio で設定されています。
注記Red Hat CodeReady Studio で Target runtime を 7.4 以降に設定し、プロジェクトは Jakarta EE 8 仕様と互換性があります。
Red Hat CodeReady Studio における Jakarta Enterprise Beans プロジェクトの作成
New EJB Project ウィザードを開きます。
- File メニューに移動して New を選択し、Project を選択します。
New Project ウィザードが表示されたら、EJB/EJB Project を選択して Next をクリックします。
図2.1 新しい EJB プロジェクトウィザード
以下の詳細を入力します。
- Project name: Red Hat CodeReady Studio に表示されるプロジェクトの名前、およびデプロイされた JAR ファイルのデフォルトのファイル名。
- Project location: プロジェクトファイルが保存されるディレクトリー。デフォルトは、現在のワークスペースのディレクトリーです。
- Target runtime: これは、プロジェクトに使用されるサーバーランタイムです。これは、デプロイするサーバーによって使用されるものと同じ JBoss EAP ランタイムに設定する必要があります。
- Jakarta Enterprise Beans モジュールバージョン: これは、エンタープライズ Bean が準拠する EJB 仕様のバージョンです。Red Hat は、3.2 の使用を推奨します。
Configuration: これにより、プロジェクトで対応している機能を調整することができます。選択したランタイムにデフォルト設定を使用します。
Next をクリックして先に進みます。
Java プロジェクト設定画面では、Java ソースファイルを含むディレクトリーを追加し、ビルドの出力用にディレクトリーを指定できます。
この設定は変更せず、Next をクリックします。
EJB Module 設定画面で、デプロイメント記述子が必要な場合に ejb-jar.xml デプロイメント記述子の生成 を確認します。デプロイメント記述子は Jakarta Enterprise Beans 3.2 では任意で、必要な場合は後で追加できます。
Finish をクリックするとプロジェクトが作成され、Project Explorer に表示されます。
図2.2 Project Explorer で新たに作成された Jakarta Enterprise Beans プロジェクト
デプロイメントのためにプロジェクトをサーバーに追加するには、Servers タブで対象のサーバーを右クリックし、Add and Remove を選択します。
Add and Remove ダイアログで、Available コラムからデプロイするリソースを選択して、Add ボタンをクリックします。リソースは Configured コラムに移動します。Finish をクリックしてダイアログを閉じます。
図2.3 ダイアログの追加または削除
これで、Red Hat CodeReady Studio には、指定のサーバーにビルドしてデプロイできる Jakarta Enterprise Beans プロジェクトができました。
プロジェクトにエンタープライズ bean が追加されない場合、Red Hat CodeReady Studio は、An EJB module must contain one or more enterprise beans (EJB モジュールには、1 つ以上のエンタープライズ Bean が必要です) という警告が表示されます。この警告は、エンタープライズ Bean がプロジェクトに追加されると消えます。
2.2. Maven での Jakarta Enterprise Beans アーカイブプロジェクトの作成
このタスクは、JAR ファイルにパッケージ化されたエンタープライズ Bean を含む Maven を使用してプロジェクトを作成する方法を示しています。
要件
- Maven がすでにインストールされている。
- Maven の基本的な使用方法を理解している。
Maven での Jakarta Enterprise Beans アーカイブプロジェクトの作成
Create the Maven project: Jakarta Enterprise Beans プロジェクトは、Maven のアーキテクトシステムと
ejb-javaee7
アーキテクトタイプを使用して作成できます。これを実行するには、以下のパラメーターを指定してmvn
コマンドを実行します。$ mvn archetype:generate -DarchetypeGroupId=org.codehaus.mojo.archetypes -DarchetypeArtifactId=ejb-javaee7
Maven はプロジェクトの
groupId
、artifactId
、version
、package
をプロンプトします。$ mvn archetype:generate -DarchetypeGroupId=org.codehaus.mojo.archetypes -DarchetypeArtifactId=ejb-javaee7 [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-javaee7:1.5] found in catalog remote Define value for property 'groupId': : com.shinysparkly Define value for property 'artifactId': : payment-arrangements Define value for property 'version': 1.0-SNAPSHOT: : Define value for property 'package': com.shinysparkly: : Confirm properties configuration: groupId: com.company artifactId: payment-arrangements 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]$
-
Add your enterprise beans: エンタープライズ Bean を作成し、Bean のパッケージの適切なサブディレクトリーにある
src/main/java
ディレクトリーの下のプロジェクトに追加します。 -
Build the project: プロジェクトを構築するには、
pom.xml
ファイルと同じディレクトリーでmvn package
コマンドを実行します。これにより、Java クラスがコンパイルされ、JAR ファイルがパッケージ化されます。ビルド JAR ファイルの名前は-.jar
です。このファイルは、target/
ディレクトリーに置かれます。
これで、JAR ファイルをビルドし、パッケージ化する Maven プロジェクトが作成されました。これでプロジェクトにはエンタープライズ Bean を含めることができるようになりました。このプロジェクトは、JAR ファイルはアプリケーションサーバーにデプロイできます。
2.3. Jakarta Enterprise Beans プロジェクトを含む EAR プロジェクトの作成
このタスクでは、Jakarta Enterpise Beans プロジェクトを含む Red Hat CodeReady Studio で新しいエンタープライズアーカイブ (EAR) プロジェクトを作成する方法を説明します。
要件
JBoss EAP のサーバーおよびサーバーランタイムが設定されている。
注記Red Hat CodeReady Studio で Target runtime を 7.4 以降に設定し、プロジェクトは Jakarta EE 8 仕様と互換性があります。
Jakarta Enterprise Beans プロジェクトを含む EAR プロジェクトの作成
New Java EE EAR Project ウィザードを開きます。
- File メニューに移動して New を選択し、Project を選択します。
- New Project ウィザードが表示されたら、Java EE/Enterprise Application Project を選択し、Next をクリックします。
図2.4 新規 EAR アプリケーションプロジェクトウィザード
以下の詳細を入力します。
- Project name: Red Hat CodeReady Studio に表示されるプロジェクトの名前、およびデプロイされた EAR ファイルのデフォルトのファイル名。
- Project location: プロジェクトファイルが保存されるディレクトリー。デフォルトは、現在のワークスペースのディレクトリーです。
- Target runtime: これは、プロジェクトに使用されるサーバーランタイムです。これは、デプロイするサーバーによって使用されるものと同じ JBoss EAP ランタイムに設定する必要があります。
EAR version: これは、プロジェクトが準拠する Jakarta EE 8 仕様のバージョンです。
Red Hat は Jakarta EE 8 を使用することを推奨します。
Configuration: これにより、プロジェクトで対応している機能を調整することができます。選択したランタイムにデフォルト設定を使用します。
Next をクリックして先に進みます。
新しい Jakarta Enterprise Beans モジュールを追加します。
ウィザードの Enterprise Applicaiton ページから、新しいモジュールを追加できます。新しい Jakarta Enterprise Beans プロジェクトをモジュールとして追加するには、以下の手順に従います。
- New Moduleをクリックし、Create Default Modules チェックボックスのチェックを外し、Enterprise Java Bean を選択して Next をクリックします。New EJB Project ウィザード が表示されます。
New EJB Project ウィザードは、新しいスタンドアロン Jakarta Enterprise Beans プロジェクトの作成に使用されるウィザードと同じで、Create Jakarta Enterprise Beans Archive Project Using Red Hat CodeReady Studio で説明されています。
プロジェクトの作成に必要な最低限の詳細は、以下のとおりです。
- プロジェクト名
- ターゲットランタイム
- Jakarta Enterprise Beans モジュールバージョン
Configuration (設定)
ウィザードの他のすべての手順はオプションです。Finish をクリックして Jakarta Enterprise Beans プロジェクトの作成を完了します。
新規作成した Jakarta Enterprise Beans プロジェクトは Java EE モジュール依存関係にリスト表示され、チェックボックスにチェックが付けられます。
オプションで、
application.xml
デプロイメント記述子を追加します。必要な場合は、Generate application.xml deployment descriptor チェックボックスにチェックを入れます。
Finish をクリックします。
Jakarta Enterprise Beans と EAR という 2 つのプロジェクトが表示されます。
デプロイメントを行うためにサーバーにビルドアーティファクトを追加します。
Server タブで、ビルドされたアーティファクトをデプロイするサーバーの Servers タブで Add and Remove ダイアログを開き、Add and Remove を選択します。
Available コラムからデプロイする EAR リソースを選択し、Add ボタンをクリックします。リソースは Configured コラムに移動します。Finish をクリックしてダイアログを閉じます。
図2.5 ダイアログの追加または削除
これで、メンバー Jakarta Enterprise Beans プロジェクトを含む Enterprise Application Project ができました。これにより、Jakarta Enterprise Beans サブデプロイメントを含む単一の EAR デプロイメントとして指定のサーバーにビルドされ、デプロイされます。
2.4. Jakarta Enterprise Beans プロジェクトへのデプロイメント記述子の追加
Jakarta Enterprise Beans デプロイメント記述子は、1 つなしで作成された Jakarta Enterprise Beans プロジェクトに追加できます。これを行うには、以下の手順に従います。
要件
- Jakarta Enterprise Beans デプロイメント記述子を追加する Red Hat CodeReady Studio に Jakarta Enterprise Beans プロジェクトがある。
Jakarta Enterprise Beans プロジェクトへのデプロイメント記述子の追加
- Red Hat CodeReady Studio でプロジェクトを開きます。
デプロイメント記述子を追加します。
プロジェクトビューの Deployment Descriptor フォルダーを右クリックして、Generate Deployment Descriptor タブを選択します。
図2.6 デプロイメント記述子の追加
新しいファイル
ejb-jar.xml
がejbModule/META-INF/
に作成されます。プロジェクトビューの Deployment Descriptor フォルダーをダブルクリックして、このファイルを開きます。
2.5. Bean のランタイムデプロイメント情報
パフォーマンス監視のために、Bean にランタイムデプロイメント情報を追加できます。
利用可能なランタイムデータの詳細は、JBoss EAP 管理モデルの ejb3
サブシステムを参照してください。アプリケーションには、Bean コードまたはデプロイメント記述子にアノテーションとしてランタイムデータが含まれています。アプリケーションは両方のオプションを使用できます。
関連情報
-
使用可能なランタイムデータの詳細については、JBoss EAP 管理モデルの
ejb3
サブシステム を参照してください。 - ランタイムデータを取得してパフォーマンスを評価する方法は、JBoss EAP パフォーマンスチューニングガイド を参照してください。
第3章 セッション Bean
3.1. セッション Bean
セッション Bean は、関連する一連のビジネスプロセスまたはタスクをカプセル化し、それらを要求するクラスにインジェクトするエンタープライズ Bean です。セッション bean のタイプには、ステートレス、ステートフル、シングルトンの 3 つがあります。
3.2. ステートレスセッション Bean
ステートレスセッション Bean は、最も広く使用されているセッション Bean のタイプです。クライアントアプリケーションにビジネスメソッドを提供しますが、メソッド呼び出し間の状態を維持しません。各メソッドは、セッション Bean 内の共有状態に依存しない完全なタスクです。状態がないため、アプリケーションサーバーでは、各メソッド呼び出しが同じインスタンスで実行されるようにする必要はありません。これにより、ステートレスセッション Bean は非常に効率的でスケーラブルなものになります。
3.3. ステートフルセッション Bean
ステートフルセッション Bean は、ビジネスメソッドをクライアントアプリケーションに提供するエンタープライズ Bean で、クライアントとの会話状態を維持します。これは、複数の手順で実行する必要があるタスク、またはメソッド呼び出しに使用してください。これらの各タスクは、維持される前のステップの状態に依存します。アプリケーションサーバーは、各クライアントが各メソッド呼び出しに対してステートフルセッション Bean の同じインスタンスを受け取るようにします。
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 タイプのメモリーフットプリントを最小限に抑えますが、スレッドセーフとして設計する必要があります。Jakarta Enterprise Beans 3.2 では、開発者がスレッドセーフシングルトン Bean を簡単に実装できるように、コンテナー管理コンカレンシー (デプロイメント) を利用できます。ただし、CMC が詳細な柔軟性を提供しない場合、従来のマルチスレッドコード (Bean-managed Concurrency または BMC) を使用してシングルトン bean を書き込むこともできます。
3.5. Red Hat CodeReady Studio でプロジェクトにセッション Bean を追加する
Red Hat CodeReady Studio には、エンタープライズ bean クラスを迅速に作成するのに使用できるいくつかのウィザードがあります。以下の手順では、Red Hat CodeReady Studio ウィザードを使用してセッション bean をプロジェクトに追加する方法を示します。
要件
- 1 つ以上のセッション Bean を追加する Red Hat CodeReady Studio に Jakarta Enterprise Beans または動的 Web プロジェクトがある。
Red Hat CodeReady Studio でプロジェクトにセッション Bean を追加する
- Red Hat CodeReady Studio でプロジェクトを開きます。
Create EJB 3.x Session Bean ウィザードを開きます。
Create EJB 3.x Session Bean ウィザードを開くには、File メニューに移動し、New を選択して Session Bean (EJB 3.x) を選択します。
図3.1 Create EJB 3.x Session Bean ウィザード
以下の詳細を指定します。
- Project: 正しいプロジェクトが選択されていることを確認します。
- Source folder: これは、Java ソースファイルが作成されるフォルダーです。通常、これは変更する必要はありません。
- Package: クラスが属するパッケージを指定します。
- Class name: セッション Bean になるクラスの名前を指定します。
- Superclass: セッション Bean クラスはスーパークラスから継承できます。セッションにスーパークラスがある場合は、これを指定します。
- State type: セッション Bean の状態タイプ (stateless、stateful、または singleton) を指定します。
Business interfaces: デフォルトでは、No-interface ボックスがチェックされるため、インターフェイスは作成されません。定義するインターフェイスのボックスにチェックを入れ、必要に応じて名前を調整します。
Web アーカイブ (WAR) のエンタープライズ Bean は Jakarta Enterprise Beans 3.2 Lite のみをサポートし、これにはリモートビジネスインターフェイスが含まれないことに注意してください。
次へ をクリックします。
ここで追加情報を入力して、セッション Bean をさらにカスタマイズできます。ここで情報を変更する必要はありません。
変更可能なアイテムは次のとおりです。
- Bean 名
- マップされた名前
- トランザクションタイプ (マネージドコンテナーまたはマネージド Bean)
- Bean が実装する必要のある追加のインターフェイスを指定可能
- EJB 2.x Home and Component インターフェイスを必要に応じて指定することもできます。
Finish をクリックすると、新しいセッション Bean が作成され、プロジェクトに追加されます。新しいビジネスインターフェイスのファイルが指定されていれば、それらも作成されます。
図3.2 Red Hat CodeReady Studio の新しいセッション Bean
第4章 メッセージ駆動 Bean
4.1. メッセージ駆動 Bean
メッセージ駆動 Bean (MDB) は、アプリケーション開発のイベント駆動モデルを提供します。MDB のメソッドは、クライアントコードにインジェクトされず、クライアントコードから呼び出しませんが、Jakarta Messaging サーバーなどのメッセージングサービスからのメッセージの受信によってトリガーされます。Jakarta EE 仕様では Jakarta Messaging に対応する必要がありますが、他のメッセージングシステムも同様にサポートすることができます。
MDB は、特別なタイプのステートレスセッション Bean です。onMessage (Message message)
というメソッドを実装します。この方法は、MDB リッスンしている Jakarta Messaging の宛先がメッセージを受信するとトリガーされます。つまり、MDB は Jakarta Messaging プロバイダーからのメッセージを受信してトリガーされます。通常、メソッドが Jakarta Enterprise Beans クライアントによって呼び出されるステートレスセッション Bean とは異なります。
MDB は非同期にメッセージを処理します。デフォルトでは、各 MDB は最大 16 のセッションを持つことができ、そこで各セッションがメッセージを処理できます。メッセージの順番の保証はありません。メッセージの順序付けを行うには、MDB のセッションプールを 1
に制限する必要があります。
例: セッションプールを 1
に設定する管理 CLI コマンド
/subsystem=ejb3/strict-max-bean-instance-pool=mdb-strict-max-pool:write-attribute(name=derive-size,value=undefined) /subsystem=ejb3/strict-max-bean-instance-pool=mdb-strict-max-pool:write-attribute(name=max-pool-size,value=1) reload
4.2. メッセージ駆動 Bean が制御する配信
JBoss EAP は、特定の MDB でメッセージのアクティブな受信を制御する以下の属性を提供します。
4.2.1. Delivery Active
メッセージ駆動 Bean (MDB) の配信アクティブ (Delivery Active) 設定は、MDB がメッセージを受信しているかどうかを示します。MDB がメッセージを受信していない場合、メッセージはトピックまたはキューのルールに従ってキューまたはトピックに保存されます。
XML またはアノテーションを使用して delivery-group
の active
属性を設定できます。また、管理 CLI を使用してデプロイメント後にこの値を変更できます。デフォルトでは、active
属性が有効になり、MDB がデプロイされるとすぐにメッセージの配信が行われます。
Jboss-ejb3.xml ファイルでの Delivery Active の設定
Jboss-ejb3.xml
ファイルで active
の値を false
に設定し、MDB がデプロイされた直後にメッセージを受信しないことを示します。
<?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:d="urn:delivery-active:1.1" xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd" version="3.1" impl-version="2.0"> <assembly-descriptor> <d:delivery> <ejb-name>HelloWorldQueueMDB</ejb-name> <d:active>false</d:active> </d:delivery> </assembly-descriptor> </jboss:ejb-jar>
アプリケーションのすべての MDB にアクティブな値を適用する場合は、ejb-name
の代わりにワイルドカード *
を使用できます。
アノテーションを使用した Delivery Active の設定
org.jboss.ejb3.annotation.DeliveryActive
アノテーションを使用することもできます。例を以下に示します。
@MessageDriven(name = "HelloWorldMDB", activationConfig = { @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/HELLOWORLDMDBQueue"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") }) @DeliveryActive(false) public class HelloWorldMDB implements MessageListener { public void onMessage(Message rcvMessage) { // ... } }
Maven を使用してプロジェクトをビルドする場合は、以下の依存関係をプロジェクトの pom.xml
ファイルに追加してください。
<dependency> <groupId>org.jboss.ejb3</groupId> <artifactId>jboss-ejb3-ext-api</artifactId> <version>2.2.0.Final</version> </dependency>
管理 CLI を使用した配信アクティブの設定
管理 CLI を使用して、デプロイメント後に delivery-group
の active
属性を設定できます。これらの管理操作は、active
属性の値を動的に変更し、MDB の配信を有効または無効にします。Delivery Actgive の値を変更するこの方法は、サーバーを再起動しても維持されません。実行時に、管理するインスタンスに接続し、配信を管理する MDB のパスを入力します。例を以下に示します。
管理するインスタンスに移動します。
cd deployment=helloworld-mdb.war/subsystem=ejb3/message-driven-bean=HelloWorldQueueMDB
MDB への配信を停止するには、以下を行います。
:stop-delivery
MDB への配信を開始するには、以下を行います。
:start-delivery
MDB Delivery Active ステータスの表示
管理コンソールを使用して、MDB の現在の Delivery Active ステータスを表示できます。
- Runtime タブを選択し、該当するサーバーを選択します。
-
EJB をクリックし、
HelloWorldQueueMDB
などの子リソースを選択します。
結果
ステータスは Delivery Active: true
または Delivery Active: false
になります。
4.2.2. 配信グループ
配信グループは、MDB のグループの delivery-active
ステータスを管理する方法を提供します。MDB は、複数の 配信グループに所属できます。メッセージ配信は、MDB が属するすべての配信グループがアクティブの場合にのみ有効になります。クラスター化されたシングルトン MDB の場合、メッセージ配信は、MDB に関連付けられたすべての配信グループがアクティブである場合にのみ、クラスターのシングルトンノードでのみアクティブになります。
XML 設定または管理 CLI のいずれかを使用して ejb3
サブシステムに配信グループを追加できます。
jboss-ejb3.xml ファイルでの配信グループの設定
<delivery> <ejb-name>MdbName<ejb-name> <delivery-group>passive</delivery-group> </delivery>
サーバー側では、以下の例のように active
属性を true
に設定して delivery-groups
を有効にしたり、active
属性を false
に設定して無効にすることができます。
<delivery-groups> <delivery-group name="group" active="true"/> </delivery-groups>
管理 CLI を使用した配信グループの設定
delivery-groups
の状態は、管理 CLI を使用して更新できます。例を以下に示します。
/subsystem=ejb3/mdb-delivery-group=group:add /subsystem=ejb3/mdb-delivery-group=group:remove /subsystem=ejb3/mdb-delivery-group=group:write-attribute(name=active,value=true)
jboss-ejb3.xml
ファイルで Delivery Active を設定するか、アノテーションを使用すると、サーバーを再起動しても保持されます。ただし、管理 CLI を使用して配信を停止または開始すると、サーバーの再起動時に維持されません。
アノテーションを使用した複数の配信グループの設定
グループに属する各 MDB クラスで org.jboss.ejb3.annotation.DeliveryGroup
アノテーションを使用できます。
@MessageDriven(name = "HelloWorldQueueMDB", activationConfig = { @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/HELLOWORLDMDBQueue"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") }) @DeliveryGroup("delivery-group-1") @DeliveryGroup("delivery-group-2") public class HelloWorldQueueMDB implements MessageListener { ... }
4.2.3. Clustered Singleton MDBs
MDB がクラスター化されたシングルトンとして識別され、クラスターにデプロイされると、単一のノードのみがアクティブになります。このノードは、メッセージを順次使用できます。サーバーノードが失敗すると、クラスター化されたシングルトン MDB からのアクティブなノードがメッセージを消費し始めます。
MDB をクラスター化されたシングルトンとして特定
以下のいずれかの手順を使用して、MDB をクラスター化シングルトンとして識別できます。
以下の例のように、clustered-singleton 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.1" xmlns:d="urn:delivery-active:1.2" xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd" version="3.1" impl-version="2.0"> <assembly-descriptor> <c:clustering> <ejb-name>HelloWorldQueueMDB</ejb-name> <c:clustered-singleton>true</c:clustered-singleton> </c:clustering> <d:delivery> <ejb-name>*</ejb-name> <d:group>delivery-group-1</d:group> <d:group>delivery-group-2</d:group> </d:delivery> </assembly-descriptor> </jboss:ejb-jar>
-
MDB クラスで
@org.jboss.ejb3.annotation.ClusteredSingleton
を使用します。この手順では、サーバーに追加の設定は必要ありません。クラスター環境でサービスを実行する必要があります。
singleton master
に選択されているクラスターノードがわからないため、クラスター全体 (具体的にはクラスターのすべてのノード) で delivery-group
を有効化する必要があります。サーバーが singleton master
となるノードを選択し、そのノードに必要な delivery-group
をアクティブにしていない場合、クラスター内のノードはメッセージを受信しません。
JBoss EAP に含まれる messaging-clustering-singleton
クイックスタートは、統合された Apache ActiveMQ Artemis でのクラスタリングの使用を示しています。これは helloworld-mdb
クイックスタートと同じソースコードを使用しますが、設定にのみ違いがあり、クラスター化されたシングルトンとして実行されます。このクイックスタートには、2 つの Jakarta Messaging リソースが含まれています。
-
Java Naming and Directory Interface にバインドされる
HELLOWORLDMDBQueue
という名前のキュー (java:/queue/HELLOWORLDMDBQueue)
-
Java Naming and Directory Interface を
java:/topic/HELLOWORLDMDBTopic
としてバインドするHELLOWORLDMDBTopic
という名前のトピック
いずれも jboss-ejb3.xml
ファイルで指定されるシングルトン設定を含みます。
<c:clustering> <ejb-name>*</ejb-name> <c:clustered-singleton>true</c:clustered-singleton> </c:clustering>
<ejb-name>
要素のワイルドカードアスタリスク *
は、アプリケーションに含まれるすべての MDB がクラスター化シングルトンであることを示しています。これにより、クラスター内の単一のノードのみが、特定の時点で MDB がアクティブになります。このアクティブなノードがシャットダウンすると、クラスター内の別のノードが MDB でアクティブなノードになり、シングルトンプロバイダーになります。
jboss-ejb3.xml
ファイルに、配信グループの設定を検索することもできます。
<d:delivery> <ejb-name>HelloWorldTopicMDB</ejb-name> <d:group>my-mdb-delivery-group</d:group> </d:delivery>
この場合、MDB のいずれかの HelloWorldTopicMDB
のみが配信グループに関連付けられます。MDB が使用するすべて配信グループは、ejb3
サブシステム設定で設定する必要があります。配信グループは有効または無効にできます。クラスターノードで配信グループが無効になっていると、その配信グループに属するすべての MDB が、対応するクラスターノードで非アクティブになります。非クラスター化環境で配信グループを使用する場合は、配信グループが有効になっているたびに MDB がアクティブになります。
配信グループがシングルトンプロバイダーとともに使用されている場合、そのノードで配信グループが有効になっている場合にのみ、MDB をシングルトンプロバイダーノードでアクティブにすることができます。それ以外の場合、MDB はそのノードで非アクティブになり、クラスターの他のすべてのノードは非アクティブになります。
メッセージングクラスタリング用にサーバーを設定する方法や、コード例を確認する方法については、このクイックスタートに含まれている README.html
ファイルを参照してください。
JBoss EAP クイックスタートのダウンロードおよび使用方法の詳細は、JBoss EAPJBoss EAP Getting Started Guideの Using the Quickstart Examples を参照してください。
4.3. Red Hat CodeReady Studio での Jakarta Messaging ベースのメッセージ駆動 Bean の作成
この手順では、Red Hat CodeReady Studio で Jakarta Messaging ベースのメッセージ駆動 Bean をプロジェクトに追加する方法を説明します。この手順では、アノテーションを使用する Jakarta Enterprise Beans 3.x メッセージ駆動 Bean を作成します。
要件
- Red Hat CodeReady Studio で既存のプロジェクトを開いておく必要があります。
- Bean がリッスンする Jakarta Messaging 宛先の名前とタイプを知っている必要があります。
- Jakarta Messaging のサポートは、この Bean がデプロイされる JBoss EAP 設定で有効にする必要があります。
Red Hat CodeReady Studio での Jakarta Messaging ベースのメッセージ駆動 Bean の追加
Create EJB 3.x Message-LoadBalancern Bean ウィザードを開きます。
File → New → Other の順に移動します。EJB/Message-Driven Bean (EJB 3.x) を選択し、Next ボタンをクリックします。
図4.1 Create EJB 3.x Message-Driven Bean ウィザード
クラスファイル宛先の詳細を指定します。
ここでは、bean クラスに指定する詳細セット (プロジェクト、Java クラス、メッセージの宛先) があります。
Project:
- ワークスペースに複数のプロジェクトが存在する場合は、Project メニューで適切なプロジェクトが選択されていることを確認します。
-
新規 Bean のソースファイルが作成されるフォルダーは、選択したプロジェクトのディレクトリーの下の
ejbModule
になります。これは、特定の要件がある場合にのみ変更します。
Java Class:
- 必須フィールドは Java package と Class name です。
- アプリケーションのビジネスロジックで必要な場合を除いて、スーパークラスを指定する必要はありません。
Message Destination:
以下は、Jakarta Messaging ベースのメッセージ駆動 Bean に提供する必要のある詳細です。
- Destination name: Bean が応答するメッセージが含まれるキューまたはトピック名。
- デフォルトでは、JMS チェックボックスが選択されます。これは変更しないでください。
必要に応じて Destination type を Queue または Topic に設定します。
Next ボタンをクリックしてください。
メッセージ駆動 Bean 固有の情報を入力します。
ここでのデフォルト値は、コンテナー管理トランザクションを使用する Jakarta Messaging ベースのメッセージ駆動 Bean に適しています。
- Bean が Bean マネージドトランザクションを使用する場合は、Transaction type を Bean に変更します。
- クラス名とは異なる Bean 名が必要な場合は Bean name を変更します。
- JMS Message Listener インターフェイスはすでにリストされています。インターフェイスがアプリケーションのビジネスロジックに固有のものでない場合は、インターフェイスを追加または削除する必要はありません。
メソッドスタブを作成するためのチェックボックスは選択したままにしておきます。
Finish ボタンをクリックします。
結果
メッセージ駆動 Bean は、デフォルトのコンストラクターと onMessage()
メソッド用のスタブメソッドで作成されます。Red Hat CodeReady Studio エディターウィンドウが開き、対応するファイルが表示されます。
4.4. MDB に対して jboss-ejb3.xml
でのリソースアダプターの指定
jboss-ejb3.xml
デプロイメント記述子では、MDB が使用するリソースアダプターを指定できます。
MDB に対して jboss-ejb3.xml
でリソースアダプターを指定するには、以下の例を使用します。
例: 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>
4.5. MDB のリソース定義アノテーションを使用したクラスターへのデプロイ
@JMSConnectionFactoryDefinition
および @JMSDestinationDefinition
アノテーションを使用して、メッセージ駆動 Bean の接続ファクトリーと宛先を作成する場合は、オブジェクトが MDB がデプロイされたサーバーにのみ作成されることに注意してください。MDB もクラスター内のすべてのノードにデプロイされない限り、クラスターのすべてのノードには作成されません。これらのアノテーションで設定されたオブジェクトは MDB がデプロイされているサーバー上でのみ作成されるため、MDB がリモートサーバーからメッセージを読み取り、リモートサーバーに送信するリモート Jakarta Connectors トポロジーに影響します。
4.6. アプリケーションで Jakarta Enterprise Beans および MDB プロパティーの置換を有効にする
Red Hat JBoss Enterprise Application Platform では、@ActivationConfigProperty
および @Resource
アノテーションを使用して Jakarta Enterprise Beans および MDB でプロパティー置換を有効にできます。プロパティーの置換には、以下の設定およびコードの変更が必要です。
- JBoss EAP サーバー設定ファイルでプロパティー置換を有効にする必要があります。
- JBoss EAP サーバーの起動時に 、 システムプロパティーをサーバー設定ファイルに定義するか、引数として渡す必要があります。
- 置換変数を使用するように アプリケーションコードを変更する 必要があります。
以下の例は、プロパティー置換を使用するために JBoss EAP に同梱される helloworld-mdb
クイックスタートを変更する方法を示しています。完全な作業例は、helloworld-mdb-propertysubstitution
クイックスタートを参照してください。
4.6.1. プロパティー置換を有効にするようにサーバーを設定
JBoss EAP サーバーでプロパティーの置換を有効にするには、サーバー設定の ee
サブシステムの annotation-property-replacement
属性を true
に設定する必要があります。
サーバー設定ファイルをバックアップします。
helloworld-mdb-propertysubstitution
クイックスタートの例では、スタンドアロンサーバーの完全なプロファイルが必要であるため、これはEAP_HOME/standalone/configuration/standalone-full.xml
ファイルになります。マネージドドメインでサーバーを実行している場合は、EAP_HOME/domain/configuration/domain.xml
ファイルになります。JBoss EAP のインストールディレクトリーへ移動し、フルプロファイルでサーバーを起動します。
$ EAP_HOME/bin/standalone.sh -c standalone-full.xml
注記Windows Server の場合は、
EAP_HOME\bin\standalone.bat
スクリプトを使用します。管理 CLI を起動します。
$ EAP_HOME/bin/jboss-cli.sh --connect
注記Windows Server の場合は、
EAP_HOME\bin\jboss-cli.bat
スクリプトを使用します。アノテーションプロパティーの置換を有効にするには、以下のコマンドを実行します。
/subsystem=ee:write-attribute(name=annotation-property-replacement,value=true)
以下の結果が表示されるはずです。
{"outcome" => "success"}
JBoss EAP サーバー設定ファイルへの変更を確認します。
ee
サブシステムには以下の XML が含まれるはずです。ee
サブシステムの設定例<subsystem xmlns="urn:jboss:domain:ee:4.0"> ... <annotation-property-replacement>true</annotation-property-replacement> ... </subsystem>
4.6.2. システムプロパティーの定義
サーバー設定ファイルでシステムプロパティーを指定するか、JBoss EAP サーバーの起動時にコマンドラインの引数としてプロパティーを渡すことができます。サーバー設定ファイルで定義されたシステムプロパティーは、サーバーの起動時にコマンドラインに渡されるプロパティーよりも優先されます。
4.6.2.1. サーバー設定でのシステムプロパティーの定義
- 管理 CLI を起動します。
以下のコマンド構文を使用して、JBoss EAP サーバーのシステムプロパティーを設定します。
システムプロパティーを追加する構文
/system-property=PROPERTY_NAME:add(value=PROPERTY_VALUE)
以下のシステムプロパティーは、
helloworld-mdb-propertysubstitution
クイックスタートに設定されています。システムプロパティーを追加するコマンドの例
/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)
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>
4.6.2.2. サーバー起動時にシステムプロパティーを引数として渡す
必要に応じて、-DPROPERTY_NAME=PROPERTY_VALUE
の形式で JBoss EAP サーバーを起動したときに、コマンドラインで引数を渡すことができます。以下は、前のセクションで定義されたシステムプロパティーの引数を渡す方法の例になります。
サーバー起動コマンドによりシステムプロパティーを渡す例
$ 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
4.6.3. システムプロパティーの置換を使用するようアプリケーションコードを変更します。
ハードコーディングされた @ActivationConfigProperty
および @Resource
アノテーションの値を、新たに定義したシステムプロパティーの置換値に置き換えます。以下は、新たに定義したシステムプロパティーの置換を使用するように helloworld-mdb
クイックスタートを変更する方法の例になります。
HelloWorldQueueMDB
クラスの@ActivationConfigProperty
destination
プロパティー値を変更して、システムプロパティーの置換を使用します。@MessageDriven
アノテーションは以下のようになります。HelloWorldQueueMDB コードの例
@MessageDriven(name = "HelloWorldQueueMDB", activationConfig = { @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "${property.helloworldmdb.queue}"), @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") })
HelloWorldTopicMDB
クラスの@ActivationConfigProperty
destination
プロパティー値を変更して、システムプロパティーの置換を使用します。@MessageDriven
アノテーションは以下のようになります。HelloWorldTopicMDB コードの例
@MessageDriven(name = "HelloWorldQTopicMDB", activationConfig = { @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "${property.helloworldmdb.topic}"), @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") })
HelloWorldMDBServletClient
クラスの@Resource
アノテーションを変更して、システムプロパティーの置換を使用します。コードは以下のようになります。HelloWorldMDBServletClient コードの例
/** * Definition of the two Jakarta Messaging Service destinations used by the quickstart * (one queue and one topic). */ @JMSDestinationDefinitions( value = { @JMSDestinationDefinition( name = "java:/${property.helloworldmdb.queue}", interfaceName = "javax.jms.Queue", destinationName = "HelloWorldMDBQueue" ), @JMSDestinationDefinition( name = "java:/${property.helloworldmdb.topic}", interfaceName = "javax.jms.Topic", destinationName = "HelloWorldMDBTopic" ) }) /** * <p> * A simple servlet 3 as client that sends several messages to a queue or a topic. * </p> * * <p> * The servlet is registered and mapped to /HelloWorldMDBServletClient using the {@linkplain WebServlet * @HttpServlet}. * </p> * * @author Serge Pagop (spagop@redhat.com) * */ @WebServlet("/HelloWorldMDBServletClient") public class HelloWorldMDBServletClient extends HttpServlet { private static final long serialVersionUID = -8314035702649252239L; private static final int MSG_COUNT = 5; @Inject private JMSContext context; @Resource(lookup = "${property.helloworldmdb.queue}") private Queue queue; @Resource(lookup = "${property.helloworldmdb.topic}") private Topic topic; <!-- Remainder of code can be found in the `helloworld-mdb-propertysubstitution` quickstart. -->
システムプロパティーの置換値を使用するように
activemq-jms.xml
ファイルを変更します。.activemq-jms.xml ファイルの例
<?xml version="1.0" encoding="UTF-8"?> <messaging-deployment xmlns="urn:jboss:messaging-activemq-deployment:1.0"> <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> </server> </messaging-deployment>
-
アプリケーションをデプロイします。アプリケーションは、
@Resource
と@ActivationConfigProperty
プロパティー値のシステムプロパティーで指定された値を使用するようになりました。
4.7. アクティベーション設定のプロパティー
4.7.1. アノテーションを使用した MDB の設定
アクティベーションプロパティーは、@ActivationConfigProperty
アノテーションに一致する @MessageDriven
要素とサブ要素を使用してアクティベーションプロパティーを設定できます。@ActivationConfigProperty
は、MDB の設定逢プロパティーのアレイです。@ActivationConfigProperty
アノテーションの仕様は以下のようになります。
@Target(value={}) @Retention(value=RUNTIME) public @interface ActivationConfigProperty { String propertyName(); String propertyValue(); }
@ActivationConfigProperty
を表示する例
@MessageDriven(name="MyMDBName", activationConfig = { @ActivationConfigProperty(propertyName="destinationLookup",propertyValue="queueA"), @ActivationConfigProperty(propertyName = "destinationType",propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"), })
4.7.2. デプロイメント記述子を使用した MDB の設定
ejb-jar.xml
の <message-driven>
要素は、Bean を MDB として定義します。<activation-config>
および要素には、activation-config-property
要素を使用した MDB 設定が含まれます。
サンプル ejb-jar.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" xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd" version="3.1"> <enterprise-beans> <message-driven> <ejb-name>MyMDBName</ejb-name> <ejb-class>org.jboss.tutorial.mdb_deployment_descriptor.bean.MyMDBName</ejb-class> <activation-config> <activation-config-property> <activation-config-property-name>destinationLookup</activation-config-property-name> <activation-config-property-value>queueA</activation-config-property-value> </activation-config-property> <activation-config-property> <activation-config-property-name>destinationType</activation-config-property-name> <activation-config-property-value>javax.jms.Queue</activation-config-property-value> </activation-config-property> <activation-config-property> <activation-config-property-name>acknowledgeMode</activation-config-property-name> <activation-config-property-value>Auto-acknowledge</activation-config-property-value> </activation-config-property> </activation-config> </message-driven> <enterprise-beans> </jboss:ejb-jar>
名前 | 説明 |
---|---|
| キューまたはトピックの Java Naming and Directory Interface 名。これは必須の値です。 |
|
管理的に定義された
明示的に定義されていない場合は、 |
|
宛先の有効な値のタイプは |
|
|
|
トランザクション処理された Jakarta Messaging を使用していない場合の承認のタイプ。有効な値は
デフォルト値は |
| 接続のクライアント ID。これは必須の値ではありません。 |
|
トピックサブスクリプションが永続化されるかどうか。有効な値は
デフォルト値は |
| トピックサブスクリプションのサブスクリプション名。これは必須の値ではありません。 |
名前 | 説明 |
---|---|
|
|
| 接続がサブスクリプションを共有するように設定されているかどうか。
デフォルト値は |
| Jakarta Messaging 接続のユーザー。これは必須の値ではありません。 |
| Jakarta Messaging 接続のパスワード。これは必須の値ではありません。 |
| 使用する同時セッションの最大数。これは必須の値ではありません。
デフォルト値は |
| セッションのトランザクションタイムアウト (ミリ秒単位)。これは必須の値ではありません。
指定されない場合または 0 の場合、プロパティーは無視され、 |
| Java Naming and Directory Interface を使用して宛先を検索するかどうか。
デフォルト値は |
|
接続で使用する Java Naming および Directory Interface パラメーター。パラメーターは、 |
| XA の代わりにローカルトランザクションを使用します。
デフォルト値は |
| Jakarta Messaging 接続の設定を試みる回数。Jakarta Messaging リソースが利用可能になる前に MDB がデプロイされる可能性があります。この場合、リソースアダプターは、リソースが利用可能になるまで、複数回の設定を試行します。これは受信接続のみに適用されます。
デフォルト値は |
| Jakarta Messaging 接続の設定を試みる連続的間隔 (ミリ秒単位)。これは受信接続のみに適用されます。
デフォルト値は |
| 受信接続のリバランスが有効になっているかどうか。このパラメーターは、基礎となるクラスタートポロジーの変更時に受信接続をすべてリバランスできるようにします。 アウトバウンド接続にはリバランスがありません。
デフォルト値は |
| ホワイトリストのエントリーのコンマ区切りリスト。これは、信頼できるクラスおよびパッケージのリストです。このプロパティーは、リストにあるオブジェクトをデシリアライズできるように Jakarta Messaging リソースアダプターによって使用されます。 詳細は、JBoss EAPConfiguring Messagingの Controlling Jakarta Messaging ObjectMessage Deserialization を参照してください。 |
| ブラックリストのエントリーのコンマ区切りリスト。これは、信頼できないクラスおよびパッケージのリストです。このプロパティーは、リストにあるオブジェクトがデシリアライズされないように、JMS リソースアダプターによって使用されます。 詳細は、JBoss EAPConfiguring Messagingの Controlling Jakarta Messaging ObjectMessage Deserialization を参照してください。 |
4.7.3. MDB を設定するためのいくつかのユースケース
メッセージを受信する MDB のユースケース
MDB がメッセージを受信する際の基本的なシナリオは、JBoss EAP に同梱される
helloworld-mdb
クイックスタートを参照してください。メッセージを送信する MDB のユースケース
メッセージの処理後、他のビジネスシステムに通知したり、メッセージに応答する必要がある場合があります。この場合、以下のスニペットにあるように、MDB からメッセージを送信できます。
package org.jboss.as.quickstarts.mdb; import javax.annotation.Resource; import javax.ejb.ActivationConfigProperty; import javax.ejb.MessageDriven; import javax.inject.Inject; import javax.jms.JMSContext; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageListener; import javax.jms.Queue; @MessageDriven(name = "MyMDB", activationConfig = { @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "queue/MyMDBRequest"), @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") }) public class MyMDB implements MessageListener { @Inject private JMSContext jmsContext; @Resource(lookup = "java:/queue/ResponseDefault") private Queue defaultDestination; /** * @see MessageListener#onMessage(Message) */ public void onMessage(Message rcvMessage) { try { Message response = jmsContext.createTextMessage("Response for message " + rcvMessage.getJMSMessageID()); if (rcvMessage.getJMSReplyTo() != null) { jmsContext.createProducer().send(rcvMessage.getJMSReplyTo(), response); } else { jmsContext.createProducer().send(defaultDestination, response); } } catch (JMSException e) { throw new RuntimeException(e); } } }
上記の例では、MDB はメッセージを受信した後、
JMSReplyTo
で指定された宛先、または Java Naming and Directory Interface 名java:/queue/ResponseDefault
にバインドされた宛先のいずれかに応答します。MDB でのユースケースインバウンド接続のリバランスの設定
@MessageDriven(name="MyMDBName", activationConfig = { @ActivationConfigProperty(propertyName = "destinationType",propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "queueA"), @ActivationConfigProperty(propertyName = "rebalanceConnections", propertyValue = "true") } )
第5章 セッション Bean の呼び出し
5.1. Jakarta Enterprise Beans クライアントコンテキストについて
JBoss EAP には、リモート Jakarta Enterprise Beans 呼び出しを管理するための Jakarta Enterprise Beans クライアント API が導入されました。JBoss Jakarta Enterprise Beans クライアント API は、EJBClientContext を使用します。これは、1 つ以上のスレッドで割り当てられ、複数のスレッドと同時に使用される可能性があります。つまり、EJBClientContext には任意の数の Jakarta Enterprise Beans レシーバーが含まれる可能性があります。Jakarta Enterprise Beans レシーバーは、Jakarta Enterprise Beans 呼び出しを処理できるサーバーと通信する方法を認識しているコンポーネントです。通常、Jakarta Enterprise Beans リモートアプリケーションは以下のように分類できます。
- スタンドアロン Java アプリケーションとして実行されるリモートクライアント。
- 別の JBoss EAP インスタンス内で実行されるリモートクライアント。
リモートクライアントのタイプによっては、Jakarta Enterprise Beans クライアント API の観点からすべば、JVM 内に複数の EJBClientContext が存在する可能性があります。
通常、スタンドアロンアプリケーションには任意の数の Jakarta Enterprise Beans レシーバーでサポートされる単一の EJBClientContext がありますが、これは必須ではありません。スタンドアロンアプリケーションに複数の EJBClientContext がある場合、Jakarta Enterprise Beans クライアントコンテキストセレクターは適切なコンテキストを返します。
別の JBoss EAP インスタンス内で実行されるリモートクライアントの場合には、デプロイされた各アプリケーションに対応する Jakarta Enterprise Beans クライアントコンテキストがあります。アプリケーションが別の Jakarta Enterprise Beans を呼び出すたびに、対応する Jakarta Enterprise Beans クライアントコンテキストを使用して、正しい Jakarta Enterprise Beans レシーバーを検索し、呼び出しを処理します。
5.2. リモート Jakarta Enterprise Beans クライアントの使用
5.2.1. 初期コンテキストルックアップ
初期コンテキストの作成時に PROVIDER_URL
プロパティーを使用してリモートサーバーのアドレスを渡すことができます。
public class Client { public static void main(String[] args) throws NamingException, PrivilegedActionException, InterruptedException { InitialContext ctx = new InitialContext(getCtxProperties()); String lookupName = "ejb:/server/HelloBean!ejb.HelloBeanRemote"; HelloBeanRemote bean = (HelloBeanRemote)ctx.lookup(lookupName); System.out.println(bean.hello()); ctx.close(); } public static Properties getCtxProperties() { Properties props = new Properties(); props.put(Context.INITIAL_CONTEXT_FACTORY, WildFlyInitialContextFactory.class.getName()); props.put(Context.PROVIDER_URL, "remote+http://127.0.0.1:8080"); props.put(Context.SECURITY_PRINCIPAL, "joe"); props.put(Context.SECURITY_CREDENTIALS, "joeIsAwesome2013!"); return props; } }
ルックアップに使用される初期コンテキストファクトリーは org.wildfly.naming.client.WildFlyInitialContextFactory
です。
5.2.2. リモート Jakarta Enterprise Beans 設定ファイル
JBoss EAP は Elytron セキュリティーフレームワークを特長としています。クライアントアプリケーションのクラスパスの META-INF/
ディレクトリーにある wildfly-config.xml
ファイルは、Elytron セキュリティーフレームワークおよび Jakarta Enterprise Beans クライアント設定に幅広い認証および承認オプションを許可します。
<configuration> <authentication-client xmlns="urn:elytron:client:1.2"> <authentication-rules> <rule use-configuration="default" /> </authentication-rules> <authentication-configurations> <configuration name="default"> <sasl-mechanism-selector selector="DIGEST-MD5" /> <set-user-name name="admin" /> <credentials> <clear-password password="password123!" /> </credentials> </configuration> </authentication-configurations> </authentication-client> <jboss-ejb-client xmlns="urn:jboss:wildfly-client-ejb:3.0"> <connections> <connection uri="remote+http://127.0.0.1:8080" /> </connections> </jboss-ejb-client> </configuration>
初期コンテキストに PROVIDER_URL
、SECURITY_PRINCIPAL
、および SECURITY_CREDENTIALS
パラメーターを組み込む代わりに、wildfly-config.xml
ファイルの <connection-uri>
と <authentication-client>
要素を使用して接続 URI とセキュリティーを設定できます。
5.2.3. ClientTransaction アノテーション
@org.jboss.ejb.client.annotation.ClientTransaction
アノテーションは、Jakarta Enterprise Beans クライアントからのトランザクション伝搬を処理します。クライアントにトランザクションがない場合には伝搬に失敗し、クライアントがアクティブであってもトランザクションの伝搬を防ぐことができます。org.jboss.ejb.client.annotation.ClientTransactionPolicy
インターフェイスの定数を使用して、ClientTransaction
アノテーションのポリシーを制御できます。以下は、org.jboss.ejb.client.annotation.ClientTransactionPolicy
インターフェイスの定数です。
- MANDATORY: クライアント側のトランザクションコンテキストがない場合は例外で失敗します。クライアント側のトランザクションコンテキストが存在する場合は伝播します。
- NEVER: トランザクションコンテキストを伝搬することなく起動。クライアント側のトランザクションコンテキストが存在する場合は、例外が発生します。
- NOT_SUPPORTED: クライアント側のトランザクションコンテキストが存在するかどうかにかかわらず、トランザクションコンテキストを伝搬せずに起動します。
- SUPPORTS: クライアント側のトランザクションコンテキストがない場合にトランザクションなしで起動します。クライアント側のトランザクションコンテキストが存在する場合は伝播します。
アノテーションがない場合、デフォルトのポリシーは org.jboss.ejb.client.annotation.ClientTransactionPolicy#SUPPORTS
になります。存在する場合は、トランザクションのありなしに関係なく、伝搬は失敗しません。
@ClientTransaction(ClientTransactionPolicy.MANDATORY) @Remote public interface RemoteCalculator { public void callRemoteEjb() { } } @Stateless @Remote(RemoteCalculator.class) public class CalculatorBean implements RemoteCalculator { @Override public void callRemoteEjb() { } }
アノテーションでは、リモートインターフェイスプロバイダーがメソッドにトランザクションが必要であるかどうかをリモートインターフェイスのコンシューマーに指示できるようにします。
5.3. リモート Jakarta Enterprise Beans データ圧縮
Enterprise Beans プロトコルメッセージが含まれるメッセージストリームを圧縮できます。
圧縮は現在、クライアントおよびサーバー側にあるべき Jakarta Enterprise Beans インターフェイス上のアノテーションでのみ指定できます。現在、圧縮ヒントを指定するのと同等の XML はありません。
データ圧縮ヒントは、JBoss アノテーション org.jboss.ejb.client.annotation.CompressionHint
で指定できます。ヒントの値では、リクエスト、応答、要求、応答を圧縮するかどうかを指定します。@CompressionHint
デフォルトを compressResponse=true
と compressRequest=true
に追加。
アノテーションはインターフェイスレベルで指定して、以下のように Jakarta Enterprise Beans のインターフェイス内のすべてのメソッドに適用できます。
import org.jboss.ejb.client.annotation.CompressionHint; @CompressionHint(compressResponse = false) public interface ClassLevelRequestCompressionRemoteView { String echo(String msg); }
また、アノテーションは Jakarta Enterprise Beans のインターフェイスにある特定のメソッドに適用できます。以下に例を示します。
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 Jakarta Enterprise Beans Client に対してアノテーションをスキャンします。
5.4. Jakarta Enterprise Beans クライアントのリモーティング相互運用性
リモート Jakarta Enterprise Beans クライアントアプリケーションは、サーバーに接続するために remoting
サブシステムに定義されたコネクターを使用します。ニーズに合わせて、次のコネクターのいずれかを使用できます。
-
http-connector
: デフォルトポート 8080 でundertow
の HTTP アップグレード機能を介してサーバーへのクライアント接続をサポートします。このコネクターが設定されると、クライアントは、暗号化されていない接続にremote+http
URI スキームを使用し、暗号化された接続にremote+https
URI スキームを使用します。 -
コネクター
: レガシーリモート
URI スキームを使用したサーバーへのクライアント接続をサポートします。このコネクターは、古い Jakarta Enterprise Beans クライアントアプリケーションでの使用に適しています。
Jakarta Enterprise Beans クライアントは、これまでのリモーティングベースのコネクターを使用する他に、http
URI スキームを使用して undertow
および HTTP プロトコルを介してサーバーに接続できます。詳細は、Jakarta Enterprise Beans Invocation Over HTTP を参照してください。
デフォルトの HTTP コネクター
デフォルトのコネクターは http-connector
で、クライアントは URI スキーム remote+http
または remote+https
を使用する必要があります。デフォルトのリモート接続ポートは 8080
で、undertow
のデフォルトポートです。以下の例は、jboss-ejb-client
プロパティーファイルを示しています。
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false remote.connections=default remote.connection.default.host=localhost remote.connection.default.port=8080 remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
異なる JBoss EAP バージョンのクライアントのサポート
クライアントアプリケーションが JBoss EAP 6 の Jakarta Enterprise Beans クライアントライブラリーを使用し、JBoss EAP 7 サーバーへの接続が必要な場合は、8080
以外のポートでリモーティングコネクターを公開するようにサーバーを設定する必要があります。その後、そのクライアントは新しく設定されたコネクターを使用して接続する必要があります。
JBoss EAP 7 の Jakarta Enterprise Beans クライアントライブラリーを使用し、JBoss EAP 6 サーバーへの接続を必要とするクライアントアプリケーションは、サーバーインスタンスによって remoting http-remoting
コネクターは使用されず、remoting コネクターコネクターが使用されることを認識する必要があります。これは、以下の新しいクライアント側の接続プロパティーを定義することで実現されます。
remote.connection.default.protocol=remote
Jakarta Enterprise Beans クライアントアプリケーションの複数のコネクターのサポート
JBoss EAP 7.4 より前は、Jakarta Enterprise Beans クライアントアプリケーションは remoting
サブシステムに定義された 1 つのリモーティングコネクターのみの使用に制限され、サーバーに接続することがありました。このコネクターは、ejb3
サブシステムの リモート
要素の connector-ref
属性に指定されています。デフォルトの http-connector
を使用して、undertow
の HTTP アップグレード機能を介して remote+http
プロトコルで接続を提供するか、レガシー リモート
プロトコル経由で接続を提供するレガシー コネクター
を使用できます。
JBoss EAP 7.4 では、Jakarta Enterprise Beans クライアントが接続目的で使用できるコネクターのリストを指定できます。このリストを指定するには、remote
要素の新しい connectors
属性を使用します。connectors
属性は、remoting
サブシステムに定義されたコネクターのリストを受け入れます。これにより、1 台のサーバーが Jakarta Enterprise Beans クライアントアプリケーションに複数の接続を提供できます。たとえば、EAP 7.2 以降と互換性のあるクライアントは、http-connector
および EAP 7.2 の以前のバージョンと互換性のあるレガシークライアントで remote+http
プロトコルを使用してサーバーに接続できます。コネクター
でレガシー リモート
プロトコルを使用して接続できます。
例:
legacy-remoting-connector
は remoting サブシステムに定義された コネクター
であるとみなします。以下の例は、write
属性を使用して remoting コネクターの値を更新する ejb3
サブシステム設定を示しています。
/subsystem=ejb3/service=remote:write-attribute(name=connectors, value=[http-remoting-connector, legacy-remoting-connector])
domain.xml
ファイルまたは standalone.xml
ファイルを表示して、ejb3
サブシステムで設定済みのリモーティングコネクターを確認できます。
<remote cluster="ejb" connectors="http-remoting-connector legacy-remoting-connector" thread-pool-name="default"> <channel-creation-options> <option name="MAX_OUTBOUND_MESSAGES" value="1234" type="remoting"/> </channel-creation-options> </remote>
Jakarta Enterprise Beans リモート呼び出しは、JBoss EAP 6 でのみ JBoss EAP 7 でサポートされます。
Jakarta Enterprise Beans クライアントのリモーティング相互運用性のほかにも、以下のオプションを使用してレガシークライアントに接続できます。
- JBoss EAP 設定ガイドの JTS トランザクションの ORB の設定 します。
5.5. リモート Jakarta Enterprise Beans 呼び出しの IIOP の設定
JBoss EAP は、JBoss EAP にデプロイされた Jakarta Enterprise Beans への CORBA/IIOP ベースのアクセスをサポートします。
<iiop>
要素は、IIOP、CORBA、Jakarta Enterprise Beans の呼び出しを有効にするために使用されます。この要素が存在するということは、iiop-openjdk
サブシステムがインストールされていることを意味します。<iiop>
要素には、以下の属性が含まれます。
-
enable-by-default
: これがtrue
の場合、Enterprise Beans 2.x のホームインターフェイスを持つすべての Jakarta Enterprise Beans は IIOP 経由で公開されます。それ以外の場合は、jboss-ejb3.xml
を使用して明示的に有効にする必要があります。 -
use-qualified-name
: これがtrue
の場合、Jakarta Enterprise Beans はmyear/myejbjar/MyBean
などのデプロイメントのアプリケーションおよびモジュール名が含まれるバインディング名で CORBA ネーミングコンテキストにバインドされます。false
、デフォルトのバインディング名は bean 名のみになります。
通常、RemoteHome
インターフェイスは Jakarta Enterprise Beans 3 リモート呼び出しには必要ありませんが、IIOP を使用して公開される Jakarta Enterprise Beans 3 Bean に必要です。次に、jboss-ejb3.xml
ファイルを使用して IIOP を有効にするか、standalone-full.xml
設定ファイル内のすべての EJB に対して IIOP を有効にする必要があります。
IIOP の有効化
IIOP を有効にするには、IIOP OpenJDK ORB サブシステムがインストールされており、ejb3
サブシステム設定にある <iiop/>
要素がインストールされている必要があります。ディストリビューションに同梱される standalone-full.xml
設定は、どちらも有効になっています。
IIOP は、サーバー設定ファイルの iiop-openjdk
サブシステムで設定されます。
<subsystem xmlns="urn:jboss:domain:iiop-openjdk:2.1">
以下の管理 CLI コマンドを使用して iiop-openjdk
サブシステムにアクセスし、更新します。
/subsystem=iiop-openjdk
IIOP 要素は、サーバーのデフォルト動作を制御する 2 つの属性を取ります。
<subsystem xmlns="urn:jboss:domain:ejb3:5.0"> ... <iiop enable-by-default="false" use-qualified-name="false"/> ... </subsystem>
以下の管理 CLI コマンドは、ejb3
サブシステムの下に <iiop>
要素を追加します。
/subsystem=ejb3/service=iiop:add(enable-by-default=false, use-qualified-name=false)
IIOP を使用して通信する Jakarta Enterprise Beans の作成
以下の例は、クライアントからリモート IIOP 呼び出しを作成する方法を示しています。
サーバーで Enterprise Beans 2 Bean を作成します。
@Remote(IIOPRemote.class) @RemoteHome(IIOPBeanHome.class) @Stateless public class IIOPBean { public String sayHello() throws RemoteException { return "hello"; } }
必須メソッド
create()
を持つホーム実装を作成します。この方法は、ビジネスメソッドを呼び出すリモートインターフェイスのプロキシーを取得するためにクライアントによって呼び出されます。public interface IIOPBeanHome extends EJBHome { public IIOPRemote create() throws RemoteException; }
Enterprise Bean へのリモート接続のリモートインターフェイスを作成します。
public interface IIOPRemote extends EJBObject { String sayHello() throws RemoteException; }
META-INF
に記述子ファイルjboss-ejb3.xml
を作成して、リモート呼び出しの Bean を導入します。<?xml version="1.0" encoding="UTF-8"?> <jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:iiop="urn:iiop" 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-ejb3-2_0.xsd http://java.sun.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-spec-2_0.xsd urn:iiop jboss-ejb-iiop_1_0.xsd" version="3.1" impl-version="2.0"> <assembly-descriptor> <iiop:iiop> <ejb-name>*</ejb-name> </iiop:iiop> </assembly-descriptor> </jboss:ejb-jar>
注記JAR ファイルの記述子とともに、パッケージ化した Bean を JBoss EAP コンテナーにデプロイする準備が整いました。
クライアント側でコンテキストを作成します。
System.setProperty("com.sun.CORBA.ORBUseDynamicStub", "true"); final Properties props = new Properties(); props.put(Context.PROVIDER_URL, "corbaloc::localhost:3528/JBoss/Naming/root"); props.setProperty(Context.URL_PKG_PREFIXES, "org.jboss.iiop.naming:org.jboss.naming.client"); props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.cosnaming.CNCtxFactory"); props.put(Context.OBJECT_FACTORIES, "org.jboss.tm.iiop.client.IIOPClientUserTransactionObjectFactory");
注記クライアントでは、
wildfly iiop openjdk
ライブラリーをクラスパスに追加する必要があります。また、クライアントはorg.wildfly:wildfly-iiop-openjdk
アーティファクトを Maven 依存関係として追加する必要がある場合があります。コンテキストルックアップを使用して
IIOPBeanHome
ホームディレクトリーへの参照を絞り込みます。次に、ホームインターフェイスcreate()
メソッドを呼び出し、リモートインターフェイスにアクセスします。これにより、そのメソッドを呼び出すことができます。try { Context context = new InitialContext(props); final Object iiopObj = context.lookup(IIOPBean.class.getSimpleName()); final IIOPBeanHome beanHome = (IIOPBeanHome) PortableRemoteObject.narrow(iiopObj, IIOPBeanHome.class); final IIOPRemote bean = beanHome.create(); System.out.println("Bean saying: " + bean.sayHello()); } catch (Exception e) { e.printStackTrace(); }
5.6. Jakarta Enterprise Beans クライアントアドレスの設定
以下の例のように、SessionContext
インターフェイスを使用して Jakarta Enterprise Beans クライアントアドレスを確認できます。
public class HelloBean implements HelloBeanRemote { @Resource SessionContext ctx; private Long counter; public HelloBean() { } @PostConstruct public void init() { counter = 0L; } @Override @RolesAllowed("users") public String hello() { final String message = "method hello() invoked by user " + ctx.getCallerPrincipal().getName() + ", source addr = " + ctx.getContextData().get("jboss.source-address").toString(); System.out.println(message); return message; } }
スタンドアロンクライアント設定
wildfly-config.xml
ファイルに名前空間 urn:xnio:3.5
がある worker
要素内に outbound-bind-addresses
要素を設定できます。bind-address
サブ要素は、以下のように定義される属性 match
、bind-address
、bind-port
を取ります。
以下は、wildfly-config.xml
ファイルを使用したスタンドアロンクライアント設定の例です。
<configuration> <worker xmlns="urn:xnio:3.5"> <worker-name value="default"/> <outbound-bind-addresses> <bind-address bind-address=IP_ADDRESS_TO_BIND_TO bind-port=OPTIONAL_SOURCE_PORT_NUMBER match=CIDR_BLOCK /> </outbound-bind-addresses> </worker> </configuration>
Outbound-bind-address
には以下の属性が必要です。
-
match
は、10.0.0.0/8
、ff00::\8
、0.0.0.0/0
、::/0
などの Classless Inter-Domain Routing (CIDR) ブロックです。 -
bind-address
は、宛先アドレスがmatch
パラメーターで指定された CIDR ブロックと一致する場合にバインドする IP アドレスを指定します。CIDR ブロックと同じアドレスファミリーである必要があります。 bind-port
は任意のソースポート番号で、デフォルトは0
です。一致する式が存在しない場合は、アウトバウンドソケットが明示的にバインドされません。
コンテナーベースの設定
Jakarta Enterprise Beans クライアントアドレスのコンテナーベースの設定は、wildfly-config.xml
ファイルで定義されたスタンドアロンクライアント設定と似ています。
以下の例は、ejb3
サブシステムがデフォルトで使用する io
サブシステムのデフォルトの worker
要素で outbound-bind-address
を設定します。
/subsystem=io/worker=default/outbound-bind-address=SPECIFY_OUTBOUND_BIND_ADDRESS:add(bind-address=IP_ADDRESS_TO_BIND_TO, bind-port=OPTIONAL_SOURCE_PORT_NUMBER, match=CIDR_BLOCK)
5.7. HTTP 上の Jakarta Enterprise Beans 呼び出し
HTTP 上の Jakarta Enterprise Beans 呼び出しには、クライアント側実装とサーバー側実装の 2 つの異なる部分が含まれます。
5.7.1. クライアント側実装
クライアント側の実装は、Undertow HTTP クライアントを使用してサーバーを呼び出す EJBReceiver
で設定されます。接続管理は、接続プールを使用して自動的に処理されます。
HTTP トランスポートを使用するようにリモート Jakarta Enterprise Beans クライアントアプリケーションを設定するには、以下の依存関係を HTTP トランスポート実装に追加する必要があります。
<dependency> <groupId>org.wildfly.wildfly-http-client</groupId> <artifactId>wildfly-http-ejb-client</artifactId> </dependency>
HTTP 呼び出しを実行するには、http
URL スキームを使用し、HTTP インボーカーのコンテキスト名である wildfly-services
を含める必要があります。たとえば、remote+http://localhost:8080
をターゲット URL として使用している場合、HTTP トランスポートを使用するにはこれを http://localhost:8080/wildfly-services
に更新する必要があります。
5.7.2. サーバー側実装
サーバー側実装は、受信 HTTP リクエストを処理し、それらをアンマーシャルし、結果を内部 Jakarta Enterprise Beans 呼び出しコードに渡すサービスで設定されます。
サーバーを設定するには、undertow
サブシステムで使用したい各仮想ホストで http-invoker
を有効にする必要があります。これは、標準の設定ではデフォルトで有効になっています。無効になっている場合は、以下の管理 CLI コマンドを使用して再度有効にできます。
/subsystem=undertow/server=default-server/host=default-host/setting=http-invoker:add(http-authentication-factory=myfactory, path="wildfly-services")
http-invoker
には wildfly-services
がデフォルトの path
と、以下のいずれかの属性があります。
-
上記のコマンドが示すように、Elytron
http-authentication-factory
への参照である必要があるhttp-authentication-factory
。 -
レガシー
security-realm
.
上記の属性は相互排他的であることに注意してください。http-authentication-factory
と security-realm
の両方を同時に指定することはできません。
http-authentication-factory
の使用を希望するすべてのデプロイメントは、Elytron セキュリティーと、指定の HTTP 認証ファクトリーに対応する同じセキュリティードメインを使用する必要があります。
第6章 Jakarta Enterprise Beans アプリケーションセキュリティー
6.1. セキュリティーアイデンティティー
6.1.1. Jakarta Enterprise Beans セキュリティー ID について
Jakarta Enterprise Beans は、他のコンポーネントでメソッドを呼び出す際に使用するアイデンティティーを指定できます。これは、Jakarta Enterprise Beans セキュリティーアイデンティティーで、呼び出しアイデンティティーとも呼ばれます。
デフォルトでは、Jakarta Enterprise Beans は独自の呼び出し元アイデンティティーを使用します。アイデンティティーは、特定のセキュリティーロールに設定することもできます。特定のセキュリティーロールの使用は、セグメント化されたセキュリティーモデルを構築する場合に便利です。たとえば、内部 Jakarta Enterprise Beans のみへのコンポーネントセットへのアクセスを制限します。
6.1.2. Jakarta Enterprise Beans のセキュリティーアイデンティティーの設定
Jakarta Enterprise Beans のセキュリティーアイデンティティーは、セキュリティー設定の <security-identity>
タグで指定します。<security-identity>
タグが存在する場合は、Jakarta Enterprise Beans の呼び出し元アイデンティティーがデフォルトで使用されます。
例: Jakarta Enterprise Beans のセキュリティーアイデンティティーを同じ呼び出し元として設定
この例では、Jakarta Enterprise Beans によって作成されたメソッド呼び出しのセキュリティーアイデンティティーを、現在の呼び出し元のアイデンティティーと同じに設定します。<security-identity>
要素の宣言を指定しない場合は、この動作がデフォルトになります。
<ejb-jar> <enterprise-beans> <session> <ejb-name>ASessionBean</ejb-name> ... <security-identity> <use-caller-identity/> </security-identity> </session> ... </enterprise-beans> </ejb-jar>
例: Jakarta Enterprise Beans のセキュリティーアイデンティティーの特定のロールへの設定
セキュリティーアイデンティティーを特定のロールに設定するには、<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>
また、servlet 要素内に <run-as>
および <run-as-principal>
要素を使用することもできます。
6.2. Jakarta Enterprise Beans メソッドパーミッション
6.2.1. Jakarta Enterprise Beans メソッドパーミッション
Jakarta Enterprise Beans はメソッドへのアクセスを特定のセキュリティーロールに制限できます。
Jakarta Enterprise Beans <method-permission>
要素の宣言は、Jakarta Enterprise Beans のインターフェイスメソッドを呼び出すことができるロールを指定します。以下の組み合わせのパーミッションを指定できます。
- 名前付き Jakarta Enterprise Beans のすべてのホームおよびコンポーネントインターフェイスメソッド
- 名前付き Jakarta Enterprise Beans のホームまたはコンポーネントインターフェイスの指定メソッド
- オーバーロード名を持つ一連のメソッドに指定されたメソッド
6.2.2. Jakarta Enterprise Beans メソッドパーミッションの使用
<method-permission>
要素は、<method>
要素で定義される Jakarta Enterprise Beans メソッドへのアクセスを許可される論理ロールを定義します。複数の例は、xml の構文を示しています。複数のメソッドパーミッションステートメントが存在する可能性があり、それらのステートメントには累積的影響があります。<method-permission>
要素は、<ejb-jar>
記述子の <assembly-descriptor>
要素の子です。
XML 構文は、Jakarta Enterprise Beans メソッドパーミッションのアノテーションを使用する代わりになります。
例: ロールによるエンタープライズ JavaBean のすべてのメソッドへのアクセスを許可する
<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>
例: ロールによる Jakarta Enterprise Beans および Limit Method パラメーターの特定のメソッドへのアクセスの許可
<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>
例: 任意の認証されたユーザーによる Jakarta Enterprise Beans のメソッドへのアクセスの許可
<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>
例: 特定の Jakarta Enterprise Beans メソッドを完全に除外する
<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>
例: 複数の <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>
6.3. Jakarta Enterprise Beans セキュリティーアノテーション
6.3.1. Jakarta Enterprise Beans セキュリティーアノテーションについて
Jakarta Enterprise Beans javax.annotation.security
アノテーションは Jakarta Annotations 1.3 仕様で定義されます。
Jakarta Enterprise Beans はセキュリティーアノテーションを使用してセキュリティーに関する情報をデプロイヤーに渡します。これらの型には次のようなものがあります。
- @DeclareRoles
- 利用可能なロールを宣言します。
- @RunAs
- コンポーネントの伝播セキュリティーアイデンティティーを設定します。
6.3.2. Jakarta Enterprise Beans セキュリティーアノテーションの使用
XML 記述子またはアノテーションのいずれかを使用して、Jakarta Enterprise Bean でメソッドを呼び出すことのできるセキュリティーロールを制御できます。XML 記述子の使用に関する情報は、Use Jakarta Enterprise Beans Method Permissions を参照してください。
デプロイメント記述子に明示的に指定されるメソッドの値はすべて、アノテーションの値を上書きします。メソッドの値がデプロイメント記述子で指定されていない場合は、アノテーションを使用して設定された値が使用されます。上書きの粒度は、方法ごとに決定されます。
Jakarta Enterprise Beans のセキュリティーパーミッションを制御するアノテーション
- @DeclareRoles
-
@DeclareRoles
を使用して、パーミッションをチェックするセキュリティーロールを定義します。@DeclareRoles
がない場合、リストは@RolesAllowed
アノテーションから自動的にビルドされます。 - @RolesAllowed, @PermitAll, @DenyAll
-
@RolesAllowed
を使用して、単一のメソッドまたは複数のメソッドへのアクセスを許可するロールをリスト表示します。単一のメソッドまたは複数のメソッドの使用からすべてのロールを許可または拒否するには、@PermitAll
または@DenyAll
を使用します。 - @RunAs
-
@RunAs
を使用して、アノテーション付きのメソッドから呼び出しを行うときにメソッドが使用するロールを指定します。
例: セキュリティーアノテーションの例
@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
メソッドにアクセスできます。GoodBye
メソッドは、呼び出しを行う際に tempemployee
ロールを使用します。メソッド GoodbyeAdmin
や、セキュリティーアノテーションの他のメソッドには、admin
ロールのみがアクセスできます。
6.4. Jakarta Enterprise Beans へのリモートアクセス
6.4.1. リモート Jakarta Enterprise Beans クライアントでのセキュリティーレルムの使用
Jakarta Enterprise Beans をリモートで呼び出すクライアントにセキュリティーを追加する方法として、セキュリティーレルムを使用することができます。セキュリティーレルムは、ユーザー名/パスワードのペアとユーザー名/ロールのペアの単純なデータベースです。この用語は Web コンテナーのコンテキストでも使用され、意味が若干異なります。
Jakarta Enterprise Beans に対してセキュリティーレルムに存在する特定のユーザー名/パスワードのペアを認証するには、以下の手順に従います。
- 新しいセキュリティーレルムをドメインコントローラーまたはスタンドアロンサーバーに追加します。
以下の例のように、アプリケーションのクラスパスにある
wildfly-config.xml
ファイルを設定します。<configuration> <authentication-client xmlns="urn:elytron:client:1.2"> <authentication-rules> <rule use-configuration="default" /> </authentication-rules> <authentication-configurations> <configuration name="default"> <sasl-mechanism-selector selector="DIGEST-MD5" /> <set-user-name name="admin" /> <credentials> <clear-password password="password123!" /> </credentials> </configuration> </authentication-configurations> </authentication-client> <jboss-ejb-client xmlns="urn:jboss:wildfly-client-ejb:3.0"> <connections> <connection uri="remote+http://127.0.0.1:8080" /> </connections> </jboss-ejb-client> </configuration>
- 新しいセキュリティーレルムを使用するドメインまたはスタンドアロンサーバーでカスタムリモーティングコネクターを作成します。
- カスタムリモーティングコネクターでプロファイルを使用するよう設定されたサーバーグループに Jakarta Enterprise Beans を追加します。またはマネージドドメインを使用していない場合はスタンドアロンサーバーに Jakarta Enterprise Beans をデプロイします。
6.4.2. 新しいセキュリティーレルムの追加
管理 CLI の実行:
jboss-cli.sh
またはjboss-cli.bat
スクリプトを実行し、サーバーに接続します。新しいセキュリティーレルム自体を作成します。
以下のコマンドを実行し、ドメインコントローラーまたはスタンドアロンサーバーに
MyDomainRealm
という名前の新しいセキュリティーレルムを作成します。ドメインインスタンスの場合は、以下のコマンドを使用します。
/host=master/core-service=management/security-realm=MyDomainRealm:add()
スタンドアロンインスタンスの場合には、以下のコマンドを使用します。
/core-service=management/security-realm=MyDomainRealm:add()
myfile.properties
という名前のプロパティーファイルを作成します。スタンドアロンインスタンスの場合は、
EAP_HOME/standalone/configuration/myfile.properties
ファイルを作成し、ドメインインスタンスの場合はEAP_HOME/domain/configuration/myfile.properties
ファイルを作成します。これらのファイルには、ファイル所有者の読み取りおよび書き込みアクセスが必要です。$ chmod 600 myfile.properties
新規ロールについての情報を格納するプロパティーファイルへの参照を作成します。
以下のコマンドを実行して、新しいロールに関連するプロパティーが含まれる
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)
新しいセキュリティーレルムが作成されます。この新しいレルムにユーザーおよびロールを追加すると、情報はデフォルトのセキュリティーレルムとは別のファイルに保存されます。この新しいファイルは、独自のアプリケーションまたは手順を使用して管理できます。
add-user.sh
スクリプトを使用して、application-users.properties
以外のデフォルト以外のファイルにユーザーを追加する場合は、引数 --user-properties myfile.properties
を渡す必要があります。それ以外の場合は、application-users.properties
の使用を試行します。
6.4.3. セキュリティーレルムへのユーザーの追加
-
add-user
スクリプトを実行します。ターミナルを開き、EAP_HOME/bin/
ディレクトリーに移動します。Red Hat Enterprise Linux またはその他の UNIX と同様のオペレーティングシステムを使用している場合には、add-user.sh
を実行します。Windows Server を使用している場合は、add-user.bat
を実行します。 -
管理ユーザーまたはアプリケーションユーザーを追加するかどうかを選択します。この手順では、
b
と入力してアプリケーションユーザーを追加します。 -
ユーザーを追加するレルムを選択します。デフォルトでは、利用可能なレルムは
ApplicationRealm
のみです。カスタムレルムを追加してしまった場合は、その代わりにユーザーを追加します。 -
プロンプトが表示されたら、ユーザー名、パスワード、およびロールを入力します。プロンプトが表示されたら、希望のユーザー名、パスワード、および任意のロールを入力します。
yes
を入力して選択を確認するか、no
と入力して変更をキャンセルします。変更は、セキュリティーレルムの各プロパティーファイルに書き込まれます。
6.4.4. セキュリティードメインとセキュリティーレルム間の関係
Jakarta Enterprise Beans をセキュリティーレルムでセキュアにするには、セキュリティーレルムからユーザーの認証情報を取得するように設定したセキュリティードメインを使用する必要があります。これは、ドメインに Remoting および RealmDirect ログインモジュールが必要であることを意味します。セキュリティードメインの割り当ては、Jakarta Enterprise Beans で適用可能な @SecurityDomain
アノテーションによって実行されます。
other
セキュリティードメインは、基礎となるセキュリティーレルムからユーザーとパスワードデータを取得します。Jakarta Enterprise Beans に @SecurityDomain
アノテーションがなく、Jakarta Enterprise Beans にセキュリティーが保護されていると思われる他のセキュリティー関連のアノテーションのいずれかが含まれる場合は、このセキュリティードメインがデフォルトのドメインになります。
接続を確立するためにクライアントによって使用される基礎となる http-remoting connector
は、使用するセキュリティーレルムを決定します。http-remoting connector
の詳細は、JBoss EAP 設定ガイドの About the Remoting Subsystem を参照してください。
デフォルトコネクターのセキュリティーレルムは以下のように変更できます。
/subsystem=remoting/http-connector=http-remoting-connector:write-attribute(name=security-realm,value=MyDomainRealm)
6.4.5. SSL 暗号化を使用したリモート Jakarta Enterprise Beans アクセス
デフォルトでは、EJB2 および Jakarta Enterprise Beans3 Bean の Remote Method Invocation (RMI) のネットワークトラフィックは暗号化されません。暗号化が必要なインスタンスでは、クライアントとサーバー間の接続を暗号化する Secure Sockets Layer (SSL) を使用できます。また、SSL を使用すると、ファイアウォールの設定に応じて、ネットワークトラフィックが一部のファイアウォールを通過できるようになります。
Red Hat では、影響するすべてのパッケージで TLSv1.1 または TLSv1.2 を利用するために SSLv2、SSLv3、および TLSv1.0 を明示的に無効化することを推奨しています。
6.5. Elytron の ejb
サブシステムとの統合
JBoss EAP 7.1 より、デプロイメントをマッピングし、それらのセキュリティーが elytron
サブシステムによって処理されるようになりました。デプロイメントがマップされたセキュリティードメインを参照する場合、そのセキュリティーは Elytron によって処理されます。そうでない場合には、そのセキュリティーはレガシーセキュリティーサブシステムによって処理されます。このマッピングは ejb
サブシステムで定義されます。
ejb
サブシステム内で、セキュリティードメイン名から、ディプロイメント内で参照されるものとして、参照される Elytron セキュリティードメインにマッピングが作成されます。マッピングされたセキュリティードメイン名がデプロイメント内の bean に対して設定されている場合は、セキュリティーが Elytron によって処理される必要があることを示します。既存の Jakarta Enterprise Beans セキュリティーインターセプターの代わりに新しい Jakarta Enterprise Beans セキュリティーインターセプターが設定されます。
新しい Jakarta Enterprise Beans セキュリティーインターセプターは、呼び出しに関連付けられた Elytron SecurityDomain
を利用して現在の SecurityIdentity
を取得し、以下のタスクを実行します。
-
run-as
プリンシパルを確立します。 -
run-as
プリンシパルの追加ロールを作成します 。 -
run-as
ロールを作成します。 - 承認の決定を行います。
JBoss EAP 7.1 では、ejb
サブシステム application-security-domains
に新しい管理リソースが導入されました。application-security-domains
要素には、Elytron セキュリティードメインにマップする必要のあるアプリケーションセキュリティードメインが含まれます。
属性 | 説明 |
---|---|
| この属性は、デプロイメントで指定されるセキュリティードメインの名前を参照します。 |
| この属性は、使用される必要がある Elytron セキュリティードメインへの参照です。 |
| この属性は、Jakarta Authorization を使用した承認を有効にします。 |
| これは、現在 ASD を参照しているすべてのデプロイメントをリスト表示するランタイム属性です。 |
|
この属性は、着信
このパラメーターはオプションであり、デフォルト値は 'true' です。 |
管理コンソールまたは管理 CLI を使用して、ejb
サブシステムで application-security-domain
を設定できます。詳細は、以下のトピックを参照してください。
6.5.1. 管理コンソールを使用したアプリケーションセキュリティードメインの設定
- 管理コンソールにアクセスします。詳細は、JBoss EAP設定ガイドの 管理コンソール を参照してください。
- Configuration → Subsystems → EJB の順に移動し、View をクリックします。
- Security Domain タブを選択し、必要に応じてアプリケーションセキュリティードメインを設定します。
6.5.2. 管理 CLI を使用したアプリケーションセキュリティードメインの設定
以下の例では、MyAppSecurity
はデプロイメントで参照されるセキュリティードメインであり、ApplicationDomain
は elytron
サブシステムに設定された Elytron セキュリティードメインです。
/subsystem=ejb3/application-security-domain=MyAppSecurity:add(security-domain=ApplicationDomain)
以下の XML は、このコマンドの結果としてサーバー設定ファイルの ejb
サブシステムに追加されます。
<application-security-domains> <application-security-domain name="MyAppSecurity" security-domain="ApplicationDomain"/> </application-security-domains>
Elytron を使用してセキュリティーを処理する Jakarta Enterprise Beans の単純な作業例は、JBoss EAP に同梱される ejb-security
クイックスタートを参照してください。
第7章 Jakarta Enterprise Beans インターセプター
7.1. カスタムインターセプター
JBoss EAP では、カスタム Jakarta Enterprise Beans インターセプターを開発および管理できます。
以下のタイプのインターセプターを作成できます。
クライアントインターセプター
クライアントインターセプターは、JBoss EAP がクライアントとして動作するときに実行されます。
サーバーインターセプター
サーバーインターセプターは、JBoss EAP がサーバーとして動作するときに実行されます。これらのインターセプターは、サーバーにグローバルに設定できます。
コンテナーインターセプター
コンテナーインターセプターは、JBoss EAP がサーバーとして動作するときに実行されます。これらのインターセプターは Jakarta Enterprise Beans コンテナーで設定されます。
カスタムインターセプタークラスをモジュールに追加し、$JBOSS_HOME/modules
ディレクトリーに格納する必要があります。
7.1.1. インターセプターチェーン
カスタムインターセプターは、インターセプターチェーンの特定ポイントで実行されます。
Jakarta Enterprise Beans に設定されたコンテナーインターセプターは、セキュリティーインターセプターやトランザクション管理インターセプターなど、Wildfly が提供するインターセプターの前に実行されます。そのため、コンテナーインターセプターは、Wildfly インターセプターまたはグローバルインターセプターを起動する前にコンテキストデータを処理または設定できます。
サーバーインターセプターおよびクライアントインターセプターは、Wildfly 固有のインターセプターの後に実行されます。
7.1.2. カスタムクライアントインターセプター
カスタムクライアントインターセプターは、org.jboss.ejb.client.EJBClientInterceptor
インターフェイスを実装します。
Org.jboss.ejb.client.EJBClientInvocationContext
インターフェイスも含める必要があります。
以下のコードは、クライアントインターセプターの例を示しています。
クライアントインターセプターコードの例
package org.foo; import org.jboss.ejb.client.EJBClientInterceptor; import org.jboss.ejb.client.EJBClientInvocationContext; public class FooInterceptor implements EJBClientInterceptor { @Override public void handleInvocation(EJBClientInvocationContext context) throws Exception { context.sendRequest(); } @Override public Object handleInvocationResult(EJBClientInvocationContext context) throws Exception { return context.getResult(); } }
7.1.3. カスタムサーバーインターセプター
サーバーインターセプターは、@javax.annotation.AroundInvoke
アノテーションまたは javax.interceptor.AroundTimeout
アノテーションを使用して、Bean での呼び出し中に呼び出されるメソッドをマークします。
以下のコードは、サーバーインターセプターの例を示しています。
サーバーインターセプターコードの例
package org.testsuite.ejb.serverinterceptor; import javax.annotation.PostConstruct; import javax.interceptor.AroundInvoke; import javax.interceptor.InvocationContext; public class TestServerInterceptor { @AroundInvoke public Object aroundInvoke(final InvocationContext invocationContext) throws Exception { return invocationContext.proceed(); } }
7.1.4. カスタムコンテナーインターセプター
コンテナーインターセプターは、@javax.annotation.AroundInvoke
アノテーションまたは javax.interceptor.AroundTimeout
アノテーションを使用して、Bean での呼び出し中に呼び出されるメソッドをマークします。
Jakarta Enterprise Beans 3.2 仕様で定義されている標準の JakartaEE インターセプターは、コンテナーがセキュリティーコンテキストの伝搬、トランザクション管理、およびその他コンテナーによる呼び出し処理の完了後に実行されることが予想されます。
以下のコードは、呼び出しのために iAmAround
メソッドをマークするインターセプタークラスを示しています。
コンテナーインターセプターコードの例
public class ClassLevelContainerInterceptor { @AroundInvoke private Object iAmAround(final InvocationContext invocationContext) throws Exception { return this.getClass().getName() + " " + invocationContext.proceed(); } }
コンテナーインターセプターと Jakarta EE インターセプター API の違い
コンテナーインターセプターは Jakarta EE インターセプターと同様にモデル化されますが、API のセマンティクスにはいくつかの違いがあります。たとえば、これらのインターセプターは Jakarta Enterprise Beans コンポーネントの設定またはインスタンス化よりもだいぶ前に呼び出されるため、コンテナーインターセプターが javax.interceptor.InvocationContext.getTarget()
メソッドを呼び出すことは違反になります。
7.1.5. コンテナーインターセプターの設定
コンテナーインターセプターは標準の Jakarta EE インターセプターライブラリーを使用します。
そのため、ejb-jar デプロイメント記述子の 3.2 バージョンに対して ejb-jar.xml
ファイルで許可されるのと同じ XSD 要素を使用します。
それらは標準の Jakarta EE インターセプターライブラリーをベースとしているため、コンテナーインターセプターはデプロイメント記述子を使用してのみ設定できます。設計アプリケーションには、JBoss EAP 固有のアノテーションやその他のライブラリーの依存関係は必要ありません。
コンテナーインターセプターを設定するには、以下を実行します。
-
Jakarta Enterprise Beans デプロイメントの
META-INF/`
ディレクトリーにjboss-ejb3.xml
ファイルを作成します。 記述子ファイルにコンテナーインターセプター要素を設定します。
-
urn:container-interceptors:1.0
ネームスペースを使用して、コンテナーインターセプター要素の設定を指定します。 -
<container-interceptors>
要素を使用してコンテナーインターセプターを指定します。 >interceptor-binding>
要素を使用してコンテナーインターセプターを Jakarta Enterprise Beans にバインドします。インターセプターは、以下のいずれかの方法でバインドできます。- ワイルドカード (*) を使用して、インターセプターをデプロイメントのすべての Jakarta Enterprise Beans にバインドします。
- 特定の Jakarta Enterprise Beans 名を使用して、個々の Bean レベルでインターセプターをバインドします。
Jakarta Enterprise Beans の特定のメソッドレベルでインターセプターをバインドします。
注記これらの要素は、Jakarta EE インターセプターと同じ方法で Jakarta Enterprise Beans 3.2 XSD を使用して設定されます。
-
以下の記述子ファイル例は設定オプションを示しています。
コンテナーインターセプター 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>
allow-ejb-name-regex
属性を使用すると、インターセプターバインディングで正規表現を使用できるようになり、指定の正規表現に一致するすべての Bean にインターセプターをマッピングできます。以下の管理 CLI コマンドを使用して、ejb3
サブシステムの allow-ejb-name-regex
属性を true
に有効化します。
/subsystem=ejb3:write-attribute(name=allow-ejb-name-regex,value=true)
urn:container-interceptors:1.0
名前空間のスキーマは http://www.jboss.org/schema/jbossas/jboss-ejb-container-interceptors_1_0.xsd で利用できます。
7.1.6. サーバーおよびクライアントインターセプターの設定
サーバーインターセプターおよびクライアントインターセプターは、使用される設定ファイルの JBoss EAP 設定にグローバルに追加されます。
サーバーインターセプターは、ejb3
サブシステム設定の <server-interceptors>
要素に追加されます。クライアントインターセプターは、ejb3
サブシステム設定の <client-interceptors>
要素に追加されます。
以下の例は、サーバーインターセプターの追加を示しています。
/subsystem=ejb3:list-add(name=server-interceptors,value={module=org.abccorp:tracing-interceptors:1.0,class=org.abccorp.TracingInterceptor})
以下の例は、クライアントインターセプターの追加を示しています。
/subsystem=ejb3:list-add(name=client-interceptors,value={module=org.abccorp:clientInterceptor:1.0,class=org.abccorp.clientInterceptor})
サーバーインターセプターまたはクライアントインターセプターが追加されるか、インターセプターの設定が変更されるたびに、サーバーをリロードする必要があります。
7.1.7. SCC (Security Context Identity) の変更
複数のクライアント接続を開く代わりに、認証されたユーザーにアイデンティティーを切り替え、別のユーザーとして既存の接続で要求を実行するパーミッションを付与することができます。
デフォルトでは、アプリケーションサーバーにデプロイされた Jakarta Enterprise Beans へのリモート呼び出しを行うと、サーバーへの接続は認証され、接続を使用する後続のリクエストは元の認証済みアイデンティティーを使用して実行されます。これは、クライアントとサーバー間の呼び出しの両方に適用されます。同じクライアントから異なるアイデンティティーを使用する必要がある場合は、通常は、異なるアイデンティティーとして認証されるように、サーバーへの接続を複数開く必要があります。代わりに、認証されたユーザーがアイデンティティーを変更できるようにすることもできます。
認証されたユーザーのアイデンティティーを変更するには、以下を実行します。
インターセプターコードでアイデンティティーの変更を実装します。
クライアントインターセプター
インターセプターは、
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(); } }
コンテナーおよびサーバーインターセプター
これらのインターセプターはアイデンティティーが含まれる
InvocationContext
を受け取り、新しいアイデンティティーに切り替える要求を行います。以下のコードは、コンテナーインターセプターのブリッジした例を示しています。コンテナーインターセプターコードの例
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);; } } }
-
アプリケーションは、プログラムを用いて、またはサービスローダーメカニズムを使用して、クライアントインターセプターを
EJBClientContext
インターセプターチェーンに挿入できます。クライアントインターセプターを設定する手順は、Using a Client Interceptor in an Application を参照してください。 Jakarta Authentication ログインモジュールを作成します。
Jakarta Authentication LoginModule コンポーネントは、ユーザーが要求されたアイデンティティーとして要求を実行できることを確認します。以下の abridged コード例は、ログインおよび検証を実行するメソッドを示しています。
LoginModule コードの例
@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; } // If the CallbackHandler can not handle the required callbacks then no chance. return false; } 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. } // Make a trust user to decide if the user switch is acceptable. 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[0])) { // A wild card mapping was found. return true; } for (String current : allowedMappings) { if (requestedUser.equals(current)) { return true; } } return false; }
7.1.8. アプリケーションでのクライアントインターセプターの使用
アプリケーションは、プログラムを用いて、またはサービスローダーメカニズムを使用して、あるいは、ClientInterceptors アノテーションを使用して、クライアントインターセプターを EJBClientContext
インターセプターチェーンに挿入できます。
EJBClientInterceptor
は、org.jboss.ejb.client.EJBClientInvocationContext#addReturnedContextDataKey(String key)
を呼び出してサーバー側の呼び出しコンテキストから特定のデータをリクエストすることができます。要求したデータがコンテキストデータマップの提供されるキー以下に存在する場合、クライアントに送信されます。
7.1.8.1. クライアントインターセプターのプログラムでの挿入
インターセプターを登録した EJBClientContext
を作成したら、インターセプターを挿入します。
以下のコードは、インターセプターの登録で EJBClientContext
を作成する方法を示しています。
EJBClientContext ctxWithInterceptors = EJBClientContext.getCurrent().withAddedInterceptors(clientInterceptor);
EJBClientContext
の作成後、インターセプターを挿入するオプションを使用できます。
以下のコードは、
Callable
操作を使用してEJBClientContext
を適用して実行できます。Callable
操作内で実行される Jakarta Enterprise Beans 呼び出しはクライアント側のインターセプターを適用します。ctxWithInterceptors.runCallable(() -> { // perform the calls which should use the interceptor })
または、新規作成された
EJBClientContext
を新しいデフォルトとしてマークすることもできます。EJBClientContext.getContextManager().setThreadDefault(ctxWithInterceptors);
7.1.8.2. サービスローダーメカニズムを使用したクライアントインターセプターの挿入
META-INF/services/org.jboss.ejb.client.EJBClientInterceptor
ファイルを作成し、クライアントアプリケーションのクラスパスに配置またはパッケージ化します。
ファイルのルールは、Java ServiceLoader Mechanism によって指示されます。
- このファイルには、Jakarta Enterprise Beans クライアントインターセプター実装の完全修飾クラス名ごとに個別の行が含まれることが予想されます。
- Jakarta Enterprise Beans クライアントインターセプタークラスはクラスパスで利用できる必要があります。
サービスローダーメカニズムを使用して追加された Jakarta Enterprise Beans クライアントインターセプターは、クラスパスにある順序で追加され、クライアントインターセプターチェーンの最後に追加されます。
7.1.8.3. ClientInterceptor アノテーションを使用したクライアントインターセプターの挿入
@org.jboss.ejb.client.annotation.ClientInterceptors
アノテーションを使用すると、Jakarta Enterprise Beans インターセプターをリモート呼び出しのクライアント側に配置できます。
import org.jboss.ejb.client.annotation.ClientInterceptors; @ClientInterceptors({HelloClientInterceptor.class}) public interface HelloBeanRemote { public String hello(); }
第8章 クラスター化された Jakarta Enterprise Bean
8.1. クラスター化された Jakarta Enterprise Bean について
Jakarta Enterprise Beans コンポーネントは、高可用性シナリオ向けにクラスター化できます。HTTP コンポーネントとは異なるプロトコルを使用するため、複数の方法でクラスター化されます。Enterprise Beans 2 および 3 ステートフルおよびステートレス Bean はクラスター化が可能です。
シングルトンの詳細は JBoss EAP開発ガイド のHA シングルトンサービスを参照してください。
8.2. Jakarta Enterprise Beans クライアントコードの簡素化
Jakarta Enterprise Beans サーバー側のクラスター化されたコンポーネントを呼び出すときに Jakarta Enterprise Beans クライアントコードを簡素化できます。以下の手順では、Jakarta Enterprise Beans クライアントコードを単純化する複数の方法を概説します。
jboss-ejb-client.properties
ファイルの使用は非推奨となり、wildfly-config.xml
ファイルが優先されるようになりました。
8.3. Clustered Jakarta Enterprise Beans のデプロイ
クラスタリングのサポートは JBoss EAP 7.4 の HA プロファイルで利用できます。HA 機能が有効なスタンドアロンサーバーを起動するには、standalone-ha.xml
または standalone-full-ha.xml
ファイルで起動します。
$ EAP_HOME/bin/standalone.sh --server-config=standalone-ha.xml
これにより、HA 機能を持つサーバーの単一インスタンスが起動します。
クラスタリングの利点を確認できるようにするには、サーバーの複数のインスタンスが必要になります。したがって、HA 機能を持つ別のサーバーを起動します。サーバーの別のインスタンスは、同じマシンまたは別のマシンのいずれかに置くことができます。同じマシン上にある場合は、以下の点に注意する必要があります。
- 次のインスタンスのポートオフセットを渡します。
-
各サーバーインスタンスに固有の
jboss.node.name
システムプロパティーがあることを確認します。
これは、以下のシステムプロパティーを起動コマンドに渡すことで実行できます。
$ EAP_HOME/bin/standalone.sh --server-config=standalone-ha.xml -Djboss.socket.binding.port-offset=PORT_OFFSET -Djboss.node.name=UNIQUE_NODE_NAME
Jakarta Enterprise Beans デプロイメントをこのインスタンスにデプロイするのにも慣れていることに気付かれる方法にしたがいます。
クラスター化されたサーバーのスタンドアロンインスタンスの単一のノードにアプリケーションをデプロイしても、そのアプリケーションが他のクラスターインスタンスに自動的にデプロイされるわけではありません。これは、他のスタンドアロンクラスターインスタンスにも明示的にデプロイする必要があります。または、ドメインモードでサーバーを起動して、デプロイメントをサーバーグループのすべてのサーバーにデプロイできます。
クラスター化された Jakarta Enterprise Beans を持つアプリケーションを両方のインスタンスにデプロイしたことで、Jakarta Enterprise Beans はクラスタリング機能を活用できるようになりました。
JBoss EAP 7 より、JBoss EAP が HA プロファイルを使用して起動されると、ステートフルセッション bean の状態がレプリケートされます。クラスタリング動作を有効にするために @Clustered
アノテーションを使用する必要がなくなりました。
@Stateful
アノテーションで passivationCapable
を false
に設定することで、ステートフルセッション Bean のレプリケーションを無効にできます。
@Stateful(passivationCapable=false)
これは、cache-ref
ではなく passivation-disabled-cache-ref
で定義された ejb
キャッシュを使用するようサーバーに指示します。
ステートフルセッション Bean のレプリケーションをグローバルに無効にするには、以下の管理 CLI コマンドを使用します。
/subsystem=ejb3:write-attribute(name=default-sfsb-cache,value=simple)
8.4. クラスター化された Jakarta Enterprise Beans のフェイルオーバー
クラスター化された Jakarta Enterprise Beans にはフェイルオーバー機能があります。@Stateful
Jakarta Enterprise Beans の状態がクラスターノード間で複製されるため、クラスター内のいずれかのノードがダウンした場合に、その他のノードが呼び出しを引き継ぐことができます。
クラスター内のサーバーがクラッシュした場合など、クラスター環境の状況によっては、Jakarta Enterprise Beans クライアントは応答の代わりに例外を受信する場合があります。Jakarta Enterprise Beans クライアントライブラリーは、発生する障害のタイプに応じて、安全に呼び出しを再試行します。ただし、要求が失敗し、再試行の安全性を確保できない場合は、ご自分の環境に合わせて例外を処理できます。ただし、カスタムのインターセプターを使用して、再試行動作を追加することもできます。
8.5. リモートスタンドアロンクライアント
jboss-ejb-client.properties
ファイルの使用は非推奨となり、wildfly-config.xml
ファイルが優先されるようになりました。
スタンドアロンリモートクライアントは、Java Naming and Directory Interface のアプローチまたはネイティブ JBoss Jakarta Enterprise Beans クライアント API を使用してサーバーと通信できます。重要なことは、クラスター化された Jakarta Enterprise Beans デプロイメントを呼び出すときに、クラスター内のすべてのサーバーをリスト表示する必要がないことです。これは、クラスター内でのクラスターノードの追加の動的な性質があるため、実行できません。
リモートクライアントは、クラスタリング機能を持ついずれかのサーバーのみをリスト表示する必要があります。このサーバーは、クライアントとクラスター化されたノード間のクラスタートポロジー通信の開始点として機能します。
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
8.6. クラスタートポロジー通信
jboss-ejb-client.properties
ファイルの使用は非推奨となり、wildfly-config.xml
ファイルが優先されるようになりました。
JBoss Jakarta Enterprise Beans クライアント実装は、クライアントがサーバーに接続すると、サーバーにクラスタリング機能がある場合にクラスタートポロジー情報のサーバーの内部と通信します。たとえば、接続する最初のサーバーとして サーバー X がリスト表示される場合は、クライアントがサーバー X に接続すると、そのサーバーは非同期クラスタートポロジーメッセージをクライアントに送信します。このトポロジーメッセージは、クラスター名と、クラスターに属するノードの情報で設定されます。ノード情報には、必要に応じて接続するノードアドレスおよびポート番号が含まれます。この例では、サーバー X はクラスターに属する他のサーバー Y で設定されるクラスタートポロジーを返します。
ステートフルクラスター Jakarta Enterprise Beans の場合、呼び出しフローは 2 つのステップで生じます。
- Bean の Java Naming および Directory Interface ルックアップを実行するときに発生するステートフル Bean のセッションの作成。
- 返されたプロキシーの呼び出し。
ステートフル Bean のルックアップは、内部的に、クライアントからサーバーへの同期セッション作成リクエストをトリガーします。この場合、jboss-ejb-client.properties
ファイルで設定されたため、セッション作成リクエストはサーバー X に送信されます。サーバー X はクラスター化されているため、セッション ID を返し、そのセッションのアフィニティーを送り返します。クラスター化サーバーの場合、アフィニティーはステートフル Bean がサーバー側にあるクラスターの名前と同じになります。クラスター化されていない Bean の場合、アフィニティーはセッションが作成されたノード名です。この アフィニティー は、Jakarta Enterprise Beans クライアントがクラスター化 Bean のクラスター内のノード、または非クラスター Bean の特定のノードにプロキシー上の呼び出しをルーティングするのに役立ちます。このセッション作成リクエストが発生しますが、サーバー X もクラスタートポロジーが含まれる非同期メッセージを送信します。JBoss Jakarta Enterprise Beans クライアント実装は、このトポロジー情報を記録し、後でクラスター内のノードへの接続作成に使用し、必要に応じてそれらのノードへの呼び出しをルーティングします。
フェイルオーバーの仕組みを理解するには、開始点と同じサーバー X の例と、ステートフル Bean を検索し、呼び出しているクライアントアプリケーションを検討してください。これらの呼び出し中に、クライアント側はサーバーからクラスタートポロジー情報を収集します。何らかの理由でサーバー X が停止し、クライアントアプリケーションがプロキシーで呼び出されることを仮定します。この段階で JBoss Jakarta Enterprise Beans クライアント実装はアフィニティーを認識する必要があり、この場合はクラスターのアフィニティーになります。クライアントが持つクラスタートポロジー情報から、クラスターにはサーバー X とサーバー Y のノードがあることを認識します。呼び出しが完了すると、クライアントはサーバー X が停止していることを認識できるため、セレクターを使用してクラスターノードから適切なノードをフェッチします。セレクターがクラスターノードからノードを返す場合、JBoss Jakarta Enterprise Beans クライアント実装は、接続がすでに作成されていない場合にそのノードへの接続を作成し、そこから Jakarta Enterprise Beans レシーバーを作成します。この例では、クラスターの他の唯一のノードはサーバー Y なので、セレクターはサーバー Y をノードとして返し、JBoss Jakarta Enterprise Beans クライアント実装はそれを使用して Jakarta Enterprise Beans レシーバーを作成し、このレシーバーを使用してプロキシーの呼び出しを渡します。実際には、呼び出しがクラスター内の別のノードにフェイルオーバーするようになりました。
8.7. Jakarta Enterprise Beans の自動トランザクション Stickiness
Jakarta Enterprise Beans プロキシーと同じコンテキストからルックアップされるトランザクションオブジェクトは、同じホストをターゲットとします。アクティブトランザクションを使用すると、コンテキストがマルチホストである場合や、クラスター化されている場合は、呼び出しコンテキストが同じノードに固定されます。
この動作は、トランザクションをアウトフローしたか、リモートユーザートランザクションを使用しているかによって異なります。
アウトフロートランザクションの場合、アプリケーションが特定のノードでルックアップされると、同じトランザクション下にあるアプリケーションへの呼び出しすべてが、このノードを対象にしようとします。アウトフローされたトランザクションをすでに受信したノードは、まだ受信されていないノードよりも優先されます。
リモートユーザートランザクションでは、最初に成功した呼び出しによって指定のノードにトランザクションがロックされ、このトランザクション下の後続の呼び出しは同じノードに移動する必要があり、そうでない場合は例外が発生します。
8.8. 別のインスタンス上のリモートクライアント
ここでは、JBoss EAP インスタンスにデプロイされたクライアントアプリケーションが、別の JBoss EAP インスタンスにデプロイされた、クラスター化されたステートフル Bean を呼び出す方法を説明します。
以下の例では、3 つのサーバーが関与しています。サーバー X と Y の両方がクラスターに属し、クラスター化された Jakarta Enterprise Beans がクラスター内にデプロイされます。他のサーバーインスタンスサーバー C もあり、クラスタリング機能も持たない可能性があります。サーバー C は、サーバー X および Y にデプロイされたクラスター化された Bean を起動し、フェイルオーバーを達成するデプロイメントがあるクライアントとして機能します。
この設定は jboss-ejb-client.xml
ファイルで行われます。このファイルは、他のサーバーへのリモートアウトバウンド接続を参照します。サーバー C はクライアントであるため、jboss-ejb-client.xml
ファイルの設定はサーバー C のデプロイメントにあります。クライアント設定はすべてのクラスター化されたノードを参照する必要はなく、いずれか 1 つを参照します。これは、通信の開始点として機能します。
この場合、リモートアウトバウンド接続はサーバー C からサーバー X に作成され、次にサーバー X が通信の開始点として使用されます。リモートスタンドアロンクライアントの場合と同様に、サーバー C のアプリケーションがステートフル Bean をルックアップすると、セッション ID と、そのクラスターのアフィニティーを返すサーバー X にセッション作成要求が送信されます。また、サーバー X は、クラスタートポロジーが含まれるサーバー C に非同期メッセージを送信します。サーバー Y はサーバー X とともにクラスターに属するため、このトポロジー情報にはサーバー Y のノード情報が含まれます。プロキシーの後続の呼び出しはクラスター内のノードに適切にルーティングされます。前述のようにサーバー X がダウンした場合は、クラスターからの別のノードが選択され、呼び出しはそのノードに転送されます。
フェイルオーバーの観点では、リモートスタンドアロンクライアントと別の JBoss EAP インスタンス上のリモートクライアントの両方が同じように動作します。
8.9. スタンドアロンおよびサーバー内クライアントの設定
jboss-ejb-client.properties
ファイルの使用は非推奨となり、wildfly-config.xml
ファイルが優先されるようになりました。
Jakarta Enterprise Beans クライアントをクラスター化された Jakarta Enterprise Beans アプリケーションに接続するには、スタンドアロン Jakarta Enterprise Beans クライアントまたはサーバー Jakarta Enterprise Beans クライアントの既存の設定をデプロイメントして、クラスター接続設定を含める必要があります。スタンドアロン Jakarta Enterprise Beans クライアントの jboss-ejb-client.properties
、またはサーバー側のアプリケーションの jboss-ejb-client.xml
ファイルを拡張してクラスター設定を組み込む必要があります。
Jakarta Enterprise Beans クライアントは、リモートサーバーで Jakarta Enterprise Beans を使用するプログラムです。リモートサーバーを呼び出す Jakarta Enterprise Beans クライアント自体がサーバー内で実行されると、クライアントは サーバー内
で実行されます。つまり、別の JBoss EAP インスタンスを呼び出す JBoss EAP インスタンスは、サーバー内クライアントとみなされます。
以下の例は、スタンドアロン Jakarta Enterprise Beans クライアントに必要な追加のクラスター設定を示しています。
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
ファイルを設定し、クラスター設定を追加する必要があります。
<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>
remote-outbound-connection の詳細は、JBoss EAP 設定ガイド の About Remoting Subsystem を参照してください。
セキュアな接続では、認証例外を回避するために認証情報をクラスター設定に追加する必要があります。
8.10. Jakarta Enterprise Beans 呼び出しのカスタムロードバランシングポリシーの実装
jboss-ejb-client.properties
ファイルの使用は非推奨となり、wildfly-config.xml
ファイルが優先されるようになりました。
アプリケーションの Jakarta Enterprise Beans 呼び出しをサーバー間で分散するために、代替またはカスタマイズしたロードバランシングポリシーを実装することができます。
Jakarta Enterprise Beans 呼び出しに 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]; } }
Jakarta Enterprise Beans 呼び出しに 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 = 8080 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 = 8180 remote.connection.two.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
Jakarta Enterprise Beans クライアント API の使用
プロパティー remote.cluster.ejb.clusternode.selector
を PropertiesBasedEJBClientConfiguration
コンストラクターのリストに追加する必要があります。以下の例では、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", "8080"); p.put("remote.connection.one.host", "localhost"); p.put("remote.connection.two.port", "8180"); 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 application. --> <remoting-ejb-receiver outbound-connection-ref="remote-ejb-connection-1" /> </ejb-receivers> <!-- Specify the cluster configurations applicable for this client context --> <clusters> <!-- Configure the 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)
サーバー間の通信に負荷分散ポリシーを使用する場合は、クラスをアプリケーションとともにパッケージ化するか、モジュールとしてパッケージ化できます。このクラスは、トップレベルの EAR アーカイブの META-INF
ディレクトリーにある jboss-ejb-client
設定ファイルで設定されます。以下の例では RoundRobinNodeSelector
をデプロイメントノードセレクターとして使用します。
<jboss-ejb-client xmlns="urn:jboss:ejb-client:1.2"> <client-context deployment-node-selector="org.jboss.example.RoundRobinNodeSelector"> <ejb-receivers> <remoting-ejb-receiver outbound-connection-ref="..."/> </ejb-receivers> ... </client-context> </jboss-ejb-client>
スタンドアロンサーバーを実行している場合は、サーバー名の設定にオプション -Djboss.node.name=
またはサーバー設定ファイル standalone.xml
を使用します。サーバー名が一意であることを確認します。マネージドドメインを実行している場合は、ホストコントローラーは自動的に名前が一意であることを検証します。
8.11. クラスター環境の Jakarta Enterprise Beans トランザクション
クライアントコードがクラスター化された Jakarta Enterprise Beans を呼び出すと、クラスターのアフィニティーは自動的に設定されます。クライアント側のトランザクションを管理する場合は、クラスター内の特定のノードをターゲット にするか、クライアントがクラスターノードをレイジーに選択できる ようにしてトランザクションを処理します。本セクションでは、両方のオプションを説明します。
Jakarta Enterprise Beans トランザクションターゲットを特定のノードにする
以下の手順を使用して、クラスター内の特定のノードを対象にし、トランザクションを処理できます。
InitialContext
の作成時にPROVIDER_URL
プロパティーを使用してターゲットクラスターノードアドレスを指定します。props.put(Context.PROVIDER_URL, "remote+http://127.0.0.1:8080"); ... InitialContext ctx = new InitialContext(props);
クライアントで、
InitialContext
からtxn:RemoteUserTransaction
を検索します。UserTransaction ut = (UserTransaction)ctx.lookup("txn:RemoteUserTransaction");
UserTransaction
の Java Naming and Directory Interface ルックアップは、以下のコード例のようにPROVIDER_URL
プロパティーをサーバーの URL に設定し、txn:UserTransaction
を検索して実行できます。final Hashtable<String, String> jndiProperties = new Hashtable<>(); jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.wildfly.naming.client.WildFlyInitialContextFactory"); jndiProperties.put(Context.PROVIDER_URL, "remote+http://localhost:8080"); final Context context = new InitialContext(jndiProperties); SecuredEJBRemote reference = (SecuredEJBRemote) context.lookup("txn:UserTransaction");
UserTransaction
は実際の呼び出しが実行されるまで特定の宛先にバインドされません。呼び出し時に、このUserTransaction
はトランザクションのライフタイム期間中、適切な宛先にバインドされます。UserTransaction
を開始する前に、ノード名または宛先を認識する必要はありません。org.jboss.ejb.client.EJBClient.getUserTransaction ()
メソッドは、最初の呼び出しに基づいて宛先を自動的に選択するリモートUserTransaction
を提供します。Java Naming and Directory Interface からリモートUserTransaction
を検索すると、同じ方法で機能します。注記org.jboss.ejb.client.EJBClient.getUserTransaction()
メソッドが非推奨になりました。- トランザクションが開始されると、すべての Jakarta Enterprise Beans 呼び出しがその特定のノードにトランザクションの間バインドされ、サーバーのアフィニティーが確立されます。
- トランザクションが終了すると、サーバーのアフィニティーがリリースされ、Jakarta Enterprise Beans プロキシーが一般的なクラスターアフィニティーに戻ります。
Jakarta Enterprise Beans Transactions Lazily Select a Node
トランザクションに関連する最初の呼び出し中に、クライアントがクラスターノードを選択してトランザクションを処理するようにできます。これにより、クラスター全体でトランザクションの負荷分散が可能になります。このオプションを使用するには、以下の手順を行います。
-
Jakarta Enterprise Beans を呼び出すために使用される
InitialContext
ではPROVIDER_URL
プロパティーを指定しないでください。 クライアントで、
InitialContext
からtxn:RemoteUserTransaction
を検索します。UserTransaction ut = (UserTransaction)ctx.lookup("txn:RemoteUserTransaction");
- トランザクションが開始されると、あるクラスターノードが自動的に選択され、サーバーのアフィニティーが確立されて、すべての Jakarta Enterprise Beans 呼び出しがトランザクション期間中その特定のノードにバインドされます。
- トランザクションが終了すると、サーバーのアフィニティーがリリースされ、Jakarta Enterprise Beans プロキシーが一般的なクラスターアフィニティーに戻ります。
8.12. Jakarta Enterprise Bean でクラスター化されたデータベースタイマー
JBoss EAP は、クラスター環境で Jakarta Enterprise Beans タイマーを永続化するための、クラスター化されたデータベースベースのタイマーをサポートします。クラスタリングはデータベースで提供されるため、短時間以内にタイマーの数がオフになる場合、パフォーマンスが向上します。refresh-interval
を使用し、ejb3/service=timer-service/database-data-store
コンポーネントの allow-execution
属性を使用すると、パフォーマンスを最適化することができます。
以下のように、クラスター化されていないモードでデータベースタイマーを使用することもできます。
-
refresh-interval
を0
に設定します。 - すべてのノードに対して一意のパーティション名を指定するか、各ノードに別のデータベースを使用します。
Jakarta Enterprise Beans-clustered データベースタイマーは以下のように機能します。
- タイマーの実行が許可されるすべてのノードは、認識しているすべてのタイマーに対してタイムアウトをスケジュールします。
このタイムアウトが期限切れになると、各ノードでタイマーの状態を更新してタイマーをロックしようとします。
状態を更新するクエリーは、以下のクエリーに似ています。
UPDATE JBOSS_EJB_TIMER SET TIMER_STATE=? WHERE ID=? AND TIMER_STATE<>? AND NEXT_DATE=?;
トランザクションと READ_COMMITTED または SERIALIZABLE の分離モードのために、1 つのノードのみが行の更新で成功し、タイマーが実行するノードになります。
8.12.1. Jakarta Enterpise Beans でクラスター化されたタイマーの設定
データベースベースのタイマーストアを追加して、Jakarta Enterprise Beans-clustered タイマーを設定できます。
要件
- データベースは READ_COMMITTED または SERIALIZABLE 分離モードをサポートしている必要があります。
手順
データベースでサポートされるタイマーストアを作成します。
/subsystem=ejb3/service=timer-service/database-data-store=my-clustered-store:add(allow-execution=true, datasource-jndi-name="java:/MyDatasource", refresh-interval=60000, database="postgresql", partition="mypartition")
以下のパラメーターを設定します。
-
allow-execution
:true
に設定して、このノードがタイマーを実行できるようになります。false
に設定すると、JBoss EAP はこのノードのタイマーを別のノードで実行するデータベースに追加します。タイマー実行をクラスター内の複数のノードだけに制限すると、データベース全体の負荷が軽減されます。 -
datasource-jndi-name
: 使用するデータソース。 refresh-interval
: このノードは、他のノードが追加する新しいタイマーについてデータベースをチェックする前に経過する必要のある期間を設定します。値はミリ秒単位です。重要値を小さく設定すると、JBoss EAP はタイマーを高速に選択し、データベースの負荷が増えることを意味します。操作が失敗したか、
allow-execution
が false であるため、タイマーを追加したノードが実行できない場合は、ノードが更新されるまでこのタイマーは実行されません。Database
: 使用中のデータベースのタイプを定義します。一部の SQL ステートメントはデータベースによってカスタマイズされます。この属性を定義しない場合、サーバーは自動的にタイプを検出しようとします。現時点では、サポートされているタイプは
postgresql
、mysql
、oracle
、db2
、hsql
、およびh2
です。SQL は
modules/system/layers/base/org/jboss/as/ejb3/main/timers/timer-sql.properties
ファイルにあります。このファイルに新しいデータベース固有の SQL ステートメントを追加すると、実行される SQL を変更したり、新しいデータベースのサポートを追加したりできます。
-
partition
: このノードを所属させるパーティションの名前に設定します。同じパーティションのノードからタイマーのみがこのノードに表示されます。パフォーマンスを向上させるために、この属性を使用して大規模なクラスターを複数の小さなクラスターに分割します。
-
クラスターされていないタイマーにこのデータベースデータストアを使用するには、refresh-interval
をゼロに設定し、すべてのノードが一意のパーティション名を持つか、各ノードに異なるデータベースを使用していることを確認します。
8.12.2. デプロイメントでの Jakarta Enterprise Beans でクラスター化されたタイマーの使用
単一のデータストアをすべてのアプリケーションのデフォルトとして使用するか、各アプリケーションに特定のデータストアを使用できます。
要件
- Jakarta Enterprise Beans でクラスター化したデータベースベースのタイマーストアを設定している。
手順
単一のデータストアをすべてのアプリケーションにデフォルトとして使用するには、以下のように
ejb3
サブシステム内でdefault-data-store
を更新します。<timer-service thread-pool-name="timer" default-data-store="clustered-store"> <data-stores> <database-data-store name="clustered-store" datasource-jndi-name="java:jboss/datasources/ExampleDS" partition="timer"/> </data-stores> </timer-service>
特定のアプリケーションに別のデータストアを使用するには、タイマーデータストア名を
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:timer="urn:timer-service:1.0" xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd" version="3.1" impl-version="2.0"> <assembly-descriptor> <timer:timer> <ejb-name>*</ejb-name> <timer:persistence-store-name>my-clustered-store</timer:persistence-store-name> </timer:timer> </assembly-descriptor> </jboss:ejb-jar>
8.12.3. Jakarta インターセプターを使用した Jakarta Enterprise Beans でクラスタータイマーの更新
タイマーをプログラムで更新するには、ビジネスメソッドで Jakarta インターセプターを設定し、refresh-interval
が期限切れになる前にタイマーを強制的に更新することができます。
クラスター化されたデプロイメントでは、複数のノードがデータストアを短時間で更新した場合に、インメモリータイマーの状態が同期されなくなります。
要件
- データベースでサポートされるクラスター化された Jakarta Enterprise Beans を設定していること。
手順
wildfly.ejb.timer.refresh.enabled
をtrue
を有効にする Jakarta インターセプターを実装します。import javax.interceptor.AroundInvoke; import javax.interceptor.Interceptor; import javax.interceptor.InvocationContext; /** * An interceptor to enable programmatic timer refresh across multiple nodes. */ @Interceptor public class RefreshInterceptor { @AroundInvoke public Object intercept(InvocationContext context) throws Exception { context.getContextData().put("wildfly.ejb.timer.refresh.enabled", Boolean.TRUE); return context.proceed(); } }
Jakarta インターセプターを設定します。
Jakarta Interceptors は、ターゲットのステートレスまたはシングルトン Bean ビジネスメソッドに設定できます。
wildfly.ejb.timer.refresh.enabled
がtrue
に設定された場合、タイマーを返す前にTimerService.getAllTimers()
を呼び出すと、タイマーデータストアが更新されます。@Singleton public class RefreshBean1 ... { @Interceptors(RefreshInterceptor.class) public void businessMethod1() { ... // since wildfly.ejb.timer.refresh.enabled is set to true in interceptor for this business method, // calling timerService.getAllTimers() will first refresh from timer datastore before returning timers. final Collection<Timer> allTimers = timerService.getAllTimers(); ... } }
または、専用のビジネスメソッドを実装して、必要に応じてアプリケーションの他の部分が呼び出されるタイマーをプログラム的に更新できます。
@Interceptors(RefreshInterceptor.class) public List<Timer> getAllTimerInfoWithRefresh() { return timerService.getAllTimers(); } public void businessMethod1() { final LocalBusinessInterface businessObject = sessionContext.getBusinessObject(LocalBusinessInterface.class); businessObject.getAllTimerInfoWithRefresh(); // timer has been programmatically refreshed from datastore. // continue with other business logic... }
第9章 Jakarta Enterprise Beans 3 サブシステムの調整
ejb3
サブシステムのパフォーマンスを最適化するための情報は、パフォーマンスチューニングガイド のJakarta Enterprise Beans サブシステムの調整を参照してください。
付録A 参考資料
A.1. Jakarta Enterprise Beans Java Naming and Directory Interface Reference
セッション bean の Java Naming and Directory Interface ルックアップ名には、以下の構文を使用します。
ejb:<appName>/<moduleName>/<distinctName>/<beanName>!<viewClassName>?stateful
-
<appName>
: セッション Bean の JAR ファイルがエンタープライズアーカイブ (EAR) 内にデプロイされた場合、appName
はそれぞれの EAR の名前になります。デフォルトでは、EAR の名前は.ear
接尾辞を含まないファイル名です。アプリケーション名はapplication.xml
ファイルで上書きできます。セッション Bean が EAR にデプロイされていない場合は、appName
を空白のままにします。 -
<moduleName>
:moduleName
は、セッション Bean がデプロイされる JAR ファイルの名前です。JAR ファイルのデフォルト名は、.jar
接尾辞を含まないファイル名です。モジュール名は JAR のejb-jar.xml
ファイルで上書きできます。 -
<distinctName>
: JBoss EAP では、各デプロイメントで任意の一意の名前を指定できます。デプロイメントに一意の名前がない場合は、specificName
を空白のままにします。 -
<beanName>
:beanName
は、呼び出されるセッション Bean の単純なクラス名です。 -
<viewClassName>
:viewClassName
は、リモートインターフェイスの完全修飾クラス名です。これには、インターフェイスのパッケージ名が含まれます。 -
?stateful
: Java Naming and Directory Interface 名がステートフルセッション Bean を参照する場合は、?stateful
接尾辞が必要になります。他の Bean タイプには含まれません。
たとえば、リモートインターフェイス org.jboss.example.Hello
を公開したステートフル Bean org.jboss.example.HelloBean
を持つ hello.jar
をデプロイした場合、Java Naming and Directory Interface ルックアップ名は以下のようになります。
ejb:/hello/HelloBean!org.jboss.example.Hello?stateful"
A.2. Jakarta Enterprise Beans リファレンス解決
このセクションでは、JBoss EAP による @EJB
および @Resource
の実装方法について説明します。XML は常にアノテーションを上書きしますが、同じルールが適用されることに注意してください。
- @EJB アノテーションのルール
-
@EJB
アノテーションにはmappedName()
属性もあります。この仕様はこれをベンダー固有のメタデータとして残しますが、JBoss EAP は参照している Jakarta Enterprise Beans のグローバル Java Naming and Directory Interface 名としてmappedName()
を認識します。mappedName()
を指定した場合、他の属性はすべて無視され、バインディングにこのグローバル Java Naming および Directory Interface 名が使用されます。 属性が定義されていない状態で
@EJB
を指定する場合:@EJB ProcessPayment myEjbref;
次に、以下のルールが適用されます。
-
参照 Bean の Jakarta Enterprise Beans JAR は、
@EJB
インジェクションで使用されるインターフェイスで Jakarta Enterprise Beans を検索します。同じビジネスインターフェイスをパブリッシュする Jakarta Enterprise Beans が複数存在する場合、例外が発生します。このインターフェイスを持つ BIOSean が 1 つしかない場合は、その Bean が使用されます。 - EAR でインターフェイスを公開する Jakarta Enterprise Beans を検索します。重複が生じると、例外が発生します。それ以外の場合は、一致する Bean を返します。
- JBoss EAP ランタイムで、そのインターフェイスの Jakarta Enterprise Beans をグローバルに検索します。同様に、複製が見つかると、例外が発生します。
-
参照 Bean の Jakarta Enterprise Beans JAR は、
-
@EJB.beanName()
は<ejb-link>
に対応します。beanName()
が定義されている場合、検索でbeanName()
をキーとして使用する以外に定義されていない属性を持つ@EJB
と同じアルゴリズムを使用します。このルールの例外は、ejb-link # 構文を使用する場合です。これは、参照している Jakarta Enterprise Beans が置かれている EAR の JAR に相対パスを配置することができます。詳細は、Jakarta Enterprise Beans 3.2 仕様を参照してください。
-
A.3. リモート Jakarta Enterprise Beans クライアントのプロジェクト依存関係
リモートクライアントからのセッション Bean の呼び出しが含まれる Maven プロジェクトでは、JBoss EAP Maven リポジトリーから以下の依存関係が必要になります。以下のサブセクションで説明されているように、Jakarta Enterprise Beans クライアントの依存関係を宣言する方法があります。
artifactId
バージョンが変更される可能性があります。最新バージョンは、JBoss EAP Maven リポジトリーを参照してください。
リモート Jakarta Enterprise Beans クライアントの Maven 依存関係
jboss-eap-jakartaee8
Bill of Materials (BOM) は、JBoss EAP アプリケーションで通常必要とされる多くのアーティファクトの正しいバージョンをパッケージ化します。BOM 依存関係は、import
の範囲で pom.xml
の <dependencyManagement>
セクションで指定されています。
例: POM ファイル <dependencyManagement>
セクション
<dependencyManagement> <dependencies> <dependency> <groupId>org.jboss.bom</groupId> <artifactId>jboss-eap-jakartaee8</artifactId> <version>7.4.0.GA</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
残りの依存関係は、pom.xml
ファイルの <dependencies>
セクションで指定されます。
例: POM ファイル <dependencies>
セクション
<dependencies> <!-- Include the Enterprise Java Bean client JARs --> <dependency> <groupId>org.jboss.eap</groupId> <artifactId>wildfly-ejb-client-bom</artifactId> <type>pom</type> </dependency> <!-- Include any additional dependencies required by the application ... --> </dependencies>
JBoss EAP に同梱される ejb-remote
クイックスタートは、リモート Jakarta Enterprise Beans クライアントアプリケーションの完全な動作例が含まれます。リモートセッション Bean 呼び出しの依存関係設定の完全な例については、クイックスタートのルートディレクトリーにある client/pom.xml
ファイルを参照してください。
jboss-ejb-client 依存関係の単一のアーティファクト ID
wildfly-ejb-client-bom
artifactID
を使用し、jboss-ejb-client
ライブラリーを追加して Jakarta Enterprise Beans クライアントに必要な依存関係をすべて含めることができます。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jboss.eap</groupId>
<artifactId>wildfly-ejb-client-bom</artifactId>
<version>JAKARTA_ENTERPRISE_BEANS_CLIENT_BOM_VERSION</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jboss-ejb-client</artifactId>
</dependency>
</dependencies>
JBoss EAP Maven リポジトリーで利用可能な JAKARTA_ENTERPRISE_BEANS_CLIENT_BOM_VERSION を使用する必要があります。
A.4. jboss-ejb3.xml デプロイメント記述子の参照
jboss-ejb3.xml
は、Jakarta Enterprise Beans JAR または WAR アーカイブで使用できるカスタムデプロイメント記述子です。Jakarta Enterprise Beans JAR アーカイブでは、META-INF/
ディレクトリーに存在する必要があります。WAR アーカイブでは、WEB-INF/
ディレクトリーに配置する必要があります。
この形式は ejb-jar.xml
と同様で、同じネームスペースの一部を使用して追加の名前空間を提供します。jboss-ejb3.xml
のコンテンツは ejb-jar.xml
の内容でマージされ、jboss-ejb3.xml
の内容が優先されます。
本書では、jboss-ejb3.xml
で使用される追加の非標準の名前空間のみについて説明します。標準の名前空間は、http://xmlns.jcp.org/xml/ns/javaee/ を参照してください。
ルート名前空間は http://xmlns.jcp.org/xml/ns/javaee です。
- アセンブリー記述子の名前空間
-
以下の名前空間はすべて、
<assembly-descriptor>
要素で使用できます。これらは、単一の Bean や、ワイルドカード (*
) をejb-name
として使用してデプロイメントのすべての Bean に設定を適用するために使用できます。 - セキュリティー名前空間 (
urn:security
) xmlns:s="urn:security"
これにより、Jakarta Enterprise Beans の
security-domain
およびrun-as-principal
を設定できます。<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>
<?xml version="1.1" encoding="UTF-8"?> <jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee" xmlns="http://xmlns.jcp.org/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-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> </jboss:ejb-jar>
注記jboss-ejb3-spec-2_0.xsd
ファイルには、スキーマバリデーションエラーが発生する可能性がある既知の問題があります。これらのエラーは無視して構いません。詳細は、https://bugzilla.redhat.com/show_bug.cgi?id=1192591 を参照してください。
A.5. Jakarta Enterprise Beans スレッドプールの設定
Jakarta Enterprise Beans スレッドプールは、管理コンソールまたは管理 CLI を使用して作成できます。
A.5.1. 管理コンソールを使用した Jakarta Enterprise Beans スレッドプールの設定
手順
- 管理コンソールにログインします。
- Configuration → Subsystems → EJB の順に移動し、View をクリックします。
- Container → Thread Pool の順に選択します 。
- Add をクリックして、Name および Max Threads 値を指定します。
- Save をクリックします。
A.5.2. 管理 CLI を使用した Jakarta Enterprise Beans スレッドプールの設定
手順
以下の構文で
add
操作を使用します。/subsystem=ejb3/thread-pool=THREAD_POOL_NAME:add(max-threads=MAX_SIZE)
-
THREAD_POOL_NAME
は、スレッドプールに必要な名前に置き換えます。 -
MAX_SIZE
はスレッドプールの最大サイズに置き換えます。
-
read-resource
操作を使用して、スレッドプールの作成を確認します。/subsystem=ejb3/thread-pool=THREAD_POOL_NAME:read-resource
ejb3
サブシステムのすべてのサービスを、新しいスレッドプールを使用するように再設定するには、以下のコマンドを使用します。/subsystem=ejb3/thread-pool=bigger:add(max-threads=100, core-threads=10) /subsystem=ejb3/service=async:write-attribute(name=thread-pool-name, value="bigger") /subsystem=ejb3/service=remote:write-attribute(name=thread-pool-name, value="bigger") /subsystem=ejb3/service=timer-service:write-attribute(name=thread-pool-name, value="bigger") reload
XML 設定例:
<subsystem xmlns="urn:jboss:domain:ejb3:5.0"> ... <async thread-pool-name="bigger"/> ... <timer-service thread-pool-name="bigger" default-data-store="default-file-store"> ... <remote connectors="http-remoting-connector" thread-pool-name="bigger"/> ... <thread-pools> <thread-pool name="default"> <max-threads count="10"/> <core-threads count="5"/> <keepalive-time time="100" unit="milliseconds"/> </thread-pool> <thread-pool name="bigger"> <max-threads count="100"/> <core-threads count="5"/> </thread-pool> </thread-pools> ...
A.5.3. Jakarta Enterprise Beans スレッドプール属性
特定の設定のニーズに応じてより効率的に実行するには、属性を使用して Jakarta Enterprise Beans スレッドプールを設定できます。
-
max-threads
属性は、エグゼキューターがサポートするスレッドの合計数または最大数を決定します。
/subsystem=ejb3/thread-pool=default:write-attribute(name=max-threads, value=9) {"outcome" => "success"}
-
core-threads
属性は、エグゼキューターのプールに保持されるスレッドの数を決定します。これには、アイドル状態のスレッドが含まれます。core-threads
属性が指定されていない場合、デフォルトはmax-threads
の値に設定されます。
/subsystem=ejb3/thread-pool=default:write-attribute(name=core-threads, value=3) {"outcome" => "success"}
-
keepalive-time
属性は、コア以外のスレッドがアイドル状態でいられる時間を決定します。この時間を過ぎると、コア以外のスレッドが削除されます。
/subsystem=ejb3/thread-pool=default:write-attribute(name=keepalive-time, value={time=5, unit=MINUTES}) {"outcome"=> "success"}
-
keepalive-time
属性の時間単位を変更せずに時間を変更するには、以下のコマンドを使用します。
/subsystem=ejb3/thread-pool=default:write-attribute(name=keepalive-time.time, value=10) {"outcome"=> "success"}
改訂日時: 2024-02-09