BUY THIS BOOK

Safari Books Online

What is this?

Looking to Reprint this content?


Enterprise JavaBeans
Enterprise JavaBeans, Fourth Edition

By Richard Monson-Haefel, Bill Burke, Sacha Labourey

Cover | Table of Contents | Colophon


Table of Contents

Chapter 1: Introduction
This book is about Enterprise JavaBeans 2.1, the latest version of the Enterprise JavaBeans specification. It also covers Enterprise JavaBeans 2.0, which is still in widespread use. Just as the Java platform has revolutionized the way we think about software development, the Enterprise JavaBeans (EJB) specification has revolutionized the way we think about developing mission-critical enterprise software. It combines server-side components with distributed object technologies, asynchronous messaging, and web services to greatly simplify the task of application development. It automatically takes into account many of the requirements of business systems, including security, resource pooling, persistence, concurrency, and transactional integrity.
This book shows you how to use Enterprise JavaBeans to develop scalable, portable business systems. But before we can start talking about EJB itself, we'll need a brief introduction to the technologies addressed by EJB, such as component models, distributed objects, asynchronous messaging, and web services. It's particularly important to have a basic understanding of component transaction monitors, the technology that lies beneath EJB. In Chapter 2 and Chapter 3, we'll look at EJB itself and see how enterprise beans are put together. The rest of the book is devoted to developing enterprise beans for an imaginary business and discussing advanced issues.
It is assumed that you're already familiar with Java; if you're not, Learning Java, by Patrick Niemeyer and Josh Peck (O'Reilly), is an excellent introduction. This book also assumes that you're conversant in the JDBC API, or at least in SQL. If you're not familiar with JDBC, see Database Programming with JDBC and Java by George Reese (O'Reilly).
One of Java's most important features is platform independence. Since it was first released, Java has been marketed as "write once, run anywhere." While the hype has gotten a little heavy-handed at times, code written with Sun's Java programming language is remarkably platform-independent. Enterprise JavaBeans isn't just platform-independent—it's also implementation-independent. If you've worked with JDBC, you know a little about what this means. Not only can the JDBC API run on a Windows machine or on a Unix machine, it can also access relational databases of many different vendors (DB2, Oracle, MySQL, SQLServer, etc.) by using different JDBC drivers. You don't have to code to a particular database implementation—just change JDBC drivers, and you change databases. It's the same with EJB. Ideally, an EJB component—an enterprise bean—can run in any application server that implements the EJB specification. This means that you can develop and deploy your EJB business system in one server, such as BEA's WebLogic, and later move it to a different EJB server, such as Pramati, Sybase EAServer, IBM's WebSphere, or an open source project such as Apache Geronimo, OpenEJB, JOnAS, or JBoss. Implementation independence means that your business components are not dependent on the brand of server, which gives you many more options before, during, and after development and deployment.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Server-Side Components
Object-oriented languages such as Java, C++, and C# are used to write software that is flexible, extensible, and reusable—the three axioms of object-oriented development. In business systems, object-oriented languages are used to improve development of GUIs, to simplify access to data, and to encapsulate the business logic. The encapsulation of business logic into business objects is a fairly recent focus in the information-technology industry. Business is fluid, which means that a business's products, processes, and objectives evolve over time. If the software that models the business can be encapsulated into business objects, it becomes flexible, extensible, and reusable, and therefore evolves as the business evolves.
A server-side component model may define an architecture for developing distributed business objects that combines the accessibility of distributed object systems with the fluidity of objectified business logic. Server-side component models are used on the middle-tier application servers, which manage the components at runtime and make them available to remote clients. They provide a baseline of functionality that makes it easy to develop distributed business objects and assemble them into business solutions.
Server-side components can also be used to model other aspects of a business system, such as presentation and routing. The Java servlet, for example, is a server-side component that is used to generate HTML and XML data for the presentation layer of a three-tier architecture. EJB 2.1 message-driven beans, which are discussed later in this book, are server-side components that can be used to consume and process asynchronous messages.
Server-side components, like other components, can be bought and sold as independent pieces of executable software. They conform to a standard component model and can be executed without direct modification in a server that supports that component model. Server-side component models often support attribute-based programming, which allows the runtime behavior of the component to be modified when it is deployed, without having to change the programming code in the component. Depending on the component model, the server administrator can declare a server-side component's transactional, security, and even persistence behavior by setting these attributes to specific values.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Distributed Object Architectures
To understand EJB, you need to understand how distributed objects work. Distributed object systems are the foundation for modern three-tier architectures. In a three-tier architecture, as shown in Figure 1-1, the presentation logic resides on the client (first tier), the business logic resides on the middle tier (second tier), and other resources, such as the database, reside on the backend (third tier).
Figure 1-1: Three-tier architecture
All distributed object protocols are built on the same basic architecture, which is designed to make an object on one computer look like it's residing on a different computer. Distributed object architectures are based on a network communication layer that is really very simple. Essentially, there are three parts to this architecture: the business object, the skeleton, and the stub.
The business object resides on the middle tier. It's an instance of an object that models the state and business logic of some real-world concept, such as a person, order, or account. Every business object class has matching stub and skeleton classes built specifically for that type of business object. For example, a distributed business object called Person would have matching Person_Stub and Person_Skeleton classes. As shown in Figure 1-2, the business object and skeleton reside on the middle tier, and the stub resides on the client.
The stub and the skeleton are responsible for making the business object on the middle tier look as if it is running locally on the client machine. This is accomplished through some kind of remote method invocation ( RMI) protocol. An RMI protocol is used to communicate method invocations over a network. CORBA, Java RMI, and Microsoft .NET all use their own RMI protocols. Every instance of the business object on the middle tier is wrapped by an instance of its matching skeleton class. The skeleton is set up on a port and IP address and listens for requests from the stub, which resides on the client machine and is connected via the network to the skeleton. The stub acts as the business object's surrogate on the client and is responsible for communicating requests from the client to the business object through the skeleton. Figure 1-2 illustrates the process of communicating a method invocation from the client to the server object and back. The stub and the skeleton hide the communication specifics of the RMI protocol from the client and the implementation class, respectively.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Component Models
The term "component model" has many different interpretations. Enterprise JavaBeans specifies a server-side component model. Using a set of classes and interfaces from the javax.ejb package, developers can create, assemble, and deploy components that conform to the EJB specification.
The original JavaBeans is also a component model, but it's not a server-side component model like EJB. Other than sharing the name "JavaBeans," these two component models are completely unrelated. In the past, a lot of the literature referred to EJB as an extension of the original JavaBeans, but this is a misrepresentation. The two APIs serve very different purposes, and EJB does not extend or use the original JavaBeans component model.
JavaBeans is intended to be used for intraprocess purposes, while EJB is designed for inter process components. In other words, the original JavaBeans was not intended for distributed components. JavaBeans can be used to solve a variety of problems, but it is primarily used to build clients by assembling visual (GUI) and nonvisual widgets. It's an excellent component model, possibly the best one ever devised for intraprocess development, but it's not a server-side component model. EJB, on the other hand, is explicitly designed to address issues involved with managing distributed business objects in a three-tier architecture.
Given that JavaBeans and Enterprise JavaBeans are completely different, why are they both called component models? In this context, a component model defines a set of contracts between the component developer and the system that hosts the component. The contracts express how a component should be developed and packaged. Once a component is defined, it becomes an independent piece of software that can be distributed and used in other applications. A component is developed for a specific purpose but not a specific application. In the original JavaBeans, a component might be a push button or a spreadsheet that can be used in any GUI application according to the rules specified in the original JavaBeans component model. In EJB, there are several different types of components: components that represent entities in a database (
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Asynchronous Messaging
In addition to supporting RMI-based distributed business objects, Enterprise JavaBeans supports asynchronous messaging. An asynchronous messaging system allows two or more applications to exchange information in the form of messages. A message, in this case, is a self-contained package of business data and network routing headers. The business data contained in a message can be anything—depending on the business scenario—and usually contains information about some business transaction. In enterprise systems, messages inform an application of some event or occurrence in another system.
Asynchronous messages may be transmitted from one application to another on a network using message-oriented middleware (MOM). MOM products ensure that messages are properly distributed among applications. In addition, MOM usually provides fault-tolerance, load-balancing, scalability, and transactional support for enterprises that need to reliably exchange large quantities of messages. MOM vendors use different message formats and network protocols for exchanging messages, but the basic semantics are the same. An API is used to create a message, give it a payload (application data), assign it routing information, and then send the message. The same API is used to receive messages produced by other applications.
In modern enterprise-messaging systems, applications exchange messages through virtual channels called destinations . When you send a message, it's addressed to a destination, not to a specific application. Any application that subscribes or registers an interest in that destination may receive that message. In this way, the applications that receive messages and those that send messages are decoupled. Senders and receivers are not bound to each other in any way and may send and receive messages as they see fit.
Enterprise JavaBeans integrates the functionality of MOM into its component model. This integration extends the EJB platform so that it supports both RMI and asynchronous messaging. EJB 2.0 and 2.1 support asynchronous messaging through the Java Message Service (JMS) and a new component called the message-driven bean. In addition to JMS, message-driven beans in EJB 2.1 can support other synchronous and asynchronous messaging systems.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Titan Cruises: An Imaginary Business
To make things a easier and more fun, we discuss all the concepts in this book in the context of an imaginary business, a cruise line called Titan. A cruise line makes a particularly interesting example because it incorporates several different businesses: it has ship cabins that are similar to hotel rooms; it serves meals like a restaurant; it offers various recreational opportunities; and it needs to interact with other travel businesses.
This type of business is a good candidate for a distributed object system because many of the system's users are geographically dispersed. Commercial travel agents, for example, who need to book passage on Titan ships need to access the reservation system. Supporting many—possibly hundreds—of travel agents requires a robust transactional system to ensure agents have access and reservations are completed properly.
Throughout this book, we will build a fairly simple slice of Titan's EJB system that focuses on the process of making a reservation for a cruise. This exercise will give us an opportunity to develop Ship, Cabin, TravelAgent, ProcessPayment, and other enterprise beans. In the process, you will need to create relational database tables for persisting data used in the example. It is assumed that you are familiar with relational database management systems and that you can create tables according to the SQL statements provided. EJB can be used with any kind of database or legacy application, but the relational database is most commonly understood database technology, so I have chosen this as the persistence layer.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
What's Next?
To develop business objects using EJB, you have to understand the life cycles and architecture of EJB components. This means understanding the concepts of how EJB's components are managed and made available as distributed objects. Developing an understanding of the EJB architecture is the focus of the next two chapters.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: Architectural Overview
In order to use Enterprise JavaBeans effectively, you need to understand the EJB architecture. This chapter explores the core of the EJB architecture: how enterprise beans are distributed as business objects. Chapter 3 explores the services and resource-management techniques supported by EJB.
In order to be truly versatile, the EJB component design had to be smart. For application developers, assembling enterprise beans requires little or no expertise in the complex system-level issues that often plague three-tier development efforts. While EJB makes the process easier for application developers, it also provides EJB server developers with a great deal of flexibility in how they support the EJB specification.
Enterprise JavaBeans server-side components come in three fundamentally different types: entity, session, and message-driven beans. Both session and entity beans are RMI-based server-side components that are accessed using distributed object protocols. Message-driven beans process messages from non-RMI systems like Java Message Service, legacy systems, and web services. All EJB servers must at least support a JMS-based message driven bean, but they may also support other types of message-driven bean.
A good rule of thumb is that entity beans model business concepts that can be expressed as nouns. For example, an entity bean might represent a customer, a piece of equipment, an item in inventory, or even a place. In other words, entity beans model real-world objects; these objects are usually persistent records in some kind of database. Our hypothetical cruise line will need entity beans that represent cabins, customers, ships, etc.
Session beans are extensions of the client application that manage processes or tasks. A Ship bean provides methods for doing things directly to a ship, but doesn't say anything about the context under which those actions are taken. Booking passengers on the ship requires that we use a Ship bean, but it also requires a lot of things that have nothing to do with the ship itself: we'll need to know about passengers, ticket rates, schedules, and so on. A session bean is responsible for this kind of coordination. Session beans tend to manage particular kinds of activities, such as the act of making a reservation. They have a lot to do with the relationships between different entity beans. A TravelAgent session bean, for example, might make use of a Cruise, a Cabin, and a Customer—all entity beans—to make a reservation.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Enterprise Bean Component
Enterprise JavaBeans server-side components come in three fundamentally different types: entity, session, and message-driven beans. Both session and entity beans are RMI-based server-side components that are accessed using distributed object protocols. Message-driven beans process messages from non-RMI systems like Java Message Service, legacy systems, and web services. All EJB servers must at least support a JMS-based message driven bean, but they may also support other types of message-driven bean.
A good rule of thumb is that entity beans model business concepts that can be expressed as nouns. For example, an entity bean might represent a customer, a piece of equipment, an item in inventory, or even a place. In other words, entity beans model real-world objects; these objects are usually persistent records in some kind of database. Our hypothetical cruise line will need entity beans that represent cabins, customers, ships, etc.
Session beans are extensions of the client application that manage processes or tasks. A Ship bean provides methods for doing things directly to a ship, but doesn't say anything about the context under which those actions are taken. Booking passengers on the ship requires that we use a Ship bean, but it also requires a lot of things that have nothing to do with the ship itself: we'll need to know about passengers, ticket rates, schedules, and so on. A session bean is responsible for this kind of coordination. Session beans tend to manage particular kinds of activities, such as the act of making a reservation. They have a lot to do with the relationships between different entity beans. A TravelAgent session bean, for example, might make use of a Cruise, a Cabin, and a Customer—all entity beans—to make a reservation.
Similarly, message-driven beans coordinate tasks involving other session and entity beans. Message-driven beans and session beans differ primarily in how they are accessed. While a session bean provides a remote interface that defines which methods can be invoked, a message-driven bean subscribes to or listens for messages. It responds by processing the message and managing the actions that other beans take. For example, a ReservationProcessor message-driven bean would receive asynchronous messages—perhaps from a legacy reservation system—from which it would coordinate the interactions of the Cruise, Cabin, and Customer beans to make a reservation.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Using Enterprise Beans
Let's look at how a client would use an enterprise bean to do something useful. We'll start with the Cabin EJB defined earlier. A cabin is a thing or place with a description that is stored in a database. To make the example a little more real, assume that there are other entity beans: Ship, Cruise, Ticket, Customer, Employee, and so on.
Imagine that a GUI client needs to display information about a particular cruise: the cruise name, the ship name, and a list of cabins. Using the cruise ID obtained from a text field, we can use our beans to look up data about the cruise. Here's the code:
CruiseHomeRemote cruiseHome = ... ; // use JNDI to get the home
// Get the cruise ID text field 1.
String cruiseID = textField1.getText( );
// Create an EJB primary key from the cruise ID.
Integer pk = new Integer(cruiseID);
// Use the primary key to find the cruise.
CruiseRemote cruise = cruiseHome.findByPrimaryKey(pk);
// Set text field 2 to show the cruise name.
textField2.setText(cruise.getName( ));
// Get a remote reference to the ship that will be used
// for the cruise from the cruise bean.
ShipRemote ship = cruise.getShip( );
// Set text field 3 to show the ship's name.
textField3.setText(ship.getName( ));

// Get all the cabins on the ship.
Collection cabins = ship.getCabins( );
Iterator cabinItr = cabins.iterator( );

// Iterate through the enumeration, adding the name of each cabin
// to a list box.
while(cabinItr.hasNext( ))
    CabinRemote cabin = (CabinRemote)cabinItr.next( );
    listBox1.addItem(cabin.getName( ));
}
We start by getting a remote reference to the EJB home for an entity bean that represents a cruise. We need a remote reference rather than a local one because the client is an application located outside the EJB container. It's not shown in the example, but references to the EJB home are obtained using JNDI. JNDI is a powerful API for locating resources, such as remote objects, on networks. JNDI lookups are covered in subsequent chapters.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Bean-Container Contract
The environment that surrounds the beans on the EJB server is often called the container. The container is more a concept than a physical construct. It acts as an intermediary between the bean and the EJB server. It manages the EJB objects and EJB homes and helps these constructs to manage bean resources and provide services such as transactions, security, concurrency, and naming at runtime. The distinction between the container and the server is not clearly defined, but the EJB specification defines the component model in terms of the container's responsibilities, so we will follow that convention here.
Enterprise bean components interact with the EJB container through a well-defined component model. The EntityBean, SessionBean , and MessageDrivenBean interfaces provide callback methods that notify the bean class of life-cycle events. At runtime, the container invokes these methods on the bean instance when relevant events occur. For example, when the container is about to write an entity bean instance's state to the database, it first calls the bean instance's ejbStore( ) method. This call gives the bean instance an opportunity to do cleanup on its state before it's written to the database. The ejbLoad( ) method is called just after the bean's fields are populated from the database, providing the bean developer with an opportunity to manage the bean's state before the first business method is called. Other callback methods can be used by the bean class in a similar fashion. EJB defines when these various callback methods are invoked and what can be done within their contexts.
While the bean interfaces require implementations of all the callback methods, those implementations don't have to be meaningful. The method body of any or all of the callback methods can be left empty, and often is. Beans that implement callback methods usually access resources that aren't managed by the EJB system. Enterprise beans that wrap legacy systems often fall into this category.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Summary
This chapter covered a lot of ground describing the basic architecture of an EJB system. At this point, you should understand that beans are business object components. The home interfaces define life-cycle methods for creating, finding, and destroying beans, and the remote and local interfaces define the public business methods of the bean. Message-driven beans do not have component interfaces. The bean class is where the state and behavior of the bean are implemented.
There are three basic kinds of beans: entity, session, and message-driven. Entity beans are persistent and represent a person, place, or thing. Session beans are extensions of the client and embody a process or a taskflow that defines how other beans interact. Session beans are not persistent: they receive their state from the client, and they live only as long as the client needs them. Message-driven beans are integration points that allow other applications to interact with EJB applications using JMS or, in EJB 2.1, some other J2eeCA 1.5-compliant resource. Message-driven beans, like stateless session beans, are not persistent and do not maintain conversational state.
The EJB object and EJB home are conceptual constructs that delegate method invocations to session and entity beans from the client and help the container to manage the enterprise bean at runtime. The clients of entity and session beans do not interact with the instances of the bean class directly. Instead, the client software interacts with stubs, which are connected to the EJB object and EJB home. The EJB object implements the remote and/or local interface and expands the bean class's functionality. The EJB home implements the home interface and works closely with the container to create, locate, and remove beans.
Beans interact with their containers through the well-defined bean-container contract. This contract provides callback methods, the EJBContext, and the JNDI environment-naming context. The callback methods notify the bean class that it is involved in a life-cycle event. The
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 3: Resource Management and the Primary Services
Chapter 2 discussed the basic architecture of Enterprise JavaBeans, including the relationship between the bean class, the component interfaces, the EJB object and EJB home, and the EJB container. These artifacts define a common model for distributed server-side components. But the common model for distributed objects isn't enough to make EJB interesting or even particularly useful. EJB servers also manage the resources used by beans, and can manage thousands, even millions of distributed objects simultaneously. They must manage how distributed objects use memory, threads, database connections, processing power, and more. Furthermore, the EJB specification defines interfaces that help developers take advantage of these common practices.
In particular, EJB servers support six primary services: concurrency, transaction management, persistence, object distribution, naming, and security. These services provide the kind of infrastructure that is necessary for a successful three-tier system. Enterprise JavaBeans also supports two additional services: asynchronous messaging and a timer service.
This chapter discusses the resource-management facilities and the primary services that are available to Enterprise JavaBeans.
A large business system with many users can easily require thousands of objects—even millions of objects—to be in use simultaneously. As the number of interactions among these objects increases, concurrency and transactional concerns can degrade the system's response time and frustrate users. EJB servers increase performance by synchronizing object interactions and sharing resources.
There is a relationship between the number of clients and the number of distributed objects that are required to service them. Not surprisingly, the larger the client population, the more distributed objects are needed. At some point, the increase in clients affects performance and diminishes throughput. EJB explicitly supports two mechanisms that make it easier to manage large numbers of beans at runtime: instance pooling and activation. In addition, EJB supports the use of the J2EE Connector Architecture (J2EE Connectors) for managing resource connections. As the number of distributed objects and clients increase, the number of resource connections also increases. J2EE Connectors work with the EJB container to manage connections to databases, enterprise messaging, ERP, legacy systems, and other types of resources.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Resource Management
A large business system with many users can easily require thousands of objects—even millions of objects—to be in use simultaneously. As the number of interactions among these objects increases, concurrency and transactional concerns can degrade the system's response time and frustrate users. EJB servers increase performance by synchronizing object interactions and sharing resources.
There is a relationship between the number of clients and the number of distributed objects that are required to service them. Not surprisingly, the larger the client population, the more distributed objects are needed. At some point, the increase in clients affects performance and diminishes throughput. EJB explicitly supports two mechanisms that make it easier to manage large numbers of beans at runtime: instance pooling and activation. In addition, EJB supports the use of the J2EE Connector Architecture (J2EE Connectors) for managing resource connections. As the number of distributed objects and clients increase, the number of resource connections also increases. J2EE Connectors work with the EJB container to manage connections to databases, enterprise messaging, ERP, legacy systems, and other types of resources.
The concept of pooling resources is nothing new. It's common to pool database connections so that the business objects in the system can share database access. This trick reduces the number of database connections needed, which reduces resource consumption and increases throughput. The J2EE Connector Architecture (J2eeCA) is frequently the mechanism employed by EJB containers when pooling connections to databases and other resources, and is covered a little later. Most EJB containers also apply resource pooling to server-side components; this technique is called instance pooling. Instance pooling reduces the number of component instances—and therefore resources—needed to service client requests. In general, it is also less expensive to reuse pooled instances than to create and destroy instances.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Primary Services
Many value-added services are available for distributed applications. This book looks at eight value-added services called the primary services because they are required to complete the Enterprise JavaBeans platform. The primary services include concurrency, transactions, persistence, distributed objects, asynchronous messaging, timer, naming, and security. EJB servers automatically manage all the primary services. This capability relieves the application developers from the task of mastering these complicated services. Instead, developers can focus on defining the business logic that describes the system and leave the system-level concerns to the EJB server. The following sections describe each of the primary services and explain how they are supported by EJB.
Concurrency is important to all the bean types, but it has different meanings for each type.

