EJBは、多階層(3階層)の分散オブジェクト指向に基づいたJavaのためのサーバコンポーネントモデルです。サーバのアプリケーションとして必要なコンポーネントのライフサイクル管理、トランザクション管理などの低レベルのインタフェースを隠蔽し、ビジネスロジックの処理を記述するだけで、より抽象度の高いサーバコンポーネントを作成するためのフレームワークです。
EJBでは、サーバのアプリケーションに必要なライフサイクルなどの各種の管理処理をコンテナ(container)と呼ばれるサーバコンポーネントの入れ物で実現します。コンテナが煩雑な処理を肩代わりします。また、EJBではコンテナ上で動作するサーバコンポーネントをEnterprise Beanと呼びます。
コンテナにEnterprise Beanをインストールし、実行可能な状態にすることを配備と呼びます。EJBでは配備という方式の導入により、ある特定のコンテナに依存しないポータビリティのあるサーバコンポーネントの作成を可能にしています。
EJBでは、以下の機能を規定しています。
Enterprise Beanインスタンスのライフサイクル管理
トランザクション管理
セキュリティ管理
セション管理
リソース管理
Enterprise Beanには、大きく分けて、以下の種類があります。
Session Bean(セションビーン)
クライアントとの対話処理を行うEnterprise Beanです。主に業務処理で必要となる処理(ビジネスロジック)を記述します。
Message-driven Bean(メッセージドリブンビーン)
非同期通信処理を行うためのEnterprise Beanです。
以下に分類とそれぞれの用途について説明します。
注意
EJB2.1までの仕様では、データベースシステムなどのデータを扱うためのEntity Bean(エンティティビーン)があります。しかしEJB 3.0からはEntity Beanの代わりにJava Persistence APIを使うようになっているため、本マニュアルではEntity Beanの説明は省略します。
Session Bean(セションビーン)とは、アプリケーションの業務ロジック(ビジネスロジック)をサーバに配置したもので、複数のクライアントに対して、ネットワークを介してサービスを提供するものです。
Session Beanでは、他のEnterprise Beanを呼び出したり、トランザクションや処理の流れを制御したり、独自の処理を実装することで業務ロジックを実行します。
Session Beanには、以下の2種類があります。
Stateful
クライアントと1対1に対応し、クライアントから呼び出される複数のメソッドにまたがって、トランザクション状態やEnterprise Beanに定義されている変数の値を保持することができます。そのため、ある機能を提供するうえで複数の手順(メソッド)が必要な場合に使用します。
Stateless
複数のメソッドにまたがって、トランザクション状態やEnterprise Beanに定義されている変数の値を保持することができません。そのため、1つのメソッドで完結する機能を提供する場合に使用します。また、複数のクライアントが、同じSession Beanのインスタンスを共有することができるため、サーバの負荷を軽減することができます。
例えば、単なる四則演算を行うような処理をSession Beanで実現するような場合にはStatelessにすべきです。保持しなければならない情報がないので、Statelessにしてサーバの負荷を減らします。一方、オンラインショッピングサイトのショッピングカートをSession Beanで実現する場合、これはStatefulにすべきです。ユーザが買い物かごにどの商品を入れたかを複数のページに渡って保持する必要があるからです。
Message-driven Bean(メッセージドリブンビーン)
Message-driven Beanとは、クライアントから送信されたメッセージに対して非同期に処理を行うための基盤を提供するものです。
Message-driven BeanからSession Beanなどを呼び出すことで、その機能を非同期に実行できます。
Message-driven Beanは、JMSメッセージまたはリソースアダプタのメッセージを受信して処理します。JMSメッセージの場合は、メッセージの処理の方法で以下の2種類に分類できます。
Point-To-Pointモデル
送信者から送信された1つのメッセージに対して、特定の受信者が処理を行います。すなわち、メッセージに対して受信者を単独で割り当てる場合に使用します。
このモデルでは、送信されたメッセージはJMSサーバ上のキューに貯えられます。貯えられたメッセージは特定の受信者に割り当てられて処理されます。
Publish/Subscribeモデル
送信者から送信された1つのメッセージに対して、複数の受信者が処理を行います。すなわち、同一のメッセージを複数の受信者に配信する必要がある場合に使用します。
このモデルでは、送信されたメッセージはJMSサーバ上のトピックに貯えられます。貯えられたメッセージはすべての受信者に割り当てられて各受信者によって処理されます。
Java EEに含まれるEJB仕様はEJB 3.0です。EJB 3.0はJ2EE 1.4までのEJBが複雑であるという声を受けて、開発が簡単にできるように仕様が改善されています。
記述の簡素化
EJB 3.0の大きな特徴の1つは、EJBの記述が簡素化されたことです。
従来のEJB仕様ではEJBの各種定義をejb-jar.xmlというdeployment descriptorに記述する必要がありました。EJB 3.0では、EJBの各種定義はJavaのアノテーションを用いてEnterprise Beanクラスに記述するようになっています。これによりEJBのdeployment descriptorを作成する必要はほとんどの場合なくなりました。
また、EJBの各種定義も必要な場合だけ定義すれば良いように改善されています。これにより開発者が記述しなければならない定義の数も少なくなっています。例えば、Session BeanのクラスにJavaのインタフェースを1つ実装すると、それが自動的にEJBのLocalインタフェースとして扱われます。この場合、どのインタフェースがLocalインタフェースかという情報を開発者が記述する必要はありません。
加えて、Enterprise Beanの実装に最低限必要となるファイルの数も少なくなっています。従来のEJBとEJB3.0でそれぞれEnterprise Beanの開発に必要な要素は次表のとおりです。
| Enterprise Beanの種類 | 従来のEJB(~EJB 2.1) | EJB 3.0 | 
|---|---|---|
| Session Bean | 
 | 
 | 
