Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Efficient Entity EJB development

Using CMP for greater portability

Stefan Edlund (edlund@almaden.ibm.com), Research Associate, IBM, Software Group
Stefan Edlund is a research associate/staff software engineer at the IBMAlmaden Research Center. He is currently in the Web Technologies department, conducting research and designing Web-based, active, personal information management systems. Stefan has an M.S. degree in computer science from the Royal Institute of Technology in Stockholm. You can contact Stefan at edlund@almaden.ibm.com.

Summary:  As more and more programmers are using Enterprise JavaBeans (EJB) in their projects, the need for tools that simplify EJB development is growing. This article explores Container Managed Persistence (CMP) Entity Enterprise JavaBeans, and introduces a free tool for their creation.

Date:  01 Dec 2000
Level:  Introductory
Also available in:   Japanese

Activity:  3031 views
Comments:  

Container Managed Persistence (CMP) Entity Enterprise JavaBeans are in essence wrappers for persistent data -- commonly in the form of relational database tables -- with additional support for transaction control and security. A CMP entity bean is constructed from at least six separate files, having dependencies that cannot be easily verified at compile time. Proper care must be taken to ensure that object-relational database mappings are correct, and ideally the code should be designed to minimize the changes necessary when requirements change. This article describes some of the challenges with writing large EJB projects, and how some of them can be overcome by the EJBMaker tool, downloadable at the IBM alphaWorks Web site (see Resources).

EJBMaker reads a single CMP EJB description file -- written in XML -- and automatically generates Java source code and database scripts. The tool takes care of the tedious tasks of defining finder and initialization methods for the beans, and it is capable of generating relationship EJBs that associate CMP EJBs with each other. The EJBMaker keeps track of updates in the XML bean descriptor file, and only regenerates Java code for EJBs that have changed. In addition, adaptor classes are generated enabling quick initialization or data extraction from an EJB using XML. The EJBMaker is optimized for use with the IBM WebSphere application server, but with some manual tweaking can also be used with other application servers.

Entity Enterprise JavaBeans

One of the strengths of EJB technology is that, at least in theory, an EJB is only written once and can be deployed on any EJB-compliant application server. Version 2.0 of the specification, containing technologies such as the EJB query language, brings us even closer to this goal.

Even though we are not there yet with the promise of "Write Once, Run Anywhere" capability, EJBs are surprisingly easy to port from one application server environment to another -- especially for Container Managed Persistence (CMP) Entity EJBs. When writing CMP Entity EJBs, the developer does not have to worry about writing code for persistently storing the state of a bean in a database. All such code is automatically generated during the deployment stage on an application server. This decreases some of the flexibility of the bean, but on the other hand it enables more rapid development. Application server designers are free to use any method desired to persistently store and retrieve EJB data, as long as they fulfill the "entity bean component contract for container managed persistence," as defined by the EJB specification (see Resources). The most common solution by far is to store the data in a relational database using the Java Database Connectivity API (JDBC) (see Resources for information about JDBC). This is the technique used by the IBM WebSphere application server and BEA WebLogic (among others).

The other entity EJB type is Bean Managed Persistence (BMP) EJB. In this case, it is up to the developer to manually write code for persistently retrieving or storing bean information. BMP is ideal when data needs to be stored in legacy storage systems or file systems. However, the increased flexibility comes at the price of decreased portability. When the application server is not controlling all access to system resources, no guarantees can be made about the existence or compatibility of such resources across different server environments.


Anatomy of a CMP Enterprise JavaBean

