C H A P T E R  3

Scenario: An EJB Module

FIGURE 3-1 shows an EJB module and the interactions in which it participates. This module is part of a J2EE application. and the interactions in the figure are typical for EJB modules in J2EE applications. The EJB module interacts with a client module (this interaction is represented in the figure by arrow labeled #1). The EJB module also interacts with an external resource, in this case a relational database management system (this interaction is represented by the arrows labeled #3). This EJB module, like most EJB modules, contains more than one enterprise bean, and the enterprise beans interact with each other (these interactions are represented by the arrows labeled #2).

 FIGURE 3-1 The CatalogData EJB Module

Diagram of the EJB module covered in this chapter, which contains a session bean and two entity beans.[ D ]


The Interactions in This Module

This scenario describes one possible use of the EJB module and the interactions that are illustrated in FIGURE 3-1. In this scenario, the EJB module is the back end for a J2EE application that supports a retail web site. The EJB module contains a set of enterprise beans that interact with the catalog data base. The web module that serves as the application's front end calls methods of this EJB module to get the data that it displays to users. Handling method calls and interacting with a data base are typical tasks for an EJB module in a J2EE application.

The web module in the application functions as a client of the CatalogData EJB module. Shoppers use web pages that are generated by the web module to request the data they want to view. The web module is responsible for calling the CatalogData module to obtain the data, and then formatting the data and displaying it to the shoppers.

The EJB module is responsible for getting the requested data from the database and passing it to the client module. The EJB module must be able to process requests for data and then return the correct data. The EJB module in this scenario contains only three enterprise beans and provides only two business methods. The business methods process only two types of requests. Although simple, these components and interactions show you how EJB modules provide the necessary interaction between client modules and data bases. The specific interactions that are covered in this scenario are outlined in the following list:

1. The client module requests some data by calling a method of the CatalogData EJB module. In this simple scenario, the client can request either a list of all the items in the catalog, or detailed information about one item.

2. The catalog data EJB module processes the request by generating a database query that will get the requested data.

3. The catalog data EJB module executes the query and returns the data to the client module. The client module then formats the data and displays it to the user.

The interactions between the client module and the CatalogData EJB module determine the J2EE technologies you choose to implement them and the internal architecture of the CatalogData EJB module. You should consider the points listed below:

This is a common architecture for an EJB module. (For more information about modelling sessions with session beans, see Building Enterprise JavaBeans Components.)

For generating the database queries, the J2EE platform provides a type of enterprise bean known as the entity enterprise bean. Entity beans model database tables, and they have methods that execute queries. In this scenario the catalog data is stored in two tables, and the catalog data module has two entity beans. Each entity bean models one of the tables. The entity beans handle connections, query language, and other aspects of the CatalogData EJB module's interaction with the database.


Programming This Module

TABLE 3-1 summarizes the programming that is required to create the CatalogData EJB module that is described in the preceding section and illustrated in FIGURE 3-1.

TABLE 3-1 Programming Required for This Scenario

Application Element

Programming Required

Application server

None.

EJB module

Create a session enterprise bean (CatalogManagerBean) with remote interfaces. The remote interfaces are appropriate for methods that are called remotely by other modules. Add business methods to the session bean that return catalog data to the caller. One of these business methods returns all items in the catalog, the other returns detail for any item specified by the client.

Create two entity enterprise beans (ItemBean and ItemDetailBean) to represent the two database tables that contain the catalog data. Create local interfaces for these entity enterprise beans. Local interfaces are appropriate for methods that are called by other enterprise beans in the same module. Add a method to the ItemBean that returns all items in the catalog. The ItemDetailBean has an automatically generated findByPrimayKey method that returns detail on a specific item. The session bean calls these methods to obtain the catalog data.

Create two detail classes, one for Item data, one for ItemDetail data. The CatalogData EJB module returns instances of these classes to the caller.

Create the CatalogData EJB module, which is represented in the Explorer by an EJB module node. Add the three enterprise beans to the module. Use the CatalogData EJB module's property sheet to specify the datasource for the catalog data.

J2EE application

To see how you add an EJB module to a J2EE application see Chapter 4.


The sections that follow show you how to perform many of these programming tasks. The method signatures in the interfaces specify the inputs and outputs of each interaction. The procedure sections show you how to connect these inputs and outputs to other components, other modules, and the catalog database. Instructions for creating the enterprise beans, adding business methods, and implementing the business methods with Java code are not included. To learn about these tasks, see the online help or Building Enterprise JavaBeans Components.

Creating Remote Interfaces for the Session Enterprise Bean

The design for the CatalogData EJB module calls for client modules to get catalog data by making remote calls to methods of the stateful session bean. To make the remote calls possible, the session bean must have remote interfaces. You generate the remote interfaces when you create the session bean with the Session Bean wizard. CODE EXAMPLE 3-1 shows the completed home and remote interfaces for the stateful session bean.

CODE EXAMPLE 3-1 Home and Remote Interfaces for the Session Bean
public interface CatalogManagerBeanHome extends javax.ejb.EJBHome {
  public CatalogBeans.CatalogManagerBean create()
    throws javax.ejb.CreateException, java.rmi.RemoteException;
}
 
 
public interface CatalogManagerBean extends javax.ejb.EJBObject {
  public java.util.Vector getAllItems() throws java.rmi.RemoteException;
  public CatalogBeans.idDetail getOneItemDetail(java.lang.String sku)  
    throws java.rmi.RemoteException;
}

These interfaces define two interactions between the CatalogData EJB module and client modules. Clients can get a list of all the items that are in the catalog by calling the getAllItems method. Clients can also specify an item and get detailed information for it by calling the getOneItemDetail method.

Most real-world shopping applications provide more functionality than this. These real-world applications have more than two business methods in their interfaces.

When an EJB module returns references to entity bean instances, the application server tracks any changes that the client module makes to the entity bean instances and automatically generates database updates. Passing remote references to clients consumes network resources and should only be done when the client can update the data. In this scenario, the client only displays the data, and there is no need to use this feature. The CatalogData module returns instances of ordinary Java classes. These classes, known as detail classes, have the same fields as the entity beans. The CatalogData module copies data from entity bean instances to detail class instances and returns the detail class instances to the client for display. For more information on using detail classes with entity enterprise beans, see Building Enterprise JavaBeans Components.

For more information about client modules using remote interfaces to call the CatalogData module's methods, see .

The getAllItems and getOneItemDetail methods are implemented with calls to methods of the entity beans. The entity beans generate the appropriate queries and return the requested data as entity bean instances. To see the implementation of the getAllItems method, see CODE EXAMPLE 3-3.

Creating Local Interfaces for the Entity Enterprise Beans

To obtain the data that clients request, the CatalogManagerBean calls methods of the two entity beans. Since these calls are within the module there is no need for the entity beans to have the resource-consuming remote interfaces. Instead, you can generate local interfaces for the entity beans. Local interfaces are faster and more efficient than remote interfaces. You should use local interfaces whenever a remote interaction is not required.

Generate the local interfaces when you create the entity beans with the Entity Bean wizard. CODE EXAMPLE 3-2 shows the completed local interfaces for the Item entity bean. The interfaces for the ItemDetail bean are similar.

CODE EXAMPLE 3-2 Local Home and Local Interfaces for the ItemBean Enterprise Bean
public interface LocalItemBeanHome extends javax.ejb.EJBLocalHome {
  public CatalogBeans.LocalItemBean findByPrimaryKey(java.lang.Integer aKey)
    throws javax.ejb.FinderException;
  public java.util.Collection findAll() throws javax.ejb.FinderException;
}
 
 
public interface LocalItemBean extends javax.ejb.EJBLocalObject {
  public CatalogBeans.iDetail getIDetail();
}

The CatalogManagerBean calls the findAll method to obtain a list of all the items in the catalog.



Note - If you plan to test individual enterprise beans with the IDE's test application feature, you need to generate both remote and local interfaces. The test application feature will generate a web module client that exercises the enterprise bean's methods, and the web module client requires the remote interfaces.



Using the Local Interfaces in the Session Enterprise Bean

Client modules request catalog data by calling one of the CatalogManagerBean business methods. These are the methods declared in the CatalogManagerBean interface, which is shown in CODE EXAMPLE 3-1. The implementations of these business methods call entity bean methods. To make these calls to the entity beans, the CatalogManagerBean needs local EJB references to the local interfaces you created for the entity bean. You must program two separate parts of these local EJB references.

  • JNDI lookup code. Both of the session bean business methods include code that uses the JNDI naming facility to obtain a reference to an entity bean's LocalHome.
  • A declaration of the reference. This is used by the runtime environment to identify the specific bean referred to by the lookup code.

JNDI Lookup Code for Local EJB References

CODE EXAMPLE 3-3 shows the implementation of the session bean's getAllItems method. Clients of the CatalogData EJB module call this method to get a list of all the items in the online catalog. The method implementation shows you how the CatalogManagerBean gets the catalog data by interacting with the entity beans. There are three steps in this code:

1. CatalogManagerBean uses JNDI lookup to obtain a local reference to the ItemBean local home interface.

2. CatalogManagerBean calls the ItemBean.findAll method.

3. CatalogManagerBean copies the catalog data from entity bean instances to detail class instances, adds the detail class instances to a vector, and returns the vector to the client.

Comments in CODE EXAMPLE 3-3 identify these steps

CODE EXAMPLE 3-3 The getAllItems Method of the CatalogManagerBean
public java.util.Vector getAllItems() {
  java.util.Vector itemsVector = new java.util.Vector();
  try{
    if (this.itemHome == null) {
      try {
         // Use JNDI lookup to obtain reference to Entity 
         // Bean LocalHome.
        InitialContext iC = new InitialContext();
        Object objref = iC.lookup("java:comp/env/ejb/ItemBean");
        itemHome = (LocalItemBeanHome) objref;
      }
      catch (Exception e){
        System.out.println("lookup problem" + e);
      }
    }    
    // Use the local reference to call findAll();
    java.util.Collection itemsColl = itemHome.findAll();
    if (itemsColl == null) {
      itemsVector = null;
    }
    else {
      // Copy data to detail class instances.
      java.util.Iterator iter = itemsColl.iterator();
      while (iter.hasNext()) {
        iDetail detail;
        detail=((CatalogBeans.LocalItemBean)iter.next()).getIDetail();
        itemsVector.addElement(detail);
      }
    }
  }
  catch (Exception e) {
    System.out.println(e);
  }
  return itemsVector;
}

The string specified in the lookup statement is the name of the reference and not the name of the referenced enterprise bean. The enterprise bean's name is often used as the reference name, to make it easier to remember which enterprise bean is meant. The actual mapping of reference name to enterprise bean is done with the reference declaration, which is covered in the next step.

Reference Declarations for Local EJB References

After you write the JNDI lookup code, you need to set up a local EJB reference declaration. The local EJB reference declaration maps the reference name used in the lookup statement to an actual enterprise bean name. The referenced enterprise bean must be in the same module as the calling bean.

To set up a local EJB reference declaration:

1. Right click the calling bean's logical node and choose Properties right arrow References tab right arrow EJB Local References property right arrow the ellipsis (...) button right arrow the Add button.

The Add EJB Local Reference dialog box opens.

2. Define the reference in the dialog box.

a. In the Reference Name field, type the reference name used in the lookup statement.

FIGURE 3-2 shows the reference name that was used in CODE EXAMPLE 3-3.

b. Map the reference name to an enterprise bean.

Click the Browse button next to the Reference EJB Name field. This opens a browser that lets you select the matching enterprise bean. FIGURE 3-2 shows the field with ItemBean selected.

 FIGURE 3-2 Add EJB Reference Dialog Box

Screenshot of Add Local EJB Reference dialog box.[ D ]

Assembling the EJB Module

After you create the enterprise beans you create the CatalogData EJB module and add the enterprise beans. You also configure your EJB module by selecting property values that request specific runtime services from the application server.

Different application server products need different information for deployment, and the EJB module properties include some server-specific properties. This scenario uses some of the server-specific properties for the Sun ONE Application Server.

Creating the EJB Module

There are two ways to create an EJB module in the IDE. Both procedures create an EJB module node at the location you specify.

Your EJB module node represents the deployment descriptor for your module. Enterprise beans you add to the module appear as subnodes of the module node, but the IDE does not copy the source files for the enterprise beans to the directory that holds the module node. Keep this in mind when you decide where to put your EJB module.

  • If you keep all of the source code for your module in a single filesystem, consider putting your EJB module node at the top level of that filesystem.
  • If the source code for the module is in different filesystems, such as filesystems that are owned by different developers, consider creating a set of directories that contain only modules and J2EE applications. Keep these directories separate from the directories that contain the source code.

To create an EJB module beginning with an enterprise bean node:

1. Right-click the enterprise bean node and choose Create New EJB Module.

The New EJB Module dialog box opens.

2. Name the module and select a location in the filesystem for it.

a. In the Name field, type the new module's name. In this scenario, the EJB module is named CatalogData.

b. In the Select a package location for the new EJB module field, choose the filesystem, directory, or package where you want to create the new module.

c. Click OK.

A node representing your new module is created under the filesystem, directory, or node you selected. The enterprise bean you right-clicked in Step 1 is automatically included in the new module.

You can add more enterprise beans to the module. See Adding Enterprise Beans and Other Resources to the Module.

To create an EJB module from a filesystem, package, or directory node:

1. Right-click any Explorer window node and then choose New right arrow All Templates.

The New wizard's Choose Template page opens.

2. Choose the EJB Module template.

a. In the Select a Template field, expand the J2EE node and select the EJB Module node.

b. Click Next

The New Object Name page opens.

3. Define the new EJB module.

a. In the Name field, type the module name.

In this scenario the module is named CatalogData.

b. Click Finish.

The IDE creates the module and represents it in the Explorer with an EJB module under the filesystem, package, or directory you selected in step 1.

Both of these procedures create an EJB module node in the location you chose. Keep in mind that the IDE stores deployment descriptor information about the module in this directory, but the source code for the components in the module is not copied into this directory.

Adding Enterprise Beans and Other Resources to the Module

Once you have created a module, you can add enterprise beans to it.

To add an enterprise bean to an EJB module:

1. Right-click the module node and choose Add EJB.

This opens the Add EJB to EJB Module dialog box.

2. Select one or more enterprise beans.

a. In the Select the EJB(s) to add to this EJB Module field, select the enterprise beans you are adding to the module.

a. Click OK.

The IDE adds the selected enterprise beans to the module. In the Explorer, the IDE adds nodes representing the selected beans under the module node.

When you add an enterprise bean to a module, the IDE manages any dependencies of the enterprise bean on other kinds of resources (Java classes, image files, and so on). It automatically adds these resources to the module definition.

For the few exceptions to this, see Identifying Extra Files.

Specifying a Datasource for the Entity Enterprise Beans

In this scenario, the CatalogData EJB module accesses a database to get the catalog data. J2EE applications access databases through J2EE application servers, using connection pooling and other services provided by the application server. The database must be set up as an application server resource with a JNDI name. Defining a database as an application server resource maps the databases JNDI name to the actual database URL.

A J2EE application that accesses a database must be configured with a resource reference that contains the database JNDI name. The way you set up the resource reference depends on the type of entity bean you are working with:

  • If you are working with a container-managed entity bean, the application server determines how you identify the database. With most application servers, including the Sun ONE Application server, you use one of the module's server-specific properties to identify the datasource by JNDI name.
  • If you are working with a bean-managed entity bean, you must write JNDI lookup code and set up a matching resource reference declaration that maps the lookup name to the JNDI name.


Note - At development time, you can open a live connection to a database in the IDE and use the Entity Bean wizard to create an entity bean that models a database table. This kind of connection is covered in Building Enterprise JavaBeans Components. This section covers specifying the database that will be used at runtime.



Using the Server-specific Tabs for Container-managed Entity Beans

For container-managed entity beans, you use the EJB module's CMP resource property to specify the datasource by JNDI name. The IDE creates the resource reference for you automatically. The CMP Resource property contains the JNDI name for the default Pointbase database.

To configure container-managed entity beans to use a database:

1. Right-click the EJB Module node and choose Properties right arrow Sun ONE AS tab right arrow CMP Resource right arrow the ellipsis (...) button.

The CMP Resource property editor opens.

2. Type in the values that identify the database for the EJB module and its entity beans.

FIGURE 3-3 shows the CMP Resource property editor with values that give the CatalogData EJB module access to the Pointbase database named sample.

 FIGURE 3-3 EJB Module CMP Resource Property Editor

Screenshot of EJB module property sheet showing J2EE RI specific tab.[ D ]

Note - Most installations of the IDE include the Sun ONE Application Server and the PointBase database server. Installing the IDE sets up the PointBase database named sample as an application server resource with a JNDI name of jdo/PointbasePM. In this scenario, the CatalogData EJB module is configured to use the sample databse.



This procedure is for using the IDE with the Sun ONE Application Server and the installed PointBase database. If you are using another database product or another application server product, you must adapt the procedure.

  • If you are using the IDE with the Sun ONE Application Server and a database product other than PointBase, you need to use the application server's administration tools to define your database to the application server as a JDBC datasource with a JNDI name. After you do this, you can use the procedure to configure your EJB module with the datasource JNDI name.
  • If you are using an application server other than the Sun ONE Application Server, the database must be set up as a datasource resource of the application server and given a JNDI name. The procedures for this depend on the application server product. After the database is set up with a JNDI name, you can configure your EJB module with the JNDI name. In the EJB Module property sheet, use the server-specific tab for the application server product you are using. The property name may be different from CMP Resource.

If you are going to deploy your application in a managed test environment or a production environment, system administration will probably be responsible for setting up databases as application server resources and assigning JNDI names. In this case you simply need to obtain the datasource's JNDI name from system administration.

Creating Resource Factory References Explicitly for Bean-managed Entity Beans

If your EJB module contains entity beans that use bean-managed persistence instead of container-managed persistence, your entity beans already include JDBC and JTA code that prepares and executes database queries. This is covered in Building Enterprise JavaBeans Components. This code must include a JNDI lookup that obtains a resource factory reference to the datasource. The lookup uses the datasource's JNDI name to obtain the reference. Like other types of J2EE references, this type of reference has two parts:

  • A JNDI lookup. Each entity bean includes code that uses the JNDI lookup statement to obtain a reference to a named resource.
  • A declaration of the reference. The declaration maps the reference name used in the lookup statement to the datasource's JNDI name.

Any datasource you specify with an explicit lookup must be a named resource of the application server with an assigned JNDI name. The application server has the information to map the JNDI name to the actual database URL.

JNDI Lookup Code for Resource Factory References

CODE EXAMPLE 3-4 shows the code that you use in a BMP entity enterprise bean to look up a datasource:

CODE EXAMPLE 3-4 JNDI Lookup for a Database
try {
  // Obtain Initial Context--Opens Communication With JNDI Naming:
  Context ic = new InitialContext();
  // Request Lookup of Resource--In This Example a JDBC Datasource:
  javax.sql.DataSource hrDB = (javax.sql.DataSource)
                                       ic.lookup("java:comp/env/jdbc/Local_HR_DB");
}  
catch(Exception e) { 
  System.out.println(e.toString()); 
  e.printStackTrace();
  return; 
} 

Reference Declarations for Resource References

In addition to writing the lookup statement, you must set up a reference declaration for the datasource resource.

To set up a reference declaration for a datasource reference:

1. Right-click the enterprise bean's logical node and choose Properties right arrow References tab right arrow Resource References right arrow ellipsis (...) button right arrow Add button.

The Add Resource Reference dialog box opens.

2. Supply the information that identifies the datasource.

a. In the Name field, type the reference name used in the lookup statement.

FIGURE 3-4 shows the reference name that was used in CODE EXAMPLE 3-4.

 FIGURE 3-4 Add Resource Reference Dialog Box

Screenshot of EJB node's Add Resource Reference dialog.[ D ]

b. Click the Sun ONE App Server tab.

c. Map the reference name to a datasource.

FIGURE 3-5 shows the JNDI Name field with the value jdbc/jdbc-pointbase. This is the default name JNDI name for the PointBase database that is included in most installations of the IDE.

 FIGURE 3-5 Add Resource Reference Dialog Box, Server-specific Tab

Screenshot of the J2EE RI-specific tab for the Add Resource Reference dialog.[ D ]

This procedure is for using the IDE with the Sun ONE Application Server and the installed PointBase database. If you are using another database product or another application server product, you must adapt the procedure. Adapt the procedure as follows:

  • If you are using the IDE with the Sun ONE Application Server and a database product other than PointBase, you need to use the application server's administration tools to define your database to the application server as a JDBC datasource with a JNDI name. After you do this, you can use this procedure to configure your EJB module with the datasource JNDI name.
  • If you are using an application server other than the Sun ONE Application Server, the database that you use must be set up with the application server as a datasource resource with a JNDI name. The procedures for this depend on the application server product. After the database is set up with a JNDI name, you can configure your EJB module with the JNDI name. In the Add Resource Reference dialog box, use the server-specific tab for the application server product you are using.

Other Module Assembly Tasks

The preceding sections cover the assembly tasks that are required to assemble the CatalogData EJB module. This section describes some EJB module assembly tasks that were not covered in the CatalogData scenario.

Your EJB modules may require you to perform some of these other assembly tasks. This section covers several web module assembly tasks that you are likely to perform.

For each module, you need to determine what assembly tasks are required. Questions that you might ask about a module include the following:

  • Have all the references in the module been linked? Your module may contain some references to components in other modules. These references can only be linked after the module has been assembled into a J2EE application.
  • Have generic security roles been set up for the module? Have any security role references in the module's enterprise beans been linked to these generic security roles? Have method permissions been mapped to these generic security roles? For more information on these issues see Chapter 7.
  • Have container-managed transactions been defined? For more information on this issue see Chapter 6.

Some EJB module tasks that were not covered in the CatalogData EJB module scenario are described in the following sections.

Identifying Extra Files

In most cases, the IDE recognizes the dependencies of the enterprise beans that are in an EJB module and includes all of the needed files in the EJB JAR files that it generates at deployment time. There are some dependencies, however, that the IDE does not recognize. These unrecognized dependencies include:

  • Enterprise beans in your module that use a help file without calling it directly
  • Enterprise beans in your module that access a class dynamically and use the class name only as a string and not as a class declaration

In these and similar cases, the IDE does not recognize the enterprise bean's dependency and does not include the help file or class file in archive files that it creates. You need identify these files so that they are included in the archive and are available at run time.

To identify extra files:

1. Right-click the EJB module node and choose Properties right arrow Extra Files right arrow ellipsis (...) button.

The Extra Files property editor opens.

2. Select any extra file that should be deployed or archived as part of this module.

a. In the Source field, select the extra files that belong in the module.

b. Click the Add button to add the selected files to the list of extra files.

3. Click OK to close the editor and process you selections.

Excluding Duplicate JAR Files

In some cases you want to prevent the IDE from acting on some of the file dependencies it recognizes. For example, an enterprise bean in your module has a dependency on a commonly used JAR file that you know will be present in the runtime environment. You can prevent the IDE from adding an unnecessary copy of the commonly used JAR file by identifying that JAR file as a duplicate JAR file.

To exclude a duplicate JAR file:

1. Right-click the module node and choose Properties right arrow Library Jars to Exclude right arrow ellipsis (...) button.

This Library Jars to Exclude property editor opens. It displays a list of mounted JAR files.

2. Select the JAR files that should be excluded and click the Add button to move them to the list of library JARs to exclude.

3. Click OK to close the property editor and process your selections.