| Message Driven Bean | 
 | 
 | 
Java Persistence API(JPA)の導入
EJB 3.0のもう1つの大きな特徴はJPAが導入されたことです。JPAはEntity Beanに代わる永続化APIです。他のEnterprise Beanと同様に、JPAの記述もJavaのアノテーションを用いて行うことができます。また、JPAでは、データベースへのアクセスにEJB QLを拡張したクエリ言語が使用できます。
JPAの大きな特徴は、JPAが汎用的な永続化APIであることです。JPAはEJBからだけでなく、WebアプリケーションやJavaアプリケーションから使用することも可能です。
JPAおよびJPAを用いた開発の詳細については"4.1.2 JPAを使用したアプリケーションの開発"を参照してください。
以下に、EJB 3.0の主なアノテーションについて、簡単な例を示しながら紹介します。
javax.ejb.Stateless/javax.ejb.Statefulアノテーション
クラスをSession Beanとして定義するアノテーションです。以下のプロパティを指定できます。
| プロパティ名 | 解説 | 
|---|---|
| name | EJB名を定義します。このプロパティを定義しない場合、Session Beanのクラス名がEJB名になります。 | 
| mappedName | アプリケーションサーバ製品が固有のBeanマッピング名を必要とする場合に、このプロパティを使用します。 | 
| description | このSession Beanの説明を定義します。 | 
Statelessアノテーションを使用したSession Beanの作成例
| package sample;
import javax.ejb.Stateless;
@Stateless
public class CalcBean implements Calc {
      	public int add(int param1,int param2) {
            return param1 + param2;
      	}
} | 
javax.ejb.MessageDrivenアノテーション
クラスをMessage-driven Beanとして定義するアノテーションです。以下のプロパティを指定できます。
| プロパティ名 | 解説 | 
|---|---|
| name | EJB名を定義します。このプロパティを定義しない場合、Message-driven Beanのクラス名がEJB名になります。 | 
| messageListenerInterface | Beanのメッセージリスナインタフェースを定義します。このプロパティはBeanのクラスがメッセージリスナインタフェースを実装していない場合、または、複数のインタフェースを実装している場合にだけ定義する必要があります。 | 
| activationConfig | Message-driven Bean用のプロパティを定義します。 | 
| mappedName | アプリケーションサーバ製品が固有のBeanマッピング名を必要とする場合に、このプロパティを使用します。 | 
| description | このMessage-driven Beanの説明を定義します。 | 
Message Drivenアノテーションを使用したMessage Driven Beanの作成例
| package sample;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.MessageListener;
import javax.jms.Message;
@MessageDriven(mappedName = "jms/CalcBean" activationConfig = {
      @ActivationConfigProperty(
            propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
      @ActivationConfigProperty(
            propertyName = "destinationType", propertyValue = "javax.jms.Queue")
})
public class CalcBean implements MessageListener {
      	public void onMessage(Message msg) {
            ...
      }
} | 
javax.ejb.EJBアノテーション
Enterprise Beanを呼び出す場合にDependency Injectionするためのアノテーションです。以下のプロパティを指定できます。
| プロパティ名 | 解説 | 
|---|---|
| name | 参照するBeanのJNDI名 | 
| beanInterface | 参照するBeanのビジネスインタフェース。 | 
| beanName | 参照するBeanのBean名。 | 
| mappedName | アプリケーションサーバ製品が固有のBeanマッピング名を必要とする場合に、このプロパティを使用します。 | 
| description | この呼出しの説明を定義します。 | 
EJBアノテーションを使用したEJBクライアントの作成例
| @EJB
private static Calc calc;
public int callCalc(int param1,int param2) {
      return calc.add(param1,param2);
} |