Unless you have specific requirements that force a BMP implementation, CMP is the better choice. How do you write a CMP bean? The following files need to be created:

  • EJB remote interface. This file contains method signatures for any method that accesses or modifies data stored in the bean. The remote interface must extend the javax.ejb.EJBObject interface.
  • EJB remote implementation. This file provides an implementation of all the methods defined in the remote interface, in addition to methods required by the application server (for example, callback methods). To ensure that all the required methods exist, the EJB remote class must implement javax.ejb.EntityBean.
  • EJB home interface. The home interface declares method signatures for any method that creates new instances of the bean, and for all methods that are used to retrieve instances of the bean (finder methods). The EJB home interface extends the javax.ejb.EJBHome interface.
  • EJB key. The key class contains the unique primary key implementation for the bean. Version 2.0 of the EJB specification defines a primary key class as any class that is a legal value type in RMI-IIOP.
  • EJB finder helper interface. This file contains one static java.lang.String field for each finder method declared in the EJB home interface. The strings are initialized with SQL queries executed dynamically when bean instances are retrieved in a finder method. Note: This file is particular to the IBM WebSphere application server. Other application server environments (for instance Enhydra or WebLogic)put queries in XML deployment descriptors using proprietary query language formats. Forsuch environments, this file can be ignored and replaced by manual entry of queries into the deployment descriptors.
  • Deployment descriptor. The deployment descriptor is a serialized Java class that contains meta-data about the bean, such as the names for EJB classes and interfaces, and a list of the persistent fields associated with the bean. Since version 1.1 of the EJB specification, the deployment descriptor can be written in XML (subsequently translated into a serialized Java object during the deployment stage).
  • Database scripts. If the application server doesn_t create the required relational database tables used to persistently store the bean data, database scripts can be created for this purpose.

Common CMP pitfalls

In addition to making sure that all the files described above exist, there are several pitfalls developers must avoid when writing CMP entity beans. First of all, dependencies between files exist that cannot be verified at compile time:

  • Care must be taken to ensure that methods declared in the remote interface are actually implemented in the EJB remote implementation class. If the EJB remote implementation class were to implement the EJB remote interface directly, verification of dependencies could be checked at compile time. However, there is an inherent distinction between the remote interface as being a client side object, while instances of the remote implementation class belong on the server side. If the remote implementation class were to implement the remote interface, it would also have to implement methods declared by the interface extended by the remote interface -- the javax.ejb.EJBObject. This interface contains many methods that do not belong on the server side.
  • Finder methods declared in the EJBHome interface of a bean must be associated with a query that is typically defined in another file. For WebSphere, the EJB finder helper class must contain one static String field for each finder method declared in the EJB home interface, and the name of the field must match the name of the finder method. Enhydra requires that the XML deployment descriptor contains a finder-method-jdbc-mapping element matching the finder methods declared in the EJBHome etc.
  • The EJB remote implementation class must contain one ejbCreate(...) method for each create(...) method declared in the EJB home interface. In particular, it must always contain the ejbCreate(EJBKey...) method, which creates a new instance of the bean using an EJB key instance.

Other requirements include:

  • Ensuring that XML deployment descriptors contain proper class names for the EJB components and all declarations required for the persistent fields.
  • Getting the object-relational database mappings set up correctly. This includes making sure that persistent fields are mapped to database columns of the proper type, and that the tables are designed to match any special requirements existing in the persistent code automatically generated by the application server. Column order could be one such requirement.

You might think after reading all these requirements that writing CMP entity beans is probably not for the faint-hearted. Luckily, there are tools that will assist you in many of these steps. For instance, the IBM VisualAge for Java IDE contains an excellent EJB development environment that will automatically generate lots of the necessary code for you, and even help you with the object-relational database mappings. WebGain Studio and WebGain StructureBuilder from BEA Systems help developers with some of the hairier EJB development tasks by automatically converting UML models into EJB components etc. But what if you don_t have the liberty of switching IDEs? In that case you_re pretty much stuck, unless...


The EJBMaker

To help resolve some of the trickier issues associated with writing CMP beans, the EJBMaker tool was created. While the tool does generate WebSphere-specific files, modifying the output for other environments is a fairly straightforward task. All information related to the CMP beans -- including bean names, persistent field names and class, and relational database mappings -- are stored in a single file. The format of the file is XML, which is flexible and easy to extend for future versions of the EJBMaker.

From this EJBMaker XML file, the following are generated (see the previous "Anatomy of a CMP Enterprise JavaBean"):

  • Java source files for each CMP bean. This includes the EJB remote interface, the EJB remote implementation class, the EJB home interface, the EJB key class, and the EJB finder helper interface.
  • XML deployment descriptors. Contains EJB class names, persistent fields and bean attributes for transactions, security and isolation levels.
  • Database scripts. Scripts used to generated persistence tables in a relational database. The scripts are tailored for DB2, but other databases works as well with minor tweaking involved.

All the dependencies are taken care of automatically, including the object-to-relational- database mappings. Default finder methods are generated to retrieve instances matching values of each persistent field in the bean, and to retrieve all existing bean instances (getAllInstances() method). This ensures that the bean is flexible enough to be used in many different scenarios. If a special finder method is required, it can be entered directly in the XML description file.

