courseIds.addAlla; } catch Exception ex { throw new EJBException“Exception in loadCourseIds: “ + ex.getMessage; } } Invoked by theloadCourseIdsmethod, thegetCoursesmethod of the lerEJB
Trang 1Context initial = new InitialContext();
Object objref = initial.lookup(“java:comp/env/ejb/Customer”);
customerHome = (CustomerHome)PortableRemoteObject.narrow(objref, CustomerHome.class);
} catch (Exception ex) { throw new EJBException(“setEntityContext: “ + ex.getMessage());
} }
Invoked by the ejbLoad method, loadEnrollerIds is a private method thatrefreshes thecustomerIds variable There are two approaches when coding amethod such asloadCustomerIds: fetch the identifiers from thecustomerdata-base table or get them from theCustomer entity bean Fetching the identifiersfrom the database might be faster, but exposes theSalesRepEJBcode to theCus- tomerbean’s underlying database table In the future, if you were to change the
Customerbean’s table (or move the bean to a different J2EE server), then youmight need to change theSalesRepEJB code But if theSalesRepEJB gets theidentifiers from theCustomerentity bean, no coding changes would be required.The two approaches present a trade-off: performance versus flexibility The
SalesRepEJBexample opts for flexibility, loading thecustomerIds variable bycalling thefindSalesRepandgetPrimaryKeymethods of theCustomerbean.Here is the code for theloadCustomerIds method:
private void loadCustomerIds() { customerIds.clear();
try { Collection c = customerHome.findBySalesRep(salesRepId); Iterator i=c.iterator();
while (i.hasNext()) { Customer customer = (Customer)i.next();
String id = (String)customer.getPrimaryKey();
customerIds.add(id);
} } catch (Exception ex) { throw new EJBException(“Exception in loadCustomerIds: “ + ex.getMessage());
} }
Trang 2M APPING T ABLE R ELATIONSHIPS F OR B EAN -M ANAGED P
ERSIS-If a customer’s sales representative changes, the client program updates the base by calling thesetSalesRepIdmethod of theCustomerEJBclass The nexttime a business method of the SalesRepEJB is called, the ejbLoad methodinvokes loadCustomerIds, which refreshes the customerIds variable (Toensure thatejbLoadis invoked before each business method, set the transactionattributes of the business methods to Required.) For example, theSalesRepCli- ent program changes thesalesRepId for a customer named Mary Jackson:
data-Customer mary = customerHome.findByPrimaryKey(“987”);
mary.setSalesRepId(“543”);
The salesRepId543 identifies a sales representative named Janice Martin Tolist all of Janice’s customers, theSalesRepClientprogram invokes thegetCus- tomerIdsmethod, iterates through the ArrayList of identifiers, and locates each
Customer bean by calling theCustomer bean’sfindByPrimaryKey method:
SalesRep janice = salesHome.findByPrimaryKey(“543”);
ArrayList a = janice.getCustomerIds();
i = a.iterator();
while (i.hasNext()) { String customerId = (String)i.next();
Customer customer = customerHome.findByPrimaryKey(customerId);
String name = customer.getName();
System.out.println(customerId + “: “ + name);
}
Tips for Running the SalesRepEJB Example:
1 Create the database tables by typingant create-salesrep-table
2 For both beans specifyjdbc/SalesDBas the coded name for the resourcereference
3 For both beans, set the transaction attributes of the business methods toRequired
4 For theSalesRepEJBbean, add theejb/Customerenterprise bean ence
refer-5 For theSalesRepClient, add these enterprise bean references: pleSalesRep andejb/SimpleCustomer
Trang 3ejb/Sim-6 Specify the JNDI names listed in the following table.
Many-to-Many Relationships
In a many-to-many relationship, each entity may be related to multiple rences of the other entity For example, a college course has many students andeach student may take several courses In a database, this relationship is repre-sented by a cross reference table containing the foreign keys In Figure 11, thecross reference table is the enrollment table (PK indicates a primary key and FK
occur-a foreign key.)
Table 6 JNDI Names for theSalesRepEJB Example
Component or Reference Name JNDI Name
SalesRepBean MySalesRep CustomerBean MyCustomer jdbc/SalesDB jdbc/Cloudscape ejb/Customer MyCustomer ejb/SimpleSalesRep MySalesRep ejb/SimpleCustomer MyCustomer
Trang 4M APPING T ABLE R ELATIONSHIPS F OR B EAN -M ANAGED P
ERSIS-Figure 11 Many-to-Many Relationship: Students and Courses
These tables are accessed by the StudentEJB, CourseEJB, and EnrollerEJB
classes The source code for these classes is in the ler directory To compile the code, go to theexamples/srcdirectory and type
examples/src/ejb/enrol-ant enroller.TheStudentEJBandCourseEJBclasses are complementary Each class contains
anArrayListof foreign keys TheStudentEJBclass, for example, contains an
ArrayList named courseIds, which identifies the courses the student isenrolled in TheejbLoadmethod adds elements to thecourseIds ArrayListbycallingloadCourseIds, a private method TheloadCourseIdsmethod gets thecourse identifiers from the Enroller session bean The source code for the
loadCourseIds method follows:
private void loadCourseIds() { courseIds.clear();
try { Enroller enroller = enrollerHome.create();
ArrayList a = enroller.getCourseIds(studentId);
1 : Many
Student Table
studentid (PK) name
Many : 1
Enrollment Table
studentid (FK) courseid (FK)
Course Table
courseid (PK) name
Trang 5courseIds.addAll(a);
} catch (Exception ex) { throw new EJBException(“Exception in loadCourseIds: “ + ex.getMessage());
} }
Invoked by theloadCourseIdsmethod, thegetCoursesmethod of the lerEJB class queries theenrollment table:
Enrol-select courseid from enrollment where studentid = ?
Only the EnrollerEJB class accesses the enrollment table Therefore, the
EnrollerEJB class manages the student-course relationship represented in the
enrollmenttable If a student enrolls in a course, for example, the client callstheenroll business method, which inserts a row:
insert into enrollment values (studentid, courseid)
If a student drops a course, theunEnroll method deletes a row:
delete from enrollment where studentid = ? and courseid = ?
And if a student leaves the school, thedeleteStudentmethod deletes all rows
in the table for that student:
delete from enrollment where student = ?
TheEnrollerEJBclass does not delete the matching row from the student table.That action is performed by theejbRemovemethod of theStudentEJBclass Toensure that both deletes are executed as a single operation, they should belong tothe same transaction SeeTransactions (page 235) for more information
Tips for running the EnrollerEJB example:
1 Create the database tables by typingant create-enroller-table
2 For all three beans, specify jdbc/CollegeDBas the coded name for theresource reference
3 For all three beans, specify container-managed transactions
Trang 6A BOUT C ONTAINER -M ANAGED P ERSISTENCE 111
4 For the transaction attributes of the business methods, specify Required
5 For theStudentEJBandCourseEJBentity beans, specify the ler enterprise bean reference
ejb/Enrol-6 For the EnrollerClient, specify an enterprise reference for each bean:
ejb/SimpleCourse,ejb/SimpleStudent,ejb/SimpleEnroller
7 Use the JNDI names listed in the following table
About Container-Managed Persistence
TBD
A Container-Managed Persistence Example
TBD
Primary Key Class
You specify the primary key class on the Entity tabbed pane of thedeploytool.When deploying the ProductEJB bean, for example, you would specify a
Table 7 JNDI Names for the EnrollerEJB Example
Component or Reference Name JNDI Name
EnrollerBean MyEnroller StudentBean MyStudent CourseBean MyCourse jdbc/CollegeDB jdbc/Cloudscape ejb/SimpleEnroller MyEnroller ejb/SimpleStudent MyStudent ejb/SimpleCourse MyCourse
Trang 7java.lang.String as the primary key class In most cases, your primary keyclass will be aString or some other class that belongs to thejava package.
Creating a Primary Key Class
For some entity beans, you will need to define your own primary key class Forexample, if a primary key is composed of multiple fields then you must create aprimary key class In the following primary key class, theproductIdandven- dorId fields together uniquely identify an entity bean:
public class ItemKey implements java.io.Serializable { public String productId;
public String vendorId;
} public String getVendorId() { return vendorId;
} public boolean equals(Object other) {
if (other instanceof ItemKey) { return (productId.equals(((ItemKey)other).productId)
&& vendorId.equals(((ItemKey)other).vendorId)); }
return false;
} public int hashCode() {
Trang 8P RIMARY K EY C LASS 113
return productId.hashCode();
} }
Class Requirements
A primary key class must meet these requirements:
• The access control modifier of the class ispublic
• All fields are declared aspublic
• For container-managed persistence, the field names in the primary keyclass must match the corresponding container-managed fields in the entitybean class
• The class has a public default constructor
• The class implements thehashCode()andequals(Object other)ods
meth-• The class is serializable
Bean-Managed Persistence and the Primary Key Class
With bean-managed persistence, theejbCreatemethod returns the primary keyclass:
public ItemKey ejbCreate(String productId, String vendorId, String description) throws CreateException {
if (productId == null || vendorId == null) { throw new CreateException(
“The productId and vendorId are required.”);
} this.productId = productId;
Trang 9public ItemKey ejbFindByPrimaryKey(ItemKey primaryKey) throws FinderException {
try {
if (selectByPrimaryKey(primaryKey)) return primaryKey;
}
private boolean selectByPrimaryKey(ItemKey primaryKey) throws SQLException {
String selectStatement = “select productid “ + “from item where productid = ? and vendorid = ?”; PreparedStatement prepStmt =
Getting the Primary Key
A client can fetch the primary key of an entity bean by invoking the ryKey method of theEJBObject class:
getPrima-Account account;
String id = (String)account.getPrimaryKey();
The entity bean retrieves its own primary key by calling the getPrimaryKey
method of theEntityContext class:
EntityContext context;
String id = (String) context.getPrimaryKey();
Trang 10appli-method cannot find the desired object If your enterprise bean encounters a tem-level problem, it should throw a javax.ejb.EJBException The containerwill wrap theEJBExceptionin aRemoteException, which it passes back to theclient Because the EJBExceptionis a subclass of theRuntimeException, you
sys-do not have to specify it in thethrowsclause of the method declaration If a tem exception is thrown, the EJB container might destroy the bean instance
sys-Therefore, a system exception cannot be handled by the bean’s client program; itrequires intervention by a system administrator
An application exception signals an error in the business logic of an enterprisebean There are two types of application exceptions: customized and predefined
A customized exception is one that you’ve coded yourself, such as the centBalanceException thrown by the debit business method of the
Insuffi-AccountEJB example The javax.ejb package includes several predefinedexceptions that are designed to handle common problems For example, anejb- Create method should throw a CreateException to indicate an invalid inputparameter When an enterprise bean throws an application exception, the con-tainer does not wrap it in another exception The client should be able to handleany application exception it receives
If a system exception occurs within a transaction, the EJB container rolls backthe transaction However, if an application exception is thrown within a transac-tion, the container does not roll back the transaction
The following table summarizes the exceptions of the javax.ejb package All
of these exceptions are application exceptions, except for the ception and theEJBException, which are system exceptions
NoSuchEntityEx-Table 8 Exceptions
Method Name Exception It Throws Reason for Throwing
ejbCreate CreateException An input parameter is
invalid.
Trang 11The Life Cycle of an Entity Bean
The life cycle of an entity bean is controlled by the EJB container, not by yourapplication However, you may find it helpful to learn about the life cycle whendeciding in which method your entity bean will connect to a database SeeResource Connections (page 269) for more information
Figure 12 shows the stages that an entity bean passes through during its lifetime.After the EJB container creates the instance, it calls the setEntityContext
method of the entity bean class The setEntityContext method passes theentity context to the bean
After instantiation, the entity bean moves to a pool of available instances While
in the pooled stage, the instance is not associated with any particular EJB objectidentity All instances in the pool are identical The EJB container assigns anidentity to an instance when moving it to the ready stage
There are two paths from the pooled stage to the ready stage On the first path,the client invokes thecreatemethod, causing the EJB container to call theejb- Create and ejbPostCreate methods On the second path, the EJB containerinvokes the ejbActivate method While in the ready stage, an entity bean’sbusiness methods may be invoked
ejbFindByPrimaryKey (and other finder methods that return
a single object)
ObjectNotFoundException (subclass of FinderException)
The database row for the requested entity bean is cannot be found.
ejbRemove RemoveException
The entity bean’s row not be deleted from the database.
can-ejbLoad NoSuchEntityException The database row to be
loaded cannot be found.
ejbStore NoSuchEntityException The database row to be
updated cannot be found.
(all methods) EJBException A system problem has
been encountered.
Table 8 Exceptions (Continued)
Method Name Exception It Throws Reason for Throwing
Trang 12T HE L IFE C YCLE OF AN E NTITY B EAN 117
There are also two paths from the ready stage to the pooled stage First, a clientmay invoke the remove method, which causes the EJB container to call the
ejbRemove method Second, the EJB container may invoke the ejbPassivate
Does Not Exist
Trang 13In the pooled state, an instance is not associated with any particular EJB objectidentity With bean-managed persistence, when the EJB container moves aninstance from the pooled state to the ready state, it does not automatically set theprimary key Therefore, theejbCreateandejbActivatemethods must set theprimary key If the primary key is incorrect, theejbLoadandejbStoremethodscannot synchronize the instance variables with the database In theAccountEJB
example, theejbCreatemethod assigns the primary key from one of the inputparameters TheejbActivate method sets the primary key (id) as follows:
Trang 14as dispatching requests, and handling non-textual data JSP pages are moreappropriate for generating text-based markup such as HTML, SVG, WML, andXML.
This chapter describes the packaging, configuration, and deployment procedurescommon to servlets and JSP pages Subsequent chapters, Java ServletTechnology (page 133) and JavaServer Pages™ Technology (page 167), coverhow to develop the web components Many features of JSP technology are deter-mined by Java Servlet technology so you should familiarize yourself with thatmaterial, even if you do not intend to write servlets
Most web-based J2EE clients use the HTTP protocol and support for HTTP is amajor aspect of web components For a brief summary of HTTP protocol fea-tures see HTTP Overview (page 307)
Web Component Life Cycle 120Packaging Web Components 122Creating a WAR 122Adding a WAR to a J2EE Application 123Adding a Web Component to a WAR 123
Trang 15Configuring Web Components 124Application-Level Configuration 125WAR-Level Configuration 125Component-Level Configuration 127Deploying Web Components 128Executing Web Components 128Updating Web Components 129
Web Component Life Cycle
The J2EE platform provides many supporting services that enhance the ties of web components and make them easier to develop However, because itmust take into account these services, the process for creating and running a webcomponent is different than that of traditional stand-alone Java classes
capabili-Web components run within an environment called a web container The web
container provides services such as request dispatching, security, concurrency,and life cycle management It also gives web components access to the J2EEplatform APIs such as naming, transactions, and email Before it can be exe-
cuted, a web component must be installed (or deployed) into a web container.
Certain aspects of web component behavior can be configured when it is aged and deployed The configuration information is maintained in a text file in
XML format called a web application deployment descriptor When you
pack-age and deploy web components using the J2EE SDKdeploytool, it cally generates or updates the deployment descriptor based on data that youenter in deploytool wizards and inspectors You can also manually create adeployment descriptor according to the schema described in the Java Servletspecification
automati-The process for creating, deploying, and executing a web component can besummarized as follows:
1 Develop the web component code (including possibly a deploymentdescriptor)
2 Package the web component along with any static resources (for example,images) referenced by the component
3 Deploy the application
4 Access a URL that references the web component
Trang 16W EB C OMPONENT L IFE C YCLE 121
These steps are expanded on in the following sections and are illustrated with the
helloapplication This application allows a user to enter a name into an HTMLform:
and then displays a greeting after the name is submitted:
Thehelloapplication contains two web components:greetingandresponse.This tutorial has two versions of this application: a servlet version calledhello1
in which the web components are implemented by two servlet classes, ingServlet.javaandResponseServlet.javaand a JSP version calledhello2
Greet-in which the web components are implemented by two JSP pages, ing.jsp and response.jsp The two versions are used to illustrate the tasks
Trang 17greet-involved in packaging and deploying a J2EE application that contains web ponents.
com-Packaging Web Components
You add web components to a J2EE application in a package called a web cation archive (WAR), which is a JAR similar to the package used for Java class
appli-libraries A WAR usually contains other resources besides web components,including:
• Server-side utility classes
• Static web resources (HTML, image, and sound files, and so on)
• Client-side classes (applets and utility classes)
A WAR has a specific hierarchical directory structure The top-level directory of
a WAR is the document root of the application The document root is where JSP
pages, client-side classes and archives, and static web resources are stored Thedocument root contains a subdirectory calledWEB-INF, which contains the fol-lowing files and directories:
• web.xml - the web application deployment descriptor
• Tag library descriptor files (see Tag Library Descriptors (page 210))
• classes - a directory that contains server-side classes: servlet, utilityclasses, and JavaBeans components
• lib- a directory that contains JAR archives of libraries (tag libraries andany utility libraries called by server-side classes)
When you add files to a WAR,deploytoolautomatically packages them in thecorrect directory
Note: The J2EE SDK version 1.3 betadeploytoolpackages client-side classesand archives in theWEB-INFsubdirectory instead of the document root As a con-sequence, the tutorial example that includes an applet (discussed inThe ExampleJSP Pages(page 171)) uses a WAR created by theant make tool
Creating a WAR
When you add the first web component to a J2EE application,deploytoolmatically creates a new WAR to contain the component A later sectiondescribes how to add a web component