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 Java Studio Enterprise Web Services features.
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 Java Studio Enterprise 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 Java Studio Enterprise Tutorials and Code Camps page, http://developers.sun.com/prodtech/javatools/jsenterprise/learning/tutorials/index.html.
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 Chapter 1.
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.
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.
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.
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.
Creating the EJB tier requires six steps:
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.
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 Chapter 1. |
Create two entity beans, Restaurant and Customerreview, to represent the two database tables you created in Chapter 1.
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 Java Studio Enterprise help topics on EJB components. |
Note - The source code for the completed entity beans is provided in Appendix A. |
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.
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.
2. Mount the DiningGuide directory.
Mounting an object in the Explorer puts that object into the IDE's class path.
a. In the Java Studio Enterprise IDE, choose the File Mount Filesystem.
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.
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 PointBase Network Server
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.
The broken square icon redisplays as a whole square when the connection is opened.
a. Right-click the DiningGuide node in the Explorer and choose New 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].
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.
The new database schema appears under the DiningGuide directory in the Explorer. If you expand all its subnodes, it looks like this:
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 Java Package.
2. Name the new package Data and click Finish.
The new Data package appears under the DiningGuide directory.
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 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:
The New wizard looks like this.
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.
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:
c. Click OK to close the dialog box.
The type of the rating Java field is changed to int.
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.
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.
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 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:
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.
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 TABLE 1-1 in Chapter 1 to confirm the composite primary key in this table.)
Create the create methods for both entity beans, adding parameters and code to initialize the fields of the beans' instances.
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 ).
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:
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.
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:
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.
Create the create method for the Customerreview entity bean as follows:
1. Right-click the Customerreview(EJB) logical node (the bean icon ) and choose Add Create Method.
2. Use the Add button to create three parameters, one for each column of the CustomerReview table:
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.
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:
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.
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.
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:
6. Make sure the method is added to both Home and Local Home interfaces.
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.
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.
8. Accept the two default exceptions.
9. Define the EJB QL statements, as follows:
(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.
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.
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.
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.
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.
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.
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.
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. |
First, create a RestaurantDetail class and a CustomerreviewDetail class:
1. In the Explorer, right-click the Data package and choose New All Templates.
2. In the Choose Template page of the wizard, expand the Java Beans node and select Java Bean.
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 Java Bean.
Notice the IDE has created a shortcut to the Java Bean template.
6. Type CustomerreviewDetail in the Name field and click Finish.
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 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.
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)
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 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:
Tip - Remember, you can reformat code you paste 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:
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.
Create a method on each entity bean that returns an instance of its corresponding detail class.
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 ( |
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 method.
6. Find the new method under the logical bean's Business Methods node and double-click it to display it in the Source Editor.
7. Add the following bold code to the method's body:
public Data.RestaurantDetail getRestaurantDetail() { return (new RestaurantDetail(getRestaurantname(), getCuisine(), getNeighborhood(), getAddress(), getPhone(), getDescription(), getRating())); } |
8. Select the Restaurant (EJB) logical node and press F9 to compile the code.
9. In the Explorer, right-click the Customerreview (EJB) logical node and choose Add Business Method.
10. Type getCustomerreviewDetail in the Name field.
11. For the return type, use the Browse button to select the CustomerreviewDetail class icon.
12. Make sure the option Both Remote and Local Interfaces is enabled.
13. Accept all other default values and click OK to create the method.
14. Open the method in the Source Editor and add the following bold code:
public Data.CustomerreviewDetail getCustomerreviewDetail() { return (new CustomerreviewDetail(getRestaurantname(), getCustomername(), getReview())); } |
15. Right-click the Data package and choose Compile All.
The entire package should compile without errors.
You have finished creating the entity beans of the tutorial application and their detail class helpers. Your next task is to test the beans.
With the Java Studio Enterprise IDE, you can create a test client to exercise the methods on an entity bean. The test client uses JavaServer Pages technology that allows you to create instances of the bean and exercise the bean's create, finder, and business methods in a web browser.
Use this test client to exercise the Restaurant bean's create and getRating methods.
When you create a test client, the IDE generates an EJB module, a J2EE application module, and many supporting elements.
To create a test client for the Restaurant entity bean:
1. Right-click the Restaurant(EJB) logical node and choose Create New EJB Test Application.
The EJB Test Application wizard is displayed.
The wizard's window looks like this:
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. This window should go away automatically, also. If not, click OK to close the window.
4. View the resulting test objects in the Explorer.
The IDE has created an EJB module named Restaurant_EJBModule, a web module named Restaurant_WebModule (which is also mounted separately), and a J2EE application named Restaurant_TestApp. The web module contains a number of JSP pages that support the test client. The J2EE application includes references to the EJB module and to the web module.
The J2EE application created by the IDE contains references to the web module and the EJB module. You can see these objects by expanding the Restaurant_TestApp:
In order for the test client to find the database and log onto it, you must add information about your database to the application server properties of the EJB module.
To add the required information:
1. Expand the EJB module (Restaurant_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 Properties.
2. Select the Sun ONE AS tab of the Properties window.
3. Confirm that the following properties are set as follows:
If these values are displayed, continue with Step 5.
4. If the values are not displayed, remap the Restaurant reference as follows:
a. Select the value field of the Mapped Fields value and click on the ellipsis button.
The Map to Database wizard is displayed.
b. Click Next to view the Select Tables page.
c. 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 within the dgSchema schema.
d. Click Next to view the Field Mappings page.
e. If the fields are unmapped, click the Automap button.
Values for mappings appear for each field, as shown:
The values should now display as in Step 3.
5. Select the EJB module (Restaurant_EJBModule) to display its properties.
6. Select the Sun ONE AS tab of the properties window.
7. Click in the value field for the CMP Resource property to display an ellipsis button.
8. Click the ellipsis button to display the CMP Resource property editor.
9. Type jdo/PointbasePM in the Jndi Name field.
This is the JNDI name of the JDBC Persistence Manager described in Setting JDBC Resources.
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:
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.
Note - Make sure the PointBase server is running before you deploy the test application, or any other J2EE application that accesses the database. In addition, make sure Sun Java System Application Server is running and is the default application server of the IDE. See Setting the Sun Java System Application Server as the Default Server for information. |
To deploy the Restaurant test application:
Right-click the Restaurant_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:
http://server-host:server-port-number/Restaurant_TestApp/dispatch.jsp
Your browser displays the test client like this:
On the test client's web page that is displayed, use the create method of the Restaurant bean's home interface to create an instance of the bean. Then test a business method (in this case, getRating) on that instance.
1. Create an instance of the Restaurant bean by invoking the create method.
The create method is under the heading "Invoke Methods on Data.RestaurantHome." There are seven fields under it. The fields are not named, but you can deduce what they are by their order, which is the same order you created them in (see Step a under Creating Create Methods for CMP Entity Beans).
Note - Double-click the Restaurant.create method in the Explorer to display it in the Source Editor; the order of the fields is shown in the method's definition. |
Type any data you like into the fields, for example (your field order may be different):
2. Click the Invoke button next to the create method.
The deployed test application adds the records you created to the test database. The new Restaurant instance is listed by its restaurantname value in the upper left, and new data objects are listed in the upper right, as shown.
The results are shown in the Results area.
3. Test the findAll method of the Restaurant bean by clicking the Invoke button next to it.
The results area should look like this:
Notice that three items were returned. This demonstrates that the new database record you created in Step 2 was added to the two you created in Chapter 1.
4. Test the findByPrimaryKey method by typing in Bay Fox and clicking the Invoke button next to the method.
The results area shows that the Bay Fox record was returned.
Now, test the entity bean's business methods.
5. Select the instance for Joe's House of Fish listed under Data.RestaurantHome in the instances list (upper left).
The getRating method is now listed under the Invoke Methods area.
6. Click the Invoke button next to the getRating method.
The results of this action are listed in the Results area and should look like this:
This demonstrates that you have created a new record in the database and used the getRating method to retrieve the value of one of its fields.
Continue testing by selecting created objects and invoking their methods. For example, if you select one of the Data.RestaurantDetail objects, you can invoke its getter methods to view its data, or its setter methods to write new data to the database.
7. When you are finished testing, you can quit the browser, point it to a different URL, or do nothing, as you wish
To verify that the Restaurant_TestApp application inserted data in the database:
1. In the IDE, select the Runtime tab of the Explorer.
2. Expand the Databases node, the PointBase connection node, and the Tables node.
The nodes for each table in the sample database are displayed.
3. Right-click the RESTAURANT table and choose View Data.
A command editor window is displayed, showing the new Restaurant record you entered in Step 1 under Using the Test Client to Test the Restaurant Bean, as shown.
You are now ready to create the test client for the Customerreview Bean.
Create a test client for the Customerreview entity bean by repeating all the steps in Creating a Test Client for the Restaurant Bean, but using values appropriate to the Customerreview bean.
To summarize creating the test client application:
1. Select the Customerreview(EJB) logical bean and choose Create a new EJB Test Application.
2. Accept all default values and click OK.
Add database information for the plugin, similar to the description in Providing the Sun Java System Application Server Plugin With Database Information, using values appropriate to the Customerreview bean.
To summarize adding database information to the plugin:
1. Expand the EJB module (Customerreview_EJBModule), select the Customerreview node under it, and display its properties.
2. Select the Sun ONE AS tab of the Properties window.
3. Confirm that the following three values for the appropriate properties:
If these values are displayed, continue with Step 5.
4. If the values are not displayed, remap the Customerreview bean as follows:
a. Set the Mapped Schema to Data/dgSchema.
b. Set the Mapped Primary Table to CUSTOMERREVIEW.
c. Click the ellipsis button in the value field of the Mapped Fields property.
d. In the wizard, click Next to view the Select Tables page.
e. Select CUSTOMERREVIEW from the drop list of the Primary Table field.
f. Click Next to view the Field Mappings page.
g. If the fields are unmapped, click the Automap button.
5. Display the EJB module (Customerreview_EJBModule) properties.
6. Select the Sun ONE AS tab of the properties window.
7. Click the ellipsis button in the value field of the CMP Resource property.
8. In the CMP Resource property editor, type jdo/PointbasePM in the Jndi Name field.
9. For the Name and Password fields, type the User Name and Password for your database.
For the PointBase sample database, these are both PBPUBLIC.
10. Click OK to accept the values and close the property editor.
Note - Make sure the PointBase server is running before you deploy the test application, or any other J2EE application that accesses the database. In addition, make sure Sun Java System Application Server is running and is the default application server of the IDE. See Setting the Sun Java System Application Server as the Default Server for information. |
To deploy the Customerreview test application:
Right-click the Customerreview_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:
http://serve-host:server-port-number/Customerreview_TestApp/
dispatch.jsp
On the test client's web page, use the create method of the Customerreview bean's home interface to create an instance of the bean. Then test a business method (in this case, getCustomerreview) on that instance.
To test the Customerreview bean:
1. Create an instance of the Customerreview bean by invoking the create method.
The create method is under the heading "Invoke Methods on Data.CustomerreviewHome." There are three fields under it.
2. Type values in the three fields.
Type any data you like into the fields, for example (your field order may be different):
3. Click the Invoke button next to the create method.
The deployed test application adds the records you created to the test database. The new Restaurant instance is listed by its restaurantname value in the upper left, and new data objects are listed in the upper right, as shown.
4. In the field for the findByRestaurantName method, type French Lemon and click the Invoke button.
The results look like this, showing that the French Lemon record was returned:
5. In the Navigation cell (upper left), select the CustomerreviewKey instance.
6. Find the instance's getReview method and click its Invoke button.
The results display the customer review of the instance you created in Step 2 and Step 3, for example:
Continue testing by selecting created objects and invoking their methods.
7. When you are finished testing, you can quit the browser, point it to a different URL, or do nothing, as you wish.
Verify that the Customerreview_TestApp application inserted data in the database, as you tested the Restaurant_TestApp in Checking the Additions to the Database:
1. In the IDE, select the Runtime tab of the Explorer.
2. Expand the Databases node, the PointBase connection node, and the Tables node.
3. Right-click the CUSTOMERREVIEW table and choose View Data.
Your new review record should be displayed in the command editor.
Create a stateless session bean to manage the conversation between the client (the web service you will create in Chapter 4) and the entity beans.
Note - The source code for the completed session bean is provided in Appendix A. |
In version 2.0 of the EJB architecture, session beans can have local interfaces, remote interfaces, or both. In this tutorial, the session beans' methods will be called by the test application (which is local to the session bean), the web services (also local), and the client (remote). Therefore, create a session bean with both local and remote interfaces.
1. In the Java Studio Enterprise Explorer, right-click the Data package and choose New All Templates.
The New wizard is displayed, showing the Choose Templates page.
2. Expand the J2EE node and select Session EJB.
The Session Bean Name and Properties page is displayed.
4. Type DiningGuideManager in the Name field and select the following options:
The Session Bean Class Files page of the wizard is displayed, listing all the components that will be created for this session bean.
Notice that the names of the all the components are based on DiningGuideManager.
The new DiningGuideManager session bean is displayed in the Explorer.
Now create the session bean's methods.
The create method was created when you created the DiningGuideManager session bean. You will now modify it.
Create methods of stateless session beans have no arguments, because session beans do not maintain an ongoing state that needs to be initialized. The create method of the DiningGuideManager session bean must first create an initial context, which it then uses to get the required remote references.
1. Locate the DiningGuideManager's create method within the logical bean's Create folder, and double-click it to display it in the Source Editor.
2. Begin coding the method with a JNDI lookup for a remote reference to the RestaurantHome interface.
Tip - Remember, you can reformat the code you copy into the Source Editor by pressing Control-Shift F. Also remember to remove line breaks when indicated by the code comments. |
3. Under the preceding code, add a similar JNDI lookup for the CustomerreviewHome interface.
4. Now add an import statement for the javax.naming package.
Add the import statement at the top of the file. You must import javax.naming because it contains the lookup method you just used.
5. Declare the myRestaurantHome and myCustomerreviewHome fields.
Add these declarations to the definition of the DiningGuideManagerEJB session bean after the import statements.
6. Select the (DiningGuideManager(EJB) logical node and press F9 to compile the bean.
Next, create the DiningGuideManager's business methods.
The DiningGuideManager bean requires a method that retrieves all restaurant data when it receives a request from the client to see the list of restaurants. It also requires a method to retrieve review data for a specific restaurant when the client requests a list of customer reviews. Create the getAllRestaurants and getCustomerreviewsByRestaurant methods to satisfy these requirements.
To create the getAllRestaurants business method:
1. Right-click the DiningGuideManager logical node and choose Add Business Method.
The Add New Business Method dialog box is displayed.
2. Type getAllRestaurants in the Name field.
3. Type java.util.Vector in the Return Type field.
4. Make sure the option Both Remote and Local Interfaces is enabled.
This method should be added to both remote and local interfaces.
5. Accept all other default values and click OK.
The method shell is created in the DiningGuideManager session bean's business methods.
6. Open the method in the Source Editor and add the following (bold only) code:
Note - Remember to remove line breaks when indicated by the code comments. |
This code gets an instance of RestaurantDetail for each remote reference of the Restaurant bean in the context, adds it to a vector called restaurantList, and returns this vector.
7. Select the DiningGuideManager(EJB) logical node and press F9 to compile the bean.
Now, create a similar method to get a list of customer reviews.
To create the getCustomerreviewsByRestaurant method:
1. Right-click the DiningGuideManager logical node and choose Add Business Method.
The Add New Business Method dialog box is displayed.
2. Type getCustomerreviewsByRestaurant in the Name field.
3. Type java.util.Vector in the Return Type field.
4. Click the Add button to add a parameter with the following values:
5. Click OK to close the dialog box and create the method parameter.
6. Make sure the option Both Remote and Local Interfaces is enabled.
7. Accept all other default values and click OK again create the business method.
The method is created in the DiningGuideManager session bean.
8. Find the method in the Source Editor and add the following bold code:
Note - Remember to remove line breaks when indicated by the code comments. |
Similar to the getAllRestaurants code, this method retrieves an instance of CustomerreviewDetail for each remote reference of the Customerreview bean in the context, adds it to a vector called reviewList and returns this vector.
9. Select the DiningGuideManager(EJB) logical node and press F9 to compile the bean.
Now create a business method that calls the Customerreview entity bean's create method to create a new record in the database.
To create the createCustomerreview method:
1. Right-click the DiningGuideManager logical node and choose Add Business Method.
The Add New Business Method dialog box is displayed.
2. Type createCustomerreview in the Name field.
3. Type void in the Return Type field.
4. Use the Add button to add three parameters with the following values:
5. Click OK to close the Add Parameter dialog box.
6. Make sure the option Both Remote and Local Interfaces is enabled.
7. Click OK again create the business method.
The method is created in the DiningGuideManager session bean.
8. Find the method in the Source Editor and add the following bold code:
Note - Make sure you eliminate the three line breaks indicated by the comments. |
9. Select the (DiningGuideManager(EJB) logical node again and press F9 to compile the bean.
The web service you will create in Chapter 4 is a JAX-RPC implementation of the SOAP RPC web service. SOAP (Simple Object Access Protocol) is an abstract messaging technique that allows web services to communicate with one another using HTTP and XML. The SOAP runtime must know of all the Java types employed by any methods that are called by the web service in order to map them properly into XML. Because the tutorial's web service will call session bean methods, it needs to know every type used by those methods.
One type the SOAP runtime can not have knowledge of is the type of objects that make up collections. The methods that you just created (getAllRestaurants and getCustomerreviewsByRestaurant) all return collections of the detail classes. You must provide knowledge of these classes to the SOAP runtime by creating, for each detail class, a method that returns the class. The methods you will create are the getRestaurantDetail and getCustomerreviewDetail methods.
You created methods with the same names on the entity beans (see Creating Business Methods on the Entity Beans to Fetch the Detail Classes), but the methods you create now are empty, their purpose being simply to supply the required return type to the SOAP runtime.
For more information on Java Studio Enterprise web services and the SOAP runtime, see Building Web Services in the Sun Java Studio Enterprise 6 Programming series.
To create the getRestaurantDetail method:
1. Right-click the DiningGuideManager 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.
Be sure to select the class (), 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:
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:
7. Right-click DiningGuideManager(EJB) and choose Validate EJB.
The DiningGuideManager session bean should validate without errors.
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 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.
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:
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:
The EJB References dialog box looks like this:
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.
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.
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:
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.
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.
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:
You must add database information to the Sun Java System Application Server properties of the EJB module. You performed this task with the entity bean test client in Providing the Sun Java System Application Server 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 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 Java System Application Server in the Server Registry. See Setting the Sun Java System Application Server as the Default Server to correct this problem. |
3. Confirm that the following three values for the appropriate properties:
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.
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 Setting JDBC Resources.
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:
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 Save All.
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. |
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 Java System Application Server 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.
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.
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.
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.
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:
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.
6. Click the Invoke button on the getCustomerreviewDetail method.
The result is shown in the Results section.
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:
9. Click the Invoke button on the getRestaurantDetail method.
The result is shown in the Results section.
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).
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.
Congratulations, you have successfully completed the EJB tier of the DiningGuide application. You are ready to go on to Chapter 4, to use the Java Studio Enterprise 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 Java Studio Enterprise 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.
For example, the following methods offer good example lookup code:
Copyright © 2004, Sun Microsystems, Inc. All rights reserved.