C H A P T E R  3

Building the EJB Tier of the DiningGuide Application

This chapter describes, step by step, how to create the EJB tier of the DiningGuide tutorial application. Along the way, you learn how to use the EJB Builder to create both entity and session beans, and how to use the IDE's test mechanism to test the beans. The topics covered in this chapter are:

By the end of this chapter, you will be able to run the whole EJB tier of the DiningGuide application as a deployed test application.

After you have created the EJB tier, you are free to create your own web services and client pages. Alternatively, you can continue on to Chapter 4, to learn how to create the application's web services using the Sun ONE Studio 5 Web Services features.


Overview of the Tutorial's EJB Tier

In this chapter, you create the module that is the heart of the tutorial application, namely, its EJB tier. As you create each component, you test it using the IDE's test application facility, which automatically creates a test web service and test client.

The EJB tier you create will include:

For a complete discussion of the role of the EJB tier within J2EE architecture, see Building Enterprise JavaBeans Components in the Sun ONE Studio 5 Programming series. That document provides full descriptions of all the bean elements, and explains how transactions, persistence, and security are supported in enterprise beans.

To examine an application that also uses an EJB tier and a web service generated from it, see the PartSupplier example on the Sun ONE Studio 5 examples page, http://forte.sun.com/ffj/documentation/tutorialsandexamples.html

The Entity Beans

An entity bean provides a consistent interface to a set of shared data that defines a concept. In this tutorial, there are two concepts: restaurant and customer review. The Restaurant and Customerreview entity beans that you create represent the database tables you created in .

Entity beans can have either container-managed persistence (CMP) or bean-managed persistence (BMP). With a BMP entity bean, the developer must provide code for mapping the bean's fields to the database table columns. With a CMP entity bean, the EJB execution environment manages persistence operations. In this tutorial, you use CMP entity beans. Using the IDE's EJB Builder wizard, you connect to the database and indicate which columns to map. The wizard creates the entity beans mapped to the database.

The EJB Builder creates the CMP entity bean's framework, including the required home interface, remote interface, and bean class. The wizard also creates a logical node to organize and facilitate customization of the entity bean.

You manually define the entity bean's create, finder, and business methods. When you define these methods, the IDE automatically propagates the method to the appropriate bean components. For example, a create method is propagated to the bean's home interface and a corresponding ejbCreate method to the bean's class. When you edit the method, the changes are propagated as well.

With finder methods, you must define the appropriate database statements to find the objects you want. The EJB 2.0 architecture defines a database-independent version of SQL, called EJB QL, which you use for your statements. At deployment, the Sun ONE Application Server plugin translates the EJB QL into the SQL appropriate for your database and places the SQL in the deployment descriptor.

The Session Bean

Entity beans represent shared data, but session beans access data that spans concepts and is not shared. Session beans can also manage the steps required to accomplish a particular task. Session beans can be stateful or stateless. A stateful session bean performs tasks on behalf of a client while maintaining a continued conversational state with the client. A stateless session bean does not maintain a conversational state and is not dedicated to one client. Once a stateless bean has finished calling a method for a client, the bean is available to service a request from a different client.

In the DiningGuide application, client requests might include obtaining data on all the restaurants in the database or finding all the customer reviews for a given restaurant. Submitting a review for a given restaurant is another client request. These requests are not interrelated, and don't require maintenance of a conversational state. For these reasons, the DiningGuide tutorial uses a stateless session bean to manage the different steps required for each request.

The session bean repeatedly builds collections of restaurant and customer review records to satisfy a client's request. This task could be accomplished by adding getter and setter methods for each field onto the entity beans, but this approach would require calling a method for every field each time the session bean has to retrieve a row of the table. To reduce the number of method calls, this tutorial uses special helper classes, called detail classes, to hold the row data.

The Detail Classes

A detail class is a Java class that has fields that correspond to the container-managed fields of the entity beans, plus getter and setter methods for each field. When the session bean looks up an entity bean, it uses the corresponding detail class to create an instance of each remote reference returned by the entity bean. The session bean just calls the detail class's constructor to instantiate a row of data for viewing. In this way, the session bean can create a collection of row instances that can be formatted into an HTML page for the client to view. Returning detail class instances to the client consumes less network bandwidth than returning remote references for the entity bean instances.

FIGURE 3-1 shows graphically how the detail classes work.

 FIGURE 3-1 Function of a Detail Class

Figure showing how the test client JSP page and the DiningGuideManager session bean interact as described in the text.

The numbered items in FIGURE 3-1 signify the following actions:

1. The web container passes a client's request for all restaurant data to the DiningGuideManager session bean.

2. The session bean calls the Restaurant entity bean's findAll method to perform a lookup on the Restaurant entity bean.

3. The findAll method obtains all available remote references to the entity bean.

4. For each remote reference returned, the session bean calls the Restaurant bean's getRestaurantDetail business method to fetch the RestaurantDetail class.

5. The getRestaurantDetail method returns a RestaurantDetail object, which is added to the collection.

6. The session bean returns a collection of all RestaurantDetail objects to the web container, which formats the data appropriately for the client to view.

Summary of Steps

Creating the EJB tier requires six steps:

1. Creating the entity beans

