Creating Container-managed Entity Beans with JBoss

n Entity Bean is an Enterprise JavaBean (EJB) that represents a persistent object in a relational database. JBoss provides two methods of entity bean persistence, Bean Managed Persistence (BMP) and Container-Managed Persistence (CMP). With BMP, the entity bean developer must implement all the persistence logic. With CMP, the application server manages entity bean persistence; the developer provides interfaces and configuration.

Applications that use entity beans?particularly entity beans that use CMP? quickly become complex. Therefore, to describe the configuration process in detail without getting bogged down by code complexity, I designed the sample application for this article, JBlog, to be functional and illustrative, yet simple. I also wanted a timely example, which led to the idea of blogging. JBlog is a small blogger application that uses CMP entity beans to persist blog content.

What You Need
To build and run the sample JBlog application, you need JBoss 3.2.1, Java 2 SDK 1.4, Java 2 EE SDK 1.3, Ant 1.5, and JUnit 3.8.1.

JBlog’s interface consists of two Web pages, one for viewing a blog and one for posting new entries. The interface uses two entity beans: Story for blog entries and Author for content authors. In the rest of this article, you’ll see how to construct, configure, and persist those entity beans.

An entity bean using CMP has several interfaces, explained in the following sections. You don’t have to implement all the interfaces for every CMP entity bean.

The Home Interface (optional)
External clients use an entity bean’s home interface to create, remove, and find instances of the entity bean. You don’t need to create a home interface if external clients will not use the bean directly. The home interface defines the following methods:

  • Create. Creates an entity bean instance.
  • Remove. (required) Removes an entity bean instance.
  • Finder methods. Find one or more entity bean instances. Finder method names must start with “find”. For a CMP entity bean, the finder method findByPrimaryKey must be defined.
  • Home methods. These methods act like static methods for an entity bean. Home methods can be called from the home interface (remote or local) to execute entity bean methods without creating an instance of the entity bean.

Both the entity beans in JBlog have home interfaces. To see the full code, look at the StoryHome.java and AuthorHome.java files in the JBlog source directory. The main page (index.jsp) uses the AuthorHome interface to find the author “bigt.”

   // Create AuthorHome.   AuthorHome authorHome = (AuthorHome) PortableRemoteObject.narrow(      ctx.lookup("ejb/JBlog/Author"), AuthorHome.class);      // Find author.   Author author = authorHome.findByPrimaryKey("bigt");

The Remote Interface (optional)
External clients interact with an entity bean via its remote interface, which defines the entity bean’s public business methods. If the entity bean will not be used by external clients, you don’t need to create a remote interface.

Both of the entity beans in JBlog have remote interfaces. To see the code for them, look at Story.java and Author.java in the JBlog source directory. The main page uses Author to get an author’s stories and Story to display a story.

   // Get an author's stories      // Create AuthorHome and StoryHome.   AuthorHome authorHome = (AuthorHome) PortableRemoteObject.narrow(      ctx.lookup("ejb/JBlog/Author"), AuthorHome.class);   StoryHome storyHome = (StoryHome) PortableRemoteObject.narrow(      ctx.lookup("ejb/JBlog/Story"), StoryHome.class);      // Find author and get stories.   Author author = authorHome.findByPrimaryKey("bigt");   Collection stories = author.getStoryKeys();   <%      // Display stories.      for (Iterator i = stories.iterator(); i.hasNext(); ) {         Integer key = (Integer) i.next();         Story story = storyHome.findByPrimaryKey(key);   %>   

<%= story.getTitle() %>
Posted <%= story.getPubDate() %>
<%= story.getText() %>

...

The posting page (post.jsp) uses Author to assign an author to a new story.

   // Assign author to new story      // Find author.   Author author = authorHome.findByPrimaryKey("bigt");            // Create story.   Story story = storyHome.create(request.getParameter("title"),       request.getParameter("text"), author);

The Local Home Interface (required)
Local clients?other components running in the same container as the entity bean?use the local home interface to create, remote, and find instances of an entity bean. Like the home interface, the local home interface defines create, remove, finder methods, and home methods. Additionally, the local home interface may define select methods, which are local query methods. You must create a local home interface for a CMP entity bean.

