Topics
Enterprise Architecture
Enterprise JavaBeans 3.0仕様入門
Pages:
1,
2,
3,
4,
5,
6
Beanは依存性注釈を通じて、その環境コンテキスト内のリソースまたはその他のエントリに対する依存性を宣言します。依存性注釈では、Beanが依存するオブジェクトまたはリソースのタイプ、その特性、オブジェクトまたはリソースにアクセスするための名前を指定します。
依存性注釈の例を次に示します。
@EJB(name="mySessionBean", beanInterface=MySessionIF.class)
@Resource(name="myDB", type="javax.sql.DataSource.class")
依存性注釈はBeanクラスに、あるいはそのクラスのインスタンス変数またはインスタンスメソッドに付けることができます。依存性注釈で指定する必要がある情報の量は、その使用コンテキストと、コンテキストから推量される情報の量に応じて変化します。
@Resourceによる任意のリソースの注入
@EJB注釈はEJBスタブの注入のみを行います。より汎用的な依存性注入注釈は
@Resourceです。
@Resource注 釈を利用すると、JNDIにある任意のサービスオブジェクトを、オブジェクトのJNDI名を使用して注入することができます。グローバル(java:/) およびローカル(java:comp/env)両方のJNDIツリーが検索されます。次の例は、メッセージング接続ファクトリおよびメッセージングキュー を注入します。
@Resource (name="ConnectionFactory") QueueConnectionFactory factory;
@Resource (name="queue/A") Queue queue;
TimerServiceや
SessionContextなどの「よく知られた」オブジェクトについては、JNDI名は標準であるため、
@Resource注釈では次のように、「name」属性を明示的に指定することなくこれらのオブジェクトを注入できます。
@Resource TimerService tms;
@Resource SessionContext ctx;
@EJB注釈と同様に、
@Resource注釈はセッターメソッドに、注釈は
@Resources配列に適用できます。
@EJB注釈と
@Resource注釈はどちらも、注入するリソースの種類に合わせて特別にカスタマイズされています。これらの注釈により、開発者の作業が簡素化されます。
次の例では、変数
customerDBは
myDBというJNDI名でDataSourceオブジェクトに割り当てられます。選択した変数の名前
customerDBはJNDI名
myDBと異なるため、「name」属性の指定が必要です。「type」属性は変数の型(例:
DataSource)から取得可能なため、この属性の指定は不要です。
@Stateless public class MySessionBean implements MySession {
//type is inferred from variable
@Resource(name="myDB") public DataSource customerDB;
public void myMethod1(String myString){
try {
Connection conn = customerDB.getConnection();
...
catch (Exception ex)
}
}
よく知られているように、EJBには4つのタイプがあり、EJB 3.0ではそれぞれのタイプのEJBに多少の変更が加えられています。この節では、各タイプのEJBに対して仕様で提案されている変更について順次見てい きます。EJB 3.0の主なメリットの1つは、すべての管理対象サービスオブジェクトがPOJO(例:セッションBean)またはきわめて軽量なコンポーネント(例: メッセージ駆動型Bean)であるという点です。これまでに述べたように、EJB 3.0ではEJBの開発が簡素化され、容易になっています。
EJB 3.0のセッションBeanはEJBコンテナによって管理されるPOJOです。
セッションBeanの機能は、通常の従来型Javaインタフェース(POJI)であるそのサービスインタフェース(ビジネスインタフェースとも呼ば れる)によって定義されます。セッションBeanのクライアントは、インタフェースクラス名を使用してBeanのスタブオブジェクトをサーバのJNDIか ら取得します。スタブオブジェクトはBeanのサービスインタフェースを実装します。クライアントはその後、スタブオブジェクトに対してBeanのインタ フェースメソッドの呼び出しを行うことができます。スタブオブジェクトの働きは、コンテナ内の実際のBeanインスタンスオブジェクトに呼び出しを渡すこ とだけです。呼び出されるメソッドの実装を持ち、実際の処理を行うのはこれらのインスタンスオブジェクトです。スタブオブジェクトはEJBコンテナによっ て自動生成され、Beanメソッドの呼び出しをコンテナにルーティングするメカニズムを備えています。開発者がスタブオブジェクトの実装を提供する必要は ありません。ステートレスセッションBeanの場合、クライアント側のスタブオブジェクトが、その時点でコンテナ管理のオブジェクトプール内で利用可能な Beanインスタンスを調べ、そのインスタンスにメソッド呼び出しをルーティングすることができます。したがって開発者は、Beanの状態を格納するため のフィールド変数を一切、Beanクラスに定義するべきではありません。
ビジネスインタフェースは、ステートレスセッションBeanに対して必須です。ただし、それを定義することが常に必要とは限りません。開発者が定義 しない場合は自動的に生成されます。生成されるインタフェースのタイプ(ローカルまたはリモート)はBeanクラスの注釈から決定され、注釈がなければ ローカルインタフェースになります。自動生成されるビジネスインタフェースにはBeanクラスのすべてのpublicメソッドが取り込まれます。
ステートレスセッションBeanにはホームインタフェースは不要です。クライアントは変数の注入または注釈によってステートレスセッションBeanへの参照を取得できます。
ステートレスセッションBeanには、ステートレスであることを示す注釈を付ける必要があります。または、ステートレスセッションBeanであることをデプロイメント記述子で定義する必要があります。Beanクラスは
javax.ejb.SessionBeanインタフェースを実装する必要はありません。
@Stateless注釈は、BeanがステートレスセッションBeanであることを示します。次に例を示します。
@Stateless
public class TraderBean implements Trader {
public void buy (String symbol, int quantity){
System.out.println("Buying "+quantity+ " of "+ symbol);
}
public void sell (String symbol, int quantity);{
System.out.println("Selling "+quantity+ " of "+ symbol);
}
}
セッションBeanをEJB 3.0コンテナにデプロイすると、スタブオブジェクトが作成され、サーバのJNDIレジストリに登録されます。クライアントコードは、JNDIに登録され たインタフェースのクラス名を使用してBeanのスタブを取得します。次に示すのは、このJSPページに対して
TraderBeanのスタブインスタンスを取得する方法の例です。クライアントはスタブオブジェクトに対してメソッド呼び出しを行うことができ、呼び出しはEJB 3.0コンテナ内のBeanインスタンスに透過的に委譲されます。
private Trader tr = null;
public void initialize () {
try {
InitialContext ctx = new InitialContext();
tr = (Trader) ctx.lookup(
Trader.class.getName());
}catch (Exception e) {
e.printStackTrace ();
}
}
// ... ...
public void service (Request req, Response rep) {
// ... ...
double res = tr.buy("SNPS",1000);
}
ステートレスセッションBeanに対しては、次のライフサイクルイベントコールバックがサポートされています。
PostConstruct
PreDestroy
PostConstructコールバックは、コンテナによって何らかの依存性注入が実行された後、および、Beanに対する初回のビジネスメソッド呼び出しの前に発生します。
PostConstructメソッドは、未指定のトランザクションコンテキストおよびセキュリティコンテキストで呼び出されます。
PreDestroyコールバックはBeanインスタンスが破棄されるときに発生します。
PreDestroyメソッドは未指定のトランザクションコンテキストおよびセキュリティコンテキストで実行されます。
セッションBeanでは、それぞれ異なる種類のクライアントをターゲットとする複数のインタフェースを実装することもできます。デフォルトでは、イ ンタフェースのターゲットはEJB 3.0コンテナと同じJVM内で動作する「ローカル」クライアントです。Java参照を通じたメソッド呼び出しは高速で効率的です。もう1つのタイプの セッションBeanインタフェースであるリモートインタフェースは、リモートクライアントをターゲットとしたものです。クライアントがリモートインタ フェースを介してセッションBeanのスタブをルックアップすると、コンテナはリモートインタフェースを実装するシリアライズされたスタブオブジェクトを 返します。リモートスタブは、クラスタ環境の場合も含め、サーバにリモートプロシージャコール(RPC)を渡すメカニズムを備えています。リモートインタ フェースは通常の従来型Javaインタフェース(POJI)でもあります。
注意すべきは、リモートインタフェースの使用にはスタブのシリアライズとデシリアライズが伴い、Beanインスタンスへのすべての呼び出しはネット ワーク経由で行われるという点です。このアプローチは、ローカルインタフェースの使用と比べてかなり非効率的です。そのため、ローカルクライアントからの リモートインタフェースのルックアップは避けるべきです。
セッションBeanの実装で
@Localおよび
@Remote注釈を使用すると、このBeanに対するローカルおよびリモートのインタフェースを指定することができます。次に示すのは、ローカルインタフェースとリモートインタフェースの両方を実装するBeanの例です。
@Stateless
@Local ({Trader.class})
@Remote ({RemoteTrader.class})
public class TraderBean implements Trader, RemoteTrader {
public void buy (String symbol, int quantity){
System.out.println("Buying "+quantity+ " of "+ symbol);
}
public void sell (String symbol, int quantity);{
System.out.println("Selling "+quantity+ " of "+ symbol);
}
}
@Localおよび
@Remote注釈は、Beanの実装クラスではなくセッションBeanのインタフェースにタグ付けする目的にも使用できます。たとえば、次のコードはRemoteTraderがリモートインタフェースであることを指定します。これにより、
TraderBean上の
@Remoteタグは不要になります。