First, you create database schemas in the IDE, mapped from the tutorial's database tables. Next, using the EJB Builder, you create CMP entity beans that model the tables with the EJB Builder wizard. Then, you program the entity beans by adding and coding create, finder, and business methods.

2. Creating detail classes to be passed to the client for display

You create two JavaBeans classes with the same fields as the corresponding entity beans, and include the same accessor methods. These classes are used by the entity beans as types for parameters, fields, and return values. Returning these classes to the client is more efficient regarding network bandwidth than returning remote references for the entity bean instances.

3. Creating business methods on the entity beans to fetch the detail classes

4. Testing the entity beans' methods with the IDE's test application facility

From each entity bean, you automatically generate a test client that, when viewed in a web browser, allows you to create an instance of the bean and then exercise the business methods on the instance.

5. Creating the session bean

You use the EJB Builder to create a stateless session bean. You program the bean's create method to perform a lookup on the entity beans and its getter methods to construct collections of detail objects (from the detail classes for each entity bean. You create a method that creates customer review record in the database. You also create two dummy business methods required by the SOAP runtime.

6. Testing the session bean's methods

Before testing the session bean, you add references to the CMP entity beans to the EJB module's property sheet. From the session bean, you then generate a test application, which includes an EJB module. To this module, you add the EJB modules from the entity beans' test applications. Then you use the test client to create an instance of the session bean and then exercise its methods.


Note - Before you can begin work on the tutorial application, you must first have performed all the setup steps described in .




Creating Entity Beans With the EJB Builder

Create two entity beans, Restaurant and Customerreview, to represent the two database tables you created in .

In version 2.0 of the EJB architecture, entity beans can have local interfaces, remote interfaces, or both. The criterion for deciding which to use rests on whether the client that calls the bean's methods is remote or local to the bean. In this tutorial, you create the entity beans with both remote and local interfaces, for flexibility regarding how the web service will access the beans' methods. Two possibilities are the session bean accesses the beans' methods (using local interfaces), or the web service accesses the methods directly (using remote interfaces).



Tip - For more details about working with the EJB Builder, see the Sun ONE Studio 5 help topics on EJB components.





Note - The source code for the completed entity beans is provided in Appendix A.



Creating the Restaurant and Customerreview Entity Beans

First, create a directory to contain the application, then mount the directory in the IDE. Mounting a directory puts it in the IDE's class path. Next, in the mounted directory, create a database schema from the two database tables. Finally, create a package for the EJB tier and create two entity beans in it that are modeled from the database schema.

Creating the Tutorial's Directory

Create a directory to contain the tutorial's files and mount it in the IDE's file system, as follows:

1. Somewhere on your file system, create a directory and name it DiningGuide.



Note - If you create this as a subdirectory of another directory, the specifications of some methods you create for this tutorial, which include the file specification, may become very long. This may cause execution problems for platforms using Microsoft Windows 2000 with a Service Pack number less than 3. To avoid this, create this directory at the top level of a disk or volume (for example c:\DiningGuide).



2. Mount the DiningGuide directory.

Mounting an object in the Explorer puts that object into the IDE's class path.

a. In the Sun ONE Studio 5 IDE, choose the File right arrow Mount Filesystem.

The New wizard is displayed.

b. Select Local Directory, and click Next.

The Select Directory page of the New wizard is displayed.

c. Use the Look In file finder to find the DiningGuide directory, select it, and click Finish.

The new directory (for example, c:\DiningGuide) is mounted in the Explorer.

Creating a Database Schema for the Tutorial's Tables

Now create a database schema that models the Restaurant and Customerreview database tables. The IDE reads table definitions from the database and creates the schema.

1. Start the PointBase server by choosing Tools right arrow PointBase Network Server right arrow Start Server.

If the Start Server command is dimmed, the server is already running.

2. Open a connection to the PointBase sample database.

a. Select the Runtime tab of the Explorer.

b. Expand the Databases node.

The broken square icon redisplays as a whole square when the connection is opened.



Note - If there is no square icon, your IDE and application server were installed separately from each other and the PointBase JDBC driver has not been enabled in the IDE; consult the Sun ONE Studio 5, Mobile Edition Getting Started Guide for instructions on connecting an external PointBase database to the IDE.



3. Begin creating the schema.

a. Right-click the DiningGuide node in the Explorer and choose New right arrow All Templates.

The New Wizard is displayed, showing the Choose Template page.

b. Expand the Databases node, select Database Schema, and click Next.

The New Object Name page of the New wizard is displayed.

4. Type dgSchema in the Name field and click Next.

The Database Connection page of the wizard is displayed.

5. Specify the source database for the schema.

a. Enable the Existing Connection option.

b. Select from the list jdbc:pointbase:server://localhost:9092/sample [PBPUBLIC on PBPUBLIC].

c. Click Next.

The Tables and Views page is displayed.

6. Select the table to be modeled in the schema.

a. Select the CUSTOMERREVIEW table in the list of available tables and click the Add button.

b. Select the RESTAURANT table in the list and click the Add button.

The CUSTOMERREVIEW and RESTAURANT tables appear in the list of selected tables and views.

c. Click Finish.

The new database schema appears under the DiningGuide directory in the Explorer. If you expand all its subnodes, it looks like this:

Portion of Explorer window showing expanded dgSchema node, dgSchema database node, the RESTAURANT and CUSTOMERREVIEW table nodes and subnodes. 

