Download
FAQ History |
API
Search Feedback |
Advanced CMP Topics: The OrderApp Example
The
OrderApp
application is an advanced CMP example. It contains entity beans that have self-referential relationships, one-to-one relationships, unidirectional relationships, unknown primary keys, primitive primary key types, and composite primary keys.Structure of OrderApp
OrderApp
is a simple inventory and ordering application for maintaining a catalog of parts and placing an itemized order of those parts. It has entity beans that represent parts, vendors, orders, and line items. These entity beans are accessed using a stateful session bean that holds the business logic of the application. A simple command-line client adds data to the entity beans, manipulates the data, and displays data from the catalog.The information contained in an order can be divided into different elements. What is the order number? What parts are included in the order? What parts make up that part? Who makes the part? What are the specifications for the part? Are there any schematics for the part?
OrderApp
is a simplified version of an ordering system that has all these elements.This example assumes that you have successfully built, assembled, and deployed the
RosterApp
example application and that you are familiar with assembling entity beans indeploytool
.
OrderApp
consists of three modules:DataRegistryJAR
, an enterprise bean JAR file containing the entity beans, the support classes, and the database schema file;RequestJAR
, an enterprise bean JAR containing a stateful session bean that accesses the data in the entity beans; andOrderAppClient
, the application client that populates the entity beans with data and manipulates the data, displaying the results in a terminal.Figure 27-10 shows
OrderApp
's database tables.
Figure 27-10 Database Tables in
OrderApp
Bean Relationships in OrderApp
The
RosterApp
example application shows how to set up one-to-many and many-to-many relationships between entity beans.OrderApp
demonstrates two additional types of entity bean relationships (see Figure 27-11): one-to-one and self-referential relationships.
Figure 27-11 Relationships between Entity Beans in
OrderApp
Self-Referential Relationships
A self-referential relationship is a relationship between container-managed relationship fields (CMR) in the same entity bean.
PartBean
has a CMR fieldbomPart
that has a one-to-many relationship with the CMR fieldparts
, which is also inPartBean
. That is, a part can be made up of many parts, and each of those parts has exactly one bill-of-material part.The primary key for
PartBean
is a compound primary key, a combination of thepartNumber
andrevision
fields. It is mapped to thePART_NUMBER
andREVISION
columns in thePART
table.One-to-One Relationships
PartBean
has a CMR field,vendorPart
, that has a one-to-one relationship withVendorPartBean
's CMR fieldpart
. That is, each part has exactly one vendor part, and vice versa.One-to-Many Relationship Mapped to Overlapping Primary and Foreign Keys
OrderBean
has a CMR field,lineItems
, that has a one-to-many relationship withLineItemBean
's CMR fieldorder
. That is, each order has one or more line item.
LineItemBean
uses a compound primary key that is made up of theorderId
anditemId
fields. This compound primary key maps to theORDER_ID
andITEM_ID
columns in theLINEITEM
database table.ORDER_ID
is a foreign key to theORDER_ID
column in theORDERS
table. This means that theORDER_ID
column is mapped twice: once as a primary key field,orderId
; and again as a relationship field,order
.Unidirectional Relationships
LineItemBean
has a CMR field,vendorPart
, that has a unidirectional many-to-one relationship withVendorPartBean
. That is, there is no CMR field in the target entity bean in this relationship.Primary Keys in OrderApp's Entity Beans
The
OrderApp
example uses more complicated primary keys than doesRosterApp
.Unknown Primary Keys
In
OrderApp
,VendorPartBean
uses an unknown primary key. That is, the enterprise bean does not specify primary key fields and usesjava.lang.Object
as the primary key class. See The Primary Key Class for more information on primary keys.Primitive Type Primary Keys
VendorBean
uses a primary key that is a Java programming language primitive type, anint
. To use a primitive type as the primary key, you must create a wrapper class.VendorKey
is the wrapper class forVendorBean
.The wrapper primary key class has the same requirements as described in The Primary Key Class. This is the
VendorKey
wrapper class:package dataregistry; public final class VendorKey implements java.io.Serializable { public int vendorId; public boolean equals(Object otherOb) { if (this == otherOb) { return true; } if (!(otherOb instanceof VendorKey)) { return false; } VendorKey other = (VendorKey) otherOb; return (vendorId == other.vendorId); } public int hashCode() { return vendorId; } public String toString() { return "" + vendorId; } }Compound Primary Keys
A compound primary key is made up of multiple fields and follows the requirements described in The Primary Key Class. To use a compound primary key, you must create a wrapper class.
In
OrderApp
, two entity beans use compound primary keys:PartBean
andLineItemBean
.
PartBean
uses thePartKey
wrapper class.PartBean
's primary key is a combination of the part number and the revision number.PartKey
encapsulates this primary key.
LineItemBean
uses theLineItemKey
class.LineItemBean
's primary key is a combination of the order number and the item number.LineItemKey
encapsulates this primary key. This is theLineItemKey
compound primary key wrapper class:package dataregistry; public final class LineItemKey implements java.io.Serializable { public Integer orderId; public int itemId; public boolean equals(Object otherOb) { if (this == otherOb) { return true; } if (!(otherOb instanceof LineItemKey)) { return false; } LineItemKey other = (LineItemKey) otherOb; return ((orderId==null?other.orderId==null:orderId.equals (other.orderId)) && (itemId == other.itemId)); } public int hashCode() { return ((orderId==null?0:orderId.hashCode()) ^ ((int) itemId)); } public String toString() { return "" + orderId + "-" + itemId; } }Entity Bean Mapped to More Than One Database Table
PartBean
's fields map to more than one database table:PART
andPART_DETAIL
. ThePART_DETAIL
table holds the specification and schematics for the part. When you set up the container-managed fields and relationships indeploytool
, you will addPART_DETAIL
as a secondary table forPartBean
.Finder and Selector Methods
VendorBean
has two finder methods:findByPartialName
andfindByOrder
. ThefindByPartialName
method searches through the vendor list for matches to a partial name.findByOrder
finds all vendors for a particular order.
LineItemBean
has one finder method,findAll
, which finds all line items.
OrderBean
has one selector method,ejbSelectAll
, which returns all orders.
VendorPartBean
has two selector methods.ejbSelectAvgPrice
returns the average price of all parts from a vendor.ejbSelectTotalPricePerVendor
returns the price of all the parts from a particular vendor.Selector methods cannot be accessed outside a bean instance because the selector methods are not defined in the bean interface. If you are using a selector method to return data to a caller, the selector method must be called from a home or business method. In
OrderApp
, theLocalVendorPartHome.getAvgPrice
method returns the result of theejbSelectAvgPrice
method inVendorPartBean
.The return type of a selector query is usually defined by the return type of the
ejbSelect
methods. You must specify the return type asRemote
if the method returns a remote interface or ajava.util.Collection
of remote interfaces. If the return type is a local interface or ajava.util.Collection
of local interfaces, set the return type toLocal
. If the return type is neither a local nor a remote interface, nor a collection of local or remote interfaces, do not set the return type (indeploytool
, set the return type toNone
). TheOrderBean.ejbSelectAll
method returns a collection of local interfaces.VendorPartBean.ejbSelectAvgPrice
andVendorPartBean.ejbSelectTotalPricePerVendor
return aDouble
, so the return type is set toNone
.Using Home Methods
Home methods are defined in the home interface of a bean and correspond to methods named
ejbHome<
METHOD
>
in the bean class. For example, a methodgetValue
, defined in theLocalExampleHome
interface, corresponds to theejbHomeGetValue
method implemented inExampleBean
. TheejbHome<
METHOD
>
methods are implemented by the bean developer.
OrderApp
uses three home methods:LocalOrderHome.adjustDiscount
,LocalVendorPartHome.getAvgPrice
, andLocalVendorPartHome.getTotalPricePerVendor
. Home methods operate on all instances of a bean rather than on any particular bean instance. That is, home methods cannot access the container-managed fields and relationships of a bean instance on which the method is called.For example,
LocalOrderHome.adjustDiscount
is used to increase or decrease the discount on all orders.Cascade Deletes in OrderApp
Entity beans that use container-managed relationships often have dependencies on the existence of the other bean in the relationship. For example, a line item is part of an order, and if the order is deleted, then the line item should also be deleted. This is called a cascade delete relationship.
In
OrderApp
, there are two cascade delete dependencies in the bean relationships. If theOrderBean
to which aLineItemBean
is related is deleted, then theLineItemBean
should also be deleted. If theVendorBean
to which aVendorPartBean
is related is deleted, then theVendorPartBean
should also be deleted.BLOB and CLOB Database Types in OrderApp
The
PART_DETAIL
table in the database has a column,DRAWING
, of typeBLOB
.BLOB
stands for binary large objects, which are used for storing binary data such as an image. TheDRAWING
column is mapped to the container-managed fieldPartBean
.drawing
of typejava.io.Serializable
.
PART_DETAIL
also has a column,SPECIFICATION
, of typeCLOB
.CLOB
stands for character large objects, which are used to store string data too large to be stored in aVARCHAR
column.SPECIFICATION
is mapped to the container-managed fieldPartBean.specification
of typejava.lang.String
.
Note: You cannot use a
BLOB
orCLOB
column in theWHERE
clause of a finder or selector EJB QL query.
Building and Running the OrderApp Example
This section assumes that you are familiar with how to package entity beans in
deploytool
as described in Building and Running the RosterApp Example, have started the PointBase server, and have created the JDBC resource.Create the Database Tables
To create the database tables, do the following:
Capture the Database Schema
To capture the database schema, do the following:
Build the Application
To build the application components of
OrderApp
, do the following:Package the Application
You will now package the enterprise beans, support classes, database schema, and client class in
deploytool
. This section assumes that you are familiar with how to package these application modules indeploytool
.Create the Application Modules
- Create a new application in
deploytool
namedOrderApp
in
<
INSTALL
>/j2eetutorial14/examples/ejb/cmporder/
- Create an enterprise bean JAR named
RequestJAR
that contains the files in
<
INSTALL
>/j2eetutorial14/examples/ejb/cmporder/build/
request/- Set up a stateful session bean,
RequestBean
, inRequestJAR
with a remote home interface ofrequest.RequestHome
and a remote interface ofrequest.Request
.- Create an enterprise bean JAR named
DataRegistryJAR
that contains the files in
<
INSTALL
>/j2eetutorial14/examples/ejb/cmporder/build/
dataregistryAnd the database schema file:
<
INSTALL
>/j2eetutorial14/examples/ejb/cmporder/build/
cmporder.dbschema- Set up the entity beans (
LineItemBean
,OrderBean
,PartBean
,VendorBean
, andVendorPartBean
) according to Table 27-2 through Table 27-6.Configure the Entity Bean Relationships
Now we'll configure the relationships of the entity beans and map the fields and relationships to the database tables.
- Set up the bean relationships according to Table 27-7:
- Set the JNDI Name of the CMP Resource to
jdbc/ejbTutorialDB
.- Create the database mappings using the
cmporder.dbschema
file in the Sun-specific Settings dialog box, CMP Database view.- Manually map
OrderBean
to theORDERS
database table in the Sun-specific Settings dialog box, CMP Database view:- Map
PartBean
to thePART
andPART_DETAIL
database tables:
- Select
PartBean
in the Enterprise Bean field under Persistent Field Mappings.- Click Advanced Settings under Mappings for Bean
PartBean
.- Click Add.
- In the Secondary Table field select
PART_DETAIL
.- Select
PART_NUMBER
in the Primary Table Column.- Select
PART_NUMBER
in the Secondary Table Column.- Click Add Pair.
- Select
REVISION
in the Primary Table Column.- Select
REVISION
in the Secondary Table Column.- Click OK.
- Click OK.
- Click Automap All to automatically map the fields and relationships to the database tables. Repeat this step for all the entity beans until all the relationships and fields are mapped.
- Click Close.
Add the Finder and Selector Queries
Add the finder and selector queries to the entity beans as listed in Table 27-8 and Table 27-9:
Note: The queries are included in the
cmporderQueries.txt
file, located in<
INSTALL
>/j2eetutorial14/examples/ejb/cmporder/
to make it easier to enter the queries.
Set the Transaction Attributes
The transactions for all our enterprise beans (
RequestBean
,LineItemBean
,OrderBean
,PartBean
,VendorBean
, andVendorPartBean
) must be managed by the container.Set RequestBean's Enterprise Bean References
RequestBean
accesses the local entity beans contained inDataRegistryJAR
. You must set the references to the entity beans inRequestBean
.
- Select
RequestBean
inRequestJAR
.- Click the EJB Ref's tab.
- Enter the references according to Table 27-10. All the references are to local entity beans.
Package the Application Client
Now we'll add the application client to the EAR.
Deploy the Enterprise Application
OrderApp
is now ready to be deployed:Run the Client Application
The client application accesses the
RequestBean
session bean, which in turn manipulates data inOrderApp
's entity beans.
Note: This example will perform poorly compared with a well-designed CMP application.
OrderApp
is designed primarily for instructional purposes, and does not follow the best practices recommendations as outlined in the book Designing Enterprise Applications with the J2EE Platform, Second Edition, Inderjeet Singh et al., (Addison-Wesley, 2002).
To run the client, follow these steps:
- In a terminal, go to
<
INSTALL
>/j2eetutorial14/examples/ejb/cmporder/
- Enter the following command:
appclient -client OrderAppClient.jar
- You will see the following output in the terminal:
Cost of Bill of Material for PN SDFG-ERTY-BN Rev: 7: $241.86
Cost of Order 1111: $664.68
Cost of Order 4312: $2,011.44
Adding 5% discount
Cost of Order 1111: $627.75
Cost of Order 4312: $1,910.87
Removing 7% discount
Cost of Order 1111: $679.45
Cost of Order 4312: $2,011.44
Average price of all parts: : $117.55
Total price of parts for Vendor 100: : $501.06
Ordered list of vendors for order 1111
200 Gadget, Inc. Mrs. Smith
100 WidgetCorp Mr. Jones
Found 6 line items
Removing Order
Found 3 line items
Found 1 out of 2 vendors with 'I' in the name:
Gadget, Inc.
Note: Re-create the database tables using the
create-db_common
task before re-running the client.
Download
FAQ History |
API
Search Feedback |
All of the material in The J2EE(TM) 1.4 Tutorial is copyright-protected and may not be published in other works without express written permission from Sun Microsystems.