| JBoss EJB 3.0と拡張機能
サービスオブジェクトの注入
はじめに
| ここまで、いろいろなサービスオブジェクトの作成方法と、どのようにクライアント側から使用するかを学んできました。基本的にはJNDIを利用してサービスのスタブオブジェクトをルックアップします。しかし、サービスオブジェクトが増えてくると、すぐにルックアップのコードは長く乱雑になってしまいます。また、サービスをルックアップするには、サーバ側とクライアント側で事前に各サービスの名前を取り決めておく必要があり、開発者がそれらを記録しておく必要があります。ルックアップ後は、サービスのスタブオブジェクトを適切なインタフェースの型に手動でキャストする必要があり、型が違っていた場合には実行時に例外が発生してしまいます。さらに、サービスのルックアップのコードは、全アプリケーションに渡って重複され散らかっています。 EJB 3.0アプリケーション内でオブジェクトを取得する場合、JNDIのルックアップよりもはるかに良い簡単な方法は、依存性注入のデザインパターンを使うことです。このトレイルでは、EJB 3.0の依存性注入について学びます。 依存性注入（Inversion of Control: IoCとも言います）の背後にある考え方は、各アプリケーションコンポーネントがどんなタイプのサービスオブジェクトを必要としているか（これを依存性と言います）を宣言するということです。コンテナがアプリケーションコンポーネント間の依存性を解決し、サービスオブジェクトをインスタンス化し、サービスのスタブを実行時にアプリケーションに注入します。注入は自動的にJavaBeanのセッターメソッドを呼び出すか、あるいは直接データフィールドへ値を代入することで行います。 EJB 3.0は、依存性注入のデザインパターンの実装をとてもエレガントな方法、つまりアノテーションで提供しています。では、どのように使用するか見ていきましょう。 EJB 3.0の依存性注入アノテーションはEJBオブジェクトでのみ使用できることに注意してください。一般的なPOJOでは利用できません。たとえば、サーブレットに依存性注入アノテーションを使用してセッションBeanオブジェクトを取得することはできません。さらに、EJB 3.0の依存性注入はローカルJNDIでのみ使用できます。つまり、リモートサーバからオブジェクトを注入することはできません。
サンプルアプリケーション
| このトレイルでは、注入リソースをたくさん利用するサンプルアプリケーションを見ていきます。概観はメッセージ駆動型Beanのサンプルアプリケーションとだいたい同じです。`CalculatorMDB`は、メッセージキュー`queue/injection`の終端ですが、サービスそのものは実行せず、計算と結果保存の仕事を２つのステートレスセッションBean、`CalculatorBean`と`RecordManagerBean`、に委譲します。これら２つのBeanのスタブオブジェクトが`CalculatorMDB`に注入されます。 `RecordManagerBean`は、`check.jsp`ページがルックアップできるように、計算結果をサーバの組み込みデータベースに保存します。`RecordManagerBean`はJNDIで注入されたJDBCリソース経由でデータベースにアクセスします。
`@EJB`でEJBを注入する
| EJBのスタブを注入するには`@EJB`タグを使用します。以前のトレイルで見たJSPページのセッションBeanのルックアップのコードは不要になります。下の例では、`CalculatorMDB`クラスのフィールド変数`rm`は`RecordManager`型で、これは`RecordManagerBean`ステートレスセッションBeanのローカルインタフェースです。つまり、コンテナは`RecordManagerBean`のスタブを取得する方法を見つけ、最初に使用される前に`rm`にスタブを割り当てます。開発者の視点で見ると、ルックアップをしなくても`rm`に自動的に値が代入されます。
    public class CalculatorMDB implements MessageListener {

      @EJB RecordManager rm;

      // use the rm variable
      // ... ...
    }
あるいは、依存性注入のアノテーションをセッターメソッドに使用することもできます。つまり、下に示すコードは上記のコードと全く同じ動作になります。コンテナが自動的に行ってくれるので、開発者は`setCal()`メソッドを呼ぶ必要はありません。
    public class CalculatorMDB implements MessageListener {

      RecordManager rm;

      @EJB
      public void setRm (RecordManager rm) {
        this.rm = rm;
      }

      // use the rm variable
      // ... ...
    }
