はじめに
EJB 2.1からEJB 3.0への移行方法を説明する前に、この移行によるメリットを紹介しなければなりません。基本的に、EJB 3.0ではEJBの作成に必要なクラス、インターフェイス、および配備記述子の数が削減されています。EJB 3.0仕様では、Beanの抽象クラスの代わりに従来の普通のJavaオブジェクト(Plain Old Java Object:POJO)を使い、コンポーネントインターフェイスとホームインターフェイスの代わりに従来の普通のJavaインターフェイス(Plain Old Java Interfaces:POJI)を使うことによってEJB開発を簡易化しています。ただし、インターフェイスの指定は任意なので、必ずしも含める必要はありません。
EJB 3.0での変更点は次のとおりです。
- EJB名を指定する配備記述子「ejb-jar.xml」、Beanクラス名、インターフェイス、finderメソッド、コンテナ管理リレーションシップ(Container-Managed Relationship:CMR)、およびベンダ固有の配備記述子は必要なくなりました。これらの代わりに、Beanクラス内のメタデータアノテーションを使います。アノテーションが利用できるようになったのはJDK 5.0からなので、EJB 3.0仕様のEJBを開発する場合にはJDK 5.0が必要です。
- EJB 3.0では、EJB 2.1の
create()メソッドとfinderメソッドの代わりに、javax.persistence.EntityManagerAPIを使います。EJB 2.1では、クライアントアプリケーションはエンティティBeanオブジェクトとセッションBeanオブジェクトの参照を取得する場合にJNDI名を使いますが、EJB 3.0では@Resourceアノテーション、@Injectアノテーション、および@EJBアノテーションを使います。 - EJB 2.1では、エンティティBeanとセッションBeanの開発にjavax.ejbパッケージのクラスとインターフェイスを使い、セッションBeanは
SessionBeanインターフェイスを実装し、エンティティBeanはEntityBeanインターフェイスを実装していました。一方、EJB 3.0では、セッションBeanクラスとエンティティBeanクラスはPOJOで、SessionBeanインターフェイスとEntityBeanインターフェイスは実装しません。 - EJB 2.1では、セッションBeanクラスは1つ以上の
ejbCreateメソッド、コールバックメソッド、setSessionContextメソッド、およびビジネスメソッドを指定します。同様に、エンティティEJBは、ejbCreate()メソッド、ejbPostCreate()メソッド、コールバックメソッド、コンテナ管理パーシスタンス(Container-Managed Persistence:CMP)、getter CMR、setter CMR、getterメソッド、setterメソッド、およびビジネスメソッドを指定します。EJB 3.0では、セッションBeanクラスが指定するのはビジネスメソッドのみです。同様に、エンティティBeanが指定するのは、ビジネスメソッド、各種Beanプロパティのgetter/setterメソッド、およびBeanリレーションシップのgetter/setterメソッドのみです。 - EJB 2.1では、ホームインターフェイスは
javax.ejb.EJBHomeインターフェイスを拡張し、ローカルホームインターフェイスはjavax.ejb.EJBLocalHomeインターフェイスを拡張します。リモートインターフェイスはjavax.ejb.EJBObjectインターフェイスを拡張し、ローカルインターフェイスはjavax.ejb.EJBLocalObjectインターフェイスを拡張します。EJB 3.0では、ローカルインターフェイスとホームインターフェイスを指定しません。代わりにPOJIのビジネスインターフェイスを使います。セッションBeanクラスでビジネスインターフェイスが指定されないと、EJBサーバーはセッションBeanクラスからPOJIのビジネスインターフェイスを生成します。
これらの変更点を念頭に置いて、本稿ではサンプルセッションBeanとサンプルエンティティBeanをEJB 2.1からEJB 3.0に移行する場合に知っておかなければならないことを中心に詳しく説明します。
セッションBeanを移行する
EJB 2.1のサンプルセッションBeanクラスであるBookCatalogBeanには、ejbCreateメソッド、getTitle()ビジネスメソッド、および次のコールバックメソッドが定義されています。
// BookCatalogBean.java import javax.ejb.SessionBean; import javax.ejb.SessionContext; public class BookCatalogBean implements SessionBean { private SessionContext ctx; public String getEdition(String title) { if(title.equals("Java & XML")) return new String("2nd edition"); if(title.equals("Java and XSLT")) return new String("1st edition"); } public void ejbCreate(){} public void ejbRemove() {} public void ejbActivate() {} public void ejbPassivate() {} public void setSessionContext(SessionContext ctx) {this.ctx=ctx;} }
EJB 3.0では、セッションBeanはメタデータのアノテーションを使ってBeanの種類を指定します。Beanがステートフルの場合は@Statefulアノテーション、ステートレスの場合は@Statelessアノテーションを使います。また、セッションBeanでは、コンポーネントインターフェイスとホームインターフェイスの代わりにビジネスインターフェイスを使います。ビジネスインターフェイスはPOJIで、アノテーション@Localと@Remoteを使って、ローカルまたはリモートのいずれかを指定することができます。また、セッションBeanでは、ローカルインターフェイスとリモートインターフェイスの両方を実装することもできます。
Beanクラスでインターフェイス(ローカルまたはリモート)を指定しないと、既定ではEJBサーバーによって自動的にローカルビジネスインターフェイスが生成されます。また、@Localアノテーションと@Remoteアノテーションを使ってインターフェイスクラスを指定することもできます。
次に示すEJB 3.0のセッションBeanは、「BookCatalogBean.java」という名前のPOJOで、前述のEJB 2.1のステートレスセッションBeanを移行したものです。@Statelessアノテーションを使い、ローカルビジネスインターフェイスを実装し、@Localアノテーションでローカルインターフェイスのクラス名を指定していることに注意してください。
// BookCatalogBean.java EJB 3.0 Session Bean @Stateless @Local ({BookCatalogLocal.java}) public class BookCatalogBean implements BookCatalogLocal { public String getEdition(String title) { if(title.equals("Java & XML")) return new String("2nd edition"); if(title.equals("Java and XSLT")) return new String("1st edition"); } }
また、このEJB 3.0のセッションBeanでは、EJB 2.1バージョンのコンポーネントインターフェイスとホームインターフェイスの代わりに、@Localアノテーションを使ってアノテーションを付けてローカルビジネスインターフェイス(POJI)を使っています。
EJBセッションBeanのクライアントを移行する
EJB 2.1では、セッションBeanのクライアントはJNDI名を使ってセッションBeanオブジェクトを取得します。次に示すクライアントは、JNDI名「BookCatalogLocalHome」を使ってローカルホームオブジェクトを取得し、create()メソッドを呼び出します。その後、クライアントは、getEdition(String)ビジネスメソッドを使って指定されたタイトルの版の値を出力します。
import javax.naming.InitialContext; public class BookCatalogClient { public static void main(String[] argv) { try{ InitialContext ctx=new InitialContext(); Object objref=ctx.lookup( "BookCatalogLocalHome"); BookCatalogLocalHome catalogLocalHome = (BookCatalogLocalHome)objref; BookCatalogLocal catalogLocal = (BookCatalogLocal) catalogLocalHome. create(); String title="Java and XML"; String edition = catalogLocal.getEdition(title); System.out.println("Edition for Title: " + title + " " + edition); } catch(Exception e){} } }
EJB 3.0では、@Injectアノテーション、@Resourceアノテーション、または@EJBアノテーションを使って実装する依存性注入によって、セッションBeanオブジェクトの参照を取得します。次に示すEJB 3.0のセッションBeanのクライアントクラスは、@Injectアノテーションを使ってBookCatalogBeanクラスを注入します。タイトルの版の値の取得には、これまでどおりgetEdition(String)ビジネスメソッドを使います。
public class BookCatalogClient { @Inject BookCatalogBean; BookCatalogBean catalogBean; String title="Java and XML"; String edition=catalogBean.getEdition(edition); System.out.println("Edition for Title: " + title + " " + edition); }