This is an example of a single CMP bean described in the EJBMaker XML format:

 <?xml version="1.0"?>
 <!DOCTYPE ejbmaker SYSTEM "ejbmaker.dtd">
 <ejbmaker>
       <! --  default attributes for beans  -- >
       <transaction-attr>TX_REQUIRED</transaction-attr>
       <isolation-level>SERIALIZABLE</isolation-level>
       <run-as-mode>SPECIFIED_IDENTITY</run-as-mode>
       <re-entrant>false</re-entrant>
  
       <! -- A Simple Account CMP entity EJB  -- >
       <bean name = "Account" type = "entity">
             <persistent_field dt="int" col_dt="INTEGER">
        ACCTNUMBER
   </persistent_field>
             <persistent_field dt="java.lang.String" col_dt="VARCHAR(13)">
        SSN
   </persistent_field>
             <persistent_field dt="double" col_dt="DOUBLE">
        BALANCE
   </persistent_field>
             <finder_method name="findNegativeAcct">
                   <sql>
        SELECT * FROM EJB.ACCOUNTBEANTBL WHERE BALANCE < 0
    </sql>
             </finder_method>
       </bean>
 </ejbmaker>

There are several parts to this file. The transaction-attr, isolation-level, run-as-mode, and re-entrant are taken directly from Sun_s XML EJB deployment descriptor format. These bean attributes are copied as default attributes for all beans into the deployment descriptors generated.

 <bean name = "Account" type = "entity">

This is the beginning of a new bean declaration. The Java Naming and Directory Interface (JNDI) name of the bean is _Account_, and the type of the bean is _entity_. The EJBMaker currently only supports the _entity_ bean type.

The next few lines indicate how to identify a persistent field:

<persistent_field dt="int" col_dt="INTEGER">
       ACCTNUMBER
</persistent_field>

The first persistent field defined in the Account bean is ACCTNUMBER. The Java class used to store the persistent field is the primitive int class (declared by the dt attribute), and the data type for the database column is declared using the col_dt attribute as INTEGER. Two more persistent fields are defined, SSN and BALANCE.

The next few lines indicate how to specify a special finder method:

<finder_method name="findNegativeAcct">
       <sql>
       SELECT * FROM EJB.ACCOUNTBEANTBL WHERE BALANCE < 0
     </sql>
 </finder_method>

The name of the finder method is findNegativeAcct. Notice that SQL code placed in elements must follow the rules of XML content. In particular this means that reserved XML characters such as the less-than sign must be escaped.

Passing the XML file through the EJBMaker generates source code, XML deployment descriptor, and database scripts.


Source Code

From the example above, the following Java classes and methods are generated:

  • Account.java
    Methods: getACCTNUMBER(), setACCTNUMBER(int), getSSN(), setSSN(String), getBalance(), setBalance(double), getKey(), initialize(TXDocument), getXML()
  • AccountBean.java
    Methods: getACCTNUMBER(), setACCTNUMBER(int), getSSN(), setSSN(String), getBalance(), setBalance(double), getKey(), initialize(TXDocument), getXML(), ejbActivate(), ejbLoad(), ejbPassivate(), ejbStore(), ejbRemove(), setEntityContext(), unsetEntityContext()
  • AccountHome.java
    Methods: create(AccountKey), findByPrimaryKey(AccountKey), findAllInstances(), findByACCTNUMBER(int), findBySSN(String), findByBALANCE(double), findNegativeAcct()
  • AccountKey.java
    Methods: AccountKey(), AccountKey(String), equals(Object)
  • AccountBeanFinderHelper
    No methods
  • AccountXMLAdaptor
    Methods: AccountXMLAdaptor(), AccountXMLAdaptor(TXDocument), getXML(), setACCTNUMBER(Integer), getACCTNUMBER(), setSSN(String), getSSN(), setBALANCE(Double), getBALANCE()

Some of the methods merit further explanation. The remote interface (Account.java), and the implementation of the remote interface (AccountBean.java) have a method called getKey(). The method simply returns the primary key of the bean as a String instance, instead of as an AccountKey instance which is returned by the superclass_ getPrimaryKey() method.