ある状況下では、コンテナがBeanインスタンスを見つける方法を指定するために、`@EJB`アノテーションにいくつかの属性を指定することもできます。 `beanName`属性はEJBのクラス名（パッケージ名無し）を指定します。あるいはEJBにXML記述子がある場合は、`ejb-name`属性を指定します。 `beanInterface`属性は、変数の型がビジネスインタフェースの親クラスだった場合に、Beanのローカルビジネスインタフェースまたはリモートビジネスインタフェースを指定します。Beanインスタンスが注入され、自動的にフィールド変数の型にキャストされます。 `mappedName`属性はBeanインスタンスのJNDI名を指定します。デフォルトのJNDI名は、"EARファイルの基本名"/"Beanクラス名"/local（またはremote）です。 下に示すコードは、`beanName`属性と`mappedName`属性を使用して`StatelessCalculator`セッションBeanを見つけ、注入する例です。
    public class CalculatorMDB implements MessageListener {

      @EJB (beanName="StatelessCalculator")
      // or @EJB (mappedName="EJB3Trail/StatelessCalculator/local")
      Calculator cal;

      // use the cal variables
      // ... ...
    }
最後の注入方法は、`@EJBs`アノテーションを使用して、配列に複数のEJBインスタンスを注入することです。
`@Resource`で任意のリソースを注入する
| `@EJB`アノテーションはEJBスタブのみを注入します。さらに汎用的な依存性注入用のアノテーションは`@Resource`です。`RecordManagerBean`は`@Resource`を使ってサーバのデフォルトの`DataSource`である組み込みのHSQLデータベースを注入します。Beanは各計算結果を、`DataSource`から取得したJDBCコネクションを使ってデータベースに保存します。Web層の`check.jsp`ページはデータベースを定期的にチェックし、新たな計算結果が取得できたら表示します。アノテーションの`name`属性の`"java:/DefaultDS"`が`DataSource`のグローバルJNDI名を表します。
    public class RecordManagerBean implements RecordManager {

      // Inject resources based on jndi names
      @Resource (mappedName="java:/DefaultDS")
      DataSource myDb;

      // use myDb to obtain JDBC connection
      // and operate the database ...
    }
一般的には、オブジェクトのJNDI名を使えばどのサービスオブジェクトでもJNDIから注入できます。JNDIオブジェクトがローカルなJNDIツリー（`java:comp/env`）にある場合は、マップされた名前を接頭辞なしに指定すれば、自動的にローカルツリーが検索されます。メッセージのコネクションファクトリとメッセージキューを注入する例を下に示します。
    @Resource (mappedName="ConnectionFactory")
    QueueConnectionFactory factory;

    @Resource (mappedName="queue/A")
    Queue queue;
「よく知られた」オブジェクトであれば、JNDI名がなくても`@Resource`アノテーションで注入できます。オブジェクトの型からオブジェクト名を推測します。たとえば、次のようなものがあります。
    @Resource
    TimerService tms;

    @Resource
    SessionContext ctx;
`@EJB`アノテーションと同様、`@Resource`アノテーションはセッターメソッドにも配列にも使用できます。
その他の依存性注入アノテーション
| `@EJB`アノテーションも`@Resource`アノテーションも、注入するリソース用に特注されています。開発者の作業を簡単にするためです。もう１つの重要な依存性注入アノテーションは`EntityManager`オブジェクトの注入です。`EntityManager`オブジェクトはEJB 3.0コンテナでPOJOデータの永続性処理を行います。EntityManagerとその依存性注入アノテーションについては後のトレイルで学習します。
ソースコード参照
| サーバ CalculatorMDB.java: `queue/injection`キューのメッセージを処理するメッセージ駆動型Bean。２つのセッションBeanが注入される。 CalculationRecord.java: `CalculatorMDB`の個々の計算結果を保存するデータオブジェクトクラス。オブジェクトはサービス要求メッセージのタイムスタンプ"sent"で一意に識別される。 RecordManager.java: サーバ組み込みデータベースの計算結果レコードを保存したり取得したりするセッションBeanのインタフェース。 RecordManagerBean.java: サーバ組み込みデータベースの計算結果レコードを保存したり取得したりするセッションBeanの実装。`DataSource`に対応したデータベースが注入される。 クライアント calculator.jsp: ユーザからの入力を受け取り、投資計算のサービス要求メッセージを送信するクライアントJSP。 check.jsp: `RecordManager`を使用して`CalculatorBean`の処理が終了するのを待つクライアントJSP。待機するサービス要求メッセージは、メッセージのタイムスタンプ"sent"で識別される。
まとめ
| このトレイルでは、アプリケーションにサービスオブジェクトを注入する依存性注入アノテーションの使い方についてお教えしました。依存性注入のデザインパターンは、コードを単純にし、アプリケーションの構造を改善します。これでEJB 3.0サービスオブジェクト管理のトレイルは終了です。 このトレイルの`RecordManagerBean`セッションBeanは、注入された`DataSource`とJDBCを使いリレーショナルデータベースからデータを取得・保存しています。しかしJavaアプリケーションでデータベースを管理するさらに良い方法は、データPOJOを使うことです。次のハイキングでは、EJB 3.0のエンティティBeanについて学習し、POJOデータの永続性とデータアクセスについて学びます。