- The client’s view
- Fundamentals of the EJB architecture
- Types of EJB
- Distributed and local EJB semantics
- Anatomy of an EJB
- Principle of operation: session and entity EJBs
- Principle of operation: message-driven EJBs
- The EJB container and its proxies
- Overview of the EJB API
- EJB rules, standards and limitations
- Assembly and deployment
- Configuration
- Summary
3.5 Anatomy of an EJB
When authoring a session or entity EJB, the developer must provide at least three Java .class files: two interfaces that expose the methods of the EJB that are accessible to clients, and an implementation class (often called the ‘bean class’ or ‘EJB class’). We need two interfaces because one exposes the factory methods of the EJB (create(), find()), while the other exposes the business methods that can be called on the specific EJB. In EJB 1.1, all EJB method calls were RMI calls, and only one pair of interfaces was required, the home interface and the remote interface. Of these, the former exposed the factory methods, and the latter the business methods.
As we have discussed, in EJB 2.0, to support the notion of intra-JVM EJB interaction, the developer can choose whether to specify a ‘local’ view, a ‘remote’ view, or both. When the local view is used, the factory methods are exposed by an interface called the local home interface, and business methods by the local interface. These interfaces and their relationships are summarized in Table 3.1. Although the names of the remote view interfaces have changed between EJB 1.1 and EJB 2.0, their functions have not, and neither has the Java code required to define them. All the interfaces are described in more detail later.
On a practical note, the factory interfaces tell the container how to implement the factory proxy, while the business method interfaces fulfill the same function for the business method proxy. These objects are described later in this chapter. Where we are providing a remote view, the interfaces also tell the server how to generate the stubs and skeletons needed to support RMI.
For a message-driven EJB only the implementation class is necessary.
All classes and interfaces must be supplied in a JAR file with a particular structure (see below).
As we shall see, the implementation class must provide implementations not only of the methods exposed by the interfaces, but of the life cycle management methods, which are called by the EJB container, not the client.
The correspondence between the interfaces and container-generated proxies is shown in Figures 3.3 to 3.5. These diagrams are for reference, rather than study, so please don’t try to memorize them (yet!).
Figure 3.3 . The relationship between the factory and business method interfaces in general. Bold boxes indicate Java classes or interfaces supplied by the EJB developer. The proxies will be generated automatically by the server vendor’s tools.
Figure 3.4 . The relationship between the factory and business method interfaces in the remote client view. With EJB 1.1, this is the only view available.
Figure 3.5 . The relationship between the factory and business method interfaces in the local client view. Note how much simpler this model is than Figure 3.4, as a result of the absence of RMI support classes.
Table 3.1. Interfaces supplied by the EJB developer in EJB 1.1 and EJB 2.0. It is unusual0 for both distributed and local interfaces to be provided for the same EJB.
EJB usage |
EJB 1.1 interface |
EJB 2.0 interface |
Exposes |
Distributed interaction |
Home interface |
Remote home interface |
Factory methods |
† | Remote interface |
Remote interface |
Business methods |
Local interaction |
n/a |
Local home interface |
Factory methods |
† | n/a |
Local interface |
Business methods |
Along with these three .class files, the EJB developer must provide at least one other file: the deployment descriptor. This is an XML file that contains information about the structure of the EJB.
3.5.1 Business method interfaces
Session and entity EJBs need a business method interface, 8 which will expose to clients the business methods they may call. Message-driven EJBs don’t have clients in the strict sense, and therefore don’t need a business method interface.
When the EJB provides a local client view, the business method interface is provided by the local interface. For the remote client view, it is provided by the remote interface. Despite the different names, these interfaces have exactly the same function: to expose business methods on the EJB to clients. Each method that the client will call on the EJB must be specified in the remote or local interface. Local interfaces are new in Version 2.0 of the EJB Specification. It is unlikely that both a remote and a local interface will be required for the same EJB, but where both are provided, they will probably expose the same methods.
For example, if the EJB is to have a method withdrawFunds(double amount), which can throw an exception InsufficientBalanceException, then it would be defined in the remote interface like this:
public void withdrawFunds(double amount) throws RemoteException, InsufficientBalanceException;
As in Java RMI, methods in the remote interface must be defined to throw RemoteException, because the class that actually implements the remote interface (the remote stub; see below) will need to be able to throw this exception. In addition, the remote interface must declare any other exceptions that can be thrown from the EJB’s methods. In the local interface, the definition would read:
public void withdrawFunds(double amount) throws InsufficientBalanceException;
That is, there is no provision to throw RemoteException. This is because the local interface is used only for intra-JVM calls; no stubs are required and there is therefore nothing to throw this exception.
All EJB remote interfaces must be subinterfaces—direct or indirect—of javax. ejb.EJBObject. Local interfaces must be subclasses of javax.ejb.EJBLocal Object.
When the EJB is deployed, the deployment tool or the EJB server will use the remote interface to generate a proxy for the EJB called the EJB object. 9 It will use the local interface to generate a proxy called the local object.
3.5.2 Factory interface
The factory interface of a session or entity EJB exposes the methods that the client can call that relate to life cycle management of the EJB. These methods do not necessarily correspond to method calls in the implementation class: They may be handled entirely by the EJB container. With distributed client view, the factory interface is formally called the remote home interface, while with local client view, it is the local home interface. Because EJB 1.1 only supported distributed clients, there was no concept of a ‘local home interface.’ Thus the terms ‘factory interface’ and ‘home interface’ were synonyms. For simplicity, this book follows that same pattern, and the term ‘home interface’ refers to either factory method. I will use the terms ‘remote home interface’ and ‘local home interface’ only when it is necessary to distinguish between them. Such circumstances will be rare, as the remote and local home interfaces fulfill exactly the same purpose.
The home interface (local or remote) can specify two types of method: ‘create’ methods and ‘find’ methods. These relate to the two ways in which the client can get a reference to an EJB: It can create a new one or find an existing one. For example, all stateless session EJBs must specify the following method in the remote home interface:
public [remote] create() throws RemoteException, javax.ejb.CreateException;
where [remote] is the type of the remote interface. This method creates an EJB, and returns to the client a reference to the EJB object that acts as the EJB’s proxy.
For local home interfaces, the equivalent is:
public [local] create() throws javax.ejb.CreateException;
where [local] is the type of the local interface. In this case, the EJB server returns a reference to the the local object that acts as the EJB’s proxy.
To accompany the method definitions in the interface, the implementation class must provide a method, ejbCreate(), that matches each create() in the home interface.
All remote home interfaces must be subinterfaces—direct or indirect—of javax. ejb.EJBHome, while local home interfaces must be subinterfaces of javax.ejb.EJB LocalHome.
When the EJB is deployed, the deployment tool or the EJB server will use the home interface to generate a proxy called the home object.
Message-driven EJBs don’t need a home interface.
3.5.3 Implementation class: session and entity EJBs
In a session or entity EJB, the implementation class provides implementations of the methods specified in the business method interface, and perhaps of those in the factory interface. The quotes around the word ‘implementations’ are there because, however odd it sounds at first, the implementation class does not implement either of these interfaces in the Java sense. That is, if we are providing a remote client view (as we usually will be) where the home interface is MyHome and the remote interface MyRemote, we will not write code like this:
public class MyImplementation implements MyHome, MyRemote
Instead, it is the container-generated stubs and proxies that will implement the home and remote interfaces. Of course, the implementation class must provide code that supports the methods specified in the interfaces. We will see how this is done later.
In addition to the business and factory methods provided for the benefit of clients, this class must implement the methods that will be called by the EJB container during life cycle management. For example, there will be method calls that indicate when the implementation class instance is created and destroyed.
Methods that are called by the EJB container are usually referred to as callback methods or life cycle methods.
The implementation class must implement javax.ejb.SessionBean, javax. ejb.EntityBean, or javax.ejb.MessageDrivenBean, depending on whether it is a session, entity, or message-driven EJB. Thus implementations must be provided for all the methods in these interfaces, although in many cases the method bodies may be empty.
3.5.4 Implementation class: message-driven EJBs
A message-driven EJB’s implementation has no business methods. The container calls the onMessage() method when a message arrives. These EJBs have no home or remote interface, and no home object or EJB object is generated. However, like session and entity EJBs, the message-driven EJB’s implementation class must handle the callback methods that are concerned with life cycle management.
3.5.5 Deployment descriptor
The deployment descriptor provides configuration information to the EJB server. Information in the descriptor includes the following:
the display name: the name of the EJB displayed by deployment tools;
names of the classes that the EJB requires: implementation, interfaces, and primary key class, if any;
the type (session, entity, message-driven) and subtypes (stateful, stateless, etc.);
security attributes (see Chapter 16);
transaction attributes (see Chapter 9);
configuration (‘environment’) variables (see Chapter 7);
EJB cross-reference information;
resource reference information (e.g., names of databases used).
The deployment descriptor is an XML file, and the EJB Specification [EJB2.0 21] states exactly what its syntax should be. In addition, it specifies that the deployment descriptor must be a file called ejb-jar.xml in a directory META-INF in the JAR file.
The format of the deployment descriptor is not particularly complex, but it can be quite lengthy. While it is straightforward to construct the file manually for simple applications, most serious development work will require the use of software tools. Most developers use graphical tools supplied by the vendor of the EJB server, which are often part of an integrated EJB assembly and deployment tool. For that reason, this book will not have much to say about the deployment descriptor in the text, but a brief overview is presented in Appendix B. More interested readers should refer to [EJB2.0 23] for full details.
3.5.6 EJB class naming conventions
Because the deployment descriptor defines the roles of the .class files that make up the EJB, the names used for the implementation class, home interface, and remote interface are arbitrary. However, it is sensible for clarity to adopt a naming convention that indicates immediately what the different classes and interfaces do. A convention that is widely used, and that I have followed in this book, is to base the class and interface names on the EJB name. For example, if the name of the EJB is to be Booking, then the names would be:
Home interface |
BookingHome |
Remote interface |
Booking |
Bean class |
BookingBean |
In particular, the remote interface has the same name as the EJB, as this is the name that will be manipulated most frequently in client code. Of course, none of this applies to message-driven EJBs, as they don’t have home or remote interfaces. There is, as yet, no widely established naming convention for the local home interface or local interface.