The remote interface and the remote implementation class also have the initialize(TXDocument) and the getXML() method. These two methods are used to quickly initialize a bean using XML and to extract information stored in a bean as XML. See this example of how to use these two methods.

The code also explains how to use the AccountXMLAdaptor class. It is a wrapper around an Account XML document, and contains methods to set and get properties associated with Accounts. Observe that persistent fields of a primitive Java classes are converted to their equivalent non-primitive class in the adaptor. This way it is possible to use null values to represent the non-initialized state, which is useful for setting only a subset of the persistent fields. All information related to an Account is encoded in XML using the getXML() method of adaptor class. The XML format is straightforward; the root element is always the name of the EJB, which encloses one element for each persistent field. For the Account example, an EJB instance could be serialized into the following XML document:

<Account>
  <ACCTNR>1111</ACCTNR>
       <SSN>123-45-6778</SSN>
       <BALANCE>1000000</BALANCE>
 </Account>


Relationships among beans

The EJBMaker can also generate EJBs that are used to represent many-to-many relationships between beans. For example, consider a simple calendar application. Two CMP entity beans are used; one contains information about calendar events (called Event), and the other contains information about the clients of the calendar application (called Client). We now want to represent clients that attend particular calendar events. A crude solution is to add a field to the Event bean containing the primary keys of all clients attending that particular event. The primary keys could be concatenated, using, for instance, comma separation. To retrieve all clients attending an event, code would have to be written that takes the comma-separated string of primary keys and does a lookup using findByPrimaryKey(...) in the Client home interface for each of the keys. Even if the code is written inside a session bean, performance will be slow compared to the second solution.

A more elegant solution would be to use an additional table to represent the relationship between events and clients. Two columns contain primary keys for Event EJB instances and Client EJB instances. Now the task of retrieving all clients participating in an event is simply a matter of writing a finder method in the Client home interface, and an SQL query in the helper finder class. This is exactly what the EJBMaker does. A relationship between two beans is constructed using the following technique:

<ejbmaker> 
  <! -- Event and Client EJB declarations go here  -- >
  <relation name = "Attendee">
             <bean_ref_1>Event</bean_ref_1>
             <bean_ref_2>Client</bean_ref_2>
  </relation>
 </ejbmaker>

The relationship is represented by a new CMP entity bean called Attendee, having two fields (three if we count the primary key field). The fields contain primary key instances of Event EJBs and Client EJBs. In addition, two additional finder methods are created, one in the Event home interface and one in the Client home interface. The Event home interface finder method is:

java.util.Enumeration findByAttendee(String pkey)

_pkey_ is a primary key of a Client EJB. The method returns an Enumeration of the events that a particular client is attending. The client home interface has the same method: java.util.Enumeration findByAttendee(String pkey)

However, in this class 'pkey' is a primary key of the Event EJB, and the method returns an Enumeration of clients attending a particular event.


Database Scripts

The final pieces of code generated by the EJBMaker are database scripts for creating persistent EJB tables. One script is created for each EJB, in addition to the CreateTables.ddl script that creates all the required tables. However, the tables are not ready to be used by the application server until virtual tables (or Views) have been created. The views shuffle around the column order of the tables so that the columns correspond to the order expected by the generated EJB persistence code. The EJBMaker comes with a tool that generates the CreateViews.ddl script for you. The script must be regenerated every time an EJB is redeployed, or the columns might end up in the wrong order. By using the view abstraction between the application server and the physical database tables, we are able to keep information stored in a persistence table even if the EJB is redeployed.


Conclusion

This article has given an overview of the challenges with writing entity EJBs, and some of the features of the EJBMaker tool. We encourage you to download the software from alphaWorks and try it out for yourself. Remember to send feedback and suggestions, which will help us to improve future versions of the product.


Resources

About the author

Stefan Edlund is a research associate/staff software engineer at the IBMAlmaden Research Center. He is currently in the Web Technologies department, conducting research and designing Web-based, active, personal information management systems. Stefan has an M.S. degree in computer science from the Royal Institute of Technology in Stockholm. You can contact Stefan at edlund@almaden.ibm.com.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=SOA and Web services
ArticleID=86773
ArticleTitle=Efficient Entity EJB development
publish-date=12012000
author1-email=edlund@almaden.ibm.com
author1-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Try IBM PureSystems. No charge.

Special offers