開発ガイド
JBoss Enterprise Application Platform 6 向け
エディッション 3
Nidhi Chaudhary
Lucas Costi
Russell Dickenson
Sande Gilda
Vikram Goyal
Eamon Logue
Darrin Mison
Scott Mumford
David Ryan
Misty Stanley-Jones
Keerat Verma
Tom Wells
概要
第1章 アプリケーションの開発
1.1. はじめに
1.1.1. JBoss Enterprise Application Platform 6 について
1.2. 要件
1.2.1. Java Enterprise Edition 6 を理解する
1.2.1.1. EE 6 プロファイルの概要
1.2.1.2. Java Enterprise Edition 6 Web Profile
Java EE 6 Web Profile の要件
- Java Platform、Enterprise Edition 6
Java Web テクノロジー
- Servlet 3.0 (JSR 315)
- JSP 2.2 および Expression Language (EL) 1.2
- JavaServer Faces (JSF) 2.0 (JSR 314)
- JSP 1.2 向けの Java Standard Tag Library (JSTL)
- Debugging Support for Other Languages 1.0 (JSR 45)
エンタープライズアプリケーションテクノロジー
- Contexts and Dependency Injection (CDI) (JSR 299)
- Dependency Injection for Java (JSR 330)
- Enterprise JavaBeans 3.1 Lite (JSR 318)
- Java Persistence API 2.0 (JSR 317)
- Common Annotations for the Java Platform 1.1 (JSR 250)
- Java Transaction API (JTA) 1.1 (JSR 907)
- Bean Validation (JSR 303)
1.2.1.3. Java Enterprise Edition 6 Full Profile
EE 6 Full Profile に含まれるアイテム
- EJB 3.1 (Lite ではない) (JSR 318)
- Java EE Connector Architecture 1.6 (JSR 322)
- Java Message Service (JMS) API 1.1 (JSR 914)
- JavaMail 1.4 (JSR 919)
Web サービステクノロジー
- Jax-RS RESTful Web Services 1.1 (JSR 311)
- Implementing Enterprise Web Services 1.3 (JSR 109)
- JAX-WS Java API for XML-Based Web Services 2.2 (JSR 224)
- Java Architecture for XML Binding (JAXB) 2.2 (JSR 222)
- Web Services Metadata for the Java Platform (JSR 181)
- Java APIs for XML-based RPC 1.1 (JSR 101)
- Java APIs for XML Messaging 1.3 (JSR 67)
- Java API for XML Registries (JAXR) 1.0 (JSR 93)
管理およびセキュリティテクノロジー
- Java Authentication Service Provider Interface for Containers 1.0 (JSR 196)
- Java Authentication Contract for Containers 1.3 (JSR 115)
- Java EE Application Deployment 1.2 (JSR 88)
- J2EE Management 1.1 (JSR 77)
1.2.2. JBoss Enterprise Application Platform 6 で使用されるモジュールと新しいモジュラークラスローディングシステムについて
1.2.2.1. モジュール
- 静的モジュール
- 静的モジュールは、アプリケーションサーバーの
EAP_HOME/modules/
ディレクトリに事前定義されます。各サブディレクトリは 1 つのモジュールを表し、1 つまたは複数の JAR ファイルと設定ファイル (module.xml
) が含まれます。モジュールの名前は、module.xml
ファイルで定義されます。アプリケーションサーバーで提供されるすべての API (Java EE API や JBoss Logging などの他の API を含む) は、静的モジュールとして提供されます。カスタム静的モジュールの作成は、同じサードパーティーライブラリを使用する同じサーバー上に多くのアプリケーションがデプロイされる場合に役立ちます。これらのライブラリを各アプリケーションとバンドルする代わりに、JBoss 管理者はこれらのライブラリが含まれるモジュールを作成およびインストールできます。アプリケーションは、カスタム静的モジュールで明示的な依存関係を宣言できます。 - 動的モジュール
- 動的モジュールは、各 JAR または WAR デプロイメント (または、EAR 内のサブデプロイメント) に対してアプリケーションサーバーによって作成およびロードされます。動的モジュールの名前は、デプロイされたアーカイブの名前から派生されます。デプロイメントはモジュールとしてロードされるため、依存関係を設定でき、他のデプロイメントが依存関係として使用できます。
1.2.2.2. クラスロードとモジュールの概要
1.3. 開発環境の設定
1.3.1. JBoss Developer Studio のダウンロードとインストール
1.3.1.1. JBoss Developer Studio の設定
1.3.1.2. JBoss Developer Studio 5 のダウンロード
- https://access.redhat.com/ にアクセスします。
- ダウンロード → JBoss Enterprise Middleware → ダウンロード と選択します。
- ドロップボックスから JBoss Developer Studio を選択します。
- 適切なバージョンを選択し、ダウンロード をクリックします。
1.3.1.3. JBoss Developer Studio 5 のインストール
手順1.1 JBoss Developer Studio 5 のインストール
- 端末を開きます。
- ダウンロードした
.jar
ファイルが含まれるディレクトリへ移動します。 - 次のコマンドを実行して GUI インストーラーを開始します。
java -jar jbdevstudio-build_version.jar
- [Next] をクリックしてインストールを開始します。
- [I accept the terms of this license agreement] を選択し、[Next] をクリックします。
- インストールパスを調整し、[Next] をクリックします。
注記
インストールパスのフォルダーが存在しない場合はメッセージが表示されます。[Ok] をクリックしてフォルダーを作成します。 - デフォルトの JVM が選択されます。他の JVM を選択するか、そのまま [Next] をクリックします。
- 使用可能なアプリケーションプラットフォームを追加し、[Next] をクリックします。
- インストールの詳細を確認し、[Next] をクリックします。
- インストールが完了したら [Next] をクリックします。
- JBoss Developer Studio のデスクトップショートカットを設定し、[Next] をクリックします。
- [Done] をクリックします。
1.3.1.4. JBoss Developer Studio の起動
手順1.2 JBoss Developer Studio を起動するコマンド
- 端末を開きます。
- インストールディレクトリへ移動します。
- 次のコマンドを実行して JBoss Developer Studio を起動します。
[localhost]$ ./jbdevstudio
1.3.1.5. JBoss Enterprise Application Platform 6 サーバーの JBoss Developer Studio への追加
手順1.3 サーバーの追加
- [Servers]タブを開きます。[Servers]タブがない場合は次のようにパネルへ追加します。
- [Window] → [Show View] → [Other...] をクリックします。
- [Servers] フォルダーより [Server] を選択し、[OK] をクリックします。
- [new server wizard]リンクをクリックするか、空のサーバーパネル内で右クリックし、[New] → [Server] と選択します。
図1.1 新しいサーバーの追加 - 使用できるサーバーがない場合
- [JBoss Enterprise Middleware] を拡張し、 [JBoss Enterprise Application Platform 6.x] を選択します。その後、[Next] ボタンをクリックします。
図1.2 サーバータイプの選択
- [Browse] をクリックし、JBoss Enterprise Application Platform 6 のインストール場所へ移動します。そして [Next] をクリックします。
図1.3 サーバーインストールの閲覧
- この画面でサーバーの動作を定義します。手作業でサーバーを起動するか、JBoss Developer Studio に管理を任せます。デプロイメントのリモートサーバーを定義し、そのサーバーの管理ポートを公開するかどうかを決定できます (たとえば、JMX を使用してこのサーバーに接続する必要がある場合)。この例では、サーバーがローカルサーバーであり、JBoss Developer Studio がサーバーを管理するため、何もチェックする必要がないことを前提とします。次へ (Next) をクリックします。
図1.4 新しい JBoss サーバーの挙動の定義
- この画面により新しいサーバーに対して既存のプロジェクトを設定することが可能です。現時点ではプロジェクトがないため、 [Finish] をクリックします。
図1.5 新しい JBoss サーバーのリソースの変更
JBoss Enterprise Application Server 6.0 のランタイムサーバーは [Servers] タブに表示されます。

