Developer: J2EE

Converting an EJB 2.0 Entity Bean to EJB 3.0
by Deepak Vohra

Learn how to convert an EJB 2.0 entity bean to an EJB 3.0 entity bean, step by step.

 

Downloads for this article:
 Sample Files
 Oracle Application Server 10g
 Oracle XDK 10g

Published January 2006

The Enterprise JavaBeans (EJB) 3.0 specification has facilitated the development of EJBs, by providing an annotations-based API in which the remote/local and home/local home interfaces are not required. The deployment descriptors that form the basis of an EJB 2.0 entity bean are also not required for deploying an EJB 3 entity bean.

This tutorial covers the procedure for converting an EJB 2.0 entity bean to an EJB 3.0 entity bean.

Overview

EJB 3.0 support is implemented in Oracle Application Server (10g) 10.1.3 (in Developer Preview at the time of this writing). The EJB 3.0 entity bean classes are simplified in comparison to the EJB 2.0 specification classes.

The EJB 3.0 entity bean class is a Plain Old Java Object (POJO) instead of a class implementing the EntityBean interface. The component interfaces in EJB 2.0, which were required to extend the EJBLocalObject/EJBObject and home interfaces, which were required to extend the EJBLocalHome/EJBHome interfaces, are replaced with the javax.persistence.EntityManager API to create, find, and update entity bean instances.

Preliminary Setup

This tutorial uses the oraxsl utility to provide the XSLT transformation for converting the EJB 2.0 entity bean to the EJB 3.0 specification. Download Oracle XML Developer's Kit (XDK) 10g, and add <XDK10g>\lib\xmlparserv2.jar to Classpath. The example EJB 2.0 entity EJB is included in the samples zip file.

Migrating the Entity Bean Class

The EJB 3.0 entity bean class is a nonabstract POJO class with implementations for the getter/setter methods, in comparison to the EJB 2.0 entity bean class, which is abstract with abstract getter/setter methods. EJB 3.0 does not require component and home interfaces. The entity bean class may implement a business interface.

The EntityManager class is used to create, find, and update an entity EJB. In EJB 3.0, deployment descriptors are not required and are replaced with metadata annotations. If the deployment descriptors are included, the deployment descriptor values override the annotations. An entity EJB is specified with the @Entity annotation.

 

The table name, column name, and primary key column properties are specified with the metadata annotations listed below.

Annotation Description Annotation Elements
@Table Specifies the table used for entity bean persistence name (if the name element is not specified, the EJB class name is used as the table name)
@Column Specifies a column corresponding to an EJB property name, nullable, length, updatable, primaryKey
@Id Specifies a primary key column property  
@Transient Specifies a property that is not persistent  

EJB Query Language (QL) queries in EJB 2.0 are specified with the <query/> element in the ejb-jar.xml deployment descriptor. EJB QL queries in EJB 3.0 are specified with the metadata annotations @NamedQuery and @NamedQueries, which are listed below.

Annotation Description Annotation Elements
@NamedQueries Specifies a group of EJB QL queries  
@NamedQuery Specifies an EJB QL query name="query name"
queryString="SQL query"

The entity bean container-managed relationship (CMR) relationships in EJB 2.0 are specified with the <ejb-relation/> elements in the ejb-jar.xml deployment descriptor, and the entity bean CMR relationships in EJB 3.0 are specified in the bean class. The metadata annotations used to specify the entity bean CMR relationships are:

Annotation Description
@OneToMany One-to-many entity bean CMR relationship
@OneToOne One-to-one entity bean CMR relationship
@ManyToOne Many-to-one entity bean CMR relationship
@ManyToMany Many-to-many entity bean CMR relationship

The EJB 2.0 entity bean being migrated to EJB 3.0 in our example is shown below.

                               
import javax.ejb.*;
abstract public class CatalogBean implements EntityBean {
private EntityContext ctx;
public CatalogBean() {};
 public void setEntityContext(EntityContext ctx) {
  this.ctx = ctx;
 }

 public void unsetEntityContext() {
  this.ctx = null;
 }
        abstract public String getCatalogId();
        abstract public void setCatalogId(String catalogId);

        abstract public String getJournal();
        abstract public void setJournal(java.lang.String journal);

        abstract public String getPublisher();
        abstract public void setPublisher(String publisher);

 public void ejbActivate() {
   }
 public void ejbPassivate() {
   }
 public void ejbLoad() {
   }
 public void ejbStore() {
   }
 public void ejbRemove()
  throws RemoveException
 {
   }

 public String ejbCreate(String catalogId, String journal, String publisher)
  throws CreateException
 {
  setCatalogId(catalogId);
  setJournal(journal);
  setPublisher(publisher);

  return null;  }

 public void ejbPostCreate(String catalogId, String journal, String publisher)
 {
   }
}

                            