To see the code for the local home interfaces of JBlog’s entity beans, look at the files AuthorLocalHome.java and StoryLocalHome.java in the JBlog source directory. These interfaces are referenced in the EJB jar descriptor and the JBoss CMP descriptor and are used by JBoss.

The Local Interface (required)
Local clients interact with an entity bean via its local interface, which defines the local business methods of the entity bean. You must create a local interface for a CMP entity bean.

To see the code for the local interfaces of JBlog’s entity beans, look at the AuthorLocal.java and StoryLocal.java files in the JBlog source directory. These interfaces are referenced in the EJB jar descriptor and the JBoss CMP descriptor and are used by JBoss. Additionally, AuthorBean uses the StoryLocal interface to get a list of the primary keys of the author’s stories.

   // Get primary keys of author's stories   public Collection getStoryKeys() {      Vector keys = new Vector();      Collection stories = getStories();  // List of StoryLocal instances         for (Iterator i = stories.iterator(); i.hasNext(); ) {         StoryLocal storyLocal = (StoryLocal) i.next();         keys.add(0, storyLocal.getPrimaryKey());      }         return keys;   }

Similarly, StoryBean uses the AuthorLocal interface to assign an author to a story.

   // Assign author (local) to story   // This method is called by the container after entity bean is created.   public void ejbPostCreate(String title, String text, AuthorLocal author) {      setAuthor(author);   }

The Entity Bean Class
The entity bean class contains the entity bean logic. However, with CMP, the entity class is abstract, because many of the methods are defined in the class but implemented by the container. The entity bean class defines the following methods:

  • Accessor methods. (required) Get and set the entity bean’s fields. Accessor methods must be both public and abstract, and must match the of a or in the EJB jar descriptor, using JavaBean naming conventions. For example, the field “name” must have the following accessor methods:
   public abstract void setName(String name)   public abstract String getName()
  • EJB home methods. Implement the home methods defined in the home interface and the local home interface. Home method names must start with “ejbHome”.
  • EJB select methods. Find one or more local entity bean instances. Select methods are mapped to EJB-QL queries in the EJB jar descriptor. Select method names must start with “ejbSelect”.
  • Business methods. Implement any business methods defined in the remote and local interfaces.

To see the code for the entity bean classes in JBlog, look at AuthorBean.java and StoryBean.java in the JBlog source directory. AuthorBean and StoryBean are referenced in the EJB jar descriptor and the JBoss CMP descriptor.

The EJB Jar Descriptor
The EJB jar descriptor file, ejb-jar.xml, specifies deployment information for the EJBs in an EJB jar. For each entity bean, the descriptor must contain one child element in the element. The element contains the following child elements:

  • (required). Display name of entity bean.
  • (required). Entity bean name. For CMP, this name must be a valid Java identifier.
  • . Fully qualified name of home interface.
  • . Fully qualified name of remote interface.
  • (required). Fully qualified name of local home interface.
  • (required). Fully qualified name of local interface.
  • (required). Fully qualified name of entity bean class.
  • . Indicator that the bean is reentrant.
  • . Must be “Container” for CMP.
  • . Must be “2.x” for CMP2.
  • . Name of table in elements.
  • . Fully qualified name of primary key class, for example, “java.lang.String”.
  • . Name of primary key field.
  • . Container managed field. The field name is specified with and should correspond to accessor methods in the entity bean class.
  • . Query for a finder method or select method in EJB Query Language (EJB-QL). The method name and parameters are specified in . The query is specified in .
EJB-QL is beyond the scope of this article. For more information on EJB-QL, see the EJB 2.0 specification.

JBlog’s EJB jar descriptor contains two elements, one for Author (see Listing 1) and one for Story (see Listing 2).

Specifying Bean Relationships in the EJB Jar Descriptor File
With CMP 2.0, you can define relationships between entity beans in the EJB jar descriptor file rather than the entity bean code. Note, though, that you can define such relationships only for local interfaces. For each relationship, the EJB jar descriptor must contain one child element in the element.

The element contains the following elements:

  • (required). Relationship name.
  • (required). Relationship role. You should specify one of these elements for each entity in the relationship.