Creating a Java Package for the EJB Tier

Create a Java package within the mounted DiningGuide node to hold the EJB tier, which is the data of your application.

1. Right-click the DiningGuide node and choose New right arrow Java Package.

2. Name the new package Data and click Finish.

The new Data package appears under the DiningGuide directory.

Creating the Restaurant Entity Bean

Create an entity bean to model the Restaurant table, as follows:

1. Begin creating the Restaurant entity bean.

a. Right-click the new Data package and choose New right arrow All Templates.

b. From the Templates wizard, expand the J2EE node, select CMP Entity EJB and click Next.

The CMP Entity Bean Name and Properties page of the New wizard (used by the EJB Builder module) is displayed. If you click the Help button on any page of the wizard, you can get context-sensitive help on creating CMP entity beans.

c. Name the new CMP entity bean Restaurant and select the following options:

Option Category

Option to Select

Source for Entities and Fields

Table from Database Schema Object

Component Interfaces

Both Remote and Local Interfaces


The New wizard looks like this.

New wizard's CMP Entity Bean Home and Properties page shows example values entered. The buttons are Back, Next, Finish, Cancel, and Help. 

d. Click Next.

This displays the Table from Database Schema Object page.

2. Specify the RESTAURANT schema.

a. Expand the DiningGuide node and the nodes under the dgSchema node, and select the RESTAURANT table.

The page looks like this:

Table from Database Schema Object page shows RESTAURANT table selected. Buttons are the five wizard buttons. 

b. Click Next to go to the CMP Fields page.

3. Customize any fields you wish to define the CMP bean.

You see a side-by-side display of the columns of the Restaurant database table and the corresponding Java fields that the columns will be mapped to when the wizard creates the Restaurant entity bean. For this tutorial, you want to change the type of the rating field.

a. Select the rating field and click the Edit button.

The Edit Persistent Field dialog box is displayed.

b. Delete the existing text in the Type field and type int.

The dialog box looks like this:

Edit Persistent Field dialog box showing example values. Buttons are Browse, OK, and Cancel. 

c. Click OK to close the dialog box.

The type of the rating Java field is changed to int.

d. Click Next.

The CMP Entity Bean Class Files page is displayed, listing the parts of the Restaurant bean that will be created. Notice that the EJB Builder wizard has automatically named the new entity bean with the same name as the database table.

4. Finish creating the bean by clicking Finish.

The new Restaurant entity bean and all its parts are created and displayed in the Explorer window.

Explorer window showing the six parts of the Restaurant bean, as described next. All except logical bean show "need to compile" badge. 

Five of the parts are interfaces and one part is the bean class. The sixth part is the logical node that groups all the elements of the enterprise bean together and facilitates working with them.

Creating the Customerreview Entity Bean

Create the Customerreview entity bean as you did the Restaurant bean, using the following steps:

1. Begin creating the Customerreview entity bean.

a. Right-click the new Data package and choose New right arrow CMP Entity EJB.

Notice that this item appears in the contextual menu. This shortcut is created for your convenience whenever you select an item from the New menu.

b. Name the new CMP bean Customerreview and select the following options:

Option Category

Option to Select

Source for Entities and Fields

Table from Database Schema Object

Component Interfaces

Both Remote and Local Interfaces


c. Click Next.

This displays the Table from Database Schema Object page.

2. Specify the CUSTOMERREVIEW schema.

a. Expand the DiningGuide node and all the nodes under the dgSchema node.

b. Select the CUSTOMERREVIEW table.

c. Click Next.

3. Finish creating the bean.

a. Click Next on the CMP Fields page.

b. Click Finish on the last page (CMP Entity Bean Class Files page).

The Customerreview entity bean is displayed in the Data package in the Explorer. Notice that there is also a primary key class named CustomerreviewKey. This class is automatically created when the entity bean has a composite primary key. (See in to confirm the composite primary key in this table.)

Screenshot repeating the same six parts as shown in previous screen shot, except for Customerreview bean, which has a Primary key class in addition. 

Creating Create Methods for CMP Entity Beans

Create the create methods for both entity beans, adding parameters and code to initialize the fields of the beans' instances.

Creating the Restaurant Bean's Create Method

Create the create method for the Restaurant entity bean as follows:

1. In the Explorer, right-click the Restaurant(EJB) logical node (the bean icon Java bean icon.).

2. Choose Add Create Method from the contextual menu.

The Add New Create Method dialog box is displayed.

3. Add method parameters for each column of the Restaurant database.

a. Click the Add button in the Parameters section.

The Enter Method Parameter dialog box is displayed.

b. Type restaurantname for the Field Name.

c. Select java.lang.String for the Type.

d. Click OK (or press Enter) to create the parameter and close the dialog box.

e. Similarly, create the other parameters:

Field Name

Type

cuisine

java.lang.String

neighborhood

java.lang.String

address

java.lang.String

phone

java.lang.String

description

java.lang.String

rating

int




Note - The order in which you create these parameters becomes important when you test the bean with the test application facility. Create them in the order given here.



Keep the two exceptions created by default, and make sure the method is added to both Home and Local Home interfaces.

4. Click OK.