Modify the ejb-jar.xml deployment descriptor for the example entity bean to include elements for the table name, field type, and EJB QL query collection type for multi-entity return values. Add the <table-name/>, <field-type/>, and <collection-type/> elements to ejb-jar.xml. The modified ejb-jar.xml deployment descriptor for the example entity bean is shown below.

                               
<?xml version="1.0"?>
<!DOCTYPE ejb-jar PUBLIC 
"-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" 
"http://bit.ly/14q2yGO">

<ejb-jar>
 <enterprise-beans>
  <entity>
   <table-name>Catalog</table-name>
   <ejb-name>Catalog</ejb-name>
   <local-home>CatalogHome</local-home>
   <local>Catalog</local>
   <ejb-class>CatalogBean</ejb-class>
   <persistence-type>Container</persistence-type>
   <prim-key-class>CatalogPK</prim-key-class>
   <reentrant>False</reentrant>
   <cmp-version>2.x</cmp-version>
   <abstract-schema-name>CatalogBean</abstract-schema-name>
   <cmp-field>
    <field-name>catalogId</field-name>
    <field-type>String</field-type>
   </cmp-field>
   <cmp-field>
    <field-name>journal</field-name>
    <field-type>String</field-type>
   </cmp-field>
   <cmp-field>
    <field-name>publisher</field-name>
    <field-type>String</field-type>
   </cmp-field>
   <primkey-field>catalogId</primkey-field>
   <query>
    <query-method>
     <method-name>findByCatalogId</method-name>
     <method-params>
      <method-param>java.lang.String</method-param>
     </method-params>
    </query-method>
    <ejb-ql>
     <![CDATA[SELECT OBJECT(a) FROM CatalogBean AS a WHERE a.catalogId = ?1
    </ejb-ql>
    
   </query>
   <query>
    <query-method>
     <method-name>findByJournal</method-name>
     <method-params>
      <method-param>java.lang.String</method-param>
     </method-params>
    </query-method>
    <ejb-ql>
     <![CDATA[SELECT OBJECT(a) FROM CatalogBean AS a WHERE a.journal= ?1
    </ejb-ql>
    <collection-type>java.util.Collection</collection-type>
   </query>
   
  </entity>
 </enterprise-beans>
</ejb-jar>

                            

Next, convert the modified ejb-jar.xml to an EJB 3.0 entity bean with XSLT.

The EJB 3.0 entity bean class is generated with the oraxsl utility:

                               
>oraxsl ejb-jar-modified.xml 
entity-bean.xslt CatalogBean.java

                            

The XSLT entity-bean.xslt used to generate the EJB 3.0 entity bean is available in the resources zip file. Here is the EJB 3.0 entity bean generated from the EJB 2.0 entity bean:

                               
import javax.persistence.Entity;

import javax.persistence.Id;
import javax.persistence.Column;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.ejb.Remote;
import javax.ejb.Local;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.ManyToOne;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
@Table(name="Catalog")
@NamedQueries({@NamedQuery(name="FindByCatalogId",
                                

              queryString=" SELECT OBJECT(a) FROM CatalogBean AS a WHERE a.catalogId = ?1"),
@NamedQuery(name="FindByJournal",
            queryString=" SELECT OBJECT(a) FROM CatalogBean AS a WHERE a.journal= ?1 ")
})

public class CatalogBean implements java.io.Serializable {
public CatalogBean(){}

public CatalogBean(
String catalogId
){

this.catalogId=catalogId;

}

private String catalogId;
private String journal;
private String publisher;

@Id
@Column(name="CATALOGID", primaryKey=true)
public String getCatalogId() {return catalogId;}
public void setCatalogId(String catalogId){this.catalogId=catalogId;}
 
public String getJournal() {return journal;}
public void setJournal(String journal){this.journal=journal;}

public String getPublisher() {return publisher;}
public void setPublisher(String publisher){this.publisher=publisher;}

}       
                              
                            

The EJB 3.0 bean class has the import statements for the javax.persistence package classes. The @Entity annotation specifies the class as an entity EJB class. The @Table annotation specifies the database table name for the entity EJB, the @NamedQueries annotation specifies the named queries, the @Id annotation specifies the identifier property/primary key field, and the @Column annotation specifies the database column corresponding to the identifier property. The EJB 2.0-to-EJB 3.0 conversion XSLT also includes the conversion of entity bean CMR relationships.

Developing a Session Facade for an Entity Bean

In EJB 2.0, an entity bean is created with the create method in the home/local home interface and the entity bean fields are modified with the getter/setter methods in the local/remote interface. In EJB 3.0, an entity bean is created and modified with the EntityManager API. The EntityManager class provides methods for finding, persisting, and removing an entity bean instance. This section covers generation of a session EJB that implements the EntityManager API.

In the session EJB bean class, the EntityManager is obtained with the @Resource annotation.

                               
@Resource private EntityManager em;

                            

Some of the commonly used methods of the EntityManager class are listed below.

EntityManager Method Description
persist(Object entity) Saves an entity bean instance in the database. The persist method returns the entity bean that is persisted in the database.
find(String entityName, Object primaryKey) Finds an entity bean instance with a primary key.
remove(Object entityBean) Removes an entity bean from the database.
createQuery(String ejbQlString) Creates an EJB QL query.
createNamedQuery(String queryName) Creates a NamedQuery query.

In the session bean class, an entity bean is created with the create method. For example, the create method corresponding to the identifier property catalogId is

                               
public void create(String catalogId)
  {   CatalogBean catalogBean = new CatalogBean(catalogId);
  em.persist(catalogBean);
 }

                            

The persist method of the EntityManager class saves a new entity EJB in the database.

The remove method of the EntityManager class is used to remove an Entity bean.

                               
public void remove(CatalogBean  catalogBean) {
    em.remove(catalogBean);
  }

                            

The find method of the EntityManager class is used to find an entity bean. For example, the findByPrimaryKey method corresponding to the identifier property catalogId, which is defined in the entity bean class with the @Id annotation, is

                               
public CatalogBean findByPrimaryKey(String catalogId) 
   {   return (CatalogBean)em.find("CatalogBean" , catalogId);
 }

                            

In the session EJB, add finder methods for the named queries defined in the EJB bean class. The createNamedQuery method is used to obtain a query object for a named query. For example, the finder method corresponding to the named query FindByCatalogId, which is defined in the entity bean class, is

                               
public CatalogBean findByCatalogId(java.lang.String param1)  
   {Query query=em.createNamedQuery("FindByCatalogId");
  query.setParameter(0, param1);
  return (CatalogBean)(query.getSingleResult());
 }

                            

In the findByCatalogId method, a javax.persistence.Query object is obtained from the named query FindByCatalogId. The parameter values are set on the query object. An entity EJB bean instance is obtained with the getSingleResult method of the query object. The named query FindByCatalogId returns a single entity of the entity EJB bean.

A named query may also return a collection of entities. For example, the named query FindByJournal returns a collection. The finder method corresponding to the FindByJournal named query is

                               
public java.util.List<CatalogBean> findByJournal(java.lang.String param1)
   {   Query query= em.createNamedQuery("FindByJournal");
  query.setParameter(0, param1);
  return query.getResultList();
}

                            

In the findByJournal method, a query object is obtained from the named query and a java.util.List of entity beans is obtained with the getResultList method of the query object.

Next, generate the EJB 3.0 session bean class that implements the EntityManager API with XSLT:

                               
> oraxsl ejb-jar-modified.xml 
facade-bean.xslt CatalogFacadeBean.java

                            

The EJB 3.0 session bean class implements the EJB 3.0 session bean remote interface CatalogFacade. The session bean class generated is sh own below.

                               
import javax.persistence.EntityManager;
import javax.ejb.Resource;
import javax.ejb.Stateless;
import javax.persistence.Query;

@Stateless
                
 public class CatalogFacadeBean implements CatalogFacade{

@Resource
private EntityManager em;
private CatalogBean catalog;

public void create(String catalogId) {
  CatalogBean catalogBean = new CatalogBean(catalogId);
  em.persist(catalogBean);
 }

public void remove(CatalogBean catalogBean) {
  em.remove(catalogBean);
 }

public CatalogBean findByPrimaryKey(String catalogId) {
  return (CatalogBean)em.find("CatalogBean", catalogId);
 }


public CatalogBean findByCatalogId(java.lang.String param1) {
  
Query query=em.createNamedQuery("FindByCatalogId");


 query.setParameter(0, param1);

   return (CatalogBean)(query.getSingleResult());
 }

public java.util.List<CatalogBean> findByJournal(java.lang.String param1){
    
 Query query= em.createNamedQuery("FindByJournal");
  query.setParameter(0, param1);
  return query.getResultList();}


}

                            

The @Stateless annotation specifies a stateless session EJB. Generate the session bean interface with XSLT facade.xslt.

                               
> oraxsl ejb-jar-modified.xml 
facade.xslt CatalogFacade.java

                            

Here's the session bean interface:

                               
import javax.ejb.Remote;
import javax.ejb.Remove;

@Remote
                
public interface CatalogFacade{

void create(String catalogId); 


void remove(CatalogBean catalogBean); 

CatalogBean findByPrimaryKey(String catalogId); 

CatalogBean findByCatalogId(java.lang.String param1); 

java.util.List<CatalogBean> findByJournal(java.lang.String param1); 

}

                            

The @Remote annotation specifies a remote interface. The XSLT facade-bean.xslt, used to generate the session bean class, and the XSLT facade.xslt, session bean interface are available in the samples zip file.

Conclusion

Entity EJBs developed with the previous versions of EJB specifications can be converted to the EJB 3.0 specification with XSLT transforms. The example XSLT transforms can be used to convert EJB 2.0 and EJB 2.1.

An entity bean generated with the conversion can be deployed in Oracle Application Server by use of the procedure explained in the tutorial How to Develop an Entity Bean Using EJB 3.0.

 


Deepak Vohra ( dvohra09@yahoo.com) is a Web developer, NuBean consultant, and Sun Certified Java Programmer.

 

Send us your comments