In turn, each element contains elements that describe the relationship itself:

  • (required). Role name of role.
  • (required). Source entity bean. You specify class name in the element.
  • (required). Multiplicity of the . Valid values are “One” and “Many”.
  • . Indicates that entities in this role should be deleted if an entity in the parent role (the role with multiplicity “One”) is deleted.
  • (required). Container managed relationship field. You specify the field name with the element, which should correspond to access methods in the entity bean class. You specify the field type with the element.

JBlog’s EJB jar descriptor contains one element for the relationship Author-Story.

   // The Author-Story relation as specified in    // the EJB jar descriptor            Author-Story                               author-stories                     One                         Author                                            stories             java.util.Collection                                                 stories-author                                 Many                                                 Story                                             author                    

The JBoss CMP Descriptor File
The JBoss CMP descriptor file, jbosscmp-jdbc.xml, contains database and relationship mapping information for the entity beans in an EJB jar. For each entity defined in the EJB jar descriptor, the JBoss CMP descriptor must contain one child element in the element. The element contains:

  • (required). Entity bean name, which must match an element in the EJB jar descriptor.
  • . JNDI name of data source where entity bean is persisted. This element is required unless specified in the element. (See the JBoss documentation for more information.)
  • . Name of data source type mapping. (Default is “Hypersonic SQL”.)
  • (required). Name of table where entity data is stored.
  • . Indicator that the table should be created when the entity bean is deployed.
  • . Indicator that the table should be removed when the entity bean is undeployed.
  • . Indicator that a primary key constraint should be added to the table when it is created.
  • . Indicator that the table cannot be updated.
  • . Amount of time (milliseconds) that a read on a read-only field is valid.
  • . Indicator that row locking should be used in transactions.
  • . Indicator that read-ahead caching should be used for queries.
  • . Number of read lists that can be tracked by the entity.

For each container managed field in the entity bean, the element must contain one , which includes:

  • (required). Container managed field name. The value should match the of a in the corresponding in the EJB jar descriptor.
  • . Name of the column that corresponds to the field in the table. The default is the value of .
  • – Indicator that null is not an allowed value. The default for primary key fields and fields with primitive data types is “true”.
  • . JDBC type of the field. This element is required only when you include an element. Valid values are the types defined in java.sql.Types. The data source mapping determines the default value.
  • . SQL type of the table column. This element is required only when is specified. Valid values are the types defined by the database. The data source mapping determines the default value.

JBlog’s JBoss CMP descriptor contains two elements, one for Author and one for Story.

   // Author entity element in JBoss CMP descriptor            Author      author                  username                              password                              name               // Listing 10: Story entity element in JBoss CMP descriptor            Story      story                  storyId         story_id                              pubDate         pub_date                              title                              text                              username         

Specifying Bean Relationships in the JBoss CMP Descriptor File
For each relationship defined in the EJB jar descriptor, the JBoss CMP descriptor must contain one child element in the element. Each element can contain the following child elements:

  • (required). Relationship name, which must correspond to a relationship name in the EJB jar descriptor.
  • . Indicator that foreign keys should be used to map the related entities. This element has no value and is required for one-to-many and many-to-one relationships.
  • . Indicator that a join table should be used to map the related entities. This element is required for many-to-many relationships. The join table is specified with .
  • (required). Defines a relationship role. One of these elements should be specified for each entity in the relationship.

Each element contains:

  • (required). Role name, which must correspond to a role name in the EJB jar descriptor.
  • . Indicator that a foreign key constraint should be added to the table.
  • . Indicator that read-ahead caching should be used.
  • (required). Mapping of foreign key fields. This element contains one element for each foreign key field. The field in the source entity is specified with ,and the column in the destination entity’s table is specified with . Also, this element must be empty for the child role.

JBlog’s JBoss CMP descriptor contains one element for the relationship Author-Story.

   // The Author-Story relation element in JBoss CMP descriptor            Author-Story                         author-stories                                                   username                              username                                               stories-author                   

As you can see from the code and configuration file sections listed in this article, entity beans that use CMP don’t require much code; however, to achieve that code simplicity, bean configuration is extremely complex (far too complex, in my opinion). To compound the problem, because so much of the substance of a bean lies in the configuration files rather than the code, many errors are undetectable until deployment or runtime; therefore, you can lose many hours searching through the JBoss server log for clues to the cause of the errors. When developing your own entity beans using CMP and JBoss, keep in mind that everything depends on correct configuration.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Related Posts