The IDE propagates a create method under the RestaurantHome interface, another create method under the LocalRestaurantHome interface, and an ejbCreate method under the Restaurant bean class (RestaurantBean). A related ejbPostCreate method is also added to the bean class.

5. Expand the Restaurant(EJB) logical node and the Create Methods folder, and double-click the create method.

The Source Editor is displayed with the cursor at the ejbCreate method of the bean.



Note - If you right-click the create method node and choose Help, you can get online help information on create methods.



6. Add the following code (the bold text only) to the body of the ejbCreate method to initialize the fields of the bean instance:

public String ejbCreate(java.lang.String restaurantname, java.lang.String cuisine, java.lang.String neighborhood, java.lang.String address, java.lang.String phone, java.lang.String description, int rating) throws javax.ejb.CreateException {
	if (restaurantname == null) {
// Join the following two lines in the Source Editor
			throw new javax.ejb.CreateException("The restaurant name is required.");
	}
	setRestaurantname(restaurantname);
	setCuisine(cuisine);
	setNeighborhood(neighborhood);
	setAddress(address);
	setPhone(phone);
	setDescription(description);
	setRating(rating);
 
	return null;
}



Tip - After you enter code (either by typing or copying and pasting) into the Source Editor, press Control-Shift F to reformat it properly. If you are copying from the PDF file, join the lines that get broken by word wrap, as indicated by the code comment.



When the Restaurant entity bean's create method is called, it creates a new record in the database, based on the container-managed fields of this bean.

7. Select the Restaurant(EJB) logical node and press F9 to compile the bean.

The Restaurant entity bean should compile without errors.

Creating the Customerreview Bean's Create Method

Create the create method for the Customerreview entity bean as follows:

1. Right-click the Customerreview(EJB) logical node (the bean icon Java bean icon.) and choose Add Create Method.

2. Use the Add button to create three parameters, one for each column of the CustomerReview table:

Field Name

Type

restaurantname

java.lang.String

customername

java.lang.String

review

java.lang.String




Note - As in Step a, create these parameters in the order given.



Keep the two exceptions created by default, and make sure the method is added to both Home and Local Home interfaces.

3. Click OK.

4. Open the Customerreview(EJB) logical node and the Create Methods folder, and double-click the create method.

The Source Editor opens with the cursor at the ejbCreate method of the bean.

5. Add the following (bold) code to the body of the ejbCreate method to initialize the fields of the bean instance:

public CustomerreviewKey ejbCreate(java.lang.String restaurantname, java.lang.String customername, java.lang.String review) throws javax.ejb.CreateException {
	if ((restaurantname == null) || (customername == null)) {
// Join the following two lines in the Source Editor
			throw new javax.ejb.CreateException("Both the restaurant name and customer name are required.");
	}
	setRestaurantname(restaurantname);
	setCustomername(customername);
	setReview(review);
 
	return null;
}



Tip - After you enter code (either by typing or copying and pasting) into the Source Editor, press Control-Shift F to reformat it properly. If you are copying from the PDF file, join the lines that get broken by word wrap, as indicated by the code comment.



When the ejbCreate method is called, it creates a new record in the database, based on the container-managed fields of this bean.

6. Select the Customerreview(EJB) logical node and press F9 to compile the bean.

The Customerreview entity bean should compile without errors.

Now, create finder methods on both entity beans that will locate all or selected instances of each bean in the context.

Creating Finder Methods on Entity Beans

Create a findAll method on the Restaurant bean to locate all restaurant data. Also create a findByRestaurantName on the Customerreview bean to locate review data for a given restaurant.

Every finder method, except findByPrimaryKey, must be associated with a query element in the deployment descriptor. When you create the finder methods for these two entity beans, specify SQL statements using a database-independent language specified in the EJB 2.0 specification, namely EJB QL. At deployment time, the application server plugin translates the EJB QL into the SQL of the target database.

Creating the Restaurant Bean's findAll Method

To create the Restaurant bean's findAll method:

1. Right-click the Restaurant(EJB) logical node and choose Add Finder Method.

The Add New Finder Method dialog box is displayed.

2. Type All after the "find" string in the Name field.

3. Select java.util.Collection for the Return type.

4. Accept the two default exceptions.

5. Define the EJB QL statements, as follows:

EJB QL Statement

Text

Select

Object(o)

From

Restaurant o


6. Make sure the method is added to both Home and Local Home interfaces.

7. Click OK.

The new findAll method is created in the Local and Local Home interfaces of the Restaurant bean.



Note - If you right-click the Finder Methods node and choose Help, you can get online help information on finder methods.



8. Select the Restaurant(EJB) logical node and press F9 to compile the bean.

The Restaurant entity bean should compile without errors.

Creating the Customerreview Bean's findByRestaurantName Method

To create the Customerreview bean's findByRestaurantName method:

1. Right-click the Customerreview(EJB) logical node and choose Add Finder Method.

The Add New Finder Method dialog box is displayed.

2. Type ByRestaurantName after the "find" string in the Name field.

3. Select java.util.Collection for the Return type.

4. Click the parameter's Add button.

The Enter New Parameter dialog box is displayed.

5. Type restaurantname for the parameter name.

6. Select java.lang.String for the parameter type.

7. Click OK.

8. Accept the two default exceptions.

9. Define the EJB QL statements, as follows:

EJB QL Statement

Text

Select

Object(o)

From

Customerreview o

Where

o.restaurantname = ?1


(Which numeral you use for the Where clause depends on the position of the parameter in the finder method. In this case there's only one parameter, so the numeral is "1").

10. Make sure the method is added to both Home and Local Home interfaces.

11. Click OK.

The new findByRestaurantName method is created in the Local and Local Home interfaces of the Customerreview bean.

12. Select the Customerreview(EJB) logical node and press F9 to compile the bean.

The Customerreview entity bean should compile without errors.

Creating Business Methods for Testing Purposes

Create a business method for each entity bean that returns a value of one of its parameters. The business method enables you to test the beans later. For Restaurant, create a getRating method; for Customerreview, create a getReview method.

Creating the Restaurant Bean's getRating Method

To create the getRating business method for the Restaurant bean:

1. Examine the Restaurant entity bean's business methods.

a. Expand the Restaurant(EJB) logical node, and then expand its Business Methods node.

There are no business methods yet for this entity bean.

b. Expand the Restaurant bean's class (RestaurantBean), and then expand its Methods node.

Every field on the bean has accessor methods, including a getRating method.

These methods are used by the container for synchronization with the data source. To use any of these methods in development, you have to create them as business methods.

2. Create the getRating business method.

a. Right-click the Restaurant(EJB) logical node and choose Add Business Method.

The Add New Business Method dialog box is displayed.

b. Type getRating in the Name field.

c. Select int from the list of the Return Type field.

d. Accept the default exception (RemoteException), and the designation that the method will be created in both Remote and Local Home interfaces.

e. Click OK.

3. Examine the Restaurant entity bean's business methods again.

Under the logical node's Business Methods folder, the getRating method is now accessible as a business method. When the getRating method is used, it returns the value in the rating column of a selected restaurant record.

4. Validate the bean by right-clicking the Restaurant(EJB) logical node and choosing Validate EJB from the contextual menu.

The Restaurant entity bean should compile without errors. Now, create a similar method for the Customerreview bean.

Creating the Customerreview Bean's getReview Method

To create the getReview business method for the Customerreview bean:

1. Right-click the Customerreview(EJB) logical node and choose Add Business Method.

The Add New Business Method dialog box is displayed.

2. Type getReview in the Name field.

3. Select java.lang.String in the Return Type field.

Accept the default exception (RemoteException), and the designation that the method will be created in both Remote and Local Home interfaces.

4. Click OK.

The getReview method is now accessible as a business method. When the getReview method is called, it returns the value in the review column of a selected restaurant record.

5. Right-click the Customerreview(EJB) logical node and choose Validate EJB from the contextual menu.

The Customerreview entity bean should compile without errors.

6. Check that the icons in the Explorer no longer indicate that the beans are uncompiled.

Explorer window showing all parts of both entity beans without the "need to compile" badge on any item. 


Creating Detail Classes to View Entity Bean Data

As discussed in The Detail Classes, this tutorial uses detail classes as a mechanism for holding row data for viewing and reducing method calls to the entity beans. These classes must have the same fields as the corresponding entity beans, access methods for each field, and a constructor that sets each field.



Note - The source code for the completed detail classes is provided in Appendix A.



Creating the Detail Classes

First, create a RestaurantDetail class and a CustomerreviewDetail class:

1. In the Explorer, right-click the Data package and choose New right arrow All Templates.

The New wizard is displayed.

2. In the Choose Template page of the wizard, expand the Java Beans node and select Java Bean.

3. Click Next.

The New Object Name page of the wizard is displayed.

4. Type RestaurantDetail in the Name field and click Finish.

The new bean is displayed in the Explorer.

5. Right-click the Data package node and choose New right arrow Java Bean.

Notice the IDE has created a shortcut to the Java Bean template.

6. Type CustomerreviewDetail in the Name field and click Finish.

Creating the Detail Class Properties and Their Accessor Methods

Now, duplicate the entity beans' CMP fields in the detail classes. You do this by adding these fields as bean properties. (If you look in the Bean Patterns nodes of an entity bean's bean class, you will see that the CMP fields are stored as bean properties.) While adding the fields, you can automatically create accessor methods for each field.

To create the detail class properties and methods:

1. Expand the RestaurantDetail node and the class RestaurantDetail node.

2. Right-click the Bean Patterns node and choose Add right arrow Property.

The New Property Pattern dialog box is displayed.

3. Type restaurantname in the Name field.

4. Select String for the Type.

5. Select the Generate Field option.

6. Select the Generate Return Statement option.

7. Select the Generate Set Statement option.

8. Click OK.

9. Repeat Step 2 through Step 8 to create the following additional properties:

cuisine (String)
neighborhood (String)
address (String)
phone (String)
description (String)
rating (int)

10. Expand the RestaurantDetail bean's Methods node.

Observe that accessor methods have been generated for each field.

11. Expand the CustomerreviewDetail node and the class CustomerreviewDetail node.

12. Repeat Step 2 through Step 8 to create the following properties in the Bean Properties node:

restaurantname (String)
customername (String)
review (String)

Creating the Detail Class Constructors

To create constructors for the detail classes that instantiate the class fields:

1. Expand the RestaurantDetail bean, right-click the class RestaurantDetail node, and choose Add right arrow Constructor.