図1.6 サーバーがサーバーリストに表示される
1.4. 最初のアプリケーションの実行
1.4.1. デフォルトの Welcome Web アプリケーションの置き換え
手順1.4 デフォルトの Welcome Web アプリケーションを独自の Web アプリケーションに置き換える
Welcome アプリケーションを無効にします。
管理 CLI スクリプトEAP_HOME/bin/jboss-cli.sh
を使用して次のコマンドを実行します。異なる管理対象ドメインプロファイルの変更が必要となる場合があります。スタンドアローンサーバーでは、コマンドの/profile=default
部分の削除が必要となる場合があります。/profile=default/subsystem=web/virtual-server=default-host:write-attribute(name=enable-welcome-root,value=false)
ルートコンテキストを使用するよう Web アプリケーションを設定します。
Web アプリケーションを設定してルートコンテキストを (/) を URL アドレスとして使用するには、META-INF/
またはWEB-INF/
ディレクトリにあるjboss-web.xml
を変更します。<context-root>
ディレクティブを次のようなディレクティブに置き換えます。<jboss-web> <context-root>/</context-root> </jboss-web>
アプリケーションをデプロイします。
サーバーグループか最初に変更したサーバーにアプリケーションをデプロイします。アプリケーションはhttp://SERVER_URL:PORT/
で使用できるようになります。
1.4.2. クイックスタートコードの例をダウンロードする
1.4.2.1. Java EE クイックスタートサンプルへのアクセス
JBoss Enterprise Application Platform 6 には、ユーザーが Java EE 6 の技術を使用したアプリケーションの作成を簡単に開始できるクイックスタートのサンプルが複数含まれています。
要件
- Maven 3.0.0 以降のバージョン。Maven のインストールに関する詳細は http://maven.apache.org/download.html を参照してください。
手順1.5 クイックスタートのダウンロード
- Web ブラウザーを開き、URL https://access.redhat.com/jbossnetwork/restricted/listSoftware.html?product=appplatform にアクセスします。
- リストに「Application Platform 6 クイックスタート」があることを確認します。
- [ダウンロード] ボタンをクリックし、サンプルが含まれる
.zip
ファイルをダウンロードします。 - 希望のディレクトリにアーカイブを展開します。
Java EE クイックスタートのサンプルがダウンロードされ、解凍されます。各クイックスタートのデプロイ方法については、jboss-eap-6.0-quickstarts/
ディレクトリーにある README.md
ファイルを参照してください。
1.4.3. クイックスタートの実行
1.4.3.1. JBoss Developer Studio でのクイックスタートの実行
手順1.6 JBoss Developer Studio にクイックスタートをインポートする
- この作業を行っていない場合は、 「Maven 設定を使用した JBoss Enterprise Application Platform の Maven リポジトリーの設定」に記載された手順に従ってください。
- JBoss Developer Studio を起動します。
- メニューより [File] → [Import] と選択します。
- 選択リストより [Maven] → [Maven Projects] と選択し、[Next] を選択します。
図1.7 既存の Maven プロジェクトのインポート
- インポートするクイックスタートのディレクトリーを参照し、OK をクリックします。[Projects] リストボックスに、選択したクイックスタートプロジェクトの
pom.xml
ファイルが示されます。図1.8 Maven プロジェクトの選択
- [Next] をクリックした後、 [Finish] をクリックします。
手順1.7 helloworld
クイックスタートのビルドとデプロイ
helloworld
クイックスタートは最も単純なクイックスタートの 1 つで、JBoss サーバーが適切に設定され実行されているか検証することができます。
- [Servers] タブを開き、パネルにアプリケーションを追加します。
- [Window] → [Show View] → [Other...] をクリックします。
- [Servers] フォルダーから [Server] を選択し[Ok] をクリックします。
- [Project Explorer] タブで [helloworld] を右クリックし、[Run As] → [Run on Server] を選択します。
- [JBoss EAP 6.0 Runtime Server] サーバーを選択し、[Next] をクリックします。これにより
helloworld
クイックスタートが JBoss サーバーにデプロイされます。 helloworld
が JBoss サーバーに正しくデプロイされたことを確認するには、Web ブラウザーを開いて、URL http://localhost:8080/jboss-as-helloworld でアプリケーションに接続します。
1.4.3.2. コマンドラインを使用したクイックスタートの実行
手順1.8 コマンドラインを使用したクイックスタートのビルドおよびデプロイ
クイックスタートのルートディレクトリにある
README
ファイルを確認してください。このファイルにはシステム要件に関する一般的な情報、Maven の設定方法、ユーザーの追加方法、クイックスタートの実行方法が含まれています。クイックスタートを始める前に必ず読むようにしてください。このファイルには使用可能なクイックスタートの一覧表も含まれています。この表にはクイックスタート名と使用する技術が記載され、各クイックスタートの簡単な説明と設定するために必要な経験レベルが記載されています。クイックスタートの詳細情報はクイックスタート名をクリックしてください。他のクイックスタートを向上したり拡張するため作成されたクイックスタートもあります。このようなクイックスタートはPrerequisites
カラムに記載されています。クイックスタートに前提条件がある場合、クイックスタートを始める前にこれらをインストールする必要があります。任意コンポーネントのインストールや設定が必要になるクイックスタートもあります。これらのコンポーネントはクイックスタートが必要である場合のみインストールしてください。helloworld
クイックスタートを実行します。helloworld
クイックスタートは最も単純なクイックスタートの 1 つで、JBoss サーバーが適切に設定され実行されているか検証することができます。helloworld
クイックスタートのルートにあるREADME
ファイルを開きます。このファイルにはクイックスタートのビルドおよびデプロイ方法や実行しているアプリケーションへのアクセス方法の詳細手順が含まれています。別のクイックスタートを実行します。
各クイックスタートのルートフォルダーにあるREADME
ファイルの手順に従って例を実行します。
1.4.4. クイックスタートチュートリアルの確認
1.4.4.1. helloworld クイックスタート
helloworld クイックスタートでは JBoss Enterprise Application Platform 6 に単純なサーブレットをデプロイする方法を説明します。ビジネスロジックは CDI (Contexts and Dependency Injection) Bean として提供されるサービスにカプセル化されサーブレットに挿入されます。このクイックスタートは大変単純です。「Hello World」を Web ページに出力するだけです。サーバーが適切に設定され、起動されたかを最初に確認するのに適しています。
手順1.9 helloworld クイックスタートを JBoss Developer Studio にインポートします。
- インポートしていない場合は、 「Maven 設定を使用した JBoss Enterprise Application Platform の Maven リポジトリーの設定」に記述された手順に従います。
- JBoss Developer Studio がインストールされていない場合は、 「JBoss Developer Studio 5 のインストール」に記述された手順に従います。
- 「JBoss Developer Studio の起動」に記述された手順に従います。
- メニューより [File] → [Import] と選択します。
- 選択リストより [Maven] → [Maven Projects] と選択し、[Next] を選択します。
図1.9 既存の Maven プロジェクトのインポート
QUICKSTART_HOME/quickstart/helloworld/
ディレクトリを閲覧し、[OK] をクリックします。[ Projects] リストボックスに [helloworld] クイックスタートプロジェクトからpom.xml
ファイルが追加されます。図1.10 Maven プロジェクトの選択
- [Finish] をクリックします。
手順1.10 helloworld クイックスタートのビルドとデプロイ
- JBoss Enterprise Application Platform 6 用 JBoss Developer Studio がまだ設定されていない場合は、 「JBoss Enterprise Application Platform 6 サーバーの JBoss Developer Studio への追加」に記述された手順に従います。
- [Project Explorer] タブの [jboss-as-helloworld] を右クリックし、[Run As] → [Run on Server] と選択します。
図1.11 サーバー上での実行
- [JBoss EAP 6.0 Runtime Server] サーバーを選択し、[Next] をクリックします。これにより helloworld クイックスタートが JBoss サーバーにデプロイされます。
- helloworld が JBoss サーバーに正しくデプロイされたことを確認するには、Web ブラウザーを開き、URL http://localhost:8080/jboss-as-helloworld を指定してアプリケーションにアクセスします。
手順1.11 ディレクトリ構造の確認
QUICKSTART_HOME/helloworld
ディレクトリにあります。helloworld クイックスタートはサーブレットと CDI Bean によって構成されます。また、このアプリケーションの Bean を検索し、CDI をアクティベートするよう JBoss Enterprise Application Platform 6 に伝える空の beans.xml ファイルも含まれています。
beans.xml
はクイックスタートのsrc/main/webapp/
ディレクトリにあるWEB-INF/
フォルダーにあります。src/main/webapp/
ディレクトリには、単純なメタリフレッシュを使用してユーザーのブラウザーを http://localhost:8080/jboss-as-helloworld/HelloWorld にあるサーブレットへリダイレクトするindex.html
ファイルも含まれています。- この例の全設定は、例の
src/main/webapp/
ディレクトリにあるWEB-INF/
にあります。 - クイックスタートには
web.xml
ファイルは必要ありません。
手順1.12 コードの確認
HelloWorldServlet コードの検証
HelloWorldServlet.java
はsrc/main/java/org/jboss/as/quickstarts/helloworld/
ディレクトリにあります。このサーブレットが情報をブラウザーに送ります。27. @WebServlet("/HelloWorld") 28. public class HelloWorldServlet extends HttpServlet { 29. 30. static String PAGE_HEADER = "<html><head /><body>"; 31. 32. static String PAGE_FOOTER = "</body></html>"; 33. 34. @Inject 35. HelloService helloService; 36. 37. @Override 38. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 39. PrintWriter writer = resp.getWriter(); 40. writer.println(PAGE_HEADER); 41. writer.println("<h1>" + helloService.createHelloMessage("World") + "</h1>"); 42. writer.println(PAGE_FOOTER); 43. writer.close(); 44. } 45. 46. }
表1.1 HelloWorldServlet の詳細
行 注記 27 Java EE 6 以前はサーブレットの登録に XML ファイルが使用されました。サーブレットの登録はかなり簡易化され、 @WebServlet
アノテーションを追加し、サーブレットへのアクセスに使用される URL へのマッピングを提供することのみが必要となります。30-32 各 Web ページには適切な形式の HTML が必要になります。本クイックスタートは静的な文字列を使用して最低限のヘッダーとフッターの出力を書き出します。 34-35 これらの行は実際のメッセージを生成する HelloService CDI Bean を挿入します。HelloService の API を変更しない限り、ビューレイヤーを変更せずに HelloService の実装を後日変更することが可能です。 41 この行はサービスへ呼び出し、「Hello World」というメッセージを生成して HTTP 要求へ書き出します。 HelloService コードの検証
HelloService.java
ファイルはsrc/main/java/org/jboss/as/quickstarts/helloworld/
ディレクトリにあります。このサービスは非常に単純であり、メッセージを返します。XML やアノテーションの登録は必要ありません。9. public class HelloService { 10. 11. String createHelloMessage(String name) { 12. return "Hello " + name + "!"; 32. } 33. } 34.
1.4.4.2. numberguess クイックスタート
このクイックスタートでは単純なアプリケーションを作成し、 JBoss Enterprise Application Platform 6 にデプロイする方法を説明します。ここで作成するアプリケーションは情報を永続化しません。情報は JSF ビューを使用して表示され、ビジネスロジックは 2 つの CDI (Contexts and Dependency Injection) Bean にカプセル化されます。numberguess クイックスタートでは 1 から 100 までの数字を当てるチャンスが 10 回与えられます。数字を選択した後、その数字が正解の数字より大きいか小さいかが表示されます。
QUICKSTART_HOME/numberguess
ディレクトリにあります。numberguess クイックスタートは WAR モジュールとしてパッケージ化された複数の Bean や設定ファイル、Facelets (JSF) ビューによって構成されます。
手順1.13 numberguess クイックスタートを JBoss Developer Studio にインポートします。
- JBoss Developer Studio がインストールされていない場合は、 「JBoss Developer Studio 5 のインストール」に記述された手順に従います。
- 「JBoss Developer Studio の起動」に記述された手順に従います。
- メニューより [File] → [Import] と選択します。
- 選択リストより [Maven] → [Maven Projects] と選択し、[Next] を選択します。
図1.12 既存の Maven プロジェクトのインポート
QUICKSTART_HOME/quickstart/numberguess/
ディレクトリを閲覧し、[OK] をクリックします。 [Projects] リストボックスに [numberguess] クイックスタートプロジェクトからpom.xml
ファイルが追加されます。- [Finish] をクリックします。
手順1.14 numberguess クイックスタートのビルドとデプロイ
- JBoss Enterprise Application Platform 6 用 JBoss Developer Studio がまだ設定されていない場合は、 「JBoss Enterprise Application Platform 6 サーバーの JBoss Developer Studio への追加」に記述された手順に従います。
- [Project Explorer] タブの [jboss-as-numberguess] を右クリックし、[Run As] → [Run on Server] と選択します。
- [JBoss EAP 6.0 Runtime Server] サーバーを選択し、[Next] をクリックします。これにより numberguess クイックスタートが JBoss サーバーにデプロイされます。
- numberguess が JBoss サーバーに正しくデプロイされたことを確認するには、Web ブラウザを開き、URL http://localhost:8080/jboss-as-numberguess を指定してアプリケーションにアクセスします。
手順1.15 設定ファイルの確認
src/main/webapp/
ディレクトリにある WEB-INF/
ディレクトリに格納されています。
faces-config ファイルの確認
本クイックスタートはfaces-config.xml
ファイル名の JSF 2.0 バージョンを使用します。Facelets の標準的なバージョンが JSF 2.0 のデフォルトのビューハンドラーであるため、特に必要なものはありません。ここでは JBoss Enterprise Application Platform 6 は Java EE の領域を越えます。この設定ファイルが含まれると JSF が自動的に設定されます。そのため、設定はルート要素のみで構成されます。03. <faces-config version="2.0" 04. xmlns="http://java.sun.com/xml/ns/javaee" 05. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 06. xsi:schemaLocation=" 07. http://java.sun.com/xml/ns/javaee> 08. http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"> 09. 10. </faces-config>
beans.xml ファイルの確認
アプリケーションの Bean を検索し、CDI を有効にするよう JBoss Enterprise Application Platform に伝える空のbeans.xml
ファイルも存在します。web.xml ファイルはありません
クイックスタートにはweb.xml
ファイルは必要ありません。
手順1.16 JSF コードの確認
.xhtml
ファイル拡張子を使用しますが、レンダリングされたビューには .jsf
拡張子を使用します。
home.xhtml コードの確認
home.xhtml
ファイルはsrc/main/webapp/
ディレクトリにあります。03. <html xmlns="http://www.w3.org/1999/xhtml" 04. xmlns:ui="http://java.sun.com/jsf/facelets" 05. xmlns:h="http://java.sun.com/jsf/html" 06. xmlns:f="http://java.sun.com/jsf/core"> 07. 08. <head> 09. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> 10. <title>Numberguess</title> 11. </head> 12. 13. <body> 14. <div id="content"> 15. <h1>Guess a number...</h1> 16. <h:form id="numberGuess"> 17. 18. <!-- Feedback for the user on their guess --> 19. <div style="color: red"> 20. <h:messages id="messages" globalOnly="false" /> 21. <h:outputText id="Higher" value="Higher!" 22. rendered="#{game.number gt game.guess and game.guess ne 0}" /> 23. <h:outputText id="Lower" value="Lower!" 24. rendered="#{game.number lt game.guess and game.guess ne 0}" /> 25. </div> 26. 27. <!-- Instructions for the user --> 28. <div> 29. I'm thinking of a number between <span 30. id="numberGuess:smallest">#{game.smallest}</span> and <span 31. id="numberGuess:biggest">#{game.biggest}</span>. You have 32. #{game.remainingGuesses} guesses remaining. 33. </div> 34. 35. <!-- Input box for the users guess, plus a button to submit, and reset --> 36. <!-- These are bound using EL to our CDI beans --> 37. <div> 38. Your guess: 39. <h:inputText id="inputGuess" value="#{game.guess}" 40. required="true" size="3" 41. disabled="#{game.number eq game.guess}" 42. validator="#{game.validateNumberRange}" /> 43. <h:commandButton id="guessButton" value="Guess" 44. action="#{game.check}" 45. disabled="#{game.number eq game.guess}" /> 46. </div> 47. <div> 48. <h:commandButton id="restartButton" value="Reset" 49. action="#{game.reset}" immediate="true" /> 50. </div> 51. </h:form> 52. 53. </div> 54. 55. <br style="clear: both" /> 56. 57. </body> 58. </html>
表1.2 JSF の詳細
行 注記 20-24 ユーザーに送信できるメッセージ、「Higher」(より大きい) と「Lower」(より小さい) になります。 29-32 ユーザーが数を選択するごとに数字の範囲が狭まります。有効な数の範囲が分かるようにこの文章は変更されます。 38-42 このフィールドは値式を使用して Bean プロパティーにバインドされます。 42 ユーザーが誤って範囲外の数字を入力しないようバリデーターのバインディングが使用されます。バリデーターがない場合は、ユーザーが範囲外の数字を使用することがあります。 43-45 ユーザーの選択した数字をサーバーに送る方法があるはずです。ここでは Bean 上のアクションメソッドをバインドします。
手順1.17 クラスファイルの確認
src/main/java/org/jboss/as/quickstarts/numberguess/
ディレクトリにあります。パッケージの宣言とインポートはリストには含まれていません。完全なリストはクイックスタートのソースコードにあります。
Random.java 限定子コードの検証
型に基づき挿入の対象となる 2 つの Bean 間の曖昧さを取り除くために修飾子が使用されます。修飾子の詳細については、 「修飾子を使用して不明な挿入を解決」を参照してください。@Random
限定子は乱数の挿入に使用されます。21. @Target({ TYPE, METHOD, PARAMETER, FIELD }) 22. @Retention(RUNTIME) 23. @Documented 24. @Qualifier 25. public @interface Random { 26. 27. }
MaxNumber.java 限定子コードの検証
@MaxNumber
qualifier
は最大許可数の挿入に使用されます。21. @Target({ TYPE, METHOD, PARAMETER, FIELD }) 22. @Retention(RUNTIME) 23. @Documented 24. @Qualifier 25. public @interface MaxNumber { 26. 27. }
ジェネレーターコードの検証
Generator
クラスは producer メソッドより乱数を作成する役割があります。また、producer メソッドより最大可能数も公開します。このクラスはアプリケーションスコープ指定であるため、毎回異なる乱数になることはありません。28. @ApplicationScoped 29. public class Generator implements Serializable { 30. private static final long serialVersionUID = -7213673465118041882L; 31. 32. private java.util.Random random = new java.util.Random(System.currentTimeMillis()); 33. 34. private int maxNumber = 100; 35. 36. java.util.Random getRandom() { 37. return random; 38. } 39. 40. @Produces 41. @Random 42. int next() { 43. // a number between 1 and 100 44. return getRandom().nextInt(maxNumber - 1) + 1; 45. } 46. 47. @Produces 48. @MaxNumber 49. int getMaxNumber() { 50. return maxNumber; 51. } 52. }
ゲームコードの検証
セッションスコープ指定クラスGame
はアプリケーションのプライマリエントリーポイントです。ゲームの設定や再設定、ユーザーが選択する数字のキャプチャーや検証、FacesMessage
によるユーザーへのフィードバック提供を行う役割があります。コンストラクト後の lifecycle メソッドを使用し、@Random Instance
<Integer>
Bean より乱数を読み出してゲームを初期化します。このクラスの @Named アノテーションを見てください。このアノテーションは式言語 (EL) より Bean を JSF ビューにアクセスできるようにしたい場合のみ必要です。この場合#{game}
が EL になります。035. @Named 036. @SessionScoped 037. public class Game implements Serializable { 038. 039. private static final long serialVersionUID = 991300443278089016L; 040. 041. /** 042. * The number that the user needs to guess 043. */ 044. private int number; 045. 046. /** 047. * The users latest guess 048. */ 049. private int guess; 050. 051. /** 052. * The smallest number guessed so far (so we can track the valid guess range). 053. */ 054. private int smallest; 055. 056. /** 057. * The largest number guessed so far 058. */ 059. private int biggest; 060. 061. /** 062. * The number of guesses remaining 063. */ 064. private int remainingGuesses; 065. 066. /** 067. * The maximum number we should ask them to guess 068. */ 069. @Inject 070. @MaxNumber 071. private int maxNumber; 072. 073. /** 074. * The random number to guess 075. */ 076. @Inject 077. @Random 078. Instance<Integer> randomNumber; 079. 080. public Game() { 081. } 082. 083. public int getNumber() { 084. return number; 085. } 086. 087. public int getGuess() { 088. return guess; 089. } 090. 091. public void setGuess(int guess) { 092. this.guess = guess; 093. } 094. 095. public int getSmallest() { 096. return smallest; 097. } 098. 099. public int getBiggest() { 100. return biggest; 101. } 102. 103. public int getRemainingGuesses() { 104. return remainingGuesses; 105. } 106. 107. /** 108. * Check whether the current guess is correct, and update the biggest/smallest guesses as needed. 109. * Give feedback to the user if they are correct. 110. */ 111. public void check() { 112. if (guess > number) { 113. biggest = guess - 1; 114. } else if (guess < number) { 115. smallest = guess + 1; 116. } else if (guess == number) { 117. FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Correct!")); 118. } 119. remainingGuesses--; 120. } 121. 122. /** 123. * Reset the game, by putting all values back to their defaults, and getting a new random number. 124. * We also call this method when the user starts playing for the first time using 125. * {@linkplain PostConstruct @PostConstruct} to set the initial values. 126. */ 127. @PostConstruct 128. public void reset() { 129. this.smallest = 0; 130. this.guess = 0; 131. this.remainingGuesses = 10; 132. this.biggest = maxNumber; 133. this.number = randomNumber.get(); 134. } 135. 136. /** 137. * A JSF validation method which checks whether the guess is valid. It might not be valid because 138. * there are no guesses left, or because the guess is not in range. 139. * 140. */ 141. public void validateNumberRange(FacesContext context, UIComponent toValidate, Object value) { 142. if (remainingGuesses <= 0) { 143. FacesMessage message = new FacesMessage("No guesses left!"); 144. context.addMessage(toValidate.getClientId(context), message); 145. ((UIInput) toValidate).setValid(false); 146. return; 147. } 148. int input = (Integer) value; 149. 150. if (input < smallest || input > biggest) { 151. ((UIInput) toValidate).setValid(false); 152. 153. FacesMessage message = new FacesMessage("Invalid guess"); 154. context.addMessage(toValidate.getClientId(context), message); 155. } 156. } 157. }
第2章 Maven ガイド
2.1. Maven について
2.1.1. Maven リポジトリについて
http://
、ファイルサーバーのリポジトリにはfile://
という風に共通のプロトコルを使いアクセスします。ローカルのリポジトリは、リモートリポジトリからのアーティファクトをダウンロードしキャッシュ化したものです。
2.1.2. Maven POM ファイルについて
pom.xml
ファイルでは一部の設定オプションを設定する必要があり、他のすべてのオプションはデフォルト値に設定されます。詳細については、 「Maven POM ファイルの最低要件」を参照してください。
pom.xml
ファイルのスキーマは http://maven.apache.org/maven-v4_0_0.xsd にあります。
2.1.3. Maven POM ファイルの最低要件
pom.xml
ファイルの最低要件は次の通りです。
- プロジェクトルート
- modelVersion
- groupId - プロジェクトのグループの ID
- artifactId - アーティファクト (プロジェクト) の ID
- version - 指定グループ下のアーティファクトのバージョン
基本的な pom.xml
ファイルは次のようになります。
<project> <modelVersion>4.0.0</modelVersion> <groupId>com.jboss.app</groupId> <artifactId>my-app</artifactId> <version>1</version> </project>
2.1.4. Maven 設定ファイルについて
settings.xml
ファイルには Maven に関するユーザー固有の設定情報が含まれています。開発者の ID、プロキシ情報、ローカルリポジトリの場所など、 pom.xml
ファイルで配布されてはならないユーザー固有の設定が含まれています。
settings.xml
が存在する場所は 2 つあります。
- Maven インストール
- 設定ファイルは
M2_HOME/conf/
ディレクトリにあります。これらの設定はglobal
設定と呼ばれます。デフォルトの Maven 設定ファイルはコピー可能なテンプレートで、これを基にユーザー設定ファイルを設定することが可能です。 - ユーザーのインストール
- 設定ファイルは
USER_HOME/.m2/
ディレクトリにあります。 Maven とユーザーのsettings.xml
ファイルが存在する場合、内容はマージされます。重複する内容がある場合、ユーザーのsettings.xml
ファイルが優先されます。
settings.xml
ファイルの例は以下のとおりです。
<?xml version="1.0" encoding="UTF-8"?> <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <profiles> <!-- Configure the JBoss EAP Maven repository --> <profile> <id>jboss-eap-maven-repository</id> <repositories> <repository> <id>jboss-eap</id> <url>file:///path/to/repo/jboss-eap-6.0-maven-repository</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>jboss-eap-maven-plugin-repository</id> <url>file:///path/to/repo/jboss-eap-6.0-maven-repository</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </pluginRepository> </pluginRepositories> </profile> </profiles> <activeProfiles> <!-- Optionally, make the repository active by default --> <activeProfile>jboss-eap-maven-repository</activeProfile> </activeProfiles> </settings>
settings.xml
ファイルのスキーマは http://maven.apache.org/xsd/settings-1.0.0.xsd にあります。
2.2. Maven と JBoss Maven レポジトリのインストール
2.2.1. Maven のダウンロードとインストール
- Apache Maven Project - Download Maven へアクセスし、ご使用のオペレーティングシステムに対する最新のディストリビューションをダウンロードします。
- ご使用のオペレーシングシステムに対して Apache Maven をダウンロードしインストールする方法については Maven のドキュメントを参照してください。
2.2.2. JBoss Enterprise Application Platform 6 の Maven リポジトリのインストール
2.2.3. JBoss Enterprise Application Platform 6 の Maven リポジトリのローカルインストール
リポジトリをインストールする方法には、ローカルファイルシステム上のインストール、Apache Web サーバー上のインストール、Maven リポジトリマネージャーを使用したインストールの 3 つの方法があります。この例では、ローカルのファイルシステムへ JBoss Enterprise Application Platform 6 の Maven リポジトリをダウンロードする手順を取り上げます。このオプションは設定が簡単で、ローカルマシンですぐ使用することが可能になります。開発環境で Maven の知識を深めることができますが、チームによる実稼働環境での使用は推奨されません。
手順2.1 JBoss Enterprise Application Platform 6 Maven リポジトリーをダウンロードしてローカルファイルシステムにインストールする
JBoss Enterprise Application Platform 6 の Maven リポジトリ ZIP アーカイブのダウンロード
Web ブラウザーを開き、URL https://access.redhat.com/jbossnetwork/restricted/listSoftware.html?product=appplatform にアクセスします。- リストに「Application Platform 6 Maven リポジトリ」があることを確認します。
- [ダウンロード] ボタンをクリックし、リポジトリが含まれる
.zip
ファイルをダウンロードします。 - ローカルファイルシステム上の同じディレクトリにあるファイルを希望のディレクトリへ解凍します。
これにより、jboss-eap-6.1.0.maven-repository
という名前の Maven リポジトリーディレクトリーが作成されます。
重要
settings.xml
設定ファイルで個別に設定する必要があります。各ローカルリポジトリーは、独自の <repository>
タグ内で設定する必要があります。
重要
.m2/
ディレクトリにあるキャッシュされた repository/
サブディレクトリを削除してください。
2.2.4. Apache httpd を使用するため JBoss Enterprise Application Platform 6 の Maven リポジトリをインストールする
Apache httpd を設定する必要があります。手順は Apache HTTP Server Project を参照してください。
手順2.2 JBoss Enterprise Application Platform 6 の Maven リポジトリ ZIP アーカイブのダウンロード
- Web ブラウザーを開き、URL https://access.redhat.com/jbossnetwork/restricted/listSoftware.html?product=appplatform にアクセスします。
- リストに「Application Platform 6 Maven リポジトリ」があることを確認します。
- [ダウンロード] ボタンをクリックし、リポジトリが含まれる
.zip
ファイルをダウンロードします。 - Apache サーバー上で Web にアクセス可能なディレクトリにファイルを展開します。
- Apache を設定し、作成されたディレクトリの読み取りアクセスとディレクトリの閲覧を許可します。
マルチユーザー環境が Apache httpd 上で Maven リポジトリにアクセスできるようになります。
注記
2.2.5. Nexus Maven リポジトリマネージャーを使用して JBoss Enterprise Application Platform 6 の Maven リポジトリをインストールする
手順2.3 JBoss Enterprise Application Platform 6 の Maven リポジトリ ZIP アーカイブのダウンロード
- Web ブラウザーを開き、URL https://access.redhat.com/jbossnetwork/restricted/listSoftware.html?product=appplatform にアクセスします。
- リストに「Application Platform 6 Maven リポジトリ」があることを確認します。
- [ダウンロード] ボタンをクリックし、リポジトリが含まれる
.zip
ファイルをダウンロードします。 - 希望のディレクトリにファイルを展開します。
手順2.4 Nexus Maven リポジトリマネージャーを使用して JBoss Enterprise Application Platform 6 の Maven リポジトリを追加する
- 管理者として Nexus にログインします。
- リポジトリマネージャーの左側の [Views] → [Repositories] メニューより [Repositories] セクションを選択します。
- [Add...] ドロップダウンメニューをクリックし、[Hosted Repository] を選択します。
- 新しいリポジトリに名前と ID をつけます。
- フィールド [Override Local Storage] の場所に、展開されたリポジトリへのディスク上のパスを入力します。
- リポジトリグループでアーティファクトを使用できるようにする場合は次の手順に従い設定を継続します。必要がない場合は継続しないでください。
- リポジトリグループを選択します。
- [Configure] タブをクリックします。
- [Available Repositories] リストにある新しい JBoss Maven リポジトリを左側の [Ordered Group Repositories] へドラッグします。
注記
このリストの順番により Maven アーティファクトの検索優先度が決定されます。
Nexus Maven リポジトリマネージャーを使用してリポジトリが設定されます。
2.2.6. Maven リポジトリマネージャーについて
- お客様の組織と Maven リポジトリーとの間のプロキシを設定する機能を提供します。これには、デプロイメントの高速化や効率化、Maven によるダウンロード対象を制御するレベルの向上など、さまざまな利点があります。
- 独自に生成したアーティファクトのデプロイ先を提供し、組織全体にわたる異なる開発チーム間におけるコラボレーションを可能にします。
一般的に使用される Maven リポジトリマネージャー
- Sonatype Nexus
- Nexus に関する詳しい情報は Sonatype Nexus: Manage Artifacts を参照してください。
- Artifactory
- Artifactory に関する詳しい情報は Artifactory Open Source を参照してください。
- Apache Archiva
- Apache Archiva に関する詳しい情報は Apache Archiva: The Build Artifact Repository Manager を参照してください。
2.3. Maven レポジトリの設定
2.3.1. JBoss Enterprise Application Platform の Maven リポジトリの設定
プロジェクトで Maven により JBoss Enterprise Application Platform Maven リポジトリーを使用するには 2 つの方法があります。
- リポジトリーをMaven グローバルまたはユーザー設定で設定します。
- リポジトリーをプロジェクトの POM ファイルで設定します。
手順2.5 JBoss Enterprise Application Platform の Maven リポジトリを使用するよう Maven を設定する
Maven の設定を使用して Maven リポジトリを設定する
これは推奨される方法です。リポジトリマネージャーや共有サーバーを用いたリポジトリを使用して Maven を設定すると、プロジェクトの制御や管理が向上します。また、代替のミラーを使用してプロジェクトファイルを変更せずにリポジトリマネージャーへの特定リポジトリのルックアップ要求をすべてリダイレクトすることが可能になります。ミラーに関する詳細については、http://maven.apache.org/guides/mini/guide-mirror-settings.html を参照してください。プロジェクトの POM ファイルにリポジトリ設定が含まれていない場合、この設定方法はすべての Maven プロジェクトに対して適用されます。プロジェクトの POM を使用して Maven リポジトリを設定する
通常、この方法は推奨されません。プロジェクトの POM ファイルにリポジトリーを設定する場合は慎重に計画します。ビルドに時間がかかり、想定外のリポジトリーからアーティファクトが抽出されることがあることに注意してください。注記
通常レポジトリーマネージャーが使用されるエンタープライズ環境では、Maven は、このマネージャーを使用してすべてのプロジェクトに対してすべてのアーティファクトを問い合わせる必要があります。Maven は、宣言されたすべてのリポジトリーを使用して不明なアーティファクトを見つけます。探しているものが見つからない場合は、中央リポジトリー (組み込みの親 POM で定義されます) での検索を試行します。この中央の場所をオーバーライドするには、central
で定義を追加してデフォルトの中央リポジトリーがリポジトリーマネージャーになるようにします。これは、確立されたプロジェクトには適切ですが、クリーンな、または「新しい」プロジェクトの場合は、周期的な依存関係が作成されるため、問題が発生します。このような設定では、推移的に含まれた POM も問題になります。Maven は、これらの外部リポジトリーで不明なアーティファクトを問い合わせる必要があります。これにより、ビルドに時間がかかるだけでなく、アーティファクトの抽出元を制御できなくなり、多くの場合、ビルドが破壊されます。この設定方法は、設定されたプロジェクトのグローバルおよびユーザーの Maven 設定を上書きします。
2.3.2. Maven 設定を使用した JBoss Enterprise Application Platform の Maven リポジトリーの設定
- Maven 設定を変更できます。
- プロジェクトの POM ファイルを設定できます。
注記
- ファイルシステム
file:///path/to/repo/jboss-eap-6.0.0-maven-repository
- Apache Web サーバー
http://intranet.acme.com/jboss-eap-6.0.0-maven-repository/
- Nexus リポジトリマネージャー
https://intranet.acme.com/nexus/content/repositories/jboss-eap-6.0.0-maven-repository
手順2.6 設定
- 選択した設定タイプの
settings.xml
を開きます。グローバル設定
global
設定を設定する場合はM2_HOME/conf/settings.xml
ファイルを開きます。ユーザー設定
ユーザー固有の設定を設定する場合、USER_HOME/.m2/settings.xml
ファイルが存在しない時はM2_HOME/conf/
ディレクトリのsettings.xml
ファイルをUSER_HOME/.m2/
ディレクトリにコピーします。
- 以下の XML を
settings.xml
ファイルの<profiles>
要素にコピーします。<url>
を実際のリポジトリーの場所に変更します。<profile> <id>jboss-eap-repository</id> <repositories> <repository> <id>jboss-eap-repository</id> <name>JBoss EAP Maven Repository</name> <url>file:///path/to/repo/jboss-eap-6.0.0-maven-repository</url> <layout>default</layout> <releases> <enabled>true</enabled> <updatePolicy>never</updatePolicy> </releases> <snapshots> <enabled>false</enabled> <updatePolicy>never</updatePolicy> </snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>jboss-eap-repository-group</id> <name>JBoss EAP Maven Repository</name> <url> file:///path/to/repo/jboss-eap-6.0.0-maven-repository </url> <layout>default</layout> <releases> <enabled>true</enabled> <updatePolicy>never</updatePolicy> </releases> <snapshots> <enabled>false</enabled> <updatePolicy>never</updatePolicy> </snapshots> </pluginRepository> </pluginRepositories> </profile>
次の XML をsettings.xml
ファイルの<activeProfiles>
要素へコピーします。<activeProfile>jboss-eap-repository</activeProfile>
- JBoss Developer Studio の稼働中に
settings.xml
ファイルを変更する時は、ユーザー設定をリフレッシュする必要があります。メニューより [Window] → [Preferences] と選択します。 [Preferences] ウインドウで [Maven] を開き、[User Settings] を選択します。[Update Settings] ボタンをクリックし、 JBoss Developer Studio で Maven のユーザー設定をリフレッシュします。図2.1 Maven ユーザー設定の更新
重要
- Missing artifact ARTIFACT_NAME
- [ERROR] Failed to execute goal on project PROJECT_NAME; Could not resolve dependencies for PROJECT_NAME
~/.m2/repository/
サブディレクトリー (Linux の場合) または %SystemDrive%\Users\USERNAME\.m2\repository\
サブディレクトリー (Windows の場合) に存在します。
JBoss Enterprise Application Platform のリポジトリが設定されます。
2.3.3. プロジェクト POM を用いた JBoss Enterprise Application Platform の Maven リポジトリの設定
- Maven 設定を変更できます。
- プロジェクトの POM ファイルを設定できます。
pom.xml
に追加して、JBoss Enterprise Application Platform の Maven リポジトリーを使用するよう特定のプロジェクトを設定する方法について説明します。この設定方法は、グローバル設定とユーザー設定よりも優先されます。
注記
central
で定義を追加してデフォルトの中央リポジトリーがリポジトリーマネージャーになるようにします。これは、確立されたプロジェクトには適切ですが、クリーンな、または「新しい」プロジェクトの場合は、周期的な依存関係が作成されるため、問題が発生します。
注記
- ファイルシステム
file:///path/to/repo/jboss-eap-6.0.0-maven-repository
- Apache Web サーバー
http://intranet.acme.com/jboss-eap-6.0.0-maven-repository/
- Nexus リポジトリマネージャー
https://intranet.acme.com/nexus/content/repositories/jboss-eap-6.0.0-maven-repository
- テキストエディターでプロジェクトの
pom.xml
ファイルを開きます。 - 次のリポジトリ設定を追加します。既にファイルに
<repositories>
設定が存在する場合は<repository>
要素を追加します。必ず<url>
をリポジトリが実存する場所に変更するようにしてください。<repositories> <repository> <id>jboss-eap-repository-group</id> <name>JBoss EAP Maven Repository</name> <url>file:///path/to/repo/jboss-eap-6.0.0-maven-repository/</url> <layout>default</layout> <releases> <enabled>true</enabled> <updatePolicy>never</updatePolicy> </releases> <snapshots> <enabled>true</enabled> <updatePolicy>never</updatePolicy> </snapshots> </repository> </repositories>
- 次のプラグインリポジトリ設定を追加します。既にファイルに
<pluginRepositories>
設定が存在する場合は<pluginRepository>
要素を追加します。<pluginRepositories> <pluginRepository> <id>jboss-eap-repository-group</id> <name>JBoss EAP Maven Repository</name> <url>file:///path/to/repo/jboss-eap-6.0.0-maven-repository/</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </pluginRepository> </pluginRepositories>
第3章 クラスローディングとモジュール
3.1. はじめに
3.1.1. クラスロードとモジュールの概要
3.1.3. モジュール
- 静的モジュール
- 静的モジュールは、アプリケーションサーバーの
EAP_HOME/modules/
ディレクトリに事前定義されます。各サブディレクトリは 1 つのモジュールを表し、1 つまたは複数の JAR ファイルと設定ファイル (module.xml
) が含まれます。モジュールの名前は、module.xml
ファイルで定義されます。アプリケーションサーバーで提供されるすべての API (Java EE API や JBoss Logging などの他の API を含む) は、静的モジュールとして提供されます。カスタム静的モジュールの作成は、同じサードパーティーライブラリを使用する同じサーバー上に多くのアプリケーションがデプロイされる場合に役立ちます。これらのライブラリを各アプリケーションとバンドルする代わりに、JBoss 管理者はこれらのライブラリが含まれるモジュールを作成およびインストールできます。アプリケーションは、カスタム静的モジュールで明示的な依存関係を宣言できます。 - 動的モジュール
- 動的モジュールは、各 JAR または WAR デプロイメント (または、EAR 内のサブデプロイメント) に対してアプリケーションサーバーによって作成およびロードされます。動的モジュールの名前は、デプロイされたアーカイブの名前から派生されます。デプロイメントはモジュールとしてロードされるため、依存関係を設定でき、他のデプロイメントが依存関係として使用できます。
3.1.4. モジュールの依存関係
例3.1 モジュールの依存関係
- モジュール A がモジュール C への明示的な依存関係を宣言する場合。
- または、モジュール B がモジュール B の依存関係をモジュール C でエクスポートする場合。
3.1.5. デプロイメントでのクラスローディング
- WAR デプロイメント
- WAR デプロイメントは 1 つのモジュールとして考慮されます。
WEB-INF/lib
ディレクトリのクラスはWEB-INF/classes
ディレクトリにあるクラスと同じように処理されます。war にパッケージされているクラスはすべて、同じクラスローダーでロードされます。 - EAR デプロイメント
- EAR デプロイメントは複数のモジュールで構成されます。これらのモジュールは以下のルールに従って定義されます。
- EAR の
lib/
ディレクトリは親モジュールと呼ばれる1つのモジュールです。 - また、EAR 内の各 WAR デプロイメントは1つのモジュールです。
- 同様に、EAR 内の EJB JAR デプロイメントも 1 つのモジュールとなっています。
サブデプロイメントモジュール (EAR 内の WAR、JAR デプロイメント) は、自動的に親モジュールに依存しますが、サブデプロイメント同士が自動的に依存するわけではありません。これは、サブデプロイメントの分離 (subdeployment isolation) と呼ばれ、デプロイメントごとまたはアプリケーションサーバー全体で無効にすることができます。サブデプロイメントモジュール間の明示的な依存関係については、他のモジュールと同じ方法で追加することが可能です。
3.1.6. クラスローディングの優先順位
- 暗黙的な依存性Java EE API などの、JBoss Enterprise Application Platform 6 が自動的に追加する依存性です。こちらの依存性は、一般的な機能や JBoss Enterprise Application Platform 6 が対応する API が含まれているため、優先順位が最も高くなっています。各暗黙的依存性に関する完全な詳細情報は 「暗黙的なモジュール依存関係」 を参照してください。
- 明示的な依存性アプリケーション設定にて手動で追加される依存性です。これらの依存性は、アプリケーションの
MANIFEST.MF
ファイルや、新しくオプションで追加された JBoss の配備記述子jboss-deployment-structure.xml
ファイルを使い追加可能です。明示的な依存性の追加方法については、「デプロイメントへの明示的なモジュール依存関係の追加」 を参照してください。 - ローカルリソースデプロイメント内にパッケージ化されるクラスファイル (例:WAR ファイルの
WEB-INF/classes
あるいはWEB-INF/lib
から) - デプロイメント間の依存性これらは、EAR デプロイメントにある他のデプロイメントの依存関係です。これには、EAR の
lib
ディレクトリーにあるクラス、あるいは他の EJB jar に定義されているクラスが含まれます。
3.1.7. 動的モジュールの名前付け
- WAR および JAR ファイルのデプロイメントは次の形式で名前が付けられます。
deployment.DEPLOYMENT_NAME
例えば、inventory.war
のモジュール名はdeployment.inventory.war
となり、store.jar
のモジュール名はdeployment.store.jar
となります。 - エンタープライズアーカイブ内のサブデプロイメントは次の形式で名前が付けられます。
deployment.EAR_NAME.SUBDEPLOYMENT_NAME
たとえば、エンタープライズアーカイブaccounts.ear
内にあるreports.war
のサブデプロイメントのモジュール名はdeployment.accounts.ear.reports.war
になります。
3.1.8. jboss-deployment-structure.xml
jboss-deployment-structure.xml
は JBoss Enterprise Application Platform 6 の新しいオプションデプロイメント記述子です。このデプロイメント記述子を使用すると、デプロイメントのクラスローディングを制御できます。
EAP_HOME/docs/schema/jboss-deployment-structure-1_2.xsd
にあります。
3.2. デプロイメントへの明示的なモジュール依存関係の追加
要件
- モジュール依存関係を追加するソフトウェアプロジェクトが存在する必要があります。
- 依存関係として追加するモジュールの名前を覚えておく必要があります。JBoss Enterprise Application Platform に含まれる静的モジュールのリストは 「含まれるモジュール」 を参照してください。モジュールが他のデプロイメントである場合は 「動的モジュールの名前付け」 を参照してモジュール名を判断してください。
- デプロイメントの
MANIFEST.MF
ファイルにエントリーを追加します。 jboss-deployment-structure.xml
デプロイメント記述子にエントリーを追加します。
手順3.1 MANIFEST.MF へ依存関係の設定を追加する
MANIFEST.MF
ファイルに必要な依存関係エントリを作成することができます。「Maven を使用した MANIFEST.MF エントリーの生成」 を参照してください。
MANIFEST.MF
ファイルの追加プロジェクトにMANIFEST.MF
ファイルがない場合、MANIFEST.MF
というファイルを作成します。Web アプリケーション (WAR) では、このファイルをMETA-INF
ディレクトリーに追加します。EJB アーカイブ (JAR) では、META-INF
ディレクトリーに追加します。依存関係エントリの追加
依存関係モジュール名をコンマで区切り、依存関係エントリーをMANIFEST.MF
ファイルへ追加します。Dependencies: org.javassist, org.apache.velocity
任意: 依存関係を任意にする
依存関係エントリーのモジュール名にoptional
を付けると、依存関係を任意にすることができます。Dependencies: org.javassist optional, org.apache.velocity
任意: 依存関係のエクスポート
依存関係エントリーのモジュール名にexport
を付けると、依存関係をエクスポートすることができます。Dependencies: org.javassist, org.apache.velocity export
手順3.2 jboss-deployment-structure.xml への依存関係設定の追加
jboss-deployment-structure.xml
の追加アプリケーションにjboss-deployment-structure.xml
ファイルが存在しない場合は、jboss-deployment-structure.xml
という新しいファイルを作成し、プロジェクトに追加します。このファイルは<jboss-deployment-structure>
がルート要素の XML ファイルです。<jboss-deployment-structure> </jboss-deployment-structure>
Web アプリケーション (WAR) では、このファイルをWEB-INF
に追加します。EJB アーカイブ (JAR) では、META-INF
ディレクトリに追加します。依存関係セクションの追加
<deployment>
要素をドキュメントルート内に作成し、その中に<dependencies>
要素を作成します。モジュール要素の追加
依存関係ノード内に各モジュール依存関係に対するモジュール要素を追加します。name
属性をモジュールの名前に設定します。<module name="org.javassist" />
任意: 依存関係を任意にする
値がTRUE
のモジュールエントリーにoptional
属性を追加すると依存関係を任意にすることができます。この属性のデフォルト値はFALSE
です。<module name="org.javassist" optional="TRUE" />
任意: 依存関係のエクスポート
値がTRUE
のモジュールエントリーにexport
属性を追加すると依存関係をエクスポートできます。この属性のデフォルト値はFALSE
です。<module name="org.javassist" export="TRUE" />
例3.2 2 つの依存関係を持つ jboss-deployment-structure.xml
<jboss-deployment-structure> <deployment> <dependencies> <module name="org.javassist" /> <module name="org.apache.velocity" export="TRUE" /> </dependencies> </deployment> </jboss-deployment-structure>
3.3. Maven を使用した MANIFEST.MF エントリーの生成
Dependencies
エントリーを持つ MANIFEST.MF
ファイルを生成することができます。この処理により、依存関係の一覧は自動的に生成されず、pom.xml
に指定された詳細が含まれる MANIFEST.MF
ファイルのみが作成されます。
要件
- 作業用の Maven プロジェクトが既に存在している必要があります。
- Maven プロジェクトが JAR、EJB、WAR プラグイン (
maven-jar-plugin
、maven-ejb-plugin
、maven-war-plugin
) のいずれかを使用しなければなりません。 - プロジェクトのモジュール依存関係の名前を知っていなければなりません。JBoss Enterprise Application Platform 6 に含まれる静的モジュールの一覧は 「含まれるモジュール」 を参照してください。モジュールが別のデプロイメントにある場合は 「動的モジュールの名前付け」 を参照してモジュール名を判断してください。
手順3.3 モジュール依存関係が含まれる MANIFEST.MF ファイルの生成
設定の追加
プロジェクトのpom.xml
ファイルにあるパッケージングプラグイン設定に次の設定を追加します。<configuration> <archive> <manifestEntries> <Dependencies></Dependencies> </manifestEntries> </archive> </configuration>
依存関係の一覧表示
モジュール依存関係の一覧を <Dependencies> 要素に追加します。MANIFEST.MF
に依存関係を追加する時と同じ形式を使用します。この形式に関する詳細は 「デプロイメントへの明示的なモジュール依存関係の追加」 を参照してください。<Dependencies>org.javassist, org.apache.velocity</Dependencies>
プロジェクトの構築
Maven アセンブリゴールを用いたプロジェクトの構築[Localhost ]$ mvn assembly:assembly
MANIFEST.MF
ファイルが最終アーカイブに含まれます。
例3.3 pom.xml の設定されたモジュール依存関係
<plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <configuration> <archive> <manifestEntries> <Dependencies>org.javassist, org.apache.velocity</Dependencies> </manifestEntries> </archive> </configuration> </plugin> </plugins>
3.4. モジュールが暗黙的にロードされないようにする
要件
- モジュール依存関係を除外するソフトウェアプロジェクトが存在する必要があります。
- 除外するモジュール名を知っている必要があります。暗黙的な依存関係のリストや状態については 「暗黙的なモジュール依存関係」 を参照してください。
手順3.4 jboss-deployment-structure.xml への依存関係除外設定の追加
- アプリケーションに
jboss-deployment-structure.xml
ファイルが存在しない場合は、jboss-deployment-structure.xml
という新しいファイルを作成し、プロジェクトに追加しあす。このファイルは<jboss-deployment-structure>
がルート要素の XML ファイルです。<jboss-deployment-structure> </jboss-deployment-structure>
Web アプリケーション (WAR) では、このファイルをWEB-INF
に追加します。EJB アーカイブ (JAR) では、META-INF
ディレクトリに追加します。 <deployment>
要素をドキュメントルート内に作成し、その中に<exclusions>
要素を作成します。<deployment> <exclusions> </exclusions> </deployment>
- exclusions 要素内で、除外される各モジュールに対して
<module>
要素を追加します。name
属性をモジュールの名前に設定します。<module name="org.javassist" />
例3.4 2 つのモジュールの除外
<jboss-deployment-structure> <deployment> <exclusions> <module name="org.javassist" /> <module name="org.dom4j" /> </exclusions> </deployment> </jboss-deployment-structure>
3.5. サブシステムをデプロイメントから除外する
ここではサブシステムをデプロイメントより除外するために必要な手順について説明します。jboss-deployment-structure.xml
設定ファイルを編集します。サブシステムの除外はサブシステムの削除と同じ影響がありますが、1 つのデプロイメントのみに適用されます。
手順3.5 サブシステムの除外
- テキストエディターで
jboss-deployment-structure.xml
ファイルを開きます。 - 次の XML を <deployment> タグの中に追加します。
<exclude-subsystems> <subsystem name="SUBSYSTEM_NAME" /> </exclude-subsystems>
jboss-deployment-structure.xml
ファイルを保存します。
サブシステムが除外されます。サブシステムのデプロイメントユニットプロセッサがデプロイメント上で実行されないようになります。
例3.5 jboss-deployment-structure.xml
ファイルの例
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2"> <ear-subdeployments-isolated>true</ear-subdeployments-isolated> <deployment> <exclude-subsystems> <subsystem name="resteasy" /> </exclude-subsystems> <exclusions> <module name="org.javassist" /> </exclusions> <dependencies> <module name="deployment.javassist.proxy" /> <module name="deployment.myjavassist" /> <module name="myservicemodule" services="import"/> </dependencies> <resources> <resource-root path="my-library.jar" /> </resources> </deployment> <sub-deployment name="myapp.war"> <dependencies> <module name="deployment.myear.ear.myejbjar.jar" /> </dependencies> <local-last value="true" /> </sub-deployment> <module name="deployment.myjavassist" > <resources> <resource-root path="javassist.jar" > <filter> <exclude path="javassist/util/proxy" /> </filter> </resource-root> </resources> </module> <module name="deployment.javassist.proxy" > <dependencies> <module name="org.javassist" > <imports> <include path="javassist/util/proxy" /> <exclude path="/**" /> </imports> </module> </dependencies> </module> </jboss-deployment-structure>
3.6. クラスローディングとサブデプロイメント
3.6.1. エンタープライズアーカイブのモジュールおよびクラスロード
- 各 WAR および EJB JAR サブデプロイメントはモジュールです。
- EAR アーカイブのルートにある
lib/
ディレクトリの内容はモジュールです。これは、親モジュールと呼ばれます。
- WAR サブデプロイメントでは、親モジュールとすべての EJB JAR サブデプロイメントに暗黙的な依存関係が存在します。
- EJB JAR サブデプロイメントでは、親モジュールと他のすべての EJB JAR サブデプロイメントに暗黙的な依存関係が存在します。
重要
MANIFEST.MF
ファイルのClass-Path
エントリーとして明示的に宣言されない限り、移植可能なアプリケーションがお互いにアクセスできるサブデプロイメントに依存しないことが推奨されます。
3.6.2. サブデプロイメントクラスローダーの分離
3.6.3. EAR 内のサブデプロイメントクラスローダーの分離を無効化する
重要
デプロイメント記述子ファイルの追加
jboss-deployment-structure.xml
デプロイメント記述子ファイルが存在しない場合は EAR のMETA-INF
ディレクトリへ追加し、次の内容を追加します。<jboss-deployment-structure> </jboss-deployment-structure>
<ear-subdeployments-isolated>
要素の追加<ear-subdeployments-isolated>
要素が存在しない場合はjboss-deployment-structure.xml
ファイルへ追加し、内容がfalse
となるようにします。<ear-subdeployments-isolated>false</ear-subdeployments-isolated>
この EAR デプロイメントに対してサブデプロイメントクラスローダーの分離が無効になります。そのため、EAR のサブデプロイメントは WAR ではないサブデプロイメントごとに自動的な依存関係を持ちます。
3.7. 参考資料
3.7.1. 暗黙的なモジュール依存関係
表3.1 暗黙的なモジュール依存関係
サブシステム | 常に追加されるモジュール | 条件付きで追加されるモジュール | 条件 |
---|---|---|---|
コアサーバー |
|
-
|
-
|
EE サブシステム |
|
-
|
-
|
EJB3 サブシステム |
-
|
|
Java EE 6 の仕様で指定されているように、デプロイメント内の有効な場所で
ejb-jar.xml が存在するか、アノテーションベースの EJB が存在すること (例:@Stateless 、@Stateful 、@MessageDriven など)
|
JAX-RS (Resteasy) サブシステム |
|
| デプロイメント内に JAX-RS のアノテーションが存在すること |
JCA サブシステム |
|
| デプロイメントがリソースアダプター (RAR) デプロイメントの場合 |
JPA (Hibernate) サブシステム |
|
| @PersistenceUnit または @PersistenceContext アノテーションが存在するか、デプロイメント記述子に<persistence-unit-ref> または <persistence-context-ref> が存在すること |
SAR サブシステム |
-
|
| デプロイメントが SAR アーカイブであること |
セキュリティサブシステム |
|
-
|
-
|
Web サブシステム |
-
|
| デプロイメントは WAR アーカイブです。利用されている場合は、JavaServer Faces(JSF) のみが追加されます。 |
Web サービスサブシステム |
|
-
|
-
|
Weld (CDI) サブシステム |
-
|
| beans.xml ファイルがデプロイメント内で検出された場合 |
3.7.2. 含まれるモジュール
asm.asm
ch.qos.cal10n
com.google.guava
com.h2database.h2
com.sun.jsf-impl
com.sun.jsf-impl
com.sun.xml.bind
com.sun.xml.messaging.saaj
gnu.getopt
javaee.api
javax.activation.api
javax.annotation.api
javax.api
javax.ejb.api
javax.el.api
javax.enterprise.api
javax.enterprise.deploy.api
javax.faces.api
javax.faces.api
javax.inject.api
javax.interceptor.api
javax.jms.api
javax.jws.api
javax.mail.api
javax.management.j2ee.api
javax.persistence.api
javax.resource.api
javax.rmi.api
javax.security.auth.message.api
javax.security.jacc.api
javax.servlet.api
javax.servlet.jsp.api
javax.servlet.jstl.api
javax.transaction.api
javax.validation.api
javax.ws.rs.api
javax.wsdl4j.api
javax.xml.bind.api
javax.xml.jaxp-provider
javax.xml.registry.api
javax.xml.rpc.api
javax.xml.soap.api
javax.xml.stream.api
javax.xml.ws.api
jline
net.sourceforge.cssparser
net.sourceforge.htmlunit
net.sourceforge.nekohtml
nu.xom
org.antlr
org.apache.ant
org.apache.commons.beanutils
org.apache.commons.cli
org.apache.commons.codec
org.apache.commons.collections
org.apache.commons.io
org.apache.commons.lang
org.apache.commons.logging
org.apache.commons.pool
org.apache.cxf
org.apache.httpcomponents
org.apache.james.mime4j
org.apache.log4j
org.apache.neethi
org.apache.santuario.xmlsec
org.apache.velocity
org.apache.ws.scout
org.apache.ws.security
org.apache.ws.xmlschema
org.apache.xalan
org.apache.xerces
org.apache.xml-resolver
org.codehaus.jackson.jackson-core-asl
org.codehaus.jackson.jackson-jaxrs
org.codehaus.jackson.jackson-mapper-asl
org.codehaus.jackson.jackson-xc
org.codehaus.woodstox
org.dom4j
org.hibernate
org.hibernate.envers
org.hibernate.infinispan
org.hibernate.validator
org.hornetq
org.hornetq.ra
org.infinispan
org.infinispan.cachestore.jdbc
org.infinispan.cachestore.remote
org.infinispan.client.hotrod
org.jacorb
org.javassist
org.jaxen
org.jboss.as.aggregate
org.jboss.as.appclient
org.jboss.as.cli
org.jboss.as.clustering.api
org.jboss.as.clustering.common
org.jboss.as.clustering.ejb3.infinispan
org.jboss.as.clustering.impl
org.jboss.as.clustering.infinispan
org.jboss.as.clustering.jgroups
org.jboss.as.clustering.service
org.jboss.as.clustering.singleton
org.jboss.as.clustering.web.infinispan
org.jboss.as.clustering.web.spi
org.jboss.as.cmp
org.jboss.as.connector
org.jboss.as.console
org.jboss.as.controller
org.jboss.as.controller-client
org.jboss.as.deployment-repository
org.jboss.as.deployment-scanner
org.jboss.as.domain-add-user
org.jboss.as.domain-http-error-context
org.jboss.as.domain-http-interface
org.jboss.as.domain-management
org.jboss.as.ee
org.jboss.as.ee.deployment
org.jboss.as.ejb3
org.jboss.as.embedded
org.jboss.as.host-controller
org.jboss.as.jacorb
org.jboss.as.jaxr
org.jboss.as.jaxrs
org.jboss.as.jdr
org.jboss.as.jmx
org.jboss.as.jpa
org.jboss.as.jpa.hibernate
org.jboss.as.jpa.hibernate
org.jboss.as.jpa.hibernate.infinispan
org.jboss.as.jpa.openjpa
org.jboss.as.jpa.spi
org.jboss.as.jpa.util
org.jboss.as.jsr77
org.jboss.as.logging
org.jboss.as.mail
org.jboss.as.management-client-content
org.jboss.as.messaging
org.jboss.as.modcluster
org.jboss.as.naming
org.jboss.as.network
org.jboss.as.osgi
org.jboss.as.platform-mbean
org.jboss.as.pojo
org.jboss.as.process-controller
org.jboss.as.protocol
org.jboss.as.remoting
org.jboss.as.sar
org.jboss.as.security
org.jboss.as.server
org.jboss.as.standalone
org.jboss.as.threads
org.jboss.as.transactions
org.jboss.as.web
org.jboss.as.webservices
org.jboss.as.webservices.server.integration
org.jboss.as.webservices.server.jaxrpc-integration
org.jboss.as.weld
org.jboss.as.xts
org.jboss.classfilewriter
org.jboss.com.sun.httpserver
org.jboss.common-core
org.jboss.dmr
org.jboss.ejb-client
org.jboss.ejb3
org.jboss.iiop-client
org.jboss.integration.ext-content
org.jboss.interceptor
org.jboss.interceptor.spi
org.jboss.invocation
org.jboss.ironjacamar.api
org.jboss.ironjacamar.impl
org.jboss.ironjacamar.jdbcadapters
org.jboss.jandex
org.jboss.jaxbintros
org.jboss.jboss-transaction-spi
org.jboss.jsfunit.core
org.jboss.jts
org.jboss.jts.integration
org.jboss.logging
org.jboss.logmanager
org.jboss.logmanager.log4j
org.jboss.marshalling
org.jboss.marshalling.river
org.jboss.metadata
org.jboss.modules
org.jboss.msc
org.jboss.netty
org.jboss.osgi.deployment
org.jboss.osgi.framework
org.jboss.osgi.resolver
org.jboss.osgi.spi
org.jboss.osgi.vfs
org.jboss.remoting3
org.jboss.resteasy.resteasy-atom-provider
org.jboss.resteasy.resteasy-cdi
org.jboss.resteasy.resteasy-jackson-provider
org.jboss.resteasy.resteasy-jaxb-provider
org.jboss.resteasy.resteasy-jaxrs
org.jboss.resteasy.resteasy-jsapi
org.jboss.resteasy.resteasy-multipart-provider
org.jboss.sasl
org.jboss.security.negotiation
org.jboss.security.xacml
org.jboss.shrinkwrap.core
org.jboss.staxmapper
org.jboss.stdio
org.jboss.threads
org.jboss.vfs
org.jboss.weld.api
org.jboss.weld.core
org.jboss.weld.spi
org.jboss.ws.api
org.jboss.ws.common
org.jboss.ws.cxf.jbossws-cxf-client
org.jboss.ws.cxf.jbossws-cxf-factories
org.jboss.ws.cxf.jbossws-cxf-server
org.jboss.ws.cxf.jbossws-cxf-transports-httpserver
org.jboss.ws.jaxws-client
org.jboss.ws.jaxws-jboss-httpserver-httpspi
org.jboss.ws.native.jbossws-native-core
org.jboss.ws.native.jbossws-native-factories
org.jboss.ws.native.jbossws-native-services
org.jboss.ws.saaj-impl
org.jboss.ws.spi
org.jboss.ws.tools.common
org.jboss.ws.tools.wsconsume
org.jboss.ws.tools.wsprovide
org.jboss.xb
org.jboss.xnio
org.jboss.xnio.nio
org.jboss.xts
org.jdom
org.jgroups
org.joda.time
org.junit
org.omg.api
org.osgi.core
org.picketbox
org.picketlink
org.python.jython.standalone
org.scannotation.scannotation
org.slf4j
org.slf4j.ext
org.slf4j.impl
org.slf4j.jcl-over-slf4j
org.w3c.css.sac
sun.jdk
3.7.3. JBoss デプロイメント構造のデプロイメント記述子のリファレンス
- 明示的なモジュール依存関係を定義する。
- 特定の暗黙的な依存関係がローディングされないようにする。
- デプロイメントのリソースより追加モジュールを定義する。
- EAR デプロイメントのサブデプロイメント分離の挙動を変更する。
- EAR のモジュールに追加のリソースルートを追加する。
第4章 グローバル値
4.1. バルブについて
4.2. グローバルバルブについて
4.3. オーセンティケーターバルブについて
org.apache.catalina.authenticator.AuthenticatorBase
のサブクラスで、authenticate()
メソッドを上書きします。
4.4. Web アプリケーションがバルブを使用するよう設定する
jboss-web.xml
デプロイメント記述子で設定する必要があります。
重要
要件
- バルブを作成し、アプリケーションのクラスパスに含める必要があります。これは、バルブをアプリケーションの WAR ファイルにまたは依存関係として追加されたモジュールに含めることにより、実現できます。このようなモジュールの例には、サーバーにインストールされた静的モジュールや EAR アーカイブの
lib/
ディレクトリーにある JAR ファイル (WAR が EAR でデプロイされる場合) があります。 - アプリケーションは
jboss-web.xml
デプロイメント記述子を含む必要があります。
手順4.1 ローカルバルブのためにアプリケーションを設定する
バルブ要素を追加する
name と class-name の属性を使用してバルブ要素をアプリケーションのjboss-web.xml
ファイルに追加します。name は、バルブの一意の ID であり、class-name はバルブクラスの名前です。<valve name="VALVENAME" class-name="VALVECLASSNAME"> </valve>
特定のパラメーター
バルブでパラメーターを設定できる場合は、各パラメーターのバルブ要素にparam
子要素を追加してそれぞれに対して名前と値を指定します。<param name="PARAMNAME" value = "VALUE" />
例4.1 jboss-web.xml バルブ設定
<valve name="clientlimiter" class-name="org.jboss.samplevalves.restrictedUserAgentsValve"> <param name="restricteduseragents" value = "^.*MS Web Services Client Protocol.*$" /> </valve>
4.5. Web アプリケーションがオーセンティケーターバルブを使用するよう設定する
web.xml
デプロイメント記述子を設定する必要があります。最も単純なケースでは、web.xml
設定は BASIC
認証を使用した場合と同じです。ただし、of login-config
の auth-method
子要素は、設定を実行するバルブの名前に設定されます。
要件
- 認証バルブがすでに作成されている必要があります。
- 認証バルブがグローバルバルブの場合、認証バルブはすでにインストールおよび設定されている必要があります。また、設定された名前を知っている必要があります。
- アプリケーションが使用するセキュリティーレルムのレルム名を知っている必要があります。
手順4.2 アプリケーションがオーセンティケーターバルブを使用するよう設定する
バルブを設定する
ローカルバルブを使用する場合は、jboss-web.xml
デプロイメント記述子で設定する必要があります。「Web アプリケーションがバルブを使用するよう設定する」を参照してください。グローバルバルブを使用する場合、これは不必要です。セキュリティー設定を web.xml に追加する
security-constraint、login-config、security-role などの標準的な要素を使用して、セキュリティー設定をアプリケーションの web.xml ファイルに追加します。login-config 要素で、auth-method の値をオーセンティケーターバルブの名前に設定します。また、realm-name 要素を、アプリケーションが使用している JBoss セキュリティーレルムの名前に設定する必要があります。<login-config> <auth-method>VALVE_NAME</auth-method> <realm-name>REALM_NAME</realm-name> </login-config>
4.6. カスタムバルブを作成する
手順4.3 カスタムバルブを作成する
バルブクラスを作成する
org.apache.catalina.valves.ValveBase
のサブクラスを作成します。package org.jboss.samplevalves; import org.apache.catalina.valves.ValveBase; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; public class restrictedUserAgentsValve extends ValveBase { }
呼び出しメソッドを実装する
invoke()
メソッドは、このバルブがパイプラインで実行されるときに呼び出されます。要求オブジェクトと応答オブジェクトはパラメーターとして渡されます。ここで、要求と応答の処理と変更を行います。public void invoke(Request request, Response response) { }
次のパイプラインステップを呼び出す
呼び出しメソッドが最後に実行する必要があることはパイプラインの次のステップを呼び出し、変更された要求オブジェクトと応答オブジェクトを渡すことです。これは、getNext().invoke()
メソッドを使用して行われます。getNext().invoke(request, response);
オプション: パラメーターを指定する
バルブを設定可能にする必要がある場合は、パラメーターを追加してこれを有効にします。これは、インスタンス変数と各パラメーターに対するセッターを追加して行います。private String restrictedUserAgents = null; public void setRestricteduseragents(String mystring) { this.restrictedUserAgents = mystring; }
例4.2 単純なカスタムバルブ
package org.jboss.samplevalves; import java.io.IOException; import java.util.regex.Pattern; import javax.servlet.ServletException; import org.apache.catalina.valves.ValveBase; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; public class restrictedUserAgentsValve extends ValveBase { private String restrictedUserAgents = null; public void setRestricteduseragents(String mystring) { this.restrictedUserAgents = mystring; } public void invoke(Request request, Response response) throws IOException, ServletException { String agent = request.getHeader("User-Agent"); System.out.println("user-agent: " + agent + " : " + restrictedUserAgents); if (Pattern.matches(restrictedUserAgents, agent)) { System.out.println("user-agent: " + agent + " matches: " + restrictedUserAgents); response.addHeader("Connection", "close"); } getNext().invoke(request, response); } }
第5章 開発者向けのロギング
5.1. はじめに
5.1.1. ロギングについて
5.1.2. JBoss LogManager でサポートされるアプリケーションロギングフレームワーク
- JBoss Logging - JBoss Enterprise Application Platform 6 に含まれています。
- Apache Commons Logging - http://commons.apache.org/logging/
- Simple Logging Facade for Java (SLF4J) - http://www.slf4j.org/
- Apache log4j - http://logging.apache.org/log4j/1.2/
- Java SE Logging (java.util.logging) - http://download.oracle.com/javase/6/docs/api/java/util/logging/package-summary.html
5.1.3. ログレベルについて
TRACE
、DEBUG
、INFO
、WARN
、ERROR
および FATAL
となります。
WARN
レベルのログハンドラーは、WARN
、ERROR
、および FATAL
のレベルのメッセージのみを記録します。
5.1.4. サポートされているログレベル
表5.1 サポートされているログレベル
ログレベル | 値 | 説明 |
---|---|---|
FINEST | 300 |
-
|
FINER | 400 |
-
|
TRACE | 400 |
アプリケーションの実行状態に関する詳細情報を提供するメッセージに使用します。通常、
TRACE のログメッセージはアプリケーションのデバッグ時のみにキャプチャーされます。
|
DEBUG | 500 |
アプリケーションの個別の要求またはアクティビティの進捗状況を表示するメッセージに使用します。
DEBUG のログメッセージは通常アプリケーションのデバッグ時のみにキャプチャーされます。
|
FINE | 500 |
-
|
CONFIG | 700 |
-
|
INFO | 800 |
アプリケーションの全体的な進捗状況を示すメッセージに使用します。多くの場合、アプリケーションの起動、シャットダウン、およびその他の主要なライフサイクルイベントに使用されます。
|
WARN | 900 |
エラーではないが、理想的とは見なされない状況を示すために使用されます。将来的にエラーをもたらす可能性のある状況を示します。
|
WARNING | 900 |
-
|
ERROR | 1000 |
発生したエラーの中で、現在のアクティビティや要求の完了を妨げる可能性があるが、アプリケーション実行の妨げにはならないエラーを表示するために使用されます。
|
SEVERE | 1000 |
-
|
FATAL | 1100 |
クリティカルなサービス障害やアプリケーションのシャットダウンをもたらしたり、JBoss Enterprise Application Platform 6 のシャットダウンを引き起こす可能性があるイベントを表示するのに使用します。
|
5.1.5. デフォルトのログファイルの場所
表5.2 スタンドアローンサーバー用デフォルトログファイル
ログファイル | 説明 |
---|---|
EAP_HOME/standalone/log/boot.log |
サーバールートログ。サーバーの起動に関連するログメッセージが含まれます。
|
EAP_HOME/standalone/log/server.log |
サーバーログ。サーバー起動後のすべてのログメッセージが含まれます。
|
表5.3 管理対象ドメイン用デフォルトログファイル
ログファイル | 説明 |
---|---|
EAP_HOME/domain/log/host-controller/boot.log |
ホストコントローラーブートログ。ホストコントローラーの起動に関連するログメッセージが含まれます。
|
EAP_HOME/domain/log/process-controller/boot.log |
プロセスコントローラーブートログ。プロセスコントローラーの起動に関連するログメッセージが含まれます。
|
EAP_HOME/domain/servers/SERVERNAME/log/boot.log |
指定されたサーバーのサーバーブートログ。指定されたサーバーの起動に関連するログメッセージが含まれます。
|
EAP_HOME/domain/servers/SERVERNAME/log/server.log |
指定されたサーバーのサーバーログ。指定されたサーバー起動後のすべてのログメッセージが含まれます。
|
5.2. JBoss ロギングフレームワークを用いたロギング
5.2.1. JBoss Logging について
5.2.2. JBoss ロギングの機能
- 革新的かつ使いやすい「型指定された」ロガーを提供します。
- 国際化および現地化を完全サポートします。翻訳者はプロパティーファイルのメッセージバンドルを使用します。開発者はインターフェースやアノテーションを使用できます。
- 実稼働向けにはビルド時に型指定されたロガーを生成し、開発向けにはランタイムで型指定されたロガーを生成するツール。
5.2.3. JBoss ロギングを使用してアプリケーションにロギングを追加
org.jboss.logging.Logger
) を作成し、そのオブジェクトの適切なメソッドを呼び出します。このタスクは、アプリケーションにこのオブジェクトのサポートを追加するために必要な手順を示しています。
要件
- ビルドシステムとして Maven を使用している場合は、JBoss Maven リポジトリーを含めるようプロジェクトが設定されている必要があります。「Maven 設定を使用した JBoss Enterprise Application Platform の Maven リポジトリーの設定」を参照してください。
- JBoss ロギング JAR ファイルがアプリケーションのビルドパスに指定されている必要があります。これを行う方法は、アプリケーションをビルドするのに JBoss Developer Studio を使用するか、Maven を使用するかによって異なります。
- JBoss Developer Studio を使用してビルドする場合、これを行うには JBoss Developer Studio メニューから [Project] -> [Properties] を選択し、[Targeted Runtimes] を選択して、JBoss Enterprise Application Platform 6 のランタイムがチェックされていることを確認します。
- Maven を使用してビルドする場合、これを行うには、次の依存性設定をプロジェクトの
pom.xml
ファイルに追加します。<dependency> <groupId>org.jboss.logging</groupId> <artifactId>jboss-logging</artifactId> <version>3.1.2.GA-redhat-1</version> <scope>provided</scope> </dependency>
JAR は、JBoss Enterprise Application Platform 6 がデプロイされたアプリケーションに提供するため、ビルドされたアプリケーションに含める必要はありません。
インポートの追加
使用する JBoss Logging クラスネームスペースに対して import ステートメントを追加します。少なくとも、import org.jboss.logging.Logger
をインポートする必要があります。import org.jboss.logging.Logger;
Logger オブジェクトの作成
org.jboss.logging.Logger
のインスタンスを作成し、静的メソッドLogger.getLogger(Class)
を呼び出して初期化します。各クラスに対してこれを単一インスタンス変数として作成することが推奨されます。private static final Logger LOGGER = Logger.getLogger(HelloWorld.class);
ロギングメッセージの追加
Logger
オブジェクトのメソッドへの呼び出しを、ログメッセージを送信するコードに追加します。Logger
オブジェクトには、さまざまなタイプのメッセージに対するさまざまなパラメーターを持つさまざまなメソッドが含まれます。最も使用しやすいものは次のとおりです。debug(Object message)
info(Object message)
error(Object message)
trace(Object message)
fatal(Object message)
これらのメッセージは、対応するログレベルとmessage
パラメーターを文字列として持つログメッセージを送信します。LOGGER.error("Configuration file not found.");
JBoss Logging メソッドの完全なリストについては、JBoss Enterprise Application Platform 6 API ドキュメンテーションのorg.jboss.logging
パッケージを参照してください。
例5.1 プロパティーファイルを開くときに JBoss ロギングを使用
import org.jboss.logging.Logger; public class LocalSystemConfig { private static final Logger LOGGER = Logger.getLogger(LocalSystemConfig.class); public Properties openCustomProperties(String configname) throws CustomConfigFileNotFoundException { Properties props = new Properties(); try { LOGGER.info("Loading custom configuration from "+configname); props.load(new FileInputStream(configname)); } catch(IOException e) //catch exception in case properties file does not exist { LOGGER.error("Custom configuration file ("+configname+") not found. Using defaults."); throw new CustomConfigFileNotFoundException(configname); } return props; }
5.3. ロギングプロファイル
5.3.1. ロギングプロファイルについて
重要
- 一意の名前 (必須)。
- ログハンドラーの数 (いくつでも)。
- ログカテゴリーの数 (いくつでも)。
- ルートロガー (1 つまで)。
重要
5.3.2. アプリケーションにおけるロギングプロファイルの指定
MANIFEST.MF
ファイルに指定します。
前提条件
- サーバー上に設定されたロギングプロファイルの名前を認識している必要があります。使用するプロファイルの名前についてはサーバー管理者に問い合わせてください。
手順5.1 ロギングプロファイル設定をアプリケーションへ追加
MANIFEST.MF
の編集アプリケーションにMANIFEST.MF
ファイルがない場合は、以下の内容が含まれるファイルを作成します。NAME は必要なプロファイル名に置き換えてください。Manifest-Version: 1.0 Logging-Profile: NAME
アプリケーションにMANIFEST.MF
ファイルがある場合は、以下の行を追加し、NAME を必要なプロファイル名に置き換えます。Logging-Profile: NAME
注記
maven-war-plugin
を使用している場合、MANIFEST.MF ファイルを src/main/resources/META-INF/
に置き、次の設定を pom.xml
ファイルに追加できます。
<plugin> <artifactId>maven-war-plugin</artifactId> <configuration> <archive> <manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile> </archive> </configuration> </plugin>
第6章 国際化と現地語化
6.1. はじめに
6.1.2. 多言語化について
6.2. JBoss ロギングツール
6.2.1. 概要
6.2.1.1. JBoss ロギングツールの国際化および現地語化
org.jboss.logging
アノテーションが付けられたインターフェース内でメソッド定義として作成されます。JBoss ロギングがコンパイル時にインターフェースを実装するため、インターフェースを実装する必要はありません。定義すると、これらのメソッドを使用してコードでメッセージをログに記録したり、例外オブジェクトを取得することが可能です。
6.2.1.2. JBoss ロギングツールのクイックスタート
logging-tools
には JBoss ロギングツールの機能を実証する単純な Maven プロジェクトが含まれています。このクイックスタートは本書のコード例で幅広く使用されています。
6.2.1.3. メッセージロガー
@org.jboss.logging.MessageLogger
アノテーションが付けられます。
6.2.1.4. メッセージバンドル
@org.jboss.logging.MessageBundle
アノテーションが付けられます。
6.2.1.5. 国際化されたログメッセージ
@LogMessage
と @Message
アノテーションを付ける必要があり、@Message
の値属性を使用してログメッセージを指定しなければなりません。国際化されたログメッセージはプロパティーファイルに翻訳を提供するとローカライズされます。
6.2.1.6. 国際化された例外
6.2.1.7. 国際化されたメッセージ
6.2.1.8. 翻訳プロパティーファイル
6.2.1.9. JBoss ロギングツールのプロジェクトコード
@MessageLogger
アノテーションの projectCode
属性で定義されます。
6.2.1.10. JBoss ロギングツールのメッセージ ID
@Message
アノテーションの id
属性で定義されます。
6.2.2. 国際化されたロガー、メッセージ、例外の作成
6.2.2.1. 国際化されたログメッセージの作成
logging-tools
クイックスタートを参照してください。
前提条件
- Maven プロジェクトがすでに存在している必要があります。「JBoss ロギングツールの Maven 設定」を参照してください。
- JBoss ロギングツールに必要な Maven 設定がプロジェクトにある必要があります。
手順6.1 国際化されたログメッセージバンドルの作成
メッセージロガーインターフェースの作成
ログメッセージの定義が含まれるように Java インターフェースをプロジェクトに追加します。定義されるログメッセージに対し、インターフェースにその内容を表す名前を付けます。ログメッセージインターフェースの要件は次の通りです。@org.jboss.logging.MessageLogger
アノテーションが付けられていなければなりません。org.jboss.logging.BasicLogger
を拡張しなければなりません。- このインターフェースを実装する型付きロガーのフィールドをインターフェースが定義する必要があります。
org.jboss.logging.Logger
のgetMessageLogger()
メソッドで定義します。
package com.company.accounts.loggers; import org.jboss.logging.BasicLogger; import org.jboss.logging.Logger; import org.jboss.logging.MessageLogger; @MessageLogger(projectCode="") interface AccountsLogger extends BasicLogger { AccountsLogger LOGGER = Logger.getMessageLogger( AccountsLogger.class, AccountsLogger.class.getPackage().getName() ); }
メソッド定義の追加
各ログメッセージのインターフェースにメソッド定義を追加します。ログメッセージに対する各メソッドにその内容を表す名前を付けます。各メソッドの要件は次の通りです。- メソッドは
void
を返さなければなりません。 @org.jboss.logging.LogMessage
アノテーションが付いていなければなりません。@org.jboss.logging.Message
アノテーションが付いていなければなりません。@org.jboss.logging.Message
の値属性にはデフォルトのログインメッセージが含まれます。翻訳がない場合にこのメッセージが使用されます。
@LogMessage @Message(value = "Customer query failed, Database not available.") void customerQueryFailDBClosed();
デフォルトのログレベルはINFO
です。メソッドの呼び出し
メッセージがロギングされなければならない場所にコードのインターフェースメソッドへの呼び出しを追加します。プロジェクトがコンパイルされる時にアノテーションプロセッサーがインターフェースの実装を作成するため、インターフェースの実装を作成する必要はありません。AccountsLogger.LOGGER.customerQueryFailDBClosed();
カスタムのロガーは BasicLogger よりサブクラス化されるため、BasicLogger
のロギングメソッド (debug()
やerror()
など) を使用することもできます。国際化されていないメッセージをログに記録するため他のロガーを作成する必要はありません。AccountsLogger.LOGGER.error("Invalid query syntax.");
6.2.2.2. 国際化されたメッセージの作成と使用
logging-tools
クイックスタートを参照してください。
要件
- JBoss Enterprise Application Platform 6 のリポジトリを使用する作業用の Maven プロジェクトが存在しなければなりません。「Maven 設定を使用した JBoss Enterprise Application Platform の Maven リポジトリーの設定」 を参照してください。
- JBoss ロギングツールの必要な Maven 設定が追加されている必要があります。「JBoss ロギングツールの Maven 設定」 を参照してください。
手順6.2 国際化されたメッセージの作成と使用
例外のインターフェースの作成
JBoss ロギングツールはインターフェースで国際化されたメッセージを定義します。定義されるメッセージに対し、インターフェースにその内容を表す名前を付けます。インターフェースの要件は次の通りです。- パブリックとして宣言される必要があります。
@org.jboss.logging.MessageBundle
アノテーションが付けられていなければなりません。- インターフェースと同じ型のメッセージバンドルであるフィールドをインターフェースが定義する必要があります。
@MessageBundle(projectCode="") public interface GreetingMessageBundle { GreetingMessageBundle MESSAGES = Messages.getBundle(GreetingMessageBundle.class); }
メソッド定義の追加
各メッセージのインターフェースにメソッド定義を追加します。メッセージに対する各メソッドにその内容を表す名前を付けます。各メソッドの要件は次の通りです。- 型
String
のオブジェクトを返す必要があります。 @org.jboss.logging.Message
アノテーションが付いていなければなりません。- デフォルトメッセージに
@org.jboss.logging.Message
の値属性が設定されていなければなりません。翻訳がない場合にこのメッセージが使用されます。
@Message(value = "Hello world.") String helloworldString();
呼び出しメソッド
メッセージを取得する必要がある場所でアプリケーションのインターフェースメソッドを呼び出します。System.console.out.println(helloworldString());
6.2.2.3. 国際化された例外の作成
logging-tools
クイックスタートを参照してください。
手順6.3 国際化された例外の作成と使用
JBoss ロギングツール設定の追加
JBoss ロギングツールをサポートするために必要なプロジェクト設定を追加します。「JBoss ロギングツールの Maven 設定」を参照してください。例外のインターフェースの作成
JBoss ロギングツールはインターフェースで国際化された例外を定義します。定義される例外に対し、インターフェースにその内容を表す名前を付けます。インターフェースの要件は次の通りです。public
として宣言される必要があります。@org.jboss.logging.MessageBundle
アノテーションが付けられていなければなりません。- インターフェースと同じ型のメッセージバンドルであるフィールドをインターフェースが定義する必要があります。
@MessageBundle(projectCode="") public interface ExceptionBundle { ExceptionBundle EXCEPTIONS = Messages.getBundle(ExceptionBundle.class); }
メソッド定義の追加
各例外のインターフェースにメソッド定義を追加します。例外に対する各メソッドにその内容を表す名前を付けます。各メソッドの要件は次の通りです。- 型
Exception
のオブジェクトまたはException
のサブタイプを返す必要があります。 @org.jboss.logging.Message
アノテーションが付いていなければなりません。- デフォルトの例外メッセージに
@org.jboss.logging.Message
の値属性が設定されていなければなりません。翻訳がない場合にこのメッセージが使用されます。 - メッセージ文字列の他にパラメータを必要とするコンストラクターが返された例外にある場合、
@Param
アノテーションを使用してこれらのパラメーターをメソッド定義に提供しなければなりません。パラメーターはコンストラクターと同じ型で同じ順番でなければなりません。
@Message(value = "The config file could not be opened.") IOException configFileAccessError(); @Message(id = 13230, value = "Date string '%s' was invalid.") ParseException dateWasInvalid(String dateString, @Param int errorOffset);
呼び出しメソッド
例外を取得する必要がある場所でコードのインターフェースメソッドを呼び出します。メソッドは例外をスローしませんが、スローできる例外オブジェクトを返します。try { propsInFile=new File(configname); props.load(new FileInputStream(propsInFile)); } catch(IOException ioex) //in case props file does not exist { throw ExceptionBundle.EXCEPTIONS.configFileAccessError(); }
6.2.3. 国際化されたロガー、メッセージ、例外の現地語化
6.2.3.1. Maven で新しい翻訳プロパティーファイルを生成する
logging-tools
クイックスタートを参照してください。
前提条件
- 作業用の Maven プロジェクトが既に存在している必要があります。
- JBoss ロギングツールに対してプロジェクトが設定されていなければなりません。
- 国際化されたログメッセージや例外を定義する 1 つ以上のインターフェースがプロジェクトに含まれていなければなりません。
手順6.4 Maven で新しい翻訳プロパティーファイルを生成する
Maven 設定の追加
-AgenereatedTranslationFilePath
コンパイラー引数を Maven コンパイラープラグイン設定に追加し、新しいファイルが作成されるパスを割り当てます。<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.6</source> <target>1.6</target> <compilerArgument> -AgeneratedTranslationFilesPath=${project.basedir}/target/generated-translation-files </compilerArgument> <showDeprecation>true</showDeprecation> </configuration> </plugin>
上記の設定は Maven プロジェクトのtarget/generated-translation-files
ディレクトリに新しいファイルを作成します。プロジェクトの構築
Maven を使用したプロジェクトの構築[Localhost]$ mvn compile
@MessageBundle
または @MessageLogger
アノテーションが付けられたインターフェースごとに 1 つのプロパティーファイルが作成されます。各インターフェースが宣言される Java パッケージに対応するサブディレクトリに新しいファイルが作成されます。
InterfaceName.i18n_locale_COUNTRY_VARIANT.properties
という構文を使用して名前が付けられます。InterfaceName
はこのファイルが生成されたインターフェースの名前になります。
6.2.3.2. 国際化されたロガーや例外、メッセージの翻訳
logging-tools
クイックスタートを参照してください。
要件
- 作業用の Maven プロジェクトが既に存在している必要があります。
- JBoss ロギングツールに対してプロジェクトが設定されていなければなりません。
- 国際化されたログメッセージや例外を定義する 1 つ以上のインターフェースがプロジェクトに含まれていなければなりません。
- テンプレート翻訳プロパティーファイルを生成するようプロジェクトが設定されている必要があります。
手順6.5 国際化されたロガーや例外、メッセージの翻訳
テンプレートプロパティーファイルの生成
mvn compile
コマンドを実行し、テンプレート翻訳プロパティーファイルを作成します。プロジェクトへのテンプレートファイルの追加
翻訳したいインターフェースのテンプレートを、テンプレートが作成されたディレクトリからプロジェクトのsrc/main/resources
ディレクトリへコピーします。プロパティーファイルは翻訳するインターフェースと同じパッケージに存在しなければなりません。コピーしたテンプレートファイルの名前変更
GreeterLogger.i18n_fr_FR.properties
のように、含まれる翻訳に応じてテンプレートファイルのコピーの名前を変更します。テンプレートの内容の翻訳
新しい翻訳プロパティーファイルを編集し、適切な翻訳が含まれるようにします。# Level: Logger.Level.INFO # Message: Hello message sent. logHelloMessageSent=Bonjour message envoyé.
実行された各バンドルの各翻訳に対して手順の 2、3、4 を繰り返します。
target/generated-sources/annotations/
で確認できます。
6.2.4. 国際化されたログメッセージのカスタマイズ
6.2.4.1. ログメッセージへのメッセージ IDとプロジェクトコードの追加
logging-tools
クイックスタートを参照してください。
要件
- 国際化されたログメッセージを持つプロジェクトが存在する必要があります。「国際化されたログメッセージの作成」を参照してください。
- 使用するプロジェクトコードを認識する必要があります。プロジェクトコードを 1 つ使用することも、各インターフェースに異なるコードを定義することも可能です。
手順6.6 メッセージ ID とプロジェクトコードをログメッセージに追加する
インターフェースのプロジェクトコードを指定します。
カスタムのロガーインターフェースに付けられる@MessageLogger
アノテーションの projectCode 属性を使用してプロジェクトコードを指定します。インターフェースに定義されるすべてのメッセージがこのプロジェクトコードを使用します。@MessageLogger(projectCode="ACCNTS") interface AccountsLogger extends BasicLogger { }
メッセージ ID の指定
メッセージを定義するメソッドに付けられる @Message アノテーションの id 属性を使用して各メッセージに対してメッセージ ID を指定します。@LogMessage @Message(id=43, value = "Customer query failed, Database not available.") void customerQueryFailDBClosed();
10:55:50,638 INFO [com.company.accounts.ejb] (MSC service thread 1-4) ACCNTS000043: Customer query failed, Database not available.
6.2.4.2. メッセージのログレベル設定
INFO
です。ロギングメソッドに付けられた @LogMessage
アノテーションの level
属性を用いて異なるログレベルを指定することが可能です。
手順6.7 メッセージのログレベルの指定
level 属性の指定
ログメッセージメソッド定義の@LogMessage
アノテーションにlevel
属性を追加します。ログレベルの割り当て
このメッセージに対するログレベルの値をlevel
属性に割り当てます。level
に有効な値はorg.jboss.logging.Logger.Level
に定義される 6 つの列挙定数であるDEBUG
、ERROR
、FATAL
、INFO
、TRACE
、WARN
になります。Import org.jboss.logging.Logger.Level; @LogMessage(level=Level.ERROR) @Message(value = "Customer query failed, Database not available.") void customerQueryFailDBClosed();
ERROR
レベルのログメッセージが作成されます。
10:55:50,638 ERROR [com.company.app.Main] (MSC service thread 1-4) Customer query failed, Database not available.
6.2.4.3. パラメーターによるログメッセージのカスタマイズ
手順6.8 パラメーターによるログメッセージのカスタマイズ
メソッド定義へパラメーターを追加する
すべての型のパラメーターをメソッド定義に追加することができます。型に関係なくパラメーターの String 表現がメッセージに表示されます。ログメッセージへパラメーター参照を追加する
参照は明示的なインデックスか通常のインデックスを使用できます。- 通常のインデックスを使用するには、各パラメーターを表示したいメッセージ文字列に
%s
文字を挿入します。%s
の最初のインスタンスにより最初のパラメーターが挿入され、2 番目のインスタンスにより 2 番目のパラメーターが挿入されます。 - 明示的なインデックスを使用するには、文字
%{#}
をメッセージに挿入します。# は表示したいパラメーターの数に置き換えます。
重要
例6.1 通常のインデックスを使用したメッセージパラメーター
@LogMessage(level=Logger.Level.DEBUG) @Message(id=2, value="Customer query failed, customerid:%s, user:%s") void customerLookupFailed(Long customerid, String username);
例6.2 明示的なインデックスを使用したメッセージパラメーター
@LogMessage(level=Logger.Level.DEBUG) @Message(id=2, value="Customer query failed, customerid:%{1}, user:%{2}") void customerLookupFailed(Long customerid, String username);
6.2.4.4. ログメッセージの原因として例外を指定する
Throwable
型とするか、サブクラスのいずれかに @Cause
アノテーションを付ける必要があります。このパラメーターは、他のパラメーターのようにログメッセージで参照することはできず、ログメッセージの後に表示されます。
手順6.9 ログメッセージの原因として例外を指定する
パラメーターの追加
Throwable
型のパラメーターまたはサブクラスをメソッドに追加します。@Message(id=404, value="Loading configuration failed. Config file:%s") void loadConfigFailed(Exception ex, File file);
アノテーションの追加
パラメーターに@Cause
アノテーションを追加します。import org.jboss.logging.Cause @Message(value = "Loading configuration failed. Config file: %s") void loadConfigFailed(@Cause Exception ex, File file);
メソッドの呼び出し
コードでメソッドが呼び出されると、正しい型のオブジェクトが渡され、ログメッセージの後に表示されます。try { confFile=new File(filename); props.load(new FileInputStream(confFile)); } catch(Exception ex) //in case properties file cannot be read { ConfigLogger.LOGGER.loadConfigFailed(ex, filename); }
コードがFileNotFoundException
型の例外をスローした場合、上記コード例の出力は次のようになります。10:50:14,675 INFO [com.company.app.Main] (MSC service thread 1-3) Loading configuration failed. Config file: customised.properties java.io.FileNotFoundException: customised.properties (No such file or directory) at java.io.FileInputStream.open(Native Method) at java.io.FileInputStream.<init>(FileInputStream.java:120) at com.company.app.demo.Main.openCustomProperties(Main.java:70) at com.company.app.Main.go(Main.java:53) at com.company.app.Main.main(Main.java:43)
6.2.5. 国際化された例外のカスタマイズ
6.2.5.1. メッセージ ID とプロジェクトコードを例外メッセージに追加する
要件
- 国際化された例外を持つプロジェクトが存在する必要があります。「国際化された例外の作成」を参照してください。
- 使用するプロジェクトコードを認識する必要があります。プロジェクトコードを 1 つ使用することも、各インターフェースに異なるコードを定義することも可能です。
手順6.10 メッセージ ID とプロジェクトコードを例外メッセージに追加する
プロジェクトコードの指定
例外バンドルインターフェースに付けられる@MessageBundle
アノテーションのprojectCode
属性を使用してプロジェクトコードを指定します。インターフェースに定義されるすべてのメッセージがこのプロジェクトコードを使用します。@MessageBundle(projectCode="ACCTS") interface ExceptionBundle { ExceptionBundle EXCEPTIONS = Messages.getBundle(ExceptionBundle.class); }
メッセージ ID の指定
例外を定義するメソッドに付けられる@Message
アノテーションのid
属性を使用して各例外に対してメッセージ ID を指定します。@Message(id=143, value = "The config file could not be opened.") IOException configFileAccessError();
重要
例6.3 国際化された例外の作成
@MessageBundle(projectCode="ACCTS") interface ExceptionBundle { ExceptionBundle EXCEPTIONS = Messages.getBundle(ExceptionBundle.class); @Message(id=143, value = "The config file could not be opened.") IOException configFileAccessError(); }
throw ExceptionBundle.EXCEPTIONS.configFileAccessError();
Exception in thread "main" java.io.IOException: ACCTS000143: The config file could not be opened. at com.company.accounts.Main.openCustomProperties(Main.java:78) at com.company.accounts.Main.go(Main.java:53) at com.company.accounts.Main.main(Main.java:43)
6.2.5.2. パラメーターによる例外メッセージのカスタマイズ
手順6.11 パラメーターによる例外メッセージのカスタマイズ
メソッド定義へパラメーターを追加する
すべての型のパラメーターをメソッド定義に追加することができます。型に関係なくパラメーターのString
表現がメッセージに表示されます。例外メッセージへパラメーター参照を追加する
参照は明示的なインデックスか通常のインデックスを使用できます。- 通常のインデックスを使用するには、各パラメーターを表示したいメッセージ文字列に
%s
文字を挿入します。%s
の最初のインスタンスにより最初のパラメーターが挿入され、2 番目のインスタンスにより 2 番目のパラメーターが挿入されます。 - 明示的なインデックスを使用するには、文字
%{#}
をメッセージに挿入します。#
は表示したいパラメーターの数に置き換えます。
明示的なインデックスを使用すると、メッセージのパラメーター参照の順番がメソッドで定義される順番とは異なるようになります。これは、異なるパラメーターの順番が必要な翻訳メッセージで重要になります。
重要
@Cause
アノテーションが付けられたパラメーターはパラメーターの数には含まれません。
例6.4 通常のインデックスを使用
@Message(id=143, value = "The config file %s could not be opened.") IOException configFileAccessError(File config);
例6.5 明示的なインデックスを使用
@Message(id=143, value = "The config file %{1} could not be opened.") IOException configFileAccessError(File config);
6.2.5.3. 別の例外の原因として 1 つの例外を指定する
手順6.12 別の例外の原因として 1 つの例外を指定する
パラメーターの追加
Throwable
型のパラメーターまたはサブクラスをメソッドに追加します。@Message(id=328, value = "Error calculating: %s.") ArithmeticException calculationError(Throwable cause, String msg);
アノテーションの追加
パラメーターに@Cause
アノテーションを追加します。import org.jboss.logging.Cause @Message(id=328, value = "Error calculating: %s.") ArithmeticException calculationError(@Cause Throwable cause, String msg);
メソッドの呼び出し
例外オブジェクトを取得するためインターフェースメソッドを呼び出します。キャッチした例外を原因として使用し、キャッチブロックより新しい例外をスローするのが最も一般的なユースケースになります。try { ... } catch(Exception ex) { throw ExceptionBundle.EXCEPTIONS.calculationError( ex, "calculating payment due per day"); }
例6.6 別の例外の原因として 1 つの例外を指定する
@MessageBundle(projectCode = "TPS") interface CalcExceptionBundle { CalcExceptionBundle EXCEPTIONS = Messages.getBundle(CalcExceptionBundle.class); @Message(id=328, value = "Error calculating: %s.") ArithmeticException calcError(@Cause Throwable cause, String value); }
int totalDue = 5; int daysToPay = 0; int amountPerDay; try { amountPerDay = totalDue/daysToPay; } catch (Exception ex) { throw CalcExceptionBundle.EXCEPTIONS.calcError(ex, "payments per day"); }
Exception in thread "main" java.lang.ArithmeticException: TPS000328: Error calculating: payments per day. at com.company.accounts.Main.go(Main.java:58) at com.company.accounts.Main.main(Main.java:43) Caused by: java.lang.ArithmeticException: / by zero at com.company.accounts.Main.go(Main.java:54) ... 1 more
6.2.6. 参考資料
6.2.6.1. JBoss ロギングツールの Maven 設定
pom.xml
ファイルのプロジェクトの設定を次のように変更する必要があります。
pom.xml
ファイルの例については、logging-tools
クイックスタートを参照してください。
- プロジェクトに対して JBoss Maven リポジトリが有効になっている必要があります。「Maven 設定を使用した JBoss Enterprise Application Platform の Maven リポジトリーの設定」 を参照してください。
jboss-logging
とjboss-logging-processor
の Maven 依存関係を追加する必要があります。これらの依存関係は両方 JBoss Enterprise Application Platform 6 で使用可能であるため、各依存関係の scope 要素を次のようにprovided
に設定できます。<dependency> <groupId>org.jboss.logging</groupId> <artifactId>jboss-logging-processor</artifactId> <version>1.0.0.Final</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.jboss.logging</groupId> <artifactId>jboss-logging</artifactId> <version>3.1.0.GA</version> <scope>provided</scope> </dependency>
maven-compiler-plugin
のバージョンは2.2
以上である必要があり、1.6
のターゲットソースおよび生成されたソースに対して設定する必要があります。<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin>
6.2.6.2. 翻訳プロパティーファイルの形式
java.util.Properties
クラスのドキュメントに記載されている単純な行指向の key=value
ペア形式です。
InterfaceName.i18n_locale_COUNTRY_VARIANT.properties
InterfaceName
は翻訳が適用されるインターフェースの名前です。locale
、COUNTRY
、およびVARIANT
は翻訳が適用される地域設定を識別します。locale
は ISO-639 言語コードを使用して言語を指定し、COUNTRY
は ISO-3166 国名コードを使用して国を指定します。COUNTRY
は任意です。VARIANT
は特定のオペレーティングシステムやブラウザーのみに適用される翻訳を識別するために使用される任意の識別子です。
例6.7 翻訳プロパティーファイルの例
GreeterService.i18n_fr_FR_POSIX.properties
# Level: Logger.Level.INFO # Message: Hello message sent. logHelloMessageSent=Bonjour message envoyé.
6.2.6.3. JBoss ロギングツールのアノテーションに関する参考資料
表6.1 JBoss ロギングツールのアノテーション
アノテーション | ターゲット | 説明 | 属性 |
---|---|---|---|
@MessageBundle | インターフェース |
インターフェースをメッセージバンドルとして定義します。
| projectCode |
@MessageLogger | インターフェース |
インターフェースをメッセージロガーとして定義します。
| projectCode |
@Message | メソッド |
メッセージバンドルとメッセージロガーで使用できます。メッセージロガーでは、多言語化されたロガーとしてメソッドを定義します。メッセージバンドルでは、多言語化された文字列または例外オブジェクトを返すメソッドとして定義します。
| value 、id |
@LogMessage | メソッド |
メッセージロガーのメソッドをロギングメソッドとして定義します。
| level (デフォルトは INFO ) |
@Cause | パラメーター |
ログメッセージまたは他の例外が発生したときに例外を渡すパラメーターとして定義します。
| - |
@Param | パラメーター |
例外のコンストラクターへ渡されるパラメーターとして定義します。
| - |
第7章 Enterprise JavaBeans
7.1. はじめに
7.1.1. Enterprise JavaBeans の概要
7.1.2. EJB 3.1 機能セット
- セッション Bean
- メッセージ駆動型 Bean
- ノーインターフェースビュー (No-interface view)
- ローカルインターフェース
- リモートインターフェース
- JAX-WS web サービス
- JAX-RS web サービス
- タイマーサービス
- 非同期呼び出し
- インターセプター
- RMI/IIOP 相互運用性
- トランザクションサポート
- セキュリティ
- 埋め込み API
- エンティティー Bean (コンテナおよび Bean 管理の永続性)
- EJB 2.1 エンティティー Bean のクライアントビュー
- EJB クエリ言語 (EJB QL)
- JAX-RPC ベースの Web サービス (エンドポイントおよびクライアントビュー)
7.1.3. EJB 3.1 Lite
- Web アプリケーションに適切な機能のみをサポートします。
- EJB を同じ WAR ファイルで Web アプリケーションとしてデプロイできます。
7.1.4. EJB 3.1 Lite の機能
- ステートレス、ステートフル、およびシングルトンセッション Bean
- ローカルビジネスインターフェースおよび「インターフェースなし」Bean
- インターセプター
- コンテナ管理および Bean 管理トランザクション
- 宣言およびプログラミング可能なセキュリティ
- 埋め込み API
- リモートインターフェース
- RMI と IIOP の相互運用性
- JAX-WS Web サービスエンドポイント
- EJB タイマーサービス
- 非同期セッション Bean 呼び出し
- メッセージ駆動 Bean
7.1.5. エンタープライズ Bean
重要
7.1.6. エンタープライズ Bean の記述について
7.1.7. セッション Bean ビジネスインターフェース
7.1.7.1. エンタープライズ Bean のビジネスインターフェース
7.1.7.2. EJB ローカルビジネスインターフェース
7.1.7.3. EJB リモートビジネスインターフェース
7.1.7.4. EJB のインタフェース以外の Bean
7.2. エンタープライズ Bean プロジェクトの作成
7.2.1. JBoss Developer Studio を使用した EJB アーカイブプロジェクトの作成
要件
- JBoss Enterprise Application Platform 6 のサーバーとサーバーランタイムが設定されている必要があります。
手順7.1 JBoss Developer Studio での EJB プロジェクトの作成
新規プロジェクトの作成
新規 EJB プロジェクト ウィザードを開くために、ファイル (File) メニューで 新規 (New) を選択し、次に EJB プロジェクト (EJB Project) を選択します。図7.1 New EJB Project ウィザード
詳細の指定
次の詳細を入力します。- プロジェクト名JBoss Developer Studio で表示されるプロジェクト名ですが、デプロイされた JAR ファイルのデフォルトのファイル名にもなります。
- プロジェクトの場所プロジェクトのファイルが保存されるディレクトリです。現在のワークスペースのディレクトリがデフォルトになります。
- ターゲットランタイムプロジェクトに使用されるサーバーランタイムです。デプロイするサーバーによって使用される JBoss Enterprise Application Platform 6 のランタイムと同様に設定される必要があります。
- EJB モジュールバージョン。エンタープライズ Bean が準拠する EJB 仕様のバージョンになります。Red Hat は
3.1
の使用を推奨します。 - これでプロジェクトのサポート対象機能を調整できるようになります。選択したランタイムにデフォルト設定を使用します。
[Next] をクリックして作業を継続します。Java 構築設定
この画面では、Java ソースファイルが格納されるディレクトリや構築された出力が置かれるディレクトリをカスタマイズすることが可能です。この設定は変更せずに [Next] をクリックします。EJB モジュール設定
デプロイメント記述子が必要な場合は [Generate ejb-jar.xml deployment descriptor] チェックボックスにチェックマークを付けます。EJB 3.1 ではデプロイメント記述子は任意で、必要な場合は後で追加することが可能です。[Finish] をクリックするとプロジェクトが作成され、Project Explorer に表示されます。図7.2 Project Explorer の新規作成された EJB プロジェクト
デプロイメントに対して構築アーティファクトをサーバーに追加する
サーバータブにて、構築アーティファクトをデプロイしたいサーバーを右クリックし、 [Add and Remove] ダイアログを開きます。[Add and Remove] を選択します。[Available] カラムよりデプロイするリソースを選択し、 [Add] ボタンをクリックします。リソースが [Configured] カラムに移動します。[Finish] をクリックしてダイアログを閉じます。図7.3 ダイアログの追加と削除
ビルドし、指定のサーバーにデプロイできる EJB プロジェクトが JBoss Developer Studio で作成されます。
7.2.2. Maven における EJB アーカイブプロジェクトの作成
前提条件
- Maven が既にインストールされている必要があります。
- Maven の基本的な使用法を理解している必要があります。
手順7.2 Maven における EJB アーカイブプロジェクトの作成
Maven プロジェクトの作成
Maven のアーキタイプシステムとejb-javaee6
アーキタイプを使用して EJB プロジェクトを作成することができます。作成するには、以下のパラメーターを用いてmvn
コマンドを実行します。mvn archetype:generate -DarchetypeGroupId=org.codehaus.mojo.archetypes -DarchetypeArtifactId=ejb-javaee6
プロジェクトのgroupId
、artifactId
、version
、package
を指定するよう要求されます。[localhost]$ mvn archetype:generate -DarchetypeGroupId=org.codehaus.mojo.archetypes -DarchetypeArtifactId=ejb-javaee6 [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building Maven Stub Project (No POM) 1 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] >>> maven-archetype-plugin:2.0:generate (default-cli) @ standalone-pom >>> [INFO] [INFO] <<< maven-archetype-plugin:2.0:generate (default-cli) @ standalone-pom <<< [INFO] [INFO] --- maven-archetype-plugin:2.0:generate (default-cli) @ standalone-pom --- [INFO] Generating project in Interactive mode [INFO] Archetype [org.codehaus.mojo.archetypes:ejb-javaee6:1.5] found in catalog remote Define value for property 'groupId': : com.shinysparkly Define value for property 'artifactId': : payment-arrangments Define value for property 'version': 1.0-SNAPSHOT: : Define value for property 'package': com.shinysparkly: : Confirm properties configuration: groupId: com.company artifactId: payment-arrangments version: 1.0-SNAPSHOT package: com.company.collections Y: : [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 32.440s [INFO] Finished at: Mon Oct 31 10:11:12 EST 2011 [INFO] Final Memory: 7M/81M [INFO] ------------------------------------------------------------------------ [localhost]$
エンタープライズ Bean の追加
エンタープライズ Bean を作成し、Bean のパッケージの適切なサブディレクトリにあるsrc/main/java
ディレクトリ下のプロジェクトに追加します。プロジェクトの構築
プロジェクトを構築するには、pom.xml
ファイルと同じディレクトリでmvn package
コマンドを実行します。このコマンドを実行すると、Java クラスがコンパイルされ、JAR ファイルがパッケージ化されます。ビルドされた JAR ファイルにはartifactId-version.jar
という名前が付けられ、target/
ディレクトリに置かれます。
7.2.3. EJB プロジェクトが含まれる EAR プロジェクトの作成
要件
- JBoss Enterprise Application Platform 6 のサーバーとサーバーランタイムが設定されている必要があります。詳細は 「JBoss Enterprise Application Platform 6 サーバーの JBoss Developer Studio への追加」 を参照してください。
手順7.3 EJB プロジェクトが含まれる EAR プロジェクトの作成
新しい EAR アプリケーションプロジェクトウィザードを開く
[File] メニューより [New]、 [Project] の順に選択すると、[New Project] ウィザードが表示されます。[Java EE/Enterprise Application Project] を選択し、[Next] をクリックします。図7.4 新しい EAR アプリケーションウィザード
詳細の入力
次の詳細を入力します。- プロジェクト名JBoss Developer Studio で表示されるプロジェクト名ですが、デプロイされた EAR ファイルのデフォルトのファイル名にもなります。
- プロジェクトの場所プロジェクトのファイルが保存されるディレクトリです。現在のワークスペースのディレクトリがデフォルトになります。
- ターゲットランタイムプロジェクトに使用されるサーバーランタイムです。デプロイするサーバーによって使用される JBoss Enterprise Application Platform 6 のランタイムと同様に設定される必要があります。
- EAR バージョンプロジェクトが準拠する Java Enterprise Edition 仕様のバージョンになります。Red Hat は
6
の使用を推奨します。 - これでプロジェクトのサポート対象機能を調整できるようになります。選択したランタイムにデフォルト設定を使用します。
[Next] クリックして作業を継続します。新しい EJB モジュールの追加
新しいモジュールはウィザードの Enterprise Application ページより追加することができます。次の手順に従って新しい EJB プロジェクトをモジュールとして追加します。新しい EJB モジュールの追加
[New Module] をクリックし、 [Create Default Modules] チェックボックスのチェックを外します。[Enterprise Java Bean] を選択し、[Next] をクリックすると [New EJB Project] ウィザードが表示されます。EJB プロジェクトの作成
New EJB Project ウィザードは、新しいスタンドアローン EJB プロジェクトを作成するために使用するウィザードと同じで、「JBoss Developer Studio を使用した EJB アーカイブプロジェクトの作成」 に説明されています。プロジェクト作成のために最低限必要な情報は次の通りです。- プロジェクト名
- ターゲットランタイム
- EJB モジュールのバージョン
- 設定
ウィザードの他の手順はすべて任意の手順となります。[Finish] をクリックして EJB プロジェクトの作成を完了します。
新規作成された EJB プロジェクトは Java EE モジュールの依存関係に一覧表示され、チェックボックスにチェックが付けられます。任意の作業: application.xml デプロイメント記述子の追加
必要な場合は [Generate application.xml deployment descriptor] チェックボックスにチェックを付けます。Finish のクリック
EJB プロジェクトと EAR プロジェクトの 2 つの新しいプロジェクトが表示されます。デプロイメントに対して構築アーティファクトをサーバーに追加する
[Servers] タブにて、構築アーティファクトをデプロイしたいサーバーを右クリックし、 [Add and Remove] ダイアログを開きます。[Add and Remove] を選択します。[Available] カラムよりデプロイする EAR リソースを選択し、 [Add] ボタンをクリックします。リソースが [Configured] カラムに移動します。[Finish] をクリックしてダイアログを閉じます。図7.5 ダイアログの追加と削除
メンバーの EJB プロジェクトを持つ Enterprise Application プロジェクトが作成されます。この Enterprise Application プロジェクトはビルドされ、EJB サブデプロイメントが含まれる単一の EAR デプロイメントとして指定のサーバーにデプロイされます。
7.2.4. EJB プロジェクトへのデプロイメント記述子の追加
前提条件
- EJB デプロイメント記述子を追加したい EJB プロジェクトが JBoss Developer Studio に存在している必要があります。
手順7.4 EJB プロジェクトにデプロイメント記述子を追加する
プロジェクトを開く
JBoss Developer Studio でプロジェクトを開きます。デプロイメント記述子の追加
プロジェクトビューの Deployment Descriptor フォルダーを右クリックし、[Generate Deployment Descriptor Stub] を選択します。図7.6 デプロイメント記述子の追加
ejb-jar.xml
が ejbModule/META-INF/
に作成されます。
7.3. セッション Bean
7.3.1. セッション Bean
7.3.2. ステートレスセッション Bean
7.3.3. ステートフルセッション Bean
7.3.4. シングルトンセッション Bean
7.3.5. JBoss Developer Studio のプロジェクトにセッション Bean を追加する
前提条件
- 1 つ以上のセッション Bean を追加したい EJB または動的 Web プロジェクトが JBoss Developer Studio に存在する必要があります。
手順7.5 JBoss Developer Studio のプロジェクトにセッション Bean を追加する
プロジェクトを開く
JBoss Developer Studio でプロジェクトを開きます。[Create EJB 3.x Session Bean] ウィザードを開く
[Create EJB 3.x Session Bean] ウィザードを開くために、[File] メニューへ移動し、[New] を選択してから [Session Bean (EJB 3.x)] を選択します。図7.7 [Create EJB 3.x Session Bean] ウィザード
クラス情報の指定
次の詳細を入力します。- プロジェクト正しいプロジェクトが選択されているか検証します。
- ソースホルダーJava ソースファイルが作成されるフォルダーになります。通常、変更する必要はありません。
- パッケージクラスが属するパッケージを指定します。
- クラス名セッション Bean になるクラスの名前を指定します。
- スーパークラスセッション Bean クラスはスーパークラスより継承することができます。セッションにスーパークラスがあるかどうかをここに指定します。
- ステートタイプセッション Bean のステートタイプ (ステートレス、ステートフル、シングルトン) を指定します。
- ビジネスインターフェースデフォルトでは No-interface ボックスにチェックマークが付けられているため、インターフェースは作成されません。定義したいインターフェースのボックスにチェックマークを付け、必要な場合は名前を調整します。Web アーカイブ (WAR) のエンタープライズ Bean は EJB 3.1 Lite のみをサポートするため、リモートビジネスインターフェースは含まれません。
[Next] をクリックします。セッション Bean の特定情報
ここに追加情報を入力してセッション Bean を更にカスタマイズすることが可能です。ここで情報を変更する必要はありません。変更できる項目は次の通りです。- Bean 名。
- マッピングされた名前。
- トランザクションタイプ (コンテナ管理または Bean 管理)。
- Bean が実装しなければならない追加のインターフェースを入力できます。
- 必要な場合は、EJB 2.x のホームインターフェースやコンポーネントインターフェースを指定することもできます。
完了
[Finish] をクリックすると、新しいセッション Bean が作成され、プロジェクトに追加されます。指定された場合、新しいビジネスインターフェースのファイルも作成されます。

図7.8 JBoss Developer Studio の新しいセッション Bean
7.4. メッセージ駆動型 Bean
7.4.1. メッセージ駆動型 Bean
7.4.2. リソースアダプター
7.4.3. JBoss Developer Studio に JMS ベースのメッセージ駆動型 Bean を作成する
前提条件
- JBoss Developer Studio で既存のプロジェクトが開かれていなければなりません。
- Bean がリッスンする JMS 宛先の名前とタイプを認識している必要があります。
- Bean がデプロイされる JBoss Enterprise Application Platform の設定で Java メッセージングサービス (JMS) のサポートが有効になっている必要があります。
手順7.6 JBoss Developer Studio に JMS ベースのメッセージ駆動型 Bean を追加する
[Create EJB 3.x Message-Driven Bean] ウィザードを開く
[File] → [New] → [Other] と移動します。[EJB/Message-Driven Bean (EJB 3.x)] を選択し、 [Next] ボタンをクリックします。図7.9 Create EJB 3.x Message-Driven Bean ウィザード
クラスファイルの宛先詳細の指定
Bean クラスに対して指定する詳細のセットは、プロジェクト、Java クラス、メッセージの宛先の 3 つがあります。- プロジェクト
- [Workspace] に複数のプロジェクトが存在する場合は、[Project] メニューで正しいプロジェクトが選択されるようにしてください。
- 新しい Bean のソースファイルが作成されるフォルダーは、選択されたディレクトリ下の
ejbModule
に作成されます。特定の要件がある場合のみこのフォルダーを変更します。
- Java クラス
- 必須のフィールドは [Java package] と [class name] になります。
- アプリケーションのビジネスロジックがスーパークラスを必要とする場合を除き、[Superclass] を入力する必要はありません。
- メッセージの宛先
- JMS ベースのメッセージ駆動型 Bean に提供しなければならない詳細は次の通りです。
- [Destination name]。Bean が応答するメッセージに含まれるキューまたはトピック名です。
- デフォルトでは [JMS] チェックボックスが選択されます。これは変更しないでください。
- [Destination type] を必要に応じて [Queue] または [Topic] に設定します。
[Next] ボタンをクリックします。メッセージ駆動型 Bean に固有の情報の入力
以下のデフォルト値はコンテナ管理トランザクションを使用する JMS ベースのメッセージ駆動型 Bean に適するデフォルト値となります。- Bean が Bean 管理トランザクションを使用する場合はトランザクションタイプを Bean に変更します。
- クラス名とは異なる Bean 名が必要な場合は Bean 名を変更します。
- JMS メッセージリスナーインターフェースが表示されるはずです。インターフェースがアプリケーションのビジネスロジックに固有する場合を除き、インターフェースを追加したり削除したりする必要はありません。
- メソッドスタブ作成のチェックボックスはそのまま選択された状態にしてきます。
[Finish] ボタンをクリックします。
onMessage()
メソッドによってメッセージ駆動型 Bean が作成されます。JBoss Developer Studio のエディターウィンドウが対応するファイルによって開かれます。
7.5. セッション Bean の呼び出し
7.5.1. JNDI を使用したリモートでのセッション Bean の呼び出し
ejb-remote
クイックスタートには、この機能のデモを行う Maven プロジェクトが含まれています。このクイックスタートには、デプロイするセッション Bean のプロジェクトとリモートクライアントのプロジェクトの両方が含まれています。下記のコード例はリモートクライアントのプロジェクトから引用されています。
要件
- Maven プロジェクトが作成され、使用できる状態です。
- JBoss Enterprise Application Platform 6 の Maven リポジトリが既に追加されています。
- 呼び出しするセッション Bean が既にデプロイされています。
- デプロイされたセッション Bean がリモートビジネスインターフェースを実装します。
- セッション Bean のリモートビジネスインターフェースは Maven 依存関係として使用できます。リモートビジネスインターフェースが JAR ファイルとしてのみ使用できる場合は、JAR をアーティファクトとして Maven リポジトリに追加することが推奨されます。手順については、http://maven.apache.org/plugins/maven-install-plugin/usage.html にある Maven ドキュメントの
install:install-file
ゴールを参照してください。 - セッション Bean をホストするサーバーのホスト名と JNDI ポートを覚えておく必要があります。
手順7.7 セッション Bean のリモート呼び出しに対する Maven プロジェクト設定を追加する
必要なプロジェクト依存関係の追加
必要な依存関係が含まれるようにするため、プロジェクトのpom.xml
を更新する必要があります。jboss-ejb-client.properties
ファイルの追加JBoss EJB クライアント API は、JNDI サービスの接続情報が含まれるjboss-ejb-client.properties
という名前のプロジェクトのルートにファイルがあることを想定します。このファイルを以下の内容と共にプロジェクトのsrc/main/resources/
ディレクトリーに追加します。remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false remote.connections=default remote.connection.default.host=localhost remote.connection.default.port = 4447 remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
ホスト名とポートを変更してサーバーと一致するようにします。4447
がデフォルトのポート番号です。 安全な接続の場合、SSL_ENABLED
行をtrue
に設定し、SSL_STARTTLS
行をアンコメントします。コンテナ内のリモーティングインターフェースは同じポートを使用して安全な接続と安全でない接続をサポートします。リモートビジネスインターフェースの依存関係の追加
セッション Bean のリモートビジネスインターフェースに対するpom.xml
に Maven の依存関係を追加します。<dependency> <groupId>org.jboss.as.quickstarts</groupId> <artifactId>jboss-as-ejb-remote-server-side</artifactId> <type>ejb-client</type> <version>${project.version}</version> </dependency>
手順7.8 JNDI を使用して Bean プロキシを取得し、Bean のメソッドを呼び出す
チェック例外の処理
次のコードに使用されるメソッドの 2 つ (InitialContext()
およびlookup()
) は、タイプjavax.naming.NamingException
のチェック済み例外を持っています。これらのメソッド呼び出しはNamingException
をキャッチする try/catch ブロックか、NamingException
のスローが宣言されたメソッドに存在する必要があります。ejb-remote
クイックスタートでは、2 番目の方法を使用します。JNDI コンテキストの作成
JNDI コンテキストオブジェクトはサーバーよりリソースを要求するメカニズムを提供します。次のコードを使用して JNDI コンテキストを作成します。final Hashtable jndiProperties = new Hashtable(); jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming"); final Context context = new InitialContext(jndiProperties);
JNDI サービスの接続プロパティーはjboss-ejb-client.properties
ファイルより読み取られます。JNDI コンテキストの lookup() メソッドを使用した Bean プロキシの取得
Bean プロキシのlookup()
メソッドを呼び出し、必要なセッション Bean の JNDI 名 へ渡します。これにより、呼び出したいメソッドが含まれるリモートビジネスインターフェースのタイプへキャストされなければならないオブジェクトが返されます。final RemoteCalculator statelessRemoteCalculator = (RemoteCalculator) context.lookup( "ejb:/jboss-as-ejb-remote-server-side/CalculatorBean!" + RemoteCalculator.class.getName());
セッション Bean の JNDI 名は特別な構文によって定義されます。呼び出しメソッド
プロキシ Bean オブジェクトを取得したため、リモートビジネスインターフェースに含まれるすべてのメソッドを呼び出しすることができます。int a = 204; int b = 340; System.out.println("Adding " + a + " and " + b + " via the remote stateless calculator deployed on the server"); int sum = statelessRemoteCalculator.add(a, b); System.out.println("Remote calculator returned sum = " + sum);
メソッド呼び出し要求が実行されるサーバー上で、プロキシ Bean がメソッド呼び出し要求をセッション Bean へ渡します。結果はプロキシ Bean へ返され、プロキシ Bean によって結果が呼び出し側へ返されます。プロキシ Bean とリモートセッション Bean 間の通信は呼び出し側に透過的です。
7.5.2. EJB クライアントコンテキストについて
- リモートクライアント。スタンドアロン Java アプリケーションとして実行されます。
- リモートクライアント。別の JBoss Enterprise Application Platform インスタンス内で実行されます。
7.5.3. 単一 EJB コンテキストを使用する場合の留意事項
スタンドアロンリモートクライアントで単一 EJB クライアントコンテキストを使用する場合は、アプリケーション要件を考慮する必要があります。異なるタイプのリモートクライアントの詳細については、「EJB クライアントコンテキストについて」 を参照してください。
一般的に、リモートスタンドアロンクライアントは任意の数の EJB レシーバーにより支援された唯一の EJB クライアントコンテキストを持っています。以下に、スタンドアロンリモートクライアントアプリケーションの例を示します。
public class MyApplication { public static void main(String args[]) { final javax.naming.Context ctxOne = new javax.naming.InitialContext(); final MyBeanInterface beanOne = ctxOne.lookup("ejb:app/module/distinct/bean!interface"); beanOne.doSomething(); ... } }
jboss-ejb-client.properties
ファイルにより支援され、このファイルは EJB クライアントコンテキストと EJB レシーバーをセットアップするために使用されます。また、この設定には、セキュリティークレデンシャルが含まれ、このセキュリティークレデンシャルは JBoss Enterprise Application Platform サーバーに接続する EJB レシーバーを作成するために使用されます。上記のコードが呼び出された場合、EJB クライアント API は EJB クライアントコンテキストを探します。この EJB クライアントコンテキストは EJB 呼び出し要求を受け取り処理する EJB レシーバーを選択するために使用されます。この場合は、EJB クライアントコンテキストが 1 つしかないため、Bean を呼び出すためにそのコンテキストが上記のコードにより使用されます。JNDI をリモートで使用してセッション Bean を呼び出す手順の詳細については、「JNDI を使用したリモートでのセッション Bean の呼び出し」 を参照してください。
ユーザーアプリケーションが Bean を複数回呼び出す場合に、異なるセキュリティークレデンシャルを使用して JBoss Enterprise Application Platform サーバーに接続したいことがあります。以下に、同じ Bean を 2 回呼び出すスタンドアロンリモートクライアントアプリケーションの例を示します。
public class MyApplication { public static void main(String args[]) { // Use the "foo" security credential connect to the server and invoke this bean instance final javax.naming.Context ctxOne = new javax.naming.InitialContext(); final MyBeanInterface beanOne = ctxOne.lookup("ejb:app/module/distinct/bean!interface"); beanOne.doSomething(); ... // Use the "bar" security credential to connect to the server and invoke this bean instance final javax.naming.Context ctxTwo = new javax.naming.InitialContext(); final MyBeanInterface beanTwo = ctxTwo.lookup("ejb:app/module/distinct/bean!interface"); beanTwo.doSomething(); ... } }
スコープ EJB クライアントコンテキストを使用するとこの問題を解決できます。スコープ EJB クライアントコンテキストにより、EJB クライアントコンテキストと、関連する JNDI コンテキスト (一般的に EJB 呼び出しに使用されます) を細かく制御できるようになります。スコープ EJB クライアントコンテキストの詳細については、「スコープ EJB クライアントコンテキストの使用」 と「スコープ EJB クライアントコンテキストを使用した EJB の設定」 を参照してください。
7.5.4. スコープ EJB クライアントコンテキストの使用
JBoss Enterprise Application Platform 6 の初期バージョンで EJB を呼び出すには、通常 JNDI コンテキストを作成し、PROVIDER_URL (ターゲットサーバーを示します) に渡します。JNDI コンテキストを使用してルックアップされた EJB プロキシに対して行われたすべての呼び出しは最終的にそのサーバーに対して行われます。スコープ EJB クライアントコンテキストにより、ユーザーアプリケーションは特定の呼び出しに使用される EJB レシーバーを制御できます。
スコープ EJB クライアントコンテキストが導入される前に、コンテキストは通常クライアントアプリケーションにスコープ指定されていました。スコープクライアントコンテキストにより、EJB クライアントコンテキストを JNDI コンテキストでスコープ指定できるようになりました。以下に、スコープ EJB クライアントコンテキストを使用して同じ Bean を 2 回呼び出すスタンドアロンリモートクライアントアプリケーションの例を示します。
public class MyApplication { public static void main(String args[]) { // Use the "foo" security credential connect to the server and invoke this bean instance final Properties ejbClientContextPropsOne = getPropsForEJBClientContextOne(): final javax.naming.Context ctxOne = new javax.naming.InitialContext(ejbClientContextPropsOne); final MyBeanInterface beanOne = ctxOne.lookup("ejb:app/module/distinct/bean!interface"); beanOne.doSomething(); ... // Use the "bar" security credential to connect to the server and invoke this bean instance final Properties ejbClientContextPropsTwo = getPropsForEJBClientContextTwo(): final javax.naming.Context ctxTwo = new javax.naming.InitialContext(ejbClientContextPropsTwo); final MyBeanInterface beanTwo = ctxTwo.lookup("ejb:app/module/distinct/bean!interface"); beanTwo.doSomething(); ... } }
jboss-ejb-client.properties
ファイルで使用されるのと同じプロパティーセットです。EJB クライアントコンテキストを JNDI コンテキストにスコープ指定するには、org.jboss.ejb.client.scoped.context
プロパティーを指定し、その値を true
に設定する必要があります。このプロパティーは、EJB クライアント API に、EJB クライアントコンテキスト (EJB レシーバーにより支援される) を作成する必要があることと、作成されたコンテキストが作成元の JNDI コンテキストに対してのみスコープ指定されるか、可視状態であることを通知します。この JNDI コンテキストを使用してルックアップされた、または呼び出されたすべての EJB プロキシは、この JNDI コンテキストに関連付けられた EJB クライアントコンテキストのみを認識します。EJB をルックアップし、呼び出すためにアプリケーションにより使用される他の JNDI コンテキストは、他のスコープ EJB クライアントコンテキストについて認識しません。
org.jboss.ejb.client.scoped.context
プロパティーを渡さず、EJB クライアントコンテキストにスコープ指定されない JNDI コンテキストはデフォルトの動作を使用します。デフォルトの動作では、一般的にアプリケーション全体に割り当てられた既存の EJB クライアントコンテキストを使用します。
7.5.5. スコープ EJB クライアントコンテキストを使用した EJB の設定
EJB は、マップベースのスコープコンテキストを使用して設定できます。これは、プログラムで、jboss-ejb-client.properties
にある標準的なプロパティーを使用して Properties
マップに値を入力し、org.jboss.ejb.client.scoped.context
プロパティーに true
を指定して、InitialContext
のプロパティーを渡すことにより実現されます。
手順7.9 マップベースのスコープコンテキストを使用した EJB の設定
プロパティーの設定
EJB クライアントプロパティーをプログラムで設定し、標準的なjboss-ejb-client.properties
ファイルで使用されたのと同じプロパティーセットを指定します。スコープコンテキストを有効にするには、org.jboss.ejb.client.scoped.context
プロパティーを指定し、その値をtrue
に設定する必要があります。以下は、プロパティーをプログラムで設定する例です。// Configure EJB Client properties for the InitialContext Properties ejbClientContextProps = new Properties(); ejbClientContextProps.put(“remote.connections”,”name1”); ejbClientContextProps.put(“remote.connection.name1.host”,”localhost”); ejbClientContextProps.put(“remote.connection.name1.port”,”4447”); // Property to enable scoped EJB client context which will be tied to the JNDI context ejbClientContextProps.put("org.jboss.ejb.client.scoped.context", “true”);
コンテキスト作成でプロパティーを渡す
// Create the context using the configured properties InitialContext ic = new InitialContext(ejbClientContextProps); MySLSB bean = ic.lookup("ejb:myapp/ejb//MySLSBBean!" + MySLSB.class.getName());
- ルックアップ EJB プロキシーにより生成されたコンテキストは、このスコープコンテキストによりバインドされ、重要な接続パラメーターのみを使用します。これにより、さまざまなコンテキストを作成してクライアントアプリケーション内のデータにアクセスしたり、さまざまなログインを使用してサーバーに独立してアクセスしたりできます。
- クライアントでは、スコープ
InitialContext
とスコーププロキシーの両方がスレッドに渡され、各スレッドが該当するコンテキストで動作することが可能になります。また、プロキシーを同時に使用できる複数のスレッドにプロキシーを渡すことができます。 - スコープコンテキスト EJB プロキシーは、リモートコールでシリアライズされ、サーバーでデシリアライズされます。デシリアライズされるとき、スコープコンテキスト情報が削除され、デフォルト状態に戻ります。デシリアライズされたプロキシーがリモートサーバーで使用される場合は、作成時に使用されたスコープコンテキストを持たなくなるため、
EJBCLIENT000025
エラーが発生したり、EJB 名を使用して間違った対象を呼び出したりすることがあります。
7.5.6. EJB クライアントプロパティー
以下の表は、プログラムまたは jboss-ejb-client.properties
ファイルで設定できるプロパティーを示しています。
以下の表は、同じスコープ内のライブラリー全体で有効なプロパティーを示しています。
表7.1 グローバルプロパティー
プロパティー名 | 説明 |
---|---|
endpoint.name |
クライアントエンドポイントの名前。設定されない場合、デフォルト値は
client-endpoint です。
スレッド名にはこのプロパティーが含まれるため、異なるエンドポイント設定を区別するのに役に立つことがあります。
|
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED |
すべての接続に対して SSL プロトコルが有効であるかどうかを指定するブール値。
|
deployment.node.selector | org.jboss.ejb.client.DeploymentNodeSelector の実装の完全修飾名。
これは、EJB の呼び出しを負荷分散するために使用されます。
|
invocation.timeout |
EJB ハンドシェイクまたはメソッド呼び出し要求/応答サイクルのタイムアウト。この値はミリ秒単位です。
実行にタイムアウト時間よりも長い時間がかかった場合は、任意のメソッドの呼び出しで
java.util.concurrent.TimeoutException がスローされます。実行が完了し、サーバーは中断されません。
|
reconnect.tasks.timeout |
バックグラウンド再接続タスクのタイムアウト。この値はミリ秒単位です。
複数の接続がダウンしている場合は、次のクライアント EJB 呼び出しで、適切なノードを見つけるために再接続が必要かどうかを決定するアルゴリズムが使用されます。
|
org.jboss.ejb.client.scoped.context |
スコープ EJB クライアントコンテキストを有効にするかどうかを指定するブール値。デフォルトは、
false です。
true に設定された場合、EJB クライアントは JNDI コンテキストに割り当てられたスコープコンテキストを使用します。その他の場合、EJB クライアントコンテキストは JVM でグローバルセレクターを使用して、リモート EJB およびホストを呼び出すために使用されるプロパティーを決定します。
|
接続プロパティーは、プレフィックス remote.connection.CONNECTION_NAME
で始まります。CONNECTION_NAME は、接続を一意に識別するためにのみ使用されるローカル ID です。
表7.2 接続プロパティー
プロパティー名 | 説明 |
---|---|
remote.connections |
アクティブな
connection-names のカンマ区切りのリスト。各接続はこの名前を使用して設定されます。
|
|
接続のホスト名または IP。
|
|
接続のポート。デフォルト値は 4447 です。
|
|
接続セキュリティーを認証するために使用されるユーザー名。
|
|
ユーザーを認証するために使用されるパスワード
|
|
初期接続のタイムアウト時間。この時間が経過すると、再接続タスクにより、接続を確立できるかどうかが定期的に確認されます。値はミリ秒単位です。
|
| CallbackHandler クラスの完全修飾名。これは、接続を確立するために使用され、接続がオープンである限り変更できません。
|
channel.options.org.jboss.remoting3.RemotingOptions.MAX_OUTBOUND_MESSAGES
|
アウトバウンド要求の最大数を指定する整数値。デフォルト値は 80 です。
すべての呼び出しを処理するために、サーバーに対してクライアント (JVM) からの接続が 1 つだけあります。
|
connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS
|
正常に接続するためにクライアントがクレデンシャルを提供する必要があるかどうかを決定するブール値。デフォルト値は
true です。
true に設定された場合、クライアントはクレデンシャルを提供する必要があります。false に設定された場合は、リモートコネクターがセキュリティーレルムを要求しない限り、呼び出しが許可されます。
|
connect.options.org.xnio.Options.SASL_DISALLOWED_MECHANISMS
|
接続作成中に認証に使用される特定の SASL メカニズムを無効にします。
JBOSS_LOCAL_USER の場合は、サイレント認証メカニズム (クライアントとサーバーが同じマシンにあるときに使用されます) が無効になります。
|
connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT
|
認証中のプレーンテキストメッセージの使用を有効または無効にするブール値。JAAS を使用する場合は、プレーンテキストパスワードを許可するために false に設定する必要があります。
|
connect.options.org.xnio.Options.SSL_ENABLED
|
この接続に対して SSL プロトコルが有効であるかどうかを指定するブール値。
|
connect.options.org.jboss.remoting3.RemotingOptions.HEARTBEAT_INTERVAL
|
自動的なクローズ (ファイアウォールの場合など) を回避するためにクライアントとサーバー間でハートビートを送信する間隔。値はミリ秒単位です。
|
初期接続でクラスター環境に接続する場合は、クラスターのトポロジーが自動的に非同期で受信されます。これらのプロパティーは、受信された各メンバーに接続するために使用されます。各プロパティーは、プレフィックス remote.cluster.CLUSTER_NAME
で始まります。CLUSTER_NAME は、関連するサーバーの Infinispan サブシステム設定を参照します。
表7.3 クラスタープロパティ
プロパティー名 | 説明 |
---|---|
clusternode.selector
| org.jboss.ejb.client.ClusterNodeSelector の実装の完全修飾名。
このクラス (
org.jboss.ejb.clientDeploymentNodeSelector ではない) は、クラスター環境で EJB 呼び出しを負荷分散するために使用されます。クラスターが完全にダウンしている場合、呼び出しは No ejb receiver available で失敗します。
|
channel.options.org.jboss.remoting3.RemotingOptions.MAX_OUTBOUND_MESSAGES
|
クラスター全体に対して実行できるアウトバウンド要求の最大数を指定する整数値。
|
node.NODE_NAME. channel.options.org.jboss.remoting3.RemotingOptions.MAX_OUTBOUND_MESSAGES
|
この特定のクラスターノードに対して実行できるアウトバウンド要求の最大数を指定する整数値。
|
7.6. クラスター化された Enterprise JavaBeans
7.6.1. クラスター化された Enterprise JavaBean (EJB) について
注記
7.7. 参考資料
7.7.1. EJB JNDI の名前に関する参考資料
ejb:<appName>/<moduleName>/<distinctName>/<beanName>!<viewClassName>?stateful
<appName>
- セッション Bean の JAR ファイルがエンタープライズアーカイブ (EAR) 内にデプロイされた場合、EAR の名前になります。デフォルトでは、ファイル名から
.ear
サフィックスを除いたものが EAR の名前になります。また、アプリケーション名をapplication.xml
ファイルで上書きすることも可能です。セッション Bean が EAR にデプロイされていない場合は空白のままにしておきます。 <moduleName>
- モジュール名はセッション Bean がデプロイされた JAR ファイルの名前になります。デフォルトでは、ファイル名から
.jar
サフィックスを除いたものが JAR ファイルの名前になります。また、モジュール名を JAR のejb-jar.xml
ファイルで上書きすることも可能です。 <distinctName>
- JBoss Enterprise Application Platform 6 では、各デプロイメントが任意の個別名を指定することができます。デプロイメントの個別名がない場合は空白のままにしておきます。
<beanName>
- Bean 名は呼び出されるセッション Bean のクラス名です。
<viewClassName>
- ビュークラス名はリモートインターフェースの完全修飾クラス名です。インターフェースのパッケージ名が含まれます。
?stateful
- JNDI 名がステートフルセッション Bean を参照する時に
?stateful
サフィックスが必要となります。他の Bean タイプでは含まれていません。
7.7.2. EJB 参照の解決
@EJB
や @Resource
を実装する方法について説明します。XML は常にアノテーションを上書きしますが、同じルールが適用されることに注意してください。
@EJB アノテーションのルール
@EJB
アノテーションはmappedName()
属性を持っています。仕様はこのベンダー固有のメタデータを無視しますが、 JBoss は参照しているEJBのグローバル JNDI 名としてmappedName()
を認識します。mappedName()
を指定した場合、他の属性はすべて無視され、このグローバル JNDI 名がバインディングに使用されます。- 以下のように属性を定義せずに
@EJB
を指定するとします。@EJB ProcessPayment myEjbref;
この場合、次のルールが適用されます。- 参照する Bean の EJB jar が、
@EJB
挿入に使用されるインターフェースを持つ EJB に対して検索されます。同じビジネスインターフェースをパブリッシュする EJB が複数ある場合、例外がスローされます。インターフェースを持つ Bean が 1 つのみである場合はその Bean が使用されます。 - そのインターフェースをパブリッシュする EJB に対する EAR を検索します。複製がある場合は例外がスローされます。それ以外の場合は、一致する Bean が返されます。
- JBoss ランタイムでそのインターフェースの EJB に対してグローバルに検索が行われます。ここでも複製があると例外がスローされます。
@EJB.beanName()
は<ejb-link>
に対応します。beanName()
が定義されている場合、属性が定義されていない@EJB
として同じアルゴリズムが使用されますが、検索でbeanName()
がキーとして使用されます。ejb-link の # 構文を使用する場合、このルールの例外となります。# 構文は、参照する EJB が存在する EAR の jar への相対パスを指定できるようにします。詳細については EJB 3.1 仕様を参照してください。
7.7.3. リモート EJB クライアントのプロジェクト依存関係
表7.4 リモート EJB クライアントに対する Maven の依存関係
GroupID | ArtifactID |
---|---|
org.jboss.spec | jboss-javaee-6.0 |
org.jboss.as | jboss-as-ejb-client-bom |
org.jboss.spec.javax.transaction | jboss-transaction-api_1.1_spec |
org.jboss.spec.javax.ejb | jboss-ejb-api_3.1_spec |
org.jboss | jboss-ejb-client |
org.jboss.xnio | xnio-api |
org.jboss.xnio | xnio-nio |
org.jboss.remoting3 | jboss-remoting |
org.jboss.sasl | jboss-sasl |
org.jboss.marshalling | jboss-marshalling-river |
jboss-javaee-6.0
と jboss-as-ejb-client-bom
を除き、これらの依存関係を pom.xml
ファイルの <dependencies>
セクションに追加する必要があります。
jboss-javaee-6.0
と jboss-as-ejb-client-bom
の依存関係は、スコープが import
の pom.xml
の <dependencyManagement>
セクションに追加する必要があります。
注記
artifactID
のバージョンは変更される可能性があります。該当バージョンについては、Maven リポジトリーを参照してください。
<dependencyManagement> <dependencies> <dependency> <groupId>org.jboss.spec</groupId> <artifactId>jboss-javaee-6.0</artifactId> <version>3.0.0.Final-redhat-1</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.jboss.as</groupId> <artifactId>jboss-as-ejb-client-bom</artifactId> <version>7.1.1.Final-redhat-1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
remote-ejb/client/pom.xml
を参照してください。
7.7.4. jboss-ejb3.xml デプロイメント記述子に関する参考文書
jboss-ejb3.xml
は EJB JAR または WAR アーカイブで使用できるカスタムのデプロイメント記述子です。EJB JAR アーカイブでは META-INF/
ディレクトリ、WAR アーカイブでは WEB-INF/
ディレクトリにある必要があります。
ejb-jar.xml
に似ていて、同じ名前空間を一部使用し、他の名前空間を一部提供します。jboss-ejb3.xml
の内容は ejb-jar.xml
の内容と結合されますが、jboss-ejb3.xml
の項目の方が優先されます。
jboss-ejb3.xml
によって使用される非標準の名前空間のみ取り上げます。標準的な名前空間については http://java.sun.com/xml/ns/javaee/ のドキュメントを参照してください。
http://www.jboss.com/xml/ns/javaee
です。
アセンブリ記述子の名前空間
<assembly-descriptor>
要素で使用されます。これらの名前空間の設定を 1 つの Bean に適用したり、 \*
を ejb-name
として使用してデプロイメントのすべての Bean に対して適用するために使用されます。
- クラスタリング名前空間:
urn:clustering:1.0
xmlns:c="urn:clustering:1.0"
これにより、EJB がクラスター化されているとマーク付けすることができます。これは@org.jboss.ejb3.annotation.Clustered
に相当するデプロイメント記述子です。<c:clustering> <ejb-name>DDBasedClusteredSFSB</ejb-name> <c:clustered>true</c:clustered> </c:clustering>
- セキュリティー名前空間 (
urn:security
) xmlns:s="urn:security"
これにより、EJB のセキュリティードメインと run-as プリンシパルを設定できます。<s:security> <ejb-name>*</ejb-name> <s:security-domain>myDomain</s:security-domain> <s:run-as-principal>myPrincipal</s:run-as-principal> </s:security>
- リソースアダプター名前空間:
urn:resource-adapter-binding
xmlns:r="urn:resource-adapter-binding"
これにより、メッセージ駆動 Bean にリソースアダプターを設定できます。<r:resource-adapter-binding> <ejb-name>*</ejb-name> <r:resource-adapter-name>myResourceAdaptor</r:resource-adapter-name> </r:resource-adapter-binding>
- IIOP 名前空間:
urn:iiop
xmlns:u="urn:iiop"
IIOP 名前空間には IIOP が設定されます。- プール名前空間:
urn:ejb-pool:1.0
xmlns:p="urn:ejb-pool:1.0"
これにより、含まれるステートレスセッション Bean やメッセージ駆動 Bean によって使用されるプールを選択できます。プールはサーバー設定で定義されます。<p:pool> <ejb-name>*</ejb-name> <p:bean-instance-pool-ref>my-pool</p:bean-instance-pool-ref> </p:pool>
- キャッシュ名前空間:
urn:ejb-cache:1.0
xmlns:c="urn:ejb-cache:1.0"
これにより、含まれるステートフルセッション Bean によって使用されるキャッシュを選択できます。キャッシュはサーバー設定で定義されます。<c:cache> <ejb-name>*</ejb-name> <c:cache-ref>my-cache</c:cache-ref> </c:cache>
例7.1 jboss-ejb3.xml ファイルの例
<?xml version="1.1" encoding="UTF-8"?> <jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="urn:clustering:1.0" xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd" version="3.1" impl-version="2.0"> <enterprise-beans> <message-driven> <ejb-name>ReplyingMDB</ejb-name> <ejb-class>org.jboss.as.test.integration.ejb.mdb.messagedestination.ReplyingMDB</ejb-class> <activation-config> <activation-config-property> <activation-config-property-name>destination</activation-config-property-name> <activation-config-property-value>java:jboss/mdbtest/messageDestinationQueue </activation-config-property-value> </activation-config-property> </activation-config> </message-driven> </enterprise-beans> <assembly-descriptor> <c:clustering> <ejb-name>DDBasedClusteredSFSB</ejb-name> <c:clustered>true</c:clustered> </c:clustering> </assembly-descriptor> </jboss:ejb-jar>
第8章 Web アプリケーションのクラスター化
8.1. セッションレプリケーション
8.1.1. HTTP セッションレプリケーションについて
8.1.2. Web セッションキャッシュについて
standalone-ha.xml
プロファイルを含むいずれかの HA プロファイル、管理対象ドメインプロファイル ha
または full-ha
を使用するときに設定できます。最も一般的に設定される要素は、キャッシュモードと分散キャッシュのキャッシュオーナーの数です。
キャッシュモードは、REPL
(デフォルト値) または DIST
のいずれかになります。
- REPL
REPL
モードでは、クラスターの他のノードそれぞれにキャッシュ全体がレプリケートされます。これは、最も安全なオプションですが、オーバーヘッドが増加します。- DIST
DIST
モードは、以前の実装で提供されたバディモードに似ています。このモードでは、owners
パラメーターで指定された数のノードにキャッシュを分散することによりオーバーヘッドが削減されます。オーナーのこの数のデフォルト値は2
です。
owners
パラメーターは、セッションのレプリケートされたコピーを保持するクラスターノード数を制御します。デフォルト値は、2
です。
8.1.3. Web セッションキャッシュの設定
REPL
です。DIST
モードを使用する場合は、管理 CLI で次の 2 つのコマンドを実行します。異なるプロファイルを使用する場合は、コマンドでプロファイル名を変更します。スタンドアロンサーバーを使用する場合は、コマンドの /profile=ha
部分を削除します。
手順8.1 Web セッションキャッシュの設定
デフォルトキャッシュモードを
DIST
に変更します。/profile=ha/subsystem=infinispan/cache-container=web/:write-attribute(name=default-cache,value=dist)
分散キャッシュのオーナー数を設定します。
以下のコマンドでは、5
オーナーが設定されます。デフォルト値は2
です。/profile=ha/subsystem=infinispan/cache-container=web/distributed-cache=dist/:write-attribute(name=owners,value=5)
デフォルトキャッシュモードを
REPL
に戻します。/profile=ha/subsystem=infinispan/cache-container=web/:write-attribute(name=default-cache,value=repl)
サーバーの再起動
Web キャッシュモードの変更後は、サーバーを再起動する必要があります。
サーバーでセッションレプリケーションが設定されます。独自のアプリケーションでセッションレプリケーションを使用するには、「アプリケーションにおけるセッションレプリケーションの有効化」を参照してください。
8.1.4. アプリケーションにおけるセッションレプリケーションの有効化
JBoss Enterprise Application Platform の高可用性 (HA) 機能を利用するには、アプリケーションが配布可能になるよう設定する必要があります。ここでは配布可能にする手順を説明した後、使用可能な高度な設定オプションの一部について解説します。
手順8.2 アプリケーションを配布可能にする
要件: アプリケーションが配布可能であることを示します。
アプリケーションが配布可能とマークされていないとセッションが配布されません。アプリケーションのweb.xml
記述子ファイルの<web-app>
タグ内に<distributable />
要素を追加します。例は次の通りです。例8.1 配布可能なアプリケーションの最低限の設定
<?xml version="1.0"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <distributable/> </web-app>
希望する場合はデフォルトのレプリケーション動作を変更します。
セッションレプリケーションに影響する値を変更したい場合は、<jboss-web>
要素の子要素である<replication-config>
要素内で値を上書きします。デフォルトを上書きしたい場合のみ指定の要素が含まれるようにします。以下の例に、全デフォルト設定の一覧と、最も一般的に変更されるオプションを説明する表を示します。例8.2 デフォルトの
<replication-config>
値<!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 5.0//EN" "http://www.jboss.org/j2ee/dtd/jboss-web_5_0.dtd"> <jboss-web> <replication-config> <cache-name>custom-session-cache</cache-name> <replication-trigger>SET</replication-trigger> <replication-granularity>ATTRIBUTE</replication-granularity> <use-jk>false</use-jk> <max-unreplicated-interval>30</max-unreplicated-interval> <snapshot-mode>INSTANT</snapshot-mode> <snapshot-interval>1000</snapshot-interval> <session-notification-policy>com.example.CustomSessionNotificationPolicy</session-notification-policy> </replication-config> </jboss-web>
表8.1 セッションレプリケーションの一般的なオプション
オプション
|
説明
|
---|---|
<replication-trigger>
|
クラスター全体でセッションデータのレプリケーションが引き起こされるのはどのような状態であるか制御します。セッション属性として保存された可変オブジェクトがセッションからアクセスされた後、メソッド
setAttribute() が直接呼び出されない限り、オブジェクトが変更されレプリケーションが必要であるかをコンテナは明確に認識できないため、このオプションは必須となります。
設定に関係なく、
setAttribute() を呼び出すと常にセッションレプリケーションが引き起こされます。
|
<replication-granularity>
|
レプリケートされるデータの細かさを決定します。デフォルトは
SESSION ですが、ATTRIBUTE を設定すると、ほとんどの属性は変更されずにセッションのパフォーマンスを向上することができます。
|
表8.2 セッションレプリケーションの変更が稀なオプション
オプション
|
説明
|
---|---|
<useJK>
| mod_cluster 、mod_jk 、mod_proxy などのロードバランサーの使用を前提とするか指定します。デフォルトは false です。 true に設定すると、各要求に関連付けられているセッション ID がコンテナによって確認され、フェイルオーバーが発生するとセッション ID の jvmRoute の部分が置き換えられます。
|
<max-unreplicated-interval>
|
セッションのタイムスタンプのレプリケーションがトリガーされるまで、セッション後に待機する最大間隔 (秒単位) になります。変更がないと判断された場合でも適用されます。これにより、各セッションのタイムスタンプがクラスターノードによって認識されるようにし、フェイルオーバー中にレプリケートされなかったセッションが誤って期限切れにならないようにします。また、フェイルオーバー中に
HttpSession.getLastAccessedTime() への呼び出しに正しい値を使用できるようにします。
デフォルトでは値は指定されません。値が指定されないと、コンテナの
jvmRoute 設定が JK フェイルオーバーが使用されているかを判断します。 0 を設定すると、セッションがアクセスされるたびにタイムスタンプがレプリケートされます。-1 を設定すると、要求中の他のアクティビティがレプリケーションをトリガーした場合のみタイムスタンプがレプリケートされます。 HttpSession.getMaxInactiveInterval() よりも大きい正の値を設定すると設定ミスとして扱われ、0 に変換されます。
|
<snapshot-mode>
|
セッションが他のノードへレプリケートされるタイミングを指定します。デフォルトは
INSTANT で、INTERVAL を使用することも可能です。
INSTANT モードでは要求処理スレッドが使用され、変更は要求の最後にレプリケートされます。<snapshot-interval> オプションは無視されます。
INTERVAL モードでは、バックグラウンドタスクは <snapshot-interval> によって指定される間隔で実行され、変更されたセッションがレプリケートされます。
|
<snapshot-interval>
| INTERVAL が <snapshot-mode> の値として使用された時に、変更されたセッションがレプリケートされる間隔 (ミリ秒単位) になります。
|
<session-notification-policy>
|
インターフェース
ClusteredSessionNotificationPolicy の実装の完全修飾クラス名です。登録された HttpSessionListener 、HttpSessionAttributeListener 、 HttpSessionBindingListener へサーブレット仕様の通知が送信されたかどうかを管理します。
|
8.2. HttpSession の非活性化および活性化
8.2.1. HTTP セッションパッシベーションおよびアクティベーション
- コンテナが新規セッションの作成を要求する時に現在アクティブなセッションの数が設定上限を越えている場合、サーバーはセッションの一部をパッシベートして新規セッションを作成できるようにします。
- 設定された間隔で、定期的にバックグラウンドタスクがセッションをパッシベートすべきかチェックします。
- ある Web アプリケーションがデプロイされ、他のサーバーでアクティブなセッションのバックアップコピーが、新たにデプロイする Web アプリケーションのセッションマネージャーによって取得された場合、セッションはパッシベートされることがあります。
- セッションが設定した最大アイドル時間の間利用されていない。
- アクティブなセッションの数が設定上限を越えず、セッションがアイドル時間の設定下限を超えていない。
8.2.2. アプリケーションにおける HttpSession パッシベーションの設定
HttpSession パッシベーションはアプリケーションの WEB_INF/jboss-web.xml
ファイルまたは META_INF/jboss-web.xml
ファイルで設定されます。
例8.3 jboss-web.xml
ファイルの例
<!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 5.0//EN" "http://www.jboss.org/j2ee/dtd/jboss-web_5_0.dtd"> <jboss-web version="6.0" xmlns="http://www.jboss.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-web_6_0.xsd"> <max-active-sessions>20</max-active-sessions> <passivation-config> <use-session-passivation>true</use-session-passivation> <passivation-min-idle-time>60</passivation-min-idle-time> <passivation-max-idle-time>600</passivation-max-idle-time> </passivation-config> </jboss-web>
パッシベーション設定要素
<max-active-sessions>
- 許可されるアクティブセッションの最大数です。パッシベーションが有効になっている場合、セッションマネージャーによって管理されるセッション数がこの値を越えると、設定された
<passivation-min-idle-time>
を基に過剰なセッションがパッシベートされます。それでもアクティブセッションの数が制限を越える場合は、新しいセッションの作成に失敗します。デフォルト値は-1
で、アクティブセッションの最大数は制限されません。 <passivation-config>
- この要素は、子要素などの残りのパッシベーション設定パラメーターを保持します。
<passivation-config>
子要素
<use-session-passivation>
- セッションパッシベーションを使用するかどうか。デフォルト値は
false
です。 <passivation-min-idle-time>
- アクティブなセッションの数を減らし max-active-sessions によって定義された値に従うため、コンテナがパッシベーションの実行を考慮する前にセッションが非アクティブでなければならない最小期間。デフォルト値は
-1
で、<passivation-max-idle-time>
が経過する前のセッションのパッシベートを無効にします。<max-active-sessions>
が設定されている場合、-1 や大きな値は推奨されません。 <passivation-max-idle-time>
- メモリーを節約するため、コンテナがパッシベーションを実行しようとする前にセッションが非アクティブにならなければならない最大期間。アクティブセッションの数が
<max-active-sessions>
を越えるかどうかに関係なく、このようなセッションのパッシベーションは実行されます。この値はweb.xml
の<session-timeout>
設定よりも小さい値とする必要があります。デフォルト値は-1
で、非アクティブとなる最大期間を基にしたパッシベーションを無効にします。
注記
<max-active-sessions>
を設定してください。また、他のノードからレプリケートされるセッションの数は、REPL
または DIST
キャッシュモードが有効であるかどうかによっても異なります。REPL
キャッシュモードでは、各セッションは各ノードにレプリケートされます。DIST
キャッシュモードでは、各セッションは、owner
パラメーターによって指定された数のノードにのみレプリケートされます。セッションキャッシュモードの設定については、「Web セッションキャッシュについて」および「Web セッションキャッシュの設定」を参照してください。
REPL
キャッシュモードでは、各ノードはメモリーに 800 のセッションを保存します。DIST
キャッシュモードが有効であり、デフォルトの owners
設定が 2
である場合、各ノードはメモリーに 200 のセッションを保存します。
8.3. クッキードメイン
8.3.1. クッキードメインについて
/
です。これは、発行ホストのみがクッキーの内容を読み取ることができます。特定のクッキードメインを設定すると、さまざまなホストがクッキーの内容を読み取ることができるようになります。クッキードメインの設定は 「クッキードメインの設定」 を参照してください。
8.3.2. クッキードメインの設定
http://app1.xyz.com
および http://app2.xyz.com
上のアプリケーションが SSO コンテキストを共有できるようにします。
例8.4 クッキードメインの設定例
<Valve className="org.jboss.web.tomcat.service.sso.ClusteredSingleSignOn" cookieDomain="xyz.com" />
8.4. HA シングルトンの実装
JBoss Enterprise Application Platform 5 では、HA シングルトンアーカイブは他のデプロイメントとは別に deploy-hasingleton/
ディレクトリーにデプロイされていました。これは自動デプロイメントが発生しないようにするためで、また確実に HASingletonDeployer サービスがデプロイメントを制御し、クラスターのマスターノードのみにアーカイブがデプロイされるようにするための処置でした。ホットデプロイメント機能がなかったため、再デプロイメントにはサーバーの再起動が必要でした。また、マスターノードに障害が発生し、他のノードがマスターとして引き継ぐ必要がある場合、シングルトンサービスはサービスを提供するためデプロイメントプロセス全体を実行する必要がありました。
手順8.3 HA シングルトンサービスの実装
HA シングルトンサービスアプリケーションを作成します。
シングルトンサービスとしてデプロイされる SingletonService デコレーターでラッピングされたサービスの簡単な例は次のとおりです。シングルトンサービスを作成します。
以下のリストは、シングルトンサービスの例です。package com.mycompany.hasingleton.service.ejb; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Logger; import org.jboss.as.server.ServerEnvironment; import org.jboss.msc.inject.Injector; import org.jboss.msc.service.Service; import org.jboss.msc.service.ServiceName; import org.jboss.msc.service.StartContext; import org.jboss.msc.service.StartException; import org.jboss.msc.service.StopContext; import org.jboss.msc.value.InjectedValue; /** * @author <a href="mailto:wfink@redhat.com">Wolf-Dieter Fink</a> */ public class EnvironmentService implements Service<String> { private static final Logger LOGGER = Logger.getLogger(EnvironmentService.class.getCanonicalName()); public static final ServiceName SINGLETON_SERVICE_NAME = ServiceName.JBOSS.append("quickstart", "ha", "singleton"); /** * A flag whether the service is started. */ private final AtomicBoolean started = new AtomicBoolean(false); private String nodeName; private final InjectedValue<ServerEnvironment> env = new InjectedValue<ServerEnvironment>(); public Injector<ServerEnvironment> getEnvInjector() { return this.env; } /** * @return the name of the server node */ public String getValue() throws IllegalStateException, IllegalArgumentException { if (!started.get()) { throw new IllegalStateException("The service '" + this.getClass().getName() + "' is not ready!"); } return this.nodeName; } public void start(StartContext arg0) throws StartException { if (!started.compareAndSet(false, true)) { throw new StartException("The service is still started!"); } LOGGER.info("Start service '" + this.getClass().getName() + "'"); this.nodeName = this.env.getValue().getNodeName(); } public void stop(StopContext arg0) { if (!started.compareAndSet(true, false)) { LOGGER.warning("The service '" + this.getClass().getName() + "' is not active!"); } else { LOGGER.info("Stop service '" + this.getClass().getName() + "'"); } } }
サーバー起動時にサービスを SingletonService として起動するためにシングルトン EJB を作成します。
以下のリストは、サーバー起動時に SingletonService を起動するシングルトン EJB の例です。package com.mycompany.hasingleton.service.ejb; import java.util.Collection; import java.util.EnumSet; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.ejb.Singleton; import javax.ejb.Startup; import org.jboss.as.clustering.singleton.SingletonService; import org.jboss.as.server.CurrentServiceContainer; import org.jboss.as.server.ServerEnvironment; import org.jboss.as.server.ServerEnvironmentService; import org.jboss.msc.service.AbstractServiceListener; import org.jboss.msc.service.ServiceController; import org.jboss.msc.service.ServiceController.Transition; import org.jboss.msc.service.ServiceListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A Singleton EJB to create the SingletonService during startup. * * @author <a href="mailto:wfink@redhat.com">Wolf-Dieter Fink</a> */ @Singleton @Startup public class StartupSingleton { private static final Logger LOGGER = LoggerFactory.getLogger(StartupSingleton.class); /** * Create the Service and wait until it is started.<br/> * Will log a message if the service will not start in 10sec. */ @PostConstruct protected void startup() { LOGGER.info("StartupSingleton will be initialized!"); EnvironmentService service = new EnvironmentService(); SingletonService<String> singleton = new SingletonService<String>(service, EnvironmentService.SINGLETON_SERVICE_NAME); // if there is a node where the Singleton should deployed the election policy might set, // otherwise the JGroups coordinator will start it //singleton.setElectionPolicy(new PreferredSingletonElectionPolicy(new NamePreference("node2/cluster"), new SimpleSingletonElectionPolicy())); ServiceController<String> controller = singleton.build(CurrentServiceContainer.getServiceContainer()) .addDependency(ServerEnvironmentService.SERVICE_NAME, ServerEnvironment.class, service.getEnvInjector()) .install(); controller.setMode(ServiceController.Mode.ACTIVE); try { wait(controller, EnumSet.of(ServiceController.State.DOWN, ServiceController.State.STARTING), ServiceController.State.UP); LOGGER.info("StartupSingleton has started the Service"); } catch (IllegalStateException e) { LOGGER.warn("Singleton Service {} not started, are you sure to start in a cluster (HA) environment?",EnvironmentService.SINGLETON_SERVICE_NAME); } } /** * Remove the service during undeploy or shutdown */ @PreDestroy protected void destroy() { LOGGER.info("StartupSingleton will be removed!"); ServiceController<?> controller = CurrentServiceContainer.getServiceContainer().getRequiredService(EnvironmentService.SINGLETON_SERVICE_NAME); controller.setMode(ServiceController.Mode.REMOVE); try { wait(controller, EnumSet.of(ServiceController.State.UP, ServiceController.State.STOPPING, ServiceController.State.DOWN), ServiceController.State.REMOVED); } catch (IllegalStateException e) { LOGGER.warn("Singleton Service {} has not be stopped correctly!",EnvironmentService.SINGLETON_SERVICE_NAME); } } private static <T> void wait(ServiceController<T> controller, Collection<ServiceController.State> expectedStates, ServiceController.State targetState) { if (controller.getState() != targetState) { ServiceListener<T> listener = new NotifyingServiceListener<T>(); controller.addListener(listener); try { synchronized (controller) { int maxRetry = 2; while (expectedStates.contains(controller.getState()) && maxRetry > 0) { LOGGER.info("Service controller state is {}, waiting for transition to {}", new Object[] {controller.getState(), targetState}); controller.wait(5000); maxRetry--; } } } catch (InterruptedException e) { LOGGER.warn("Wait on startup is interrupted!"); Thread.currentThread().interrupt(); } controller.removeListener(listener); ServiceController.State state = controller.getState(); LOGGER.info("Service controller state is now {}",state); if (state != targetState) { throw new IllegalStateException(String.format("Failed to wait for state to transition to %s. Current state is %s", targetState, state), controller.getStartException()); } } } private static class NotifyingServiceListener<T> extends AbstractServiceListener<T> { @Override public void transition(ServiceController<? extends T> controller, Transition transition) { synchronized (controller) { controller.notify(); } } } }
クライアントよりサービスへアクセスするためステートレスセッション Bean を作成します。
以下は、クライアントからサービスにアクセスするステートレスセッション Bean の例です。package com.mycompany.hasingleton.service.ejb; import javax.ejb.Stateless; import org.jboss.as.server.CurrentServiceContainer; import org.jboss.msc.service.ServiceController; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A simple SLSB to access the internal SingletonService. * * @author <a href="mailto:wfink@redhat.com">Wolf-Dieter Fink</a> */ @Stateless public class ServiceAccessBean implements ServiceAccess { private static final Logger LOGGER = LoggerFactory.getLogger(ServiceAccessBean.class); public String getNodeNameOfService() { LOGGER.info("getNodeNameOfService() is called()"); ServiceController<?> service = CurrentServiceContainer.getServiceContainer().getService( EnvironmentService.SINGLETON_SERVICE_NAME); LOGGER.debug("SERVICE {}", service); if (service != null) { return (String) service.getValue(); } else { throw new IllegalStateException("Service '" + EnvironmentService.SINGLETON_SERVICE_NAME + "' not found!"); } } }
SingletonService のビジネスロジックインターフェースを作成します。
以下は、SingletonService に対するビジネスロジックインターフェースの例です。package com.mycompany.hasingleton.service.ejb; import javax.ejb.Remote; /** * Business interface to access the SingletonService via this EJB * * @author <a href="mailto:wfink@redhat.com">Wolf-Dieter Fink</a> */ @Remote public interface ServiceAccess { public abstract String getNodeNameOfService(); }
クラスタリングが有効な状態で各 Jboss Enterprise Application Platform 6 インスタンスを起動します。
クラスターを有効化する方法は、サーバーがスタンドアロンであるか管理ドメインで実行されているかによって異なります。管理対象ドメインで実行されているサーバーに対してクラスタリングを有効にします。
管理 CLI を使用してクラスタリングを有効にするか、設定ファイルを手動で編集できます。管理 CLI を使用してクラスタリングを有効にします。
ドメインコントローラーを起動します。
使用しているオペレーティングシステムのコマンドプロンプトを開きます。
ドメインコントローラーの IP アドレスまたは DNS 名を渡して管理 CLI に接続します。
この例では、ドメインコントローラーの IP アドレスが192.168.0.14
であることを前提とします。- Linux の場合は、コマンドラインで以下を入力します。
$ EAP_HOME/bin/jboss-cli.sh --connect --controller=192.168.0.14 $ Connected to domain controller at 192.168.0.14
- Windows の場合は、コマンドラインで以下を入力します。
C:\>EAP_HOME\bin\jboss-cli.bat --connect --controller=192.168.0.14 C:\> Connected to domain controller at 192.168.0.14
main-server
サーバーグループを追加します。[domain@192.168.0.14:9999 /] /server-group=main-server-group:add(profile="ha",socket-binding-group="ha-sockets") { "outcome" => "success", "result" => undefined, "server-groups" => undefined }
server-one
という名前のサーバーを作成し、main-server
サーバーグループに追加します。[domain@192.168.0.14:9999 /] /host=station14Host2/server-config=server-one:add(group=main-server-group,auto-start=false) { "outcome" => "success", "result" => undefined }
main-server
サーバーグループに対して JVM を設定します。[domain@192.168.0.14:9999 /] /server-group=main-server-group/jvm=default:add(heap-size=64m,max-heap-size=512m) { "outcome" => "success", "result" => undefined, "server-groups" => undefined }
server-two
という名前のサーバーを作成し、別のサーバーグループに置き、ポートオフセットを 100 に設定します。[domain@192.168.0.14:9999 /] /host=station14Host2/server-config=server-two:add(group=distinct2,socket-binding-port-offset=100) { "outcome" => "success", "result" => undefined }
サーバー設定ファイルを手動で編集してクラスタリングを有効にします。
JBoss Enterprise Application Platform サーバーを停止します。
重要
変更がサーバーの再起動後にも維持されるようにするには、サーバー設定ファイルの編集前にサーバーを停止する必要があります。domain.xml
設定ファイルを開いて編集します。ha
プロファイルとha-sockets
ソケットバインディンググループを使用するサーバーグループを指定します。例は次のとおりです。<server-groups> <server-group name="main-server-group" profile="ha"> <jvm name="default"> <heap size="64m" max-size="512m"/> </jvm> <socket-binding-group ref="ha-sockets"/> </server-group> </server-groups>
host.xml
設定ファイルを開いて編集します。以下のようにファイルを変更します。<servers> <server name="server-one" group="main-server-group" auto-start="false"/> <server name="server-two" group="distinct2"> <socket-bindings port-offset="100"/> </server> <servers>
サーバーを起動します。
- Linux の場合は、
EAP_HOME/bin/domain.sh
と入力します。 - Microsoft Windows の場合は、
EAP_HOME\bin\domain.bat
と入力します。
スタンドアロンサーバーに対してクラスタリングを有効にします。
スタンドアロンサーバーに対してクラスタリングを有効にするには、次のようにノード名とstandalone-ha.xml
設定ファイルを使用してサーバーを起動します。- Linux の場合は、
EAP_HOME/bin/standalone.sh --server-config=standalone-ha.xml -Djboss.node.name=UNIQUE_NODE_NAME
と入力します。 - Microsoft Windows の場合は、
EAP_HOME\bin\standalone.bat --server-config=standalone-ha.xml -Djboss.node.name=UNIQUE_NODE_NAME
と入力します。
注記
1 つのマシン上で複数のサーバーが実行されている時にポートの競合が発生しないようにするため、別のインターフェースでバインドするように各サーバーインスタンスに対してstandalone-ha.xml
ファイルを設定します。または、コマンドラインで-Djboss.socket.binding.port-offset=100
のような引数を使用し、ポートオフセットを持つ後続のサーバーインスタンスを開始して対応することも可能です 。アプリケーションをサーバーにデプロイします。
Maven を使用してアプリケーションをデプロイする場合は、次の Maven コマンドを使用してデフォルトのポートで稼働しているサーバーへデプロイします。mvn clean install jboss-as:deploy
追加のサーバーをデプロイするには、サーバー名とポート番号をコマンドラインに渡します。mvn clean package jboss-as:deploy -Ddeploy.hostname=localhost -Ddeploy.port=10099
第9章 CDI
9.1. CDI の概要
9.1.1. CDI の概要
9.1.2. Contexts and Dependency Injection (CDI) について
9.1.3. CDI の利点
- CDI を使用すると、多くのコードをアノテーションに置き換えることにより、コードベースが単純化および削減されます。
- CDI は柔軟であり、CDI を使用すると、挿入およびイベントを無効または有効にしたり、代替の Bean を使用したり、非 CDI オブジェクトを簡単に挿入したりできます。
- CDI で古いコードを使用することは簡単です。これを行うには
beans.xml
をMETA-INF/
またはWEB-INF/
ディレクトリーに配置します。このファイルは空白である場合があります。 - CDI を使用すると、パッケージ化とデプロイメントが簡略化され、デプロイメントに追加する必要がある XML の量が減少します。
- CDI により、コンテキストを使用したライフサイクル管理が提供されます。挿入を要求、セッション、会話、またはカスタムコンテキストに割り当てることができます。
- また、CDI により、文字列ベースの挿入よりも安全かつ簡単にデバッグを行える、タイプセーフな依存関係挿入が提供されます。
- CDI はインターセプターと Bean を切り離します。
- CDI では、複雑なイベント通知も提供されます。
9.1.4. タイプセーフ依存関係挿入について
9.1.5. Weld、Seam 2、 および JavaServer Faces 間の関係
9.2. CDI の使用
9.2.1. 最初の手順
9.2.1.1. CDI の有効化
Contexts and Dependency Injection (CDI) は、JBoss Enterprise Application Platform の中核的なテクノロジーの 1 つであり、デフォルトで有効になります。何らかの理由で無効になっている場合は、以下の手順に従って有効にする必要があります。
手順9.1 JBoss Enterprise Application Platform での CDI の有効化
設定ファイルで、CDI サブシステムの詳細がコメントアウトされているかどうかを確認します。
サブシステムは、domain.xml
またはstandalone.xml
設定ファイルの該当するセクションをコメントアウトするか、該当するセクション全体を削除することにより、無効にできます。EAP_HOME/domain/configuration/domain.xml
またはEAP_HOME/standalone/configuration/standalone.xml
で CDI サブシステムを検索するには、これらのファイルで文字列<extension module="org.jboss.as.weld"/>
を検索します。検索候補が存在する場合、検索候補は <extensions> セクション内部に存在します。ファイルを編集する前に、JBoss Enterprise Application Platform を停止します。
JBoss Enterprise Application Platform により実行中に設定ファイルが変更されるため、設定ファイルを直接編集する前にサーバーを停止する必要があります。CDI サブシステムを復元するよう設定ファイルを編集します。
CDI サブシステムがコメントアウトされている場合は、コメントを削除します。CDI サブシステムが完全に削除されたら、次の行を、</extensions> タグのすぐ上にある新しい行に追加することにより、CDI サブシステムを復元します。<extension module="org.jboss.as.weld"/>
JBoss Enterprise Application Platform を再起動します。
更新された設定で JBoss Enterprise Application Platform を起動します。
JBoss Enterprise Application Platform は、CDI サブシステムが有効になった状態で起動します。
9.2.2. CDI を使用したアプリケーションの開発
9.2.2.1. CDI を使用したアプリケーションの開発
Contexts and Dependency Injection (CDI) を使用すると、アプリケーションの開発、コードの再利用、デプロイメント時または実行時のコードの調整、およびユニットテストを非常に柔軟に実行できます。JBoss Enterprise Application Platform には、CDI の参照実装である Weld が含まれます。これらのタスクは、エンタープライズアプリケーションで CDI を使用する方法を示しています。
9.2.2.2. 既存のコードでの CDI の使用
META-INF/
または WEB-INF/
ディレクトリーにある beans.xml
という名前のファイルです。このファイルは空白の場合があります。
手順9.2 CDI アプリケーションでのレガシー Bean の使用
Bean をアーカイブにパッケージ化します。
Bean を JAR または WAR アーカイブにパッケージ化します。beans.xml
ファイルをアーカイブに含めます。beans.xml
ファイルを JAR アーカイブのMETA-INF/
ディレクトリーまたは WAR アーカイブのWEB-INF/
ディレクトリーに配置します。このファイルは空白の場合があります。
これらの Bean を CDI で使用できます。コンテナは、Bean のインスタンスを作成および破棄し、指定されたコンテキストに関連付け、他の Bean に挿入し、EL 式で使用して、修飾子アノテーションで特殊化し、インターセプターとデコレーターをこれらに追加できます (既存のコードを変更しません)。状況によっては、いくつかのアノテーションを追加する必要がある場合があります。
9.2.2.3. スキャンプロセスからの Bean の除外
Weld の機能の 1 つである JBoss Enterprise Application Platform の CDI 実装は、スキャンからアーカイブのクラスを除外する機能であり、コンテナライフサイクルイベントを発生させ、Bean としてデプロイされます。これは、JSR-299 仕様の一部ではありません。
例9.1 Bean からのパッケージの除外
- 最初のタグでは、すべての Swing クラスが除外されます。
- 2 番目のタグでは、Google Web Toolkit がインストールされていない場合に Google Web Toolkit クラスが除外されます。
- 3 番目のタグでは、文字列
Blether
(通常の式を使用) で終了するクラスが除外されます (システムプロパティー verbosity がlow
に設定されている場合)。 - 4 番目のタグでは、Java Server Faces (JSF) クラスが除外されます (Wicket クラスが存在し、viewlayer システムプロパティーが設定されてない場合)。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:weld="http://jboss.org/schema/weld/beans" xsi:schemaLocation=" http://java.sun.com/xml/ns/javaee http://docs.jboss.org/cdi/beans_1_0.xsd http://jboss.org/schema/weld/beans http://jboss.org/schema/weld/beans_1_1.xsd"> <weld:scan> <!-- Don't deploy the classes for the swing app! --> <weld:exclude name="com.acme.swing.**" /> <!-- Don't include GWT support if GWT is not installed --> <weld:exclude name="com.acme.gwt.**"> <weld:if-class-available name="!com.google.GWT"/> </weld:exclude> <!-- Exclude classes which end in Blether if the system property verbosity is set to low i.e. java ... -Dverbosity=low --> <weld:exclude pattern="^(.*)Blether$"> <weld:if-system-property name="verbosity" value="low"/> </weld:exclude> <!-- Don't include JSF support if Wicket classes are present, and the viewlayer system property is not set --> <weld:exclude name="com.acme.jsf.**"> <weld:if-class-available name="org.apache.wicket.Wicket"/> <weld:if-system-property name="!viewlayer"/> </weld:exclude> </weld:scan> </beans>
9.2.2.4. 挿入を使用して実装を拡張
挿入を使用して、既存のコードの機能を追加または変更できます。この例は、既存のクラスに翻訳機能を追加する方法を示しています。翻訳機能は想像上の機能であり、例での実装方法は擬似コードであり、説明を目的としています。
buildPhrase
を持つ Welcome クラスがすでにあることを前提とします。buildPhrase
メソッドは、都市の名前を引数として取得し、"Welcome to Boston." などのフレーズを出力します。ここでの目標は、このような挨拶を別の言語に翻訳できる Welcome
クラスのバージョンを作成することです。
例9.2 Translator
Bean を Welcome
クラスに挿入する
Translator
オブジェクトを Welcome
クラスに挿入します。Translator
オブジェクトは、文をある言語から別の言語に翻訳できる EJB ステートレス Bean または別のタイプの Bean になります。この例では、挨拶全体を翻訳するために Translator
が使用されます。元の Welcome
クラスは実際にはまったく変更されません。Translator
は、buildPhrase
メソッドが実装される前に挿入されます。
public class TranslatingWelcome extends Welcome { @Inject Translator translator; public String buildPhrase(String city) { return translator.translate("Welcome to " + city + "!"); } ... }
9.2.3. あいまいな依存関係または満たされていない依存関係
9.2.3.1. 依存性があいまいな場合、あるいは満たされていない場合
- インジェクションポイントの Bean 型を実装する全 Bean にある修飾子アノテーションを解決します。
- 無効となっている Bean をフィルタリングします。無効な Bean とは、明示的に有効化されていない @Alternative Bean のことです。
9.2.3.2. 修飾子について
例9.3 @Synchronous
修飾子と @Asynchronous
修飾子を定義する
@Qualifier @Retention(RUNTIME) @Target({TYPE, METHOD, FIELD, PARAMETER}) public @interface Synchronous {}
@Qualifier @Retention(RUNTIME) @Target({TYPE, METHOD, FIELD, PARAMETER}) public @interface Asynchronous {}
例9.4 1@Synchronous
修飾子と @Asynchronous
修飾子を使用する
@Synchronous public class SynchronousPaymentProcessor implements PaymentProcessor { public void process(Payment payment) { ... } }
@Asynchronous public class AsynchronousPaymentProcessor implements PaymentProcessor { public void process(Payment payment) { ... } }
9.2.3.3. 修飾子を使用して不明な挿入を解決
このタスクは、不明な挿入を示し、修飾子を使用して不明な挿入を削除します。不明な挿入の詳細については、「依存性があいまいな場合、あるいは満たされていない場合」 を参照してください。
例9.5 不明な挿入
Welcome
の 2 つの実装があり、1 つは翻訳を行い、もう 1 つは翻訳を行いません。このような場合は、以下の挿入が不明であり、翻訳を行う Welcome
を使用するよう指定する必要があります。
public class Greeter { private Welcome welcome; @Inject void init(Welcome welcome) { this.welcome = welcome; } ... }
手順9.3 修飾子を使用して不明な挿入を解決する
@Translating
という修飾子アノテーションを作成します。@Qualifier @Retention(RUNTIME) @Target({TYPE,METHOD,FIELD,PARAMETERS}) public @interface Translating{}
翻訳を行う
Welcome
を@Translating
アノテーションでアノテートします。@Translating public class TranslatingWelcome extends Welcome { @Inject Translator translator; public String buildPhrase(String city) { return translator.translate("Welcome to " + city + "!"); } ... }
挿入の、翻訳を行う
Welcome
を要求します。ファクトリーメソッドパターンの場合と同様に、修飾された実装を明示的に要求する必要があります。不明な点は、挿入時に解決されます。public class Greeter { private Welcome welcome; @Inject void init(@Translating Welcome welcome) { this.welcome = welcome; } public void welcomeVisitors() { System.out.println(welcome.buildPhrase("San Francisco")); } }
Translating
Welcome
が使用されます。不明な点はありません。
9.2.4. 管理 Bean
9.2.4.1. 管理対象 Beans について
9.2.4.2. Bean であるクラスのタイプ
@ManagedBean
をアノテートすることで明示的に管理対象 Bean を宣言できますが、CDI ではその必要はありません。この仕様によると、CDI コンテナでは、以下の条件を満たすクラスはすべて管理対象 Bean として扱われます。
- 非静的な内部クラスではないこと。
- 具象クラス、あるいは
@Decorator
でアノテートされていること。 - EJB コンポーネントを定義するアノテーションでアノテートされていないこと、あるいは
ejb-jar.xml
で EJB Bean クラスとして宣言されていること。 - インターフェース
javax.enterprise.inject.spi.Extension
が実装されていないこと。 - パラメーターのないコンストラクターか、
@Inject
でアノテートされたコンストラクターがあること。
9.2.4.3. CDI を使用してオブジェクトを Bean に挿入する
META-INF/beans.xml
または WEB-INF/beans.xml
ファイルが含まれる場合、CDI を使用してデプロイメントの各オブジェクト挿入することが可能です。
@Inject
アノテーションを用いてオブジェクトを Bean の一部に挿入します。Bean 内でクラスのインスタンスを取得するには、フィールドに@Inject
アノテーションを付けます。例9.6
TranslateController
へTextTranslator
インスタンスを挿入するpublic class TranslateController { @Inject TextTranslator textTranslator; ...
挿入したオブジェクトのメソッドを使用する
挿入したオブジェクトのメソッドを直接使用することが可能です。TextTranslator
にメソッドtranslate
があることを前提とします。例9.7 挿入したオブジェクトのメソッドを使用する
// in TranslateController class public void translate() { translation = textTranslator.translate(inputText); }
Bean のコンストラクターで挿入を使用する
ファクトリーやサービスロケーターを使用して作成する代わりに、Bean のコンストラクターへオブジェクトを挿入することができます。例9.8 Bean のコンストラクターで挿入を使用する
public class TextTranslator { private SentenceParser sentenceParser; private Translator sentenceTranslator; @Inject TextTranslator(SentenceParser sentenceParser, Translator sentenceTranslator) { this.sentenceParser = sentenceParser; this.sentenceTranslator = sentenceTranslator; } // Methods of the TextTranslator class ... }
Instance(<T>)
インターフェースを使用し、プログラムを用いてインスタンスを取得します。Bean 型でパラメーター化されると、Instance
インターフェースは TextTranslator のインスタンスを返すことができます。例9.9 プログラムを用いてインスタンスを取得する
@Inject Instance<TextTranslator> textTranslatorInstance; ... public void translate() { textTranslatorInstance.get().translate(inputText); }
オブジェクトを Bean に挿入すると、Bean は全オブジェクトのメソッドとプロパティーを使用できるようになります。Bean のコンストラクターに挿入すると、挿入が既に存在するインスタンスを参照する場合以外は、Bean のコンストラクターが呼び出されると挿入されたオブジェクトのインスタンスが作成されます。例えば、セッションのライフタイムの間にセッションスコープ付けされた Bean を挿入しても、新しいインスタンスは作成されません。
9.2.5. コンテキスト、スコープ、依存関係
9.2.5.1. コンテキストおよびスコープ
@RequestScoped
、@SessionScoped
、および @ConversationScope
です。
9.2.5.2. 利用可能なコンテキスト
表9.1 利用可能なコンテキスト
コンテキスト | 説明 |
---|---|
@Dependent | Bean は、参照を保持する Bean のライフサイクルにバインドされます。 |
@ApplicationScoped | アプリケーションのライフサイクルにバインドされます。 |
@RequestScoped | 要求のライフサイクルにバインドされます。 |
@SessionScoped | セッションのライフサイクルにバインドされます。 |
@ConversationScoped | 会話のライフサイクルにバインドされます。会話スコープは、要求の長さとセッションの間であり、アプリケーションによって制御されます。 |
カスタムスコープ | 上記のコンテキストでニーズが満たされない場合は、カスタムスコープを定義できます。 |
9.2.6. Bean ライフサイクル
9.2.6.1. Bean のライフサイクルの管理
このタスクは、要求の残存期間の間 Bean を保存する方法を示しています。他の複数のスコープが存在し、独自のスコープを定義できます。
@Dependent
です。つまり、Bean のライフサイクルは、参照を保持する Bean のライフサイクルに依存します。詳細については、「コンテキストおよびスコープ」 を参照してください。
手順9.4 Bean ライフサイクルを管理する
必要なスコープに対応するスコープで Bean をアノテートします。
@RequestScoped @Named("greeter") public class GreeterBean { private Welcome welcome; private String city; // getter & setter not shown @Inject void init(Welcome welcome) { this.welcome = welcome; } public void welcomeVisitors() { System.out.println(welcome.buildPhrase(city)); } }
Bean が JSF ビューで使用される場合、Bean はステートを保持します。
<h:form> <h:inputText value="#{greeter.city}"/> <h:commandButton value="Welcome visitors" action="#{greeter.welcomeVisitors}"/> </h:form>
Bean は、指定するスコープに関連するコンテキストに保存され、スコープが適用される限り存続します。
9.2.6.2. プロデューサーメソッドの使用
このタスクは、挿入用の Bean ではないさまざまなオブジェクトを生成するプロデューサーメソッドを使用する方法を示しています。
例9.10 代替の代わりにプロデューサーメソッドを使用してデプロイメント後のポリモーフィズムを可能にします。
@Preferred
アノテーションは、修飾子アノテーションです。修飾子の詳細については、「修飾子について」を参照してください。
@SessionScoped public class Preferences implements Serializable { private PaymentStrategyType paymentStrategy; ... @Produces @Preferred public PaymentStrategy getPaymentStrategy() { switch (paymentStrategy) { case CREDIT_CARD: return new CreditCardPaymentStrategy(); case CHECK: return new CheckPaymentStrategy(); default: return null; } } }
@Inject @Preferred PaymentStrategy paymentStrategy;
例9.11 プロデューサーメソッドへのスコープの割り当て
@Dependent
です。スコープを Bean に割り当てた場合、スコープは適切なコンテキストにバインドされます。この例のプロデューサーメソッドは、1 つのセッションあたり一度だけ呼び出されます。
@Produces @Preferred @SessionScoped public PaymentStrategy getPaymentStrategy() { ... }
例9.12 プロデューサーメソッド内部での挿入の使用
@Produces @Preferred @SessionScoped public PaymentStrategy getPaymentStrategy(CreditCardPaymentStrategy ccps, CheckPaymentStrategy cps ) { switch (paymentStrategy) { case CREDIT_CARD: return ccps; case CHEQUE: return cps; default: return null; } }
注記
プロデューサーメソッドを使用して、非 Bean オブジェクトを挿入し、コードを動的に変更できます。
9.2.7. 名前付き Bean と代替の Bean
9.2.7.1. 名前付き Bean について
@Named
アノテーションを使用して名前が付けられます。Bean を命名することにより、Bean を Java Server Faces (JSF) で直接使用できるようになります。
@Named
アノテーションは、Bean 名であるオプションパラメーターを取ります。このパラメーターが省略された場合は、小文字の Bean 名が名前として使用されます。
9.2.7.2. 名前付き Bean の使用
@Named
アノテーションを使用して名前を Bean に割り当てます。@Named("greeter") public class GreeterBean { private Welcome welcome; @Inject void init (Welcome welcome) { this.welcome = welcome; } public void welcomeVisitors() { System.out.println(welcome.buildPhrase("San Francisco")); } }
Bean 名自体はオプションです。省略された場合、クラス名に基づいて Bean に名前が付けられます (最初の文字は小文字になります)。上記の例では、デフォルトの名前はgreeterBean
になります。JSF ビューで名前付き Bean を使用します。
<h:form> <h:commandButton value="Welcome visitors" action="#{greeter.welcomeVisitors}"/> </h:form>
名前付き Bean が、JSF ビューでアクションとしてコントロールに割り当てられ、コーディングが最小化されます。
9.2.7.3. 代替の Bean について
例9.13 代替の定義
@Alternative @Synchronous @Asynchronous public class MockPaymentProcessor implements PaymentProcessor { public void process(Payment payment) { ... } }
beans.xml
ファイルを編集することにより、特定の Bean アーカイブに対して有効になります。
9.2.7.4. 代替で挿入をオーバーライド
代替の Bean を使用すると、既存の Bean をオーバーライドできます。これらは、同じ役割を満たすクラスをプラグインする方法として考えることができますが、動作が異なります。これらはデフォルトで無効になります。このタスクは、代替を指定し、有効にする方法を示しています。
手順9.5 挿入をオーバーライドする
TranslatingWelcome
クラスがすでにあることを前提としています。ただし、これを "mock" TranslatingWelcome クラスでオーバーライドするとします。これは、実際の Translator Bean を使用できないテストデプロイメントのケースに該当します。
代替を定義します。
@Alternative @Translating public class MockTranslatingWelcome extends Welcome { public String buildPhrase(string city) { return "Bienvenue à " + city + "!"); } }
代替を置換します。
置換実装をアクティベートするために、完全修飾クラス名をMETA-INF/beans.xml
またはWEB-INF/beans.xml
ファイルに追加します。<beans> <alternatives> <class>com.acme.MockTranslatingWelcome</class> </alternatives> </beans>
元の実装の代わりに代替実装が使用されます。
9.2.8. ステレオタイプ
9.2.8.1. ステレオタイプについて
- デフォルトスコープ
- インターセプターバインディングのセット
- ステレオタイプを持つすべての Bean にデフォルトの Bean EL 名がある
- ステレオタイプを持つすべての Bean が代替である
@Named
アノテーションを持つ場合、配置された Bean はデフォルトの Bean 名を持ちます。この Bean は、@Named アノテーションが Bean で直接指定された場合に、この名前をオーバーライドできます。名前付き Bean の詳細については、「名前付き Bean について」 を参照してください。
9.2.8.2. ステレオタイプの使用
ステレオタイプがない場合は、アノテーションをクラスタリングできます。このタスクは、ステレオタイプを使用して煩雑さとコードを減らす方法を示しています。ステレオタイプの詳細については、「ステレオタイプについて」 を参照してください。
例9.14 アノテーションの煩雑さ
@Secure @Transactional @RequestScoped @Named public class AccountManager { public boolean transfer(Account a, Account b) { ... } }
手順9.6 ステレオタイプを定義および使用する
ステレオタイプを定義します。
@Secure @Transactional @RequestScoped @Named @Stereotype @Retention(RUNTIME) @Target(TYPE) public @interface BusinessComponent { ... }
ステレオタイプを使用します。
@BusinessComponent public class AccountManager { public boolean transfer(Account a, Account b) { ... } }
ステレオタイプにより、コードが削減され、単純化されます。
9.2.9. オブザーバーメソッド
9.2.9.1. オブサーバーメソッドについて
9.2.9.2. イベントの発生と確認
例9.15 イベントの発生
public class AccountManager { @Inject Event<Withdrawal> event; public boolean transfer(Account a, Account b) { ... event.fire(new Withdrawal(a)); } }
例9.16 修飾子を使用したイベントの発生
public class AccountManager { @Inject @Suspicious Event <Withdrawal> event; public boolean transfer(Account a, Account b) { ... event.fire(new Withdrawal(a)); } }
例9.17 イベントの確認
@Observes
アノテーションを使用します。
public class AccountObserver { void checkTran(@Observes Withdrawal w) { ... } }
例9.18 修飾されたイベントの確認
public class AccountObserver { void checkTran(@Observes @Suspicious Withdrawal w) { ... } }
9.2.10. インターセプター
9.2.10.1. インターセプターについて
インターセプションポイント
- ビジネスメソッドのインターセプション
- ビジネスメソッドのインターセプターは、Bean のクライアントによる Bean のメソッド呼び出しに適用されます。
- ライフサイクルコールバックのインターセプション
- ライフサイクルのコールバックインターセプションは、コンテナによるライフサイクルコールバックの呼び出しに適用されます。
- タイムアウトメソッドのインターセプション
- タイムアウトメソッドのインターセプターは、コンテナによる EJB タイムアウトメソッドの呼び出しに適用されます。
9.2.10.2. CDI とのインターセプターの使用
例9.19 CDI なしのインターセプター
- Bean は、インターセプター実装を直接指定する必要があります。
- アプリケーションの各 Bean は、インターセプターの完全なセットを適切な順序で指定する必要があります。この場合、アプリケーション全体でインターセプターを追加または削除するには時間がかかり、エラーが発生する傾向があります。
@Interceptors({ SecurityInterceptor.class, TransactionInterceptor.class, LoggingInterceptor.class }) @Stateful public class BusinessComponent { ... }
手順9.7 CDI とのインターセプターの使用
インターセプターバインディングタイプを定義します。
@InterceptorBinding @Retention(RUNTIME) @Target({TYPE, METHOD}) public @interface Secure {}
インターセプター実装をマークします。
@Secure @Interceptor public class SecurityInterceptor { @AroundInvoke public Object aroundInvoke(InvocationContext ctx) throws Exception { // enforce security ... return ctx.proceed(); } }
ビジネスコードでインターセプターを使用します。
@Secure public class AccountManager { public boolean transfer(Account a, Account b) { ... } }
インターセプターを
META-INF/beans.xml
またはWEB-INF/beans.xml
に追加することにより、インターセプターをデプロイメントで有効にします。<beans> <interceptors> <class>com.acme.SecurityInterceptor</class> <class>com.acme.TransactionInterceptor</class> </interceptors> </beans>
インターセプターは、リストされた順序で適用されます。
CDI により、インターセプターコードが単純化され、ビジネスコードへの適用が簡単になります。
9.2.11. デコレーターについて
@Decorator
でアノテートされます。
例9.20 デコレーターの例
@Decorator public abstract class LargeTransactionDecorator implements Account { @Inject @Delegate @Any Account account; @PersistenceContext EntityManager em; public void withdraw(BigDecimal amount) { ... } public void deposit(BigDecimal amount); ... } }
9.2.12. 移植可能な拡張機能について
- ビジネスプロセス管理エンジンとの統合
- Spring、Seam、GWT、Wicket などのサードパーティーフレームワークとの統合
- CDI プログラミングモデルに基づく新しいテクノロジー
- 独自の Bean、インターセプター、およびデコレーターをコンテナに提供します。
- 依存関係挿入サービスを使用して独自のオブジェクトに依存関係を挿入します。
- カスタムスコープのコンテキスト実装を提供します。
- アノテーションベースのメタデータを他のソースからのメタデータで拡大またはオーバーライドします。
9.2.13. Bean プロキシ
9.2.13.1. Bean プロキシ
プロキシを利用することで解決される依存関係挿入の問題
- パフォーマンス - プロキシは依存関係の挿入よりも速度が早いため、高パフォーマンスを必要とする Bean に利用することができます。
- スレッドセーフ - 複数のスレッドが同時に Bean にアクセスしている場合でも、プロキシは適切な Bean インスタンスにリクエストを転送します。依存関係の挿入はスレッドの安全性を保証しません。
プロキシ化できないクラス型
- プリミティブ型あるいはアレイ型
final
のクラスあるいはfinal
メソッドを持つクラス- プライベートではないデフォルトのコンストラクターを持つクラス
9.2.13.2. 挿入でプロキシを使用する
各 Bean のライフサイクルが異なる場合に挿入にプロキシが使用されます。プロキシはランタイム時に作成された Bean のサブクラスで、Bean クラスのプライベートメソッド以外のメソッドをすべて上書きします。プロキシは実際の Bean インスタンスへ呼び出しを転送します。
PaymentProcessor
インスタンスは直接 Shop
へ挿入されません。その代わりにプロキシが挿入され、processPayment()
メソッドが呼び出されるとプロキシが現在の PaymentProcessor
Bean インスタンスをルックアップし、processPayment()
メソッドを呼び出します。
例9.21 プロキシの挿入
@ConversationScoped class PaymentProcessor { public void processPayment(int amount) { System.out.println("I'm taking $" + amount); } } @ApplicationScoped public class Shop { @Inject PaymentProcessor paymentProcessor; public void buyStuff() { paymentProcessor.processPayment(100); } }
第10章 Java トランザクション API (JTA)
10.1. 概要
10.1.1. Java トランザクション API (JTA) の概要
これらのトピックは、 Java トランザクション API (JTA) の基礎的な内容について取り上げます。
10.2. トランザクションの概念
10.2.1. トランザクションについて
10.2.2. トランザクションの ACID プロパティーについて
Atomicity
)、一貫性 (Consistency
)、独立性 (Isolation
)、永続性 (Durability
) の略語です。この単語は通常データベースやトランザクション操作において使用されます。
ACID の定義
- 原子性 (Atomicity)
- トランザクションの原子性を保つには、トランザクション内の全メンバーが同じ決定をする必要があります。つまり、全メンバーがコミットまたはロールバックを行う必要があります。原子性が保たれない場合の結果をヒューリスティックな結果と言います。
- 一貫性 (Consistency)
- 一貫性とは、データベーススキーマの観点から、データベースに書き込まれたデータが有効なデータであることを保証するという意味です。データベースあるいは他のデータソースは常に一貫した状態でなければなりません。一貫性のない状態の例には、操作が中断される前にデータの半分が書き込みされてしまったフィールドなどがあります。すべてのデータが書き込まれた場合や、書き込みが完了しなかった時に書き込みがロールバックされた場合に、一貫した状態となります。
- 独立性 (Isolation)
- 独立性とは、トランザクションのスコープ外のプロセスがデータを変更できないように、トランザクションで操作されたデータが変更前にロックされる必要があることを意味します。
- 永続性 (Durability)
- 永続性とは、トランザクションのメンバーにコミットの指示を出してから外部で問題が発生した場合、問題が解決されると全メンバーがトランザクションのコミットを継続できるという意味です。ここで言う問題とは、ハードウェア、ソフトウェア、ネットワークなどのシステムが関係する問題のことです。
10.2.3. トラザクションコーディネーターあるいはトランザクションマネージャーについて
10.2.4. トランザクションの参加者を表示します。
10.2.5. Java Transactions API (JTA) について
10.2.6. Java Transaction Service (JTS) について
注記
10.2.7. XA データソースおよび XA トランザクションについて
10.2.8. XA リカバリーについて
10.2.9. 2 相コミットプロトコルについて
最初のフェーズでは、トランザクションをコミットできるか、あるいはロールバックする必要があるかをトランザクションの参加者がトランザクションコーディネーターに通知します。
2 番目のフェーズでは、トランザクションコーディネーターが全体のトランザクションをコミットするか、ロールバックするか決定します。参加者が 1 つでもコミットできない場合、トランザクションはロールバックしなければなりません。参加者がすべてコミットできる場合はトランザクションはコミットすることができます。コーディネーターは何を行うかをトランザクションに指示し、トランザクションは何を行ったかコーディネーターに通知します。この時点で、トランザクションが完了します。
10.2.10. トランザクションタイムアウトについて
10.2.11. 分散トランザクションについて
10.2.12. ORB 移植性 API について
ORB 移植性 API のクラス
com.arjuna.orbportability.orb
com.arjuna.orbportability.oa
10.2.13. ネストされたトランザクションについて
ネストされたトランザクションの利点
- 障害の分離
- サブトランザクションがロールバックされた場合に、使用しているオブジェクトが失敗したため、エンクローズトランザクションはロールバックする必要がありません。
- モジュール性
- 新しいトランザクションが開始されるときにトランザクションがすでに呼び出しに関連付けられている場合は、新しいトランザクションがそのトランザクション内にネストされます。したがって、オブジェクトでトランザクションが必要なことがわかっている場合は、オブジェクト内でトランザクションを開始できます。オブジェクトのメソッドがクライアントトランザクションなしで呼び出された場合は、オブジェクトのトランザクションは最上位レベルです。それ以外の場合、これらのトランザクションはクライアントのトランザクションのスコープ内でネストされます。同様に、クライアントはオブジェクトがトランザクション対応であるかどうかを知る必要がありません。クライアントは、独自のトランザクションを開始できます。
10.3. トランザクションの最適化
10.3.1. トランザクション最適化の概要
JBoss Enterprise Application Platform のトランザクションサブシステムには複数の最適化機能が含まれており、お使いのアプリケーションでご活用いただけます。
10.3.2. 1相コミット (1PC) の LRCO 最適化について
10.3.3. 推定中止 (presumed-abort) 最適化について
10.3.4. 読み取り専用の最適化について
10.4. トランザクションの結果
10.4.1. トランザクションの結果について
- ロールバック
- トランザクションの参加者のいずれかがコミットできなかったり、トランザクションコーディネーターが参加者にコミットを指示できない場合、トランザクションがロールバックされます。詳細は 「トランザクションロールバックについて」 を参照してください。
- コミット
- トランザクションの参加者すべてがコミットできる場合、トランザクションコーディネーターはコミットの実行を指示します。詳細は 「トランザクションのコミットについて」 を参照してください。
- ヒューリスティックな結果
- トランザクションの参加者の一部がコミットし、他の参加者がロールバックした場合をヒューリスティックな結果と呼びます。ヒューリスティックな結果が発生すると、人的な介入が必要になります。詳細は 「ヒューリスティックな結果について」 を参照してください。
10.4.2. トランザクションのコミットについて
10.4.3. トランザクションロールバックについて
10.4.4. ヒューリスティックな結果について
- ヒューリスティックロールバック
- 参加者の一部あるいはすべてが一方的にトランザクションをロールバックしたため、コミット操作に失敗します。
- ヒューリスティックコミット
- 参加者のすべてが一方的にコミットしたため、ロールバック操作に失敗します。例えば、コーディネーターが正常にトランザクションを準備したにも関わらず、ログ更新の失敗などコーディネーター側で障害が発生したためロールバックの実行を決定した場合などに発生します。暫定的に参加者がコミットの実行を決定する場合があります。
- ヒューリスティック混合
- 一部の参加者がコミットし、その他の参加者はロールバックした状態です。
- ヒューリスティックハザード
- 更新の一部の結果が不明な状態です。既知の更新結果はすべてコミットまたはロールバックします。
10.4.5. JBoss Transactions エラーと例外
UserTransaction
クラスのメソッドがスローする例外に関する詳細は、http://download.oracle.com/javaee/1.3/api/javax/transaction/UserTransaction.html の 『UserTransaction API』 の仕様を参照してください。
10.5. JTA トランザクションの概要
10.5.1. Java Transactions API (JTA) について
10.5.2. JTA トランザクションのライフサイクル
アプリケーションが新しいトランザクションを開始する
トランザクションを開始するには、お使いのアプリケーションが JNDI から(または、EJB の場合はアノテーションから)UserTransaction
クラスのインスタンスを取得します。UserTransaction
インターフェースには、トップレベルのトランザクションを開始、コミット、ロールバックするメソッドが含まれています。新規作成されたトランザクションは、そのトランザクションを呼び出すスレッドと自動的に関連付けされます。ネストされたトランザクションは JTA ではサポートされないため、すべてのトランザクションがトップレベルのトランザクションとなります。UserTransaction
.begin()
を呼び出すと、新規トランザクションが開始されます。この時点移行に使ったリソースはすべて、このトランザクションと関連付けられます。1つ以上のリソースが登録された場合、このトランザクションは XA トランザクションになり、コミット時に 2 相コミットプロトコルに参加します。アプリケーションがステートを変更する
次に、トランザクションが作業を実行しステートを変更します。アプリケーションがコミットまたはロールバックを決定する
お使いのアプリケーションがステータスの変更を終了すると、コミットするか、ロールバックするか決定し、適切なメソッドを呼び出します。UserTransaction
.commit()
またはUserTransaction
.rollback()
を呼び出します。1 つ以上のリソースを登録している場合は、ここで 2 相コミットプロトコル (2PC) が起こります。「2 相コミットプロトコルについて」トランザクションマネージャーが記録からトランザクションを削除する
コミットあるいはロールバックが完了すると、トランザクションマネージャーは記録を消去し、トランザクションに関する情報を削除します。
障害回復は自動的に行われます。リソース、トランザクションの参加者、アプリケーションサーバーが使用できなくなった場合、この問題が解決した時にトランザクションマネージャーがリカバリー処理を行います。
10.6. トランザクションサブシステムの設定
10.6.1. トランザクション設定の概要
次の手順は、JBoss Enterprise Application Platform のトランザクションサブシステムを設定する方法を示しています。
10.6.2. トランザクションデータソースの設定
10.6.2.1. JTA トランザクションを使用するようにデータソースを設定
ここでは、データソースで Java Transactions API (JTA) を有効にする方法を説明します。
このタスクを行う前に、 次の条件を満たす必要があります。
- お使いのデータベースまたはその他のリソースが JTA をサポートしている必要があります。不明な場合は、データソースまたはリソースの文書を参照してください。
- データベースを作成する必要があります。「管理インターフェースによる非 XA データソースの作成」 を参照してください。
- JBoss Enterprise Application Platform を停止します。
- テキストエディターで設定ファイルを直接編集できる権限を持たなければなりません。
手順10.1 JTA トランザクションを使用するようデータソースを設定する
テキストエディターで設定ファイルを開きます。
JBoss Enterprise Application Platform を管理対象ドメインまたはスタンドアロンサーバーで実行するかによって、設定ファイルの場所は異なります。管理対象ドメイン
管理対象ドメインのデフォルトの設定ファイルは、Red Hat Enterprise Linux の場合はEAP_HOME/domain/configuration/domain.xml
にあります。Microsoft Windows サーバーの場合はEAP_HOME\domain\configuration\domain.xml
にあります。スタンドアロンサーバー
スタンドアロンサーバーのデフォルトの設定ファイルは、Red Hat Enterprise Linux の場合はEAP_HOME/standalone/configuration/standalone.xml
にあります。Microsoft Windows サーバーの場合はEAP_HOME\standalone\configuration\standalone.xml
にあります。
お使いのデータソースに対応する
<datasource>
タグを探します。データソースのjndi-name
属性には作成時に指定した属性が設定されます。例えば、 ExampleDS データソースは次のようになります。<datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="H2DS" enabled="true" jta="true" use-java-context="true" use-ccm="true">
jta
属性をtrue
に設定します。上記のように、jta="true"
を<datasource>
タグの内容に追加します。設定ファイルを保存します。
設定ファイルを保存しテキストエディターを終了します。JBoss Enterprise Application Platform を起動します。
JBoss Enterprise Application Platform 6 サーバーを再起動します。
JBoss Enterprise Application Platform が起動し、データソースが JTA トランザクションを使用するように設定されます。
10.6.2.2. XA Datasource の設定
XA Datasource を追加するには、管理コンソールにログインする必要があります。詳細は 「管理コンソールへログイン」 を参照してください。
新しいデータソースの追加
新しいデータソースを JBoss Enterprise Application Platform に追加します。「管理インターフェースによる非 XA データソースの作成」 の手順に従いますが、上部の XA Datasource タブをクリックしてください。必要に応じて他のプロパティーを設定します。
データソースパラメーターの一覧は 「データソースのパラメーター」 にあります。
XA Datasource が設定され、使用する準備ができます。
10.6.2.3. 管理コンソールへログイン
要件
- JBoss Enterprise Application Platform 6 が稼働している必要があります。
手順10.2 管理コンソールへログイン
管理コンソールのスタートページに移動
Web ブラウザーで管理コンソールに移動します。デフォルトの場所は http://localhost:9990/console/ です。ポート 9990 は管理コンソールのソケットバインディングとして事前定義されています。管理コンソールへログイン
以前作成したアカウントのユーザー名とパスワードを入力し、管理コンソールのログイン画面でログインします。図10.1 管理コンソールのログイン画面
結果
- 管理対象ドメイン
- スタンドアロンサーバー
10.6.2.4. 管理インターフェースによる非 XA データソースの作成
ここでは、管理コンソールまたは管理 CLI のいずれかを使用して非 XA データソースを作成する手順について取り上げます。
要件
- JBoss Enterprise Application Platform 6 サーバーが稼働している必要があります。
注記
手順10.3 管理 CLI または管理コンソールのいずれかを使用したデータソースの作成
管理 CLI
- CLI ツールを起動し、サーバーに接続します。
- 以下のコマンドを実行して非 XA データソースを作成し、適切に変数を設定します。
data-source add --name=DATASOURCE_NAME --jndi-name=JNDI_NAME --driver-name=DRIVER_NAME --connection-url=CONNECTION_URL
- データソースを有効にします。
data-source enable --name=DATASOURCE_NAME
管理コンソール
- 管理コンソールへログインします。
管理コンソールの [Datasources] パネルに移動します。
スタンドアロンモード
コンソールの右上より [Profile] タブを選択します。ドメインモード
- コンソールの右上より [Profiles] タブを選択します。
- 左上のドロップダウンボックスより該当するプロファイルを選択します。
- コンソールの左側にある [Subsystems] メニューを展開します。
- コンソールの左側にあるメニューより [Connector] → [Datasources] と選択します。
図10.2 データソースパネル
新しいデータソースの作成
- [Datasources] パネル上部にある [Add] ボタンを選択します。
- Create Datasource ウィザードで新しいデータソースの属性を入力し、[Next] ボタンを押します。
- Create Datasource ウィザードで JDBC ドライバーの詳細を入力し、[Next] ボタンを押します。
- Create Datasource ウィザードで接続設定を入力し、[Done] ボタンを押します。
非 XA データソースがサーバーに追加されます。standalone.xml
または domain.xml
ファイル、および管理インターフェースで追加を確認することができます。
10.6.2.5. データソースのパラメーター
表10.1 非 XA および XA データソースに共通のデータソースパラメーター
パラメーター | 説明 |
---|---|
jndi-name | データソースの一意の JNDI 名。 |
pool-name | データソースの管理プール名。 |
enabled | データソースが有効かどうかを指定します。 |
use-java-context |
データソースをグローバルの JNDI にバインドするかどうかを指定します。
|
spy |
JDBC レイヤーで
spy 機能を有効にします。この機能は、データソースへの JDBC トラフィックをすべてログに記録します。また、logging-category パラメーターを org.jboss.jdbc に設定する必要があります。
|
use-ccm | キャッシュ接続マネージャーを有効にします。 |
new-connection-sql | 接続プールに接続が追加された時に実行する SQL ステートメント。 |
transaction-isolation |
次のいずれかになります。
|
url-delimiter | 高可用性 (HA) クラスターデータベースの connection-url にある URL の区切り文字。 |
url-selector-strategy-class-name | インターフェース org.jboss.jca.adapters.jdbc.URLSelectorStrategy を実装するクラス。 |
security |
セキュリティー設定である子要素が含まれます。表10.6「セキュリティーパラメーター」 を参照してください。
|
validation |
検証設定である子要素が含まれます。表10.7「検証パラメーター」 を参照してください。
|
timeout |
タイムアウト設定である子要素が含まれます。表10.8「タイムアウトパラメーター」 を参照してください。
|
statement |
ステートメント設定である子要素が含まれます。表10.9「ステートメントのパラメーター」 を参照してください。
|
表10.2 非 XA データソースのパラメーター
パラメーター | 説明 |
---|---|
jta | 非 XA データソースの JTA 統合を有効にします。XA データソースには適用されません。 |
connection-url | JDBC ドライバーの接続 URL。 |
driver-class | JDBC ドライバークラスの完全修飾名。 |
connection-property | Driver.connect(url,props) メソッドに渡される任意の接続プロパティー。各 connection-property は、文字列名と値のペアを指定します。プロパティー名は名前、値は要素の内容に基づいています。
|
pool |
プーリング設定である子要素が含まれます。表10.4「非 XA および XA データソースに共通のプールパラメーター」 を参照してください。
|
表10.3 XA データソースのパラメーター
パラメーター | 説明 |
---|---|
xa-datasource-property |
実装クラス
XADataSource に割り当てるプロパティー。name=value で指定。 setName という形式で setter メソッドが存在する場合、プロパティーは setName(value) という形式の setter メソッドを呼び出すことで設定されます。
|
xa-datasource-class |
実装クラス
javax.sql.XADataSource の完全修飾名。
|
driver |
JDBC ドライバーが含まれるクラスローダーモジュールへの一意参照。driverName#majorVersion.minorVersion の形式にのみ対応しています。
|
xa-pool |
プーリング設定である子要素が含まれます。表10.4「非 XA および XA データソースに共通のプールパラメーター」 と 表10.5「XA プールパラメーター」 を参照してください。
|
recovery |
リカバリ設定である子要素が含まれます。表10.10「リカバリーパラメーター」 を参照してください。
|
表10.4 非 XA および XA データソースに共通のプールパラメーター
パラメーター | 説明 |
---|---|
min-pool-size | プールが保持する最小接続数 |
max-pool-size | プールが保持可能な最大接続数 |
prefill | 接続プールのプレフィルを試行するかどうかを指定します。要素が空の場合は true を示します。デフォルトは、false です。 |
use-strict-min | pool-size が厳密かどうかを指定します。デフォルトは false に設定されています。 |
flush-strategy |
エラーの場合にプールをフラッシュするかどうかを指定します。有効な値は次のとおりです。
デフォルトは
FailingConnectionOnly です。
|
allow-multiple-users | 複数のユーザーが getConnection (user, password) メソッドを使いデータソースへアクセスするか、また内部プールタイプがこの動作に対応するかを指定します。 |
表10.5 XA プールパラメーター
パラメーター | 説明 |
---|---|
is-same-rm-override | javax.transaction.xa.XAResource.isSameRM(XAResource) クラスが true あるいは false のどちらを返すかを指定します。 |
interleaving | XA 接続ファクトリのインターリービングを有効にするかどうかを指定します。 |
no-tx-separate-pools | コンテキスト毎に sub-pool を作成するかどうかを指定します。これには Oracle のデータソースが必要ですが、このデータソースは JTA トランザクションの内部、外部に関わらず、XA 接続の利用ができなくなります。 |
pad-xid | Xid のパディングを行うかどうかを指定します。 |
wrap-xa-resource |
XAResource を
org.jboss.tm.XAResourceWrapper インスタンスでラップするかどうかを指定します。
|
表10.6 セキュリティーパラメーター
パラメーター | 説明 |
---|---|
user-name | 新規接続の作成に使うユーザー名 |
password | 新規接続の作成に使うパスワード |
security-domain | 認証処理を行う JAAS security-manager 名が含まれます。この名前は、JAAS ログイン設定のapplication-policy/name 属性に相関します。 |
reauth-plugin | 物理接続の再認証に使う再認証プラグインを定義します。 |
表10.7 検証パラメーター
パラメーター | 説明 |
---|---|
valid-connection-checker | SQLException.isValidConnection(Connection e) メソッドを提供し接続を検証するインターフェース org.jboss.jca.adaptors.jdbc.ValidConnectionChecker の実装。例外が発生すると接続が破棄されます。存在する場合、check-valid-connection-sql パラメーターが上書きされます。
|
check-valid-connection-sql | プール接続の妥当性を確認する SQL ステートメント。これは、管理接続をプールから取得し利用する場合に呼び出される場合があります。 |
validate-on-match |
接続ファクトリが指定のセットに対して管理対象接続をマッチしようとした時に接続レベルの検証を実行するかどうかを示します。
通常、
validate-on-match に true を指定した時に background-validation を true に指定することはありません。クライアントが使用する前に接続を検証する必要がある場合に Validate-on-match が必要になります。このパラメーターはデフォルトでは true になっています。
|
background-validation |
接続がバックグラウンドスレッドで検証されることを指定します。
validate-on-match を使用しない場合、バックグラウンドの検証はパフォーマンスを最適化します。validate-on-match が true の時に background-validation を使用すると、チェックが冗長になることがあります。バックグラウンド検証では、不良の接続がクライアントに提供される可能性があります (検証スキャンと接続がクライアントに提供されるまでの間に接続が悪くなります)。そのため、クライアントアプリケーションはこの接続不良の可能性に対応する必要があります。
|
background-validation-millis | バックグラウンド検証を実行する期間 (ミリ秒単位)。 |
use-fast-fail |
true の場合、接続が無効であれば最初に接続を割り当てしようとした時点で失敗します。デフォルトは
false です。
|
stale-connection-checker |
ブール値の
isStaleConnection(SQLException e) メソッドを提供する org.jboss.jca.adapters.jdbc.StaleConnectionChecker のインスタンス。このメソッドが true を返すと、SQLException のサブクラスである org.jboss.jca.adapters.jdbc.StaleConnectionException に例外がラップされます。
|
exception-sorter |
ブール値である
isExceptionFatal(SQLException e) メソッドを提供する org.jboss.jca.adapters.jdbc.ExceptionSorter のインスタンス。このメソッドは、例外が connectionErrorOccurred メッセージとして javax.resource.spi.ConnectionEventListener のすべてのインスタンスへブロードキャストされるべきであるかどうかを検証します。
|
表10.8 タイムアウトパラメーター
パラメーター | 説明 |
---|---|
use-try-lock | lock() の代わりに tryLock() を使用します。これは、ロックが使用できない場合に即座に失敗するのではなく、設定された秒数間ロックの取得を試みます。デフォルトは 60 秒です。たとえば、タイムアウトを 5 分に設定するには、<use-try-lock> 300</use-try-lock> を設定します。 |
blocking-timeout-millis | 接続待機中にブロックする最大時間 (ミリ秒)。この時間を超過すると、例外がスローされます。これは、接続許可の待機中のみブロックし、新規接続の作成に長時間要している場合は例外をスローしません。デフォルトは 30000 (30 秒) です。 |
idle-timeout-minutes |
アイドル接続が切断されるまでの最大時間 (分単位)。実際の最大時間は idleRemover のスキャン時間によって異なります。idleRemover のスキャン時間はプールの最小
idle-timeout-minutes の半分になります。
|
set-tx-query-timeout |
トランザクションがタイムアウトするまでの残り時間を基にクエリのタイムアウトを設定するかどうかを指定します。トランザクションが存在しない場合は設定済みのクエリのタイムアウトが使用されます。デフォルトは
false です。
|
query-timeout | クエリのタイムアウト (秒)。デフォルトはタイムアウトなしです。 |
allocation-retry | 例外をスローする前に接続の割り当てを再試行する回数。デフォルトは 0 で、初回の割り当て失敗で例外がスローされます。 |
allocation-retry-wait-millis |
接続の割り当てを再試行するまで待機する期間 (ミリ秒単位)。デフォルトは 5000 (5 秒) です。
|
xa-resource-timeout |
ゼロでない場合、この値は
XAResource.setTransactionTimeout メソッドへ渡されます。
|
表10.9 ステートメントのパラメーター
パラメーター | 説明 |
---|---|
track-statements |
接続がプールへ返され、ステートメントが準備済みステートメントキャッシュへ返された時に、閉じられていないステートメントをチェックするかどうかを指定します。false の場合、ステートメントは追跡されません。
有効な値
|
prepared-statement-cache-size | LRU (Least Recently Used) キャッシュにある接続毎の準備済みステートメントの数。 |
share-prepared-statements |
閉じずに同じステートメントを 2 回要求した場合に、同じ基盤の準備済みステートメントを使用するかどうかを指定します。デフォルトは
false です。
|
表10.10 リカバリーパラメーター
パラメーター | 説明 |
---|---|
recover-credential | リカバリーに使用するユーザー名とパスワードのペア、あるいはセキュリティドメイン。 |
recover-plugin |
リカバリーに使用される
org.jboss.jca.core.spi.recoveryRecoveryPlugin クラスの実装。
|
10.6.3. トランザクションロギング
10.6.3.1. トランザクションログメッセージについて
DEBUG
ログレベルを使用します。詳細なデバッグでは TRACE
ログレベルを使用します。トランザクションロガーの設定に関する詳細は 「トランザクションサブシステムのログ設定」 を参照してください。
TRACE
ログレベルに設定すると、トランザクションマネージャーは多くのロギング情報を生成できます。一般的に表示されるメッセージの一部は次のとおりです。他のメッセージが表示されることもあります。
表10.11 トランザクションステートの変更
トランザクションの開始 |
トランザクションが開始されると、次のコードが実行されます。
com.arjuna.ats.arjuna.coordinator.BasicAction::Begin:1342 tsLogger.logger.trace("BasicAction::Begin() for action-id "+ get_uid()); |
トランザクションのコミット |
トランザクションがコミットすると、次のコードが実行されます。
com.arjuna.ats.arjuna.coordinator.BasicAction::End:1342 tsLogger.logger.trace("BasicAction::End() for action-id "+ get_uid()); |
トランザクションのロールバック |
トランザクションがロールバックすると、次のコードが実行されます。
com.arjuna.ats.arjuna.coordinator.BasicAction::Abort:1575 tsLogger.logger.trace("BasicAction::Abort() for action-id "+ get_uid()); |
トランザクションのタイムアウト |
トランザクションがタイムアウトすると、次のコードが実行されます。
com.arjuna.ats.arjuna.coordinator.TransactionReaper::doCancellations:349 tsLogger.logger.trace("Reaper Worker " + Thread.currentThread() + " attempting to cancel " + e._control.get_uid());
その後、上記のように同じスレッドがトランザクションをロールバックすることが確認できます。
|
10.6.3.2. トランザクションサブシステムのログ設定
JBoss Enterprise Application Platform の他のログ設定に依存せずにトランザクションログの情報量を制御する手順を説明します。主に Web ベースの管理コンソールを用いた手順を説明し、管理 CLI のコマンドはその説明の後で取り上げます。
手順10.4 管理コンソールを使用したトランザクションロガーの設定
ログ設定エリアへの移動
管理コンソールにて画面の左上にある [Profiles] タブをクリックします。管理対象ドメインを使用する場合は、右上の [Profile] 選択ボックスから設定したいサーバープロファイルを選択します。[Core] メニューを展開して、[Logging] ラベルをクリックします。com.arjuna
属性を編集します。ページの下の方にある [Details] セクションの [Edit] ボタンをクリックします。ここにクラス固有のログ情報を追加できます。com.arjuna
クラスはすでに存在しています。ログレベルと親ハンドラーを使用するかどうか変更できます。- ログレベル
- デフォルトのログレベルは
WARN
です。トランザクションはログを大量に出力できるため、標準的なログレベルの意味は、トランザクションロガーでは若干異なります。通常、選択したレベルより重要度が低いレベルでタグ付けされたメッセージは破棄されます。トランザクションログのレベル (詳細度が最高レベルから最低レベルまで)
- TRACE
- DEBUG
- INFO
- WARN
- ERROR
- FAILURE
- 親ハンドラーの使用
- ロガーがログ出力を親ロガーに送信するかどうかを指定します。デフォルトの動作は
true
です。
- 変更は直ちに反映されます。
10.6.3.3. トランザクションの参照と管理
log-store
と呼ばれるリソースとして公開します。probe
と呼ばれる API 操作はトランザクションログを読み取り、各ログに対してノードを作成します。probe
コマンドは、log-store
を更新する必要があるときに、いつでも手動で呼び出すことができます。トランザクションログが現れて、すぐに消失されるのは通常のことです。