The environment that surrounds the beans on the EJB server is often referred to as the container. The container is more a concept than a physical construct. Conceptually, the container acts as an intermediary between the bean and the EJB server. It manifests and manages the EJB objects and EJB homes for a particular type of bean and helps these constructs to manage bean resources and apply primary services such as transactions, security, concurrency, naming, and so forth at runtime. Conceptually, an EJB server may have many containers, each of which may contain one or more types of enterprise beans. As you will discover a little later, the container and the server are not clearly different constructs, 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
(EJB 2.0) interfaces are the bases of
this component model. As we learned earlier, these interfaces provide
callback methods that notify the bean class of life-cycle events. At
runtime, the container invokes the callback methods on the bean
instance when appropriate life-cycle events occur. When the container
is about to write an entity bean instance’s state to the
database, for example, it first calls the bean instance’s
ejbStore()
method. This provides the bean instance with
an opportunity to do some cleanup on its state just before it’s
written to the database. The
ejbLoad()
method is called
just after the bean’s state is populated from the database,
providing the bean developer with an opportunity to manage the
bean’s state before the first business method is
called.[9] 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. This provides the bean developer
with a predictable runtime component model.
While all the callback methods are declared in bean interfaces, a
meaningful implementation of the methods is not mandatory. In other
words, the method body of any or all of the callback methods can be
left empty in the bean class. Beans that implement one or more
callback methods are usually more sophisticated and access resources
that are not managed by the EJB system. Enterprise beans that wrap
legacy systems often fall into this category. The only exception to
this is the
onMessage()
method, which is defined in the
MessageDrivenBean
interface. This method must have
a meaningful implementation if the message-driven bean is to do
anything useful.
javax.ejb.EJBContext
is an interface that is implemented
by the container and is also part of the bean-container contract.
Entity beans use a subclass of
javax.ejb.EJBContext
called
javax.ejb.EntityContext
.
Session beans use a subclass called
javax.ejb.SessionContext
.
Message-driven beans use the subclass
javax.ejb.MessageDrivenContext
. These EJBContext
types provide the bean with information about its container, the
client using the enterprise bean, and the bean itself. They also
provide other functionality that is described in more detail in
Chapter 11, Chapter 12,
and Chapter 13. The important thing about the
EJBContext
types is that they provide the
enterprise bean with information about the world around it, which the
enterprise bean can use while processing requests from clients and
callback methods from the container.
In addition to EJBContext
, EJB 1.1 and 2.0 have
expanded the enterprise bean’s interface with the container to
include a JNDI name space, called the environment naming context
,
which provides the bean with a more flexible and extensible
bean-container interface. The JNDI environment naming context is
discussed in detail in Chapter 11 and
Chapter 12.
The container-server contract is not defined by the Enterprise JavaBeans specification. It was left undefined to facilitate maximum flexibility for vendors defining their EJB server technologies. Other than isolating the beans from the server, the container’s responsibility in the EJB system is a little vague. The EJB specification defines only the bean-container contract, not the container-server contract. It is difficult to determine, for example, exactly where the container ends and the server begins when it comes to resource management and other services.
In the first few generations of EJB servers this ambiguity has not been a problem, because most EJB server vendors also provide EJB containers. Since the vendor provides both the container and the server, the interface between the two can remain proprietary. In future generations of the EJB specification, however, some work may be done to define the container-server interface and delimit the responsibilities of the container.
One advantage of defining a container-server interface is that it allows third-party vendors to produce containers that can plug into any EJB server. If the responsibilities of the container and server are clearly defined, vendors who specialize in the technologies that support these different responsibilities can focus on developing the containers or servers that best match their core competencies. The disadvantage of a clearly defined container-server interface is that the plug-and-play approach could impact performance. The high level of abstraction that would be required to clearly separate the container interface from the server would naturally lead to looser binding between these large components, which could result in lower performance. The following rule of thumb best describes the advantages and disadvantages associated with a container-server interface: the tighter the integration, the better the performance; the higher the abstraction, the greater the flexibility. The biggest deterrent to defining a container-server interface is that it would require the definition of low-level facilities, which was one of the problems established CTM vendors had with CORBA. The ability to implement low-level facilities such as transactions and security as they see fit is one of EJB’s biggest attractions for vendors.[10]
Many EJB-compliant servers actually support several different kinds of middleware technologies. It’s quite common, for example, for an EJB server to support the vendor’s proprietary CTM model as well as EJB, servlets, web-server functionality, a JMS provider, and other server technologies. Defining an EJB container concept is useful for clearly distinguishing the part of the server that supports EJB from all the other services it provides.
This said, we could define the responsibilities of containers and servers based on current implementations of the EJB specification. In other words, we could examine how current vendors are defining the container in their servers and use this as a guide. Unfortunately, the responsibilities of the container in each EJB server largely depend on the core competency of the vendor in question. Database vendors, for example, implement containers differently from TP-monitor vendors. The strategies for assigning responsibilities to the container and server are so varied that discussing them separately won’t really help you understand the overall architecture. Instead, this book addresses the architecture of the EJB system as though the container and server were one component and refers to them collectively as the EJB server or container.
[9] The ejbLoad()
and
ejbStore()
behavior illustrated here is for
container-managed persistence. With bean-managed persistence, the
behavior is slightly different. This distinction is examined in
detail in Chapter 11.
[10] Of all the commercial and open source EJB servers available today, only one, OpenEJB, has experimented with defining a container-server interface. OpenEJB is an open source EJB container system that I developed.