The Edit New Constructor dialog box is displayed.

2. Add the following method parameters and click OK:

java.lang.String restaurantname
java.lang.String cuisine
java.lang.String neighborhood
java.lang.String address
java.lang.String phone
java.lang.String description
int rating

3. Add the following bold code to the body of this RestaurantDetail constructor to initialize the fields:

public RestaurantDetail(java.lang.String restaurantname, java.lang.String cuisine, java.lang.String neighborhood, java.lang.String address, java.lang.String phone, java.lang.String description, java.lang.Integer rating){
	System.out.println("Creating new RestaurantDetail");
	setRestaurantname(restaurantname);
	setCuisine(cuisine);
	setNeighborhood(neighborhood);
	setAddress(address);
	setPhone(phone);
	setDescription(description);
	setRating(rating);
}



Tip - Remember, you can reformat code you paste or type into the Source Editor by pressing Control-Shift F.



4. Similarly, add a constructor to the CustomerreviewDetail class with the following parameters:

java.lang.String restaurantname
java.lang.String customername
java.lang.String review

5. Add the following bold code to the body of this CustomerreviewDetail constructor to initialize the fields:

public CustomerreviewDetail(java.lang.String restaurantname, java.lang.String customername, java.lang.String review){
	System.out.println("Creating new CustomerreviewDetail");
	setRestaurantname(restaurantname);
	setCustomername(customername);
	setReview(review);
}

6. Right-click the Data package and choose Compile All.

The package should compile without errors.

Now, create get methods on the entity beans to retrieve instances of the detail classes.

Creating Business Methods on the Entity Beans to Fetch the Detail Classes

Create a method on each entity bean that returns an instance of its corresponding detail class.

To create these methods:

1. In the Explorer, right-click the Restaurant (EJB) logical node and choose Add Business Method.

The Add New Business Method dialog box is displayed.

2. Type getRestaurantDetail in the Name field.

3. For the return type, use the Browse button to select the RestaurantDetail class.



Tip - Be sure to select the class java class icon, not the bean's node.


Data.RestaurantDetail is displayed in the Return Type field.

4. Make sure the option Both Remote and Local Interfaces is enabled.

5. Accept all other default values and click OK to create the business method and close the dialog box.

The method is created in the DiningGuideManager session bean.

6. Find the method in the Source Editor and add the following bold code:

public Data.RestaurantDetail getRestaurantDetail() {
	return null;
}

Creating the getCustomerreviewDetail Method

To create the getCustomerreviewDetail method:

1. Right-click the DiningGuideManager logical node and choose Add Business Method.

The Add New Business Method dialog box is displayed.

2. Type getCustomerreviewDetail in the Name field.

3. For the return type, use the Browse button to select the CustomerreviewDetail class.

Data.CustomerreviewDetail is displayed in the Return Type field.

4. Make sure the option Both Remote and Local Interfaces is enabled.

5. Click OK to create the business method and close the dialog box.

The method is created in the DiningGuideManager session bean.

6. Find the method in the Source Editor and add the following bold code:

public Data.CustomerreviewDetail getCustomerreviewDetail() {
	return null;
}

7. Right-click DiningGuideManager(EJB) and choose Validate EJB.

The DiningGuideManager session bean should validate without errors.

Adding EJB References

When you deploy a session bean, the bean's properties must contain references to any entity beans methods called by the session bean. Add them to the session bean now; you can not add them after the bean has been assembled into an EJB module.

1. In the Explorer, select the DiningGuideManager(EJB) logical node.

2. Display the bean's property sheet.

If the Properties window is not already visible, choose View right arrow Properties.

3. Select the References tab of the property window.

4. Click the EJB References field and then click the ellipsis (...) button.

The EJB References property editor is displayed.

5. Click the Add button.

The Add EJB Reference property editor is displayed.

6. Type ejb/Restaurant in the Reference Name field.

7. For the Referenced EJB Name field, click the Browse button.

The Select an EJB browser is displayed.

8. Select the Restaurant (EJB) bean under the DiningGuide/Data node and click OK.

Notice that the Home and Remote interface fields are automatically filled.

9. Set the Type field to Entity.

The Add EJB Reference property editor looks like this:

Add EJB Reference dialog box showing example values entered. 

10. Select the Sun ONE App Server tab.

11. Type ejb/Restaurant in the JNDI Name field and click OK.

This is the default JNDI name that was assigned to the Restaurant bean when you created it.

12. Similarly, add a reference to the Customerreview entity bean, so that the properties have the following values:

Tab

Property

Value

Standard

Reference Name

ejb/Customerreview

Referenced EJB Name

Customerreview

Type

Entity

Home Interface

Data.CustomerreviewHome

Remote Interface

Data.Customerreview

Sun ONE App Server

JNDI Name

ebj/Customerreview


The EJB References dialog box looks like this:

EJB References property editor showing the reference values for Restaurant and Customerreview entity beans. 

13. Click OK to close the Property Editor window.

You have now completed the EJB Tier of the tutorial application and are ready to test it. As when you tested the entity beans, the IDE's test application facility creates a web tier and JSP pages that can be read by a client in a browser.


Testing the Session Bean

Use the IDE's test application facility to test the DiningGuideManager session bean. This will test the whole EJB tier, because the session bean's methods provide access to methods on all of the tier's components.

