|
事業仕分けによる次世代スーパーコンピューターの開発予算削減について、どうお考えですか?
|
EJB 2.1からEJB 3.0への移行はじめに EJB 2.1からEJB 3.0への移行方法を説明する前に、この移行によるメリットを紹介しなければなりません。基本的に、EJB 3.0ではEJBの作成に必要なクラス、インターフェイス、および配備記述子の数が削減されています。EJB 3.0仕様では、Beanの抽象クラスの代わりに従来の普通の EJB 3.0での変更点は次のとおりです。
これらの変更点を念頭に置いて、本稿ではサンプルセッションBeanとサンプルエンティティBeanをEJB 2.1からEJB 3.0に移行する場合に知っておかなければならないことを中心に詳しく説明します。 セッションBeanを移行する EJB 2.1のサンプルセッションBeanクラスである // 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がステートフルの場合は Beanクラスでインターフェイス(ローカルまたはリモート)を指定しないと、既定ではEJBサーバーによって自動的にローカルビジネスインターフェイスが生成されます。また、 次に示すEJB 3.0のセッションBeanは、「BookCatalogBean.java」という名前のPOJOで、前述のEJB 2.1のステートレスセッションBeanを移行したものです。 // 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バージョンのコンポーネントインターフェイスとホームインターフェイスの代わりに、 EJBセッションBeanのクライアントを移行する EJB 2.1では、セッションBeanのクライアントはJNDI名を使ってセッションBeanオブジェクトを取得します。次に示すクライアントは、JNDI名「BookCatalogLocalHome」を使ってローカルホームオブジェクトを取得し、 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では、 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); } エンティティBeanを移行する 次に、EJB 2.1のエンティティBeanをEJB 3.0仕様に移行する方法を説明します。EJB 2.1のエンティティBeanは、 リスト1 BookCatalogBean.java
import javax.ejb.EntityBean; import javax.ejb.EntityContext; public class BookCatalogBean implements EntityBean { private EntityContext ctx; public abstract void setTitle(); public abstract String getTitle(); public abstract void setAuthor(); public abstract String getAuthor(); public abstract void setPublisher(); public abstract String getPublisher(); public abstract void setEditions( java.util.Collection editions); public abstract java.util.Collection getEditions(); public String ejbCreate(String title) { setTitle(title); return null; } public void ejbRemove() {} public void ejbActivate() {} public void ejbPassivate() {} public void ejbLoad() {} public void ejbStore() {} public void setEntityContext(EntityContext ctx) { this.ctx=ctx; } public void unsetEntityContext() { ctx = null; } } このEJB 2.1のエンティティBeanの「ejb-jar.xml」配備記述子(リスト2)では、EJBのクラスとインターフェイス、CMPフィールド、EJB QLクエリ、およびCMRリレーションシップを指定します。 リスト2 「ejb-jar.xml」配備記述子
<?xml version="1.0"?> <!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd"> <ejb-jar> <enterprise-beans> <entity> <ejb-name>BookCatalog</ejb-name> <local-home>BookCatalogLocalHome</local-home> <local>BookCatalogLocal</local> <ejb-class>BookCatalogBean</ejb-class> <persistence-type>Container</persistence-type> <prim-key-class>String</prim-key-class> <reentrant>False</reentrant> <cmp-version>2.x</cmp-version> <abstract-schema-name>BookCatalog</abstract-schema-name> <cmp-field> <field-name>title</field-name> </cmp-field> <cmp-field> <field-name>author</field-name> </cmp-field> <cmp-field> <field-name>publisher</field-name> </cmp-field> <query> <query-method> <method-name>findByTitle</method-name> <method-params> <method-param>java.lang.String</method-param> </method-params> </query-method> <ejb-ql> <![CDATA[SELECT DISTINCT OBJECT(obj) FROM BookCatalog obj WHERE obj.title = ?1 ]]> </ejb-ql> </query> </entity> </enterprise-beans> <relationships> <ejb-relation> <ejb-relation-name>BookCatalog-Editions</ejb-relation-name> <ejb-relationship-role> <ejb-relationship-role-name> BookCatalog-Has-Editions </ejb-relationship-role-name> <multiplicity>One</multiplicity> <relationship-role-source> <ejb-name>BookCatalog</ejb-name> </relationship-role-source> <cmr-field> <cmr-field-name>editions</cmr-field-name> <cmr-field-type>java.util.Collection</cmr-field-type> </cmr-field> </ejb-relationship-role> <ejb-relationship-role> <ejb-relationship-role-name> Editions-Belong-To-BookCatalog </ejb-relationship-role-name> <multiplicity>One</multiplicity> <cascade-delete /> <relationship-role-source> <ejb-name>Edition</ejb-name> </relationship-role-source> </ejb-relationship-role> </ejb-relation> </relationships> </ejb-jar> 一方、EJB 2.1のBeanクラスに対応するEJB 3.0のエンティティBeanクラスはPOJOで、かなり簡潔化されています(リスト3)。 リスト3 BookCatalogBean.java
import javax.persistence.Entity; import javax.persistence.NamedQuery; import javax.persistence.Id; import javax.persistence.Column; import javax.persistence.OneToMany; @Entity @NamedQuery(name="findByTitle", queryString = "SELECT DISTINCT OBJECT(obj) FROM BookCatalog obj WHERE obj.title = ?1") public class BookCatalogBean { public BookCatalogBean(){} public BookCatalogBean(String title) { this.title=title; } private String title; private String author; private String publisher; @Id @Column(name="title", primaryKey="true") public String getTitle(){return title;} public void setTitle(){this.title=title;} public void setAuthor(String author){this.author=author;} public String getAuthor(){return author;} public void setPublisher(String publisher) { this.publisher=publisher; } public String getPublisher(){return publisher;} private java.util.Collection<Edition> editions; @OneToMany public void setEditions( java.util.Collection editions) { this.editions=editions; } public java.util.Collection getEditions(){return editions;} } このBeanクラスのEJB 3.0バージョンでは、メタデータアノテーションの 表1 EJB 3.0のメタデータアノテーションの一部
EJB 3.0では、EJB 2.1のエンティティBeanクラスのfinderメソッド EJBエンティティBeanのクライアントを移行する EJB 2.1では、エンティティBeanのホームオブジェクトまたはローカルホームオブジェクトは、エンティティBeanのホームインターフェイスまたはローカルホームインターフェイスの InitialContext ctx=new InitialContext(); Object objref=ctx.lookup("BookCatalogLocalHome"); BookCatalogLocalHome catalogLocalHome = (BookCatalogLocalHome)objref; このコードでは、 EJB 2.1では、参照を取得した後、クライアントは BookCatalogLocal catalogLocal = (BookCatalogLocal) catalogLocalHome.create(title); EJB 2.1では、finderメソッドを使ってローカルホームオブジェクトまたはホームオブジェクトからローカルオブジェクトまたはリモートオブジェクトを取得します。例えば、次のように BookCatalogLocal catalogLocal = (BookCatalogLocal) catalogLocalHome.findByPrimaryKey(title); EJB 2.1では、 catalogLocal.remove(); EJB 3.0では、永続性の実装、検索、および削除には 表2 EntityManagerクラスのメソッド
EJB 3.0のエンティティBeanのクライアントクラスでは、
@Resource
private EntityManager em;
エンティティBeanのインスタンスを永続化する場合は、次のように、
BookCatalogBean catalogBean = new
BookCatalogBean (title);
em.persist(catalogBean);
同様に、エンティティBeanのインスタンスを取得する場合は、
BookCatalogBean catalogBean = (BookCatalogBean)
em.find("BookCatalogBean", title);
EJB 3.0では、名前付きクエリ
Query query=em.createNamedQuery("findByTitle");
query.setParameter(0, title); java.util.Collection catalogBeanCollection = (BookCatalogBean)query.getResultList(); 最後に、 BookCatalogBean catalogBean; em.remove(catalogBean); リスト4に、EJB 3.0のエンティティBeanに対する完全なステートレスセッションBeanのクライアントクラスを示します。 リスト4 BookCatalogClientクラス(完全なEJB 3.0クライアントクラス)
import javax.ejb.Stateless; import javax.ejb.Resource; import javax.persistence.EntityManager; import javax.persistence.Query; @Stateless @Local public class BookCatalogClient implements BookCatalogLocal { @Resource private EntityManager em; public void create(String title) { BookCatalogBean catalogBean=new BookCatalogBean(title); em.persist(catalogBean); } public BookCatalogBean findByPrimaryKey(String title) { return (BookCatalogBean)em.find("BookCatalogBean", title); } public java.util.Collection findByTitle(String title) { Query query=em.createNamedQuery("findByTitle"); query.setParameter(0, title); return (BookCatalogBean)query.getResultList(); } public void remove(BookCatalogBean catalogBean) { em.remove(catalogBean); } } 本稿では、サンプルセッションBeanとサンプルエンティティBeanをEJB 2.1からEJB 3.0に移行する場合に必要なサンプルコードの変更について説明しました。EJB 2.0から移行する場合も同様です。 本稿の執筆時では、JBoss Application Server、Oracle Application Server、Caucho Application Serverなど、EJB 3.0仕様を既にサポートしているアプリケーションサーバーがいくつかありました。残念ながら、実装はアプリケーションサーバーによって異なっているようです。必ずしもEJB 3.0の機能がすべて実装されているわけではありません。詳しくは、アプリケーションサーバーの資料でご確認ください。 著者紹介Deepak Vohra(Deepak Vohra)
O’Reillyの技術レビュー担当者として『WebLogic: The Definitive Guide』を担当。NuBeanコンサルタント、Web開発者でもある。Sun認定資格(Java 1.4プログラマおよびWebコンポーネントディベロッパJ2EEバージョン)を取得。メールの宛先はdvohra09@yahoo.com。
|