Section 3.2.1.1: Concurrency with session and entity beans

Session beans do not support concurrent access. This limitation makes sense if you consider the nature of stateful and stateless session beans. A stateful bean is an extension of one client and serves only that client. It doesn't make sense to make stateful beans concurrent if they are used only by the clients that created them. Stateless session beans don't need to be concurrent because they don't maintain state that needs to be shared. The scope of the operations performed by a stateless bean is limited to the scope of each method invocation. Because neither stateful nor stateless session beans represent shared data, there is no need for concurrency.
Entity beans represent data that is shared and may be accessed concurrently. Entity beans are shared components. In Titan's EJB system, for example, there are three ships: Paradise, Utopia, and Valhalla. At any given moment the Ship entity bean that represents the Utopia might be accessed by hundreds of clients. To make concurrent access to entity beans possible, the EJB container needs to protect the data represented by the shared bean, while allowing many clients to access the bean simultaneously.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
What's Next?
The first three chapters of this book gave you a foundation on which to develop Enterprise JavaBeans components and applications. While we haven't gone into detail, we've shown you most of the topics that you'll be dealing with. Beginning with Chapter 4, you will develop your own beans and learn how to apply them in EJB applications.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 4: Developing Your First Enterprise Beans
One of the most important features of EJB is that enterprise beans have the ability to work with containers from different vendors. However, that doesn't mean that selecting a server and installing your enterprise beans on that server are trivial processes.
The EJB server you choose should provide a utility for deploying enterprise beans. It doesn't matter whether the utility is command-line oriented or graphical, as long as it does the job. The deployment utility should allow you to work with prepackaged enterprise beans, i.e., enterprise beans that have already been developed and archived in a JAR file. Finally, the EJB server must support an SQL-standard relational database that is accessible using JDBC. For the database, you should have privileges sufficient for creating and modifying a few simple tables in addition to normal read, update, and delete capabilities. If you have chosen an EJB server that does not support a SQL-standard relational database, you may need to modify the examples to work with the product you are using.
This book does not say very much about how to install and deploy enterprise beans. That task is largely server-dependent. We'll provide some general ideas about how to organize JAR files and create deployment descriptors, but for a complete description of the deployment process, you'll have to refer to your vendor's documentation.
To get the most from this chapter, it helps to have an IDE that has a debugger and allows you to add Java files to its environment. Several Java IDEs—such as BEA's Weblogic Workshop, IBM's Eclipse, Borland's JBuilder, and Sun's Forte—fulfill this requirement. Some EJB products, such as IBM's WebSphere and BEA's Weblogic, are tightly coupled with an IDE that makes life a lot easier when it comes to writing, deploying, and debugging your applications.
Once you have an IDE set up, you need to include the Enterprise JavaBeans and other J2EE packages which will be provided by your application server vendor—usually in a single JAR file (e.g.,
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Choosing and Setting Up an EJB Server
The EJB server you choose should provide a utility for deploying enterprise beans. It doesn't matter whether the utility is command-line oriented or graphical, as long as it does the job. The deployment utility should allow you to work with prepackaged enterprise beans, i.e., enterprise beans that have already been developed and archived in a JAR file. Finally, the EJB server must support an SQL-standard relational database that is accessible using JDBC. For the database, you should have privileges sufficient for creating and modifying a few simple tables in addition to normal read, update, and delete capabilities. If you have chosen an EJB server that does not support a SQL-standard relational database, you may need to modify the examples to work with the product you are using.
This book does not say very much about how to install and deploy enterprise beans. That task is largely server-dependent. We'll provide some general ideas about how to organize JAR files and create deployment descriptors, but for a complete description of the deployment process, you'll have to refer to your vendor's documentation.
To get the most from this chapter, it helps to have an IDE that has a debugger and allows you to add Java files to its environment. Several Java IDEs—such as BEA's Weblogic Workshop, IBM's Eclipse, Borland's JBuilder, and Sun's Forte—fulfill this requirement. Some EJB products, such as IBM's WebSphere and BEA's Weblogic, are tightly coupled with an IDE that makes life a lot easier when it comes to writing, deploying, and debugging your applications.
Once you have an IDE set up, you need to include the Enterprise JavaBeans and other J2EE packages which will be provided by your application server vendor—usually in a single JAR file (e.g., j2ee.jar).
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Developing an Entity Bean
There's no better place to start than the Cabin EJB, which we have been examining throughout the previous chapters. The Cabin EJB is an entity bean that encapsulates the data and behavior associated with a cruise ship cabin in Titan's business domain.
When developing an entity bean, we first want to define its remote interface. The remote interface defines the bean's business purpose; the methods of this interface must capture the concept of the entity. We defined the remote interface for the Cabin EJB in Chapter 2; here, we add two new methods for setting and getting the ship ID and the bed count. The ship ID identifies the ship to which the cabin belongs, and the bed count tells how many people the cabin can accommodate:
package com.titan.cabin;

import java.rmi.RemoteException;

public interface CabinRemote extends javax.ejb.EJBObject {
    public String getName( ) throws RemoteException;
    public void setName(String str) throws RemoteException;
    public int getDeckLevel( ) throws RemoteException;
    public void setDeckLevel(int level) throws RemoteException;
    public int getShipId( ) throws RemoteException;
    public void setShipId(int sp) throws RemoteException;
    public int getBedCount( ) throws RemoteException;
    public void setBedCount(int bc) throws RemoteException; 
}
The CabinRemote interface defines four properties: name, deckLevel, shipId, and bedCount. Properties are attributes of an enterprise bean that can be accessed by public set and get methods.
Notice that we have made the CabinRemote interface a part of a new package named com.titan.cabin. Place all the classes and interfaces associated with each type of bean in a package specific to the bean. Because our beans are for the use of the Titan cruise line, we placed these packages in the com.titan package hierarchy. We also created directory structures that match package structures. If you are using an IDE that works directly with Java files, create a new directory called
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Developing a Session Bean
Session beans act as agents to the client, controlling taskflow (the business process) and filling the gaps between the representation of data by entity beans and the business logic. Session beans are often used to manage interactions between entity beans and can perform complex manipulations of beans. Since we have defined only one entity bean so far, we will start by manipulating this bean. The interactions of entity beans within session beans is explored in greater detail in Chapter 11.
Client applications and other beans use the Cabin EJB in a variety of ways. Some of these uses were predictable when the Cabin EJB was defined, but many were not. After all, an entity bean represents data—in this case, data describing a cabin. The uses to which we put that data change over time—hence the importance of separating the data itself from the taskflow. In Titan's business system, for example, we may need to list and report on cabins in ways that were not predictable when the Cabin EJB was defined. Rather than change the Cabin EJB every time we need to look at it differently, we will obtain the information we need using a session bean. The definition of an entity bean should only be changed within the context of a larger process—for example, a major redesign of the business system.
We'll start developing a TravelAgent EJB that is responsible for the taskflow of booking a passage on a cruise. This session bean will be used in client applications accessed by travel agents throughout the world. In addition to booking tickets, the TravelAgent EJB provides information about which cabins are available on the cruise. In this chapter, we develop the first implementation of this listing behavior. The "list cabins" behavior will be used to provide customers with a list of cabins that can accommodate their needs. The Cabin EJB does not directly support this kind of list, nor should it. The list we need is specific to the TravelAgent EJB, so it's the TravelAgent EJB's responsibility to query the Cabin EJB and produce the list.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 5: The Remote and Local Client View
Developing the Cabin EJB and the TravelAgent EJB may have raised your confidence, but it also may have raised a lot of questions. We have glossed over most of the details involved in developing, deploying, and accessing the enterprise beans. In this chapter and the ones that follow, we will peel away the layers of the Enterprise JavaBeans onion to expose the details of EJB application development.
This chapter focuses specifically on the client's remote and local view of entity and session beans. The endpoint view, which is used by Web service clients to access stateless session beans, is significantly different and is addressed separately in the Web services chapter, Chapter 14. Message-driven beans are not covered in this chapter either—they are covered in detail in Chapter 12.
In Chapter 4, the client application started by creating an InitialContext, which it then used to get a remote reference to the homes of the Cabin and TravelAgent EJBs. The InitialContext is part of a larger API called the Java Naming and Directory Interface ( JNDI). We use JNDI to look up an EJB home in an EJB server just like we might use a phone book to find the home number of a friend or business associate.
JNDI is a standard Java package that provides a uniform API for accessing a wide range of services. It is somewhat similar to JDBC, which provides uniform access to different relational databases. Just as JDBC lets us write code that doesn't care whether it's talking to an Oracle database or a DB2 database, JNDI lets us write code that can access different directory and naming services, including the naming services provided by EJB servers. EJB servers are required to support JNDI by organizing beans into a directory structure and providing a JNDI driver, called a service provider, for accessing that directory structure. Using JNDI, an enterprise can organize its beans, services, data, and other resources in a unified directory.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Locating Beans with JNDI
In Chapter 4, the client application started by creating an InitialContext, which it then used to get a remote reference to the homes of the Cabin and TravelAgent EJBs. The InitialContext is part of a larger API called the Java Naming and Directory Interface ( JNDI). We use JNDI to look up an EJB home in an EJB server just like we might use a phone book to find the home number of a friend or business associate.
JNDI is a standard Java package that provides a uniform API for accessing a wide range of services. It is somewhat similar to JDBC, which provides uniform access to different relational databases. Just as JDBC lets us write code that doesn't care whether it's talking to an Oracle database or a DB2 database, JNDI lets us write code that can access different directory and naming services, including the naming services provided by EJB servers. EJB servers are required to support JNDI by organizing beans into a directory structure and providing a JNDI driver, called a service provider, for accessing that directory structure. Using JNDI, an enterprise can organize its beans, services, data, and other resources in a unified directory.
Two of JNDI's greatest features are that it is virtual and dynamic. JNDI is virtual because it allows one directory service to be linked to another through simple URLs. The URLs in JNDI are analogous to HTML links. Just as an HTML link allows you to download a new page without worrying about the server on which that page is located, JNDI lets us drill down through directories to files, printers, and EJB home objects without knowing where the resources—or even the directory servers holding information about the resources—are located. The directories and subdirectories can be located in the same host or physically hosted at different locations. As developers or administrators, we can create virtual directories that span a variety of services over many different physical locations.
JNDI is dynamic because it allows the JNDI drivers (a.k.a. service providers) for specific types of directory services to be loaded at runtime. A driver maps a specific kind of directory service into the standard JNDI class interfaces. When a link to a different directory service is chosen, the driver for that type of directory service is automatically loaded from the directory's host, if it is not already resident on the user's machine. Automatically downloading JNDI drivers makes it possible for a client to navigate across arbitrary directory services without knowing in advance what kinds of services it is likely to find.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Remote Client API
Enterprise bean developers are required to provide a bean class, component interfaces, and, for entity beans, a primary key. The component interfaces and primary key class are visible to the client; the bean class itself is not. The component interfaces and primary key contribute to the client-side API in EJB.
Any client, whether it is in the same container system or not, may use the Remote Client API, which means that it may use the remote interface, the remote home interface, and Java RMI to access entity and session beans. Enterprise beans that are located in the same EJB container have the option of using the Local Client API. The Local Client API provides local component interfaces and avoids the restrictions and overhead of the Remote Client API. This section examines the remote component interfaces and the primary key, as well as other Java types that make up EJB's remote client-side API.
Enterprise JavaBeans defines an enterprise bean's remote client API in terms of Java RMI-IIOP, which enforces compliance with CORBA. This means that the underlying protocol used by remote clients to access enterprise beans can be anything the vendor wants as long as it supports the types of interfaces and arguments that are compatible with Java RMI-IIOP. However, in addition to any proprietary protocols, vendors must also support the CORBA IIOP 1.2 protocol as defined in the CORBA 2.3.1 specification.
To use the Remote Client API, define your component interfaces and argument types so that they comply with Java RMI-IIOP types. It's not all that difficult to comply with this restriction. The next few sections discuss the Java RMI-IIOP programming model for EJB.

Section 5.2.1.1: Java RMI return types, parameters, and exceptions

As an implementation of Java RMI, Java RMI-IIOP must first comply with the basic restrictions of Java RMI. We'll first take a look at Java RMI restrictions and then proceed to examine addition restrictions imposed by Java RMI-IIOP.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Local Client API
Enterprise JavaBeans were originally defined in terms of remote interfaces, such as the ones we've been discussing. The use of remote interfaces gave a nice, clean design: beans and bean clients did not need to worry about where other beans were located, because all bean references were treated as remote references. Beans always communicated with each other using Java RMI.
But in the real world, when two or more enterprise beans interact, they are usually co-located; that is, they are deployed in the same EJB container system and execute within the same Java Virtual Machine. In this case, RMI really isn't necessary, and imposes overhead that we'd rather do without. Why treat all beans as remote objects if, in fact, they are often local? EJB 2.0 introduced the Local Client API to give developers control over whether beans should be accessed as remote objects, using RMI, or as local objects.
In EJB 2.0 and 2.1, session and entity beans can implement either remote or local component interfaces, or both. Any type of enterprise bean (entity, session, or message-driven) can become a co-located client of a session or entity bean; for example, a message-driven bean can call methods on co-located entity beans using its local component interfaces. The Local Client API is similar to the Remote Client API, but it is less complicated. The Local Client API is composed of two interfaces, the local and local home interfaces, which are similar to the remote and remote home interfaces.
The local interface, like the remote interface, defines business methods that can be invoked by other co-located beans (co-located clients). These business methods must match the signatures of business methods defined in the bean class. For example, the CabinLocal interface is the local interface defined for the Cabin EJB:
package com.titan.cabin;

import javax.ejb.EJBException;

public interface CabinLocal extends javax.ejb.EJBLocalObject {
    public String getName( ) throws EJBException;
    public void setName(String str) throws EJBException;
    public int getDeckLevel( ) throws EJBException;
    public void setDeckLevel(int level) throws EJBException;
    public int getShipId( ) throws EJBException;
    public void setShipId(int sp) throws EJBException;
    public int getBedCount( ) throws EJBException;
    public void setBedCount(int bc) throws EJBException; 
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 6: CMP: Basic Persistence
In this chapter, we'll take a thorough look at the process of developing entity beans. A good rule of thumb is that entity beans model business concepts that can be expressed as nouns. Although this is a guideline rather than a requirement, it helps determine when a business concept is a candidate for implementation as an entity bean. In grammar school, you learned that nouns are words that describe a person, place, or thing. The concepts of "person" and "place" are fairly obvious: a person EJB might represent a customer or passenger, and a place EJB might represent a city or port-of-call. Similarly, entity beans often represent "things": real-world objects like ships, credit cards, and abstractions such as reservations. Entity beans describe both the state and behavior of real-world objects and allow developers to encapsulate the data and business rules associated with specific concepts; a Customer EJB encapsulates the data and business rules associated with a customer, for example. This makes it possible for data associated with a concept to be manipulated consistently and safely.
In Titan's cruise ship business, we can identify hundreds of business concepts that are nouns and, therefore, could conceivably be modeled by entity beans. We've already seen a simple Cabin EJB in Chapter 4, and we'll develop Customer and Address EJBs in this chapter. Titan could clearly make use of a Cruise EJB, a Reservation EJB, and many others. Each of these business concepts represents data that needs to be tracked and possibly manipulated.
Entities represent data in the database, so changes to an entity bean result in changes to the database. That's ultimately the purpose of an entity bean: to provide programmers with a simpler mechanism for accessing and changing data. It is much easier to change a customer's name by calling Customer.setName( ) than by executing an SQL command against the database. In addition, using entity beans provides opportunities for software reuse. Once an entity bean has been defined, its definition can be used throughout Titan's system in a consistent manner. The concept of a customer, for example, is used in many areas of Titan's business, including booking, accounts receivable, and marketing. A Customer EJB provides Titan with one complete way of accessing customer information, and thus it ensures that access to the information is consistent and simple. Representing data as entity beans can make development easier and more cost-effective.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Abstract Programming Model
In CMP, the container automatically manages the entity beans' state. The container takes care of enrolling the entity bean in transactions and persisting its state to the database. The developer describes the attributes and relationships of an entity bean using virtual persistence fields and relationship fields. They are called virtual fields because the bean developer does not declare these fields explicitly; instead, abstract accessor (get and set) methods are declared in the entity bean class. The implementations of these methods are generated at deployment time by the EJB vendor's container tools. It's important to remember that the terms relationship field and persistence field refer to the abstract accessor methods and not to actual fields declared in the classes.
In Figure 6-1, the Customer EJB has six accessor methods. The first four read and update the last and first names of the customer. These are examples of persistence fields: simple direct attributes of the entity bean. The last two accessor methods obtain and set references to the Address EJB through its local interface, AddressLocal. This is an example of a relationship field called the homeAddress field.
Figure 6-1: Class diagram of Customer and Address EJBs
The CMP entity bean classes are defined using abstract accessor methods that represent virtual persistence and relationship fields. As already mentioned, the actual fields themselves are not declared in the entity classes. Instead, the characteristics of these fields are described in the XML deployment descriptor used by the entity bean. The abstract persistence schema is the set of XML elements in the deployment descriptor that describe the relationship fields and the persistence fields. Together with the abstract accessor methods and some help from the deployer, the container tool will have enough information to map the entity and its relationships to other entity beans to the database.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Customer EJB
The Customer EJB is a simple CMP entity bean that models the concept of a cruise customer or passenger, but its design and use are applicable across many commercial domains. This section introduces the Customer bean's development, packaging, and deployment. We greatly expand the bean's features as we progress through the chapter.
Although CMP is database-independent, the examples throughout this book assume that you are using a relational database. This means that we will need a CUSTOMER table from which to get our customer data. The relational database table definition in SQL is as follows:
CREATE TABLE CUSTOMER 
(
    ID INT PRIMARY KEY NOT NULL, 
    LAST_NAME CHAR(20), 
    FIRST_NAME CHAR(20)
)
The CustomerBean class is an abstract class that the container uses for generating a concrete implementation, the persistence entity class. The mechanism used by the container for generating a persistence entity class varies, but most vendors generate a subclass of the abstract class provided by the bean developer (see Figure 6-4).
Figure 6-4: The container tool typically extends the bean class
The bean class must declare accessor (set and get) methods for each persistence field and relationship field defined in the deployment descriptor. The container needs both the abstract accessor methods (defined in the entity bean class) and the XML elements of the deployment descriptor to fully describe the bean's persistence schema. In this book, the entity bean class is always defined before the XML elements, because it's a more natural approach for most Java developers. Here is a very simple definition of the CustomerBean class:
package com.titan.customer;

import javax.ejb.EntityContext;

public abstract class CustomerBean implements javax.ejb.EntityBean {
       
    public Integer ejbCreate(Integer id){
        setId(id);
        return null;
    }
    public void ejbPostCreate(Integer id){
    }
   
    // abstract accessor methods

    public abstract Integer getId( );
    public abstract void setId(Integer id);
    
    public abstract String getLastName( );
    public abstract void setLastName(String lname);
    
    public abstract String getFirstName( );
    public abstract void setFirstName(String fname);
    
    // standard callback methods
    
    public void setEntityContext(EntityContext ec){}
    public void unsetEntityContext( ){}
    public void ejbLoad( ){}
    public void ejbStore( ){}
    public void ejbActivate( ){}
    public void ejbPassivate( ){}
    public void ejbRemove( ){}
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Persistence Fields
Content preview·