Creating a Test Client for a Session Bean

Create a test application from the DiningGuideManager bean. Then add the two entity beans to the EJB module.

To create a test client for the session bean:

1. Right-click the DiningGuideManager logical node and choose Create New EJB Test Application.

The EJB Test Application wizard is displayed.

2. Accept all default values and click OK.

A progress monitor appears briefly and then goes away when the process is complete. Another window is displayed informing you that the web module that was created is also visible in the Project tab. It should go away automatically, also. If not, click OK to close the window.

3. View the resulting test objects in the Explorer.

The IDE has created the following objects:

  • An EJB module (DiningGuideManager_EJBModule)
  • A web module (DiningGuideManager_WebModule)
  • A J2EE application (DiningGuideManager_TestApp)

The EJB module and the web module appear as subnodes under the Data package and also as modules contained in the J2EE application. The web module has also been mounted separately.

Adding Entity Bean References to the EJB Module

The EJB module contains only the DiningGuideManager bean, so you must add the two entity beans to it.

1. Right-click the DiningGuideManager_EJBModule and choose Add EJB.

The Add EJB to EJB Module browser is displayed.

2. Expand the DiningGuide filesystem and the Data package.

3. Using Control-Click, select both the Restaurant and Customerreview logical beans.

4. Click OK.

The IDE adds references to the two entity beans to the EJB module, and to its reference in the test applications. The DiningGuideManager_EJBModule should look like this:

Segment of Explorer window showing expanded DiningGuideManager_EJBModule and expanded DiningGuideManager_TestApp.[ D ] 

5. Choose File right arrow Save All.

Providing the Sun ONE Application Server 7 Plugin With Database Information

You must add database information to the Sun ONE Application Server 7 properties of the EJB module. You performed this task with the entity bean test client in Providing the Sun ONE Application Server 7 Plugin With Database Information.

To add the required information:

1. Expand the EJB module (DiningGuideManager_EJBModule) in the Explorer and select the Restaurant node (a reference to the Restaurant bean) under it, to display its properties.

If the Properties Window is not already displayed, choose View right arrow Properties.

2. Select the Sun ONE AS tab of the Properties window.



Note - If there is no Sun ONE AS tab on the Properties window, there is no instance of the Sun ONE Application Server 7 in the Server Registry. See to correct this problem.



3. Confirm that the following three values for the appropriate properties:

Property

Value

Mapped Fields

7 container managed fields mapped

Mapped Primary Table

RESTAURANT

Mapped Schema

dgSchema


If these values are displayed, continue with Step 5.

4. If the values are not displayed, remap the Restaurant bean as follows:

a. Set the Mapped Schema property to Data/dgSchema.

b. Set the Mapped Primary Table property to Restaurant.

c. Click in the value field of the Mapped Fields, then click on the ellipsis button.

The Map to Database wizard is displayed.

d. Click Next to view the Select Tables page.

e. Select RESTAURANT from the drop list of the Primary Table field.

If RESTAURANT is not in the list, use the Browse button to find the table with the dgSchema schema.

f. Click Next to view the Field Mappings page.

g. If the fields are unmapped, click the Automap button.

Values for mappings appear for each field.

h. Click Finish.

The values should now display as in Step 3.

5. Repeat Step 1 through Step 4 (if required) for the Customerreview reference.

6. Select the EJB module (DiningGuideManager_EJBModule) to display its properties.

7. Select the Sun ONE AS tab of the properties window.

8. Click in the value field for the CMP Resource property, then click the ellipsis button.

The CMP Resource property editor is displayed.

9. Type jdo/PointbasePM in the Jndi Name field.

This is the JNDI name of the JDBC Persistence Manager you defined in or .

10. For the Name and Password fields, type the User Name and Password for your database.

For the PointBase sample database, these are both PBPUBLIC. The editor looks similar to this:

CMP Resource editor window showing example value in JNDI Name field, "scott" in Name field, and "tiger" in Password field. 

11. Click OK to accept the values and close the property editor.

You have finished configuring the test application to use your database and now you can deploy the test application.

12. Save your work with File right arrow Save All.

Deploying and Executing the Test Application

You must first undeploy the two test applications of the entity beans (if they are still deployed) before you deploy the session bean's test application. This is because they use the same JNDI lookups to the Restaurant and Customerreview beans that are used by the DiningGuideManager_TestApp application. If you fail to undeploy these applications, the DiningGuideManager test application will deploy, but will not load.



Note - Make sure your application server instance is running and is set as the default application server, before you proceed with this section.



Undeploying the Entity Bean Test Applications

To undeploy any previously deployed applications.

1. Click the Explorer's Runtime tab to display the Runtime page.

2. Expand the servername(hostname:host-number) instance node under the Sun ONE Application Server 7 node under Installed Servers.

For example, server1(localhost:80) is the default server instance. Or your instance might have other labels, such as MyServer(localhost:82).

3. Make sure the application server is running.

a. Right-click the application server node and choose Status.

The Application Server Instance Status dialog box is displayed. If the Status is Running, go on to Step 4.

b. Click the Start Server button.

A command window appears, displaying progress messages. The server is started when this window displays the string "Application onReady complete."

c. Click Close on the instance status dialog box.

Do not close the command window, although you can minimize it if necessary.

4. Expand the Deployed Applications node.

The two entity bean test applications are displayed.

Runtime page of Explorer shows expanded Server Registry node. Under server1 instance, 2 applications are displayed under Deployed Applications node. 

If nothing is displayed, right-click the Deployed Applications node and choose Refresh List.

5. Right-click one of the applications and choose Undeploy.

The application is undeployed.

6. Repeat Step 5 to undeploy the other application.

Deploying the DiningGuideManager Test Application



Note - Make sure the PointBase server is running before you deploy the test application, or any other J2EE application that accesses the database.



To deploy the DiningGuideManager test application:

1. Click the Explorer's Filesystems tab to display the Filesystems page.

2. Right-click the DiningGuideManager_TestApp J2EE application node and choose Execute from the contextual menu.

A Progress Monitor window shows the progress of the deployment process. The server instance's log file tab on the output window displays progress messages. The application is successfully deployed when you see success messages.

The IDE starts the default web browser and displays the test application's home URL, similar to http://localhost/DiningGuideManager_TestApp/ if your application server is installed locally; it will be different if it is installed remotely.

Using the Test Client to Test a Session Bean

On the test client's web page, create an instance of the DiningGuideManager session bean by exercising the create method; then test the business methods (getRating) on that instance.

To test the DiningGuideManager bean:

1. Create an instance of the DiningGuideManager session bean by invoking the DiningGuideManagerHome's create method.

The Data.DiningGuideManager[x] instance appears in the instance list. Now you can test the bean's getter methods.

2. Select the new Data.DiningGuideManager[x] instance.

The getAllRestaurants and getCustomerreviewsByRestaurant methods are made available.

3. Type any data you like in the createCustomerreview fields.

For example:

Invoke Methods section showing createCustomerreview method with "Bay Fox," "Marcia Green," and "This is the best!" entered as parameters. 

4. Click the Invoke button next to the createCustomerreview method.

The deployed test application adds the record you created to the database. The new parameter values are listed in the Stored Objects section (upper right), and the results are shown in the Results area:

Results section showing returned as void, Method Invoked as createCustomerreview, and parameters "Bay Fox," "Marcia Green," and "This is the best!." 

5. Click the Invoke button on the getAllRestaurants method.

If you created Joe's House of Fish in the database (in Using the Test Client to Test the Restaurant Bean), a vector of size 3 appears in the list of created objects (upper right), and the results of the method invocation should look as shown (actual numbers may be different). If you didn't create this record, your results might be different.

Results section showing returned as 3 detail objects, Method Invoked as getAllRestaurants, and "none" for parameters. 

6. Click the Invoke button on the getCustomerreviewDetail method.

The result is shown in the Results section.

Results section showing returned as null, Method Invoked as getCustomerreviewDetail, and "none" for parameters. 

7. Type Joe's House of Fish in the field for the getCustomerreviewsByRestaurant method and click the Invoke button.

No CustomerreviewDetail records should be returned, because there are no customer review comments in the database. Now try the French Lemon record.

8. Type French Lemon in the same field and invoke the method.

Two CustomerreviewDetail records should be returned:

Results section showing returned as 2 detail objects, Method Invoked as getCustomerreviewsByRestaurant, and "French Lemon" for parameter. 

9. Click the Invoke button on the getRestaurantDetail method.

The result is shown in the Results section.

Results section showing returned as null, Method Invoked as getRestaurantDetail, and "none" for parameters. 

10. When you are finished testing, stop the test client by pointing your web browser at another URL or by exiting the browser (or do nothing).



Note - You do not need to stop the application server's process (which is listed in the execution window). Whenever you redeploy, the server undeploys the application and then redeploys. When you exit the IDE, a dialog box is displayed for terminating the application server's instance process. However, you can manually terminate it at any time by right-clicking the server1(hostname:host-port) node in the execution window and choosing Terminate Process.



Checking the Additions to the Database

To verify that the DiningGuideManager_TestApp application inserted data in the database, repeat the procedures described in Checking the Additions to the Database and Checking the Additions to the Database.

You are now ready to create the web service.


Comments on Creating a Client

Congratulations, you have successfully completed the EJB tier of the DiningGuide application. You are ready to go on to Chapter 4, to use the Sun ONE Studio 5 IDE's Web Services module to create web services for the application, and then on to Chapter 5 to install the provided Swing classes for your client.

You may, however, wish to create your own web services and client, in which case, the Sun ONE Studio 5 test application can offer some guidelines.

Web services that access a session bean like the DiningGuideManager bean must include a servlet and JSP pages with lookup methods for obtaining the Home interfaces and Home objects of the entity beans in the EJB tier. The web module created by the test application facility offers examples of the required code.

Lookup method examples are found in the EjbInvoker class under the web module. Specifically, look for this class under the WEB-INF/Classes/com/sun/forte4j/j2ee/ejbtest/webtest directory.

Explorer window showing expanded DiningGuide web module/WEB-ING/Classes/com/sun/forte4j/j2ee/ejbtest/webtest containing EjbInvoker class. 

For example, the following methods offer good example lookup code:

  • EjbInvoker.getHomeObject
  • EjbInvoker.getHomeInterface
  • EjbInvoker.resolveEjb