The EJB specificationIntroduction The Enterprise JavaBeans specification defines an architecture for a transactional, distributed object system based on components. The specification mandates a programming model, that is, conventions or protocols and a set of classes and interfaces that make up the EJB API. The EJB programming model provides bean developers and EJB server vendors with a set of contracts that defines a common platform for development. The goal of these contracts is to ensure portability across vendors while supporting a rich set of functionality. The EBJ container Enterprise beans are software components that run in a special environment called an EJB container. The container hosts and manages an enterprise bean in the same manner that the Java Web server hosts a servlet or an HTML browser hosts a Java applet. An enterprise bean cannot function outside of an EJB container. The EJB container manages every aspect of an enterprise bean at run time including remote access to the bean, security, persistence, transactions, concurrency, and access to and pooling of resources. The container isolates the enterprise bean from direct access by client applications. When a client application invokes a remote method on an enterprise bean, the container first intercepts the invocation to ensure persistence, transactions, and security are applied properly to every operation a client performs on the bean. The container manages security, transactions, and persistence automatically for the bean, so the bean developer doesn't have to write this type of logic into the bean code itself. The enterprise bean developer can focus on encapsulating business rules, while the container takes care of everything else. Containers will manage many beans simultaneously in the same fashion that the Java WebServer manages many servlets. To reduce memory consumption and processing, containers pool resources and manage the life cycles of all the beans very carefully. When a bean is not being used, a container will place it in a pool to be reused by another client, or possibly evict it from memory and only bring it back when it's needed. Because client applications don't have direct access to the beans -- the container lies between the client and bean -- the client application is completely unaware of the container's resource management activities. A bean that is not in use, for example, might be evicted from memory on the server, while its remote reference on the client remains intact. When the client invokes a method on the remote reference, the container simply re-incarnates the bean to service the request. The client application is unaware of the entire process. An enterprise bean depends on the container for everything it needs. If an enterprise bean needs to access a JDBC connection or another enterprise bean, it does so through the container; if an enterprise bean needs to access the identity of its caller, obtain a reference to itself, or access properties it does so through the container. The enterprise bean interacts with its container through one of three mechanisms: callback methods, the EJBContext interface, or JNDI. * Callback Methods: Every bean implements a subtype of the EnterpriseBean interface which defines several methods, called callback methods. Each callback method alerts the bean of a different event in its lifecycle and the container will invoke these methods to notify the bean when it's about to pool the bean, persist its state to the database, end a transaction, remove the bean from memory, and so on. The callback methods give the bean a chance to do some housework immediately before or after some event. Callback methods are discussed in more detail in Section 4. * EJBContext: Every bean obtains an EJBContext object, which is a reference directly to the container. The EJBContext interface provides methods for interacting with the container so that that bean can request information about its environment, like the identity of its client or the status of a transaction, or can obtain remote references to itself. * Java Naming and Directory Interface (JNDI): JNDI is a standard extension to the Java platform for accessing naming systems like LDAP, NetWare, file systems, etc. Every bean automatically has access to a special naming system called the Environment Naming Context (ENC). The ENC is managed by the container and accessed by beans using JNDI. The JNDI ENC allows a bean to access resources like JDBC connections, other enterprise beans, and properties specific to that bean. The EJB specification defines a bean-container contract, which includes the mechanisms (callbacks, EJBContext, JNDI ENC) described above as well as a strict set of rules that describe how enterprise beans and their containers will behave at run time, how security access is checked, how transactions are managed, how persistence is applied, and so on. The bean-container contract is designed to make enterprise beans portable between EJB containers so that enterprise beans can be developed once, then run in any EJB container. Vendors like BEA, IBM, and GemStone sell application servers that include EJB containers. Ideally, any enterprise bean that conforms to the specification should be able to run in any conformant EJB container. Portability is central to the value that EJB brings to the table. Portability ensures that a bean developed for one container can be migrated to another if another brand offers more performance, features, or savings. Portability also means that the bean developer's skills can be leveraged across several EJB container brands, providing organizations and developers with better opportunities. In addition to portability, the simplicity of the EJB programming model makes EJB valuable. Because the container takes care of managing complex tasks like security, transactions, persistence, concurrency and resource management the bean developer is free to focus attention on business rules and a very simple programming model. A simple programming model means that beans can be developed faster without requiring a Ph.D. in distributed objects, transactions and other enterprise systems. EJB brings transaction processing and distributed objects development into the mainstream. Enterprise beans To create an EJB server-side component, an enterprise bean developer provides two interfaces that define a bean's business methods, plus the actual bean implementation class. The client then uses a bean's public interfaces to create, manipulate, and remove beans from the EJB server. The implementation class, to be called the bean class, is instantiated at run time and becomes a distributed object. Enterprise beans live in an EJB container and are accessed by client applications over the network through their remote and home interfaces. The remote and home interfaces expose the capabilities of the bean and provide all the methods needed to create, update, interact with, and delete the bean. A bean is a server-side component that represents a business concept like a Customer or a HotelClerk. Remote and home interfaces The remote and home interfaces represent the bean, but the container insulates the beans from direct access from client applications. Every time a bean is requested, created, or deleted, the container manages the whole process. The home interface represents the life-cycle methods of the component (create, destroy, find) while the remote interface represents the business method of the bean. The remote and home interfaces extend the javax.ejb.EJBObject and javax.ejb.EJBHome interfaces respectively. These EJB interface types define a standard set of utility methods and provide common base types for all remote and home interfaces. Clients use the bean's home interface to obtain references to the bean's remote interface. The remote interface defines the business methods like accessor and mutator methods for changing a customer's name, or business methods that perform tasks like using the HotelClerk bean to reserve a room at a hotel. Below is an example of how a Customer bean might be accessed from a client application. In this case the home interface is the CustomerHome type and the remote interface is the Customer type.
CustomerHome home = // ... obtain a reference that
// implements the home interface. // Use the home interface to create a // new instance of the Customer bean. Customer customer = home.create(customerID); // using a business method on the Customer. customer.setName(someName); The remote interface defines the business methods of a bean, the methods that are specific to the business concept it represents. Remote interfaces are subclassed from the javax.ejb.EJBObject interface, which is a subclass of the java.rmi.Remote interface. The importance of the remote interfaces inheritance hierarchy is discussed later in Section 4. For now, focus on the business methods and their meaning. Below is the definition of a remote interface for a Customer bean:
import javax.ejb.EJBObject;
import java.rmi.RemoteException; public interface Customer extends EJBObject { public Name getName() throws RemoteException; public void setName(Name name) throws RemoteException; public Address getAddress() throws RemoteException; public void setAddress(Address address) throws RemoteException; } The remote interface defines accessor and mutator methods to read and update information about a business concept. This is typical of a type of bean called an entity bean, which represents a persistent business object (business objects whose data is stored in a database). Entity beans represent business data in the database and add behavior specific to that data. Business methods Business methods can also represent tasks that a bean performs. Although entity beans often have task-oriented methods, tasks are more typical of a type of bean called a session bean. Session beans do not represent data like entity beans. They represent business processes or agents that perform a service, like making a reservation at a hotel. Below is the definition of the remote interface for a HotelClerk bean, which is a type of session bean:
import javax.ejb.EJBObject;
import java.rmi.RemoteException; public interface HotelClerk extends EJBObject { public void reserveRoom(Customer cust, RoomInfo ri, Date from, Date to) throws RemoteException; public RoomInfo availableRooms(Location loc, Date from, Date to) throws RemoteException; } The business methods defined in the HotelClerk remote interface represent processes rather than simple accessors. The HotelClerk bean acts as an agent in the sense that it performs tasks on behalf of the user, but is not itself persistent in the database. You don't need information about the HotelClerk; you need the hotel clerk to perform tasks for you. This is typical behavior for a session bean. There are two basic types of enterprise beans: entity beans, which represent data in a database, and session beans, which represent processes or act as agents performing tasks. As you build an EJB application you will create many enterprise beans, each representing a different business concept. Each business concept will be manifested as either an entity bean or a session bean. You will choose which type of bean a business concept becomes based on how it is intended to be used. Entity beans For every remote interface there is an implementation class, a business object that actually implements the business methods defined in the remote interface. This is the bean class; the key element of the bean. Below is a partial definition of the Customer bean class:
import javax.ejb.EntityBean;
public class CustomerBean implements EntityBean { Address myAddress; Name myName; CreditCard myCreditCard; public Name getName() { return myName; } public void setName(Name name) { myName = name; } public Address getAddress() { return myAddress; } public void setAddress(Address address) { myAddress = address; } ... } CustomerBean is the implementation class. It holds the data and provides accessor methods and other business methods. As an entity bean, the CustomerBean provides an object view of customer data. Instead of writing database access logic in an application, the application can simply use the remote interface to the Customer bean to access customer data. Entity beans implement the javax.ejb.EntityBean type, which defines a set of notification methods that the bean uses to interact with its container. These notification methods are examined in detail under "Callback methods" in Section 4. Session beans The HotelClerk bean is a session bean, which is similar in many respects to an entity bean. Session beans represent a set of processes or tasks, which are performed on behalf of the client application. Session beans may use other beans to perform a task or access the database directly. A little bit of code shows a session bean doing both. The reserveRoom() method shown below uses several other beans to accomplish a task, while the availableRooms() method uses JDBC to access the database directly:
import javax.ejb.SessionBean;
public class HotelClerkBean implements SessionBean { public void reserveRoom(Customer cust, RoomInfo ri, Date from, Date to) { CreditCard card = cust.getCreditCard(); RoomHome roomHome = // ... get home reference Room room = roomHome.findByPrimaryKey(ri.getID()); double amount = room.getPrice(from,to); CreditServiceHome creditHome = // ... get home reference CreditService creditAgent = creditHome.create(); creditAgent.verify(card, amount); ReservationHome resHome = // ... get home reference Reservation reservation = resHome.create(cust,room,from,to); } public RoomInfo[] availableRooms(Location loc, Date from, Date to) { // Make an SQL call to find available rooms Connection con = // ... get database connection Statement stmt = con.createStatement(); ResultSet results = stmt.executeQuery("SELECT ..."); ... return roomInfoArray; } } You may have noticed that the bean classes defined above do not implement the remote or home interfaces. EJB doesn't require that the bean class implement these interfaces; in fact it's discouraged because the base types of the remote and home interfaces (EJBObject and EJBHome) define a lot of other methods that are implemented by the container automatically. The bean class does, however, provide implementations for all the business methods defined in the remote interface as well as methods. Callback methods are discussed in more detail in Section 4. Life-cycle methods In addition to a remote interface, all beans have a home interface. The home interface provides life-cycle methods for creating, destroying, and locating beans. These life-cycle behaviors are separated out of the remote interface because they represent behaviors that are not specific to a single bean instance. Below is the definition of the home interface for the Customer bean. Notice that it extends the javax.ejb.EJBHome interface, which extends the java.rmi.Remote interface.
import javax.ejb.EJBHome;
import javax.ejb.CreateException; import javax.ejb.FinderException; import java.rmi.RemoteException; public interface CustomerHome extends EJBHome { public Customer create(Integer customerNumber) throws RemoteException, CreateException; public Customer findByPrimaryKey(Integer customerNumber) throws RemoteException, FinderException; public Enumeration findByZipCode(int zipCode) throws RemoteException, FinderException; } The create() method is used to create a new entity. This will result in a new record in the database. A home may have many create() methods. The number and datatype of the arguments of each create() are left up to the bean developer, but the return type must be the remote interface datatype. In this case, invoking create() on the CustomerHome interface will return an instance of Customer. The findByPrimaryKey() and findByZipCode() methods are used to locate specific instance of the customer bean. Again, you may define as many find methods as you need. Back to the remote and home interfaces The remote and home interfaces are used by applications to access enterprise beans at run time. The home interface allows the application to create or locate the bean, while the remote interface allows the application to invoke a bean's business methods, as shown here:
CustomerHome home = // Get a reference to the CustomerHome object
Customer customer = home.create(new Integer(33)); Name name = new Name("Richard", "Wayne", "Monson-Haefel"); customer.setName(name); Enumeration enumOfCustomers = home.findByZip(55410); Customer customer2 = home.findByPrimaryKey(new Integer(33)); Name name2 = customer2.getName(); // output is "Richard Wayne Monson-Haefel" System.out.println(name); The javax.ejb.EJBHome interface also defines other methods that the CustomerBean automatically inherits, including a set of remove() methods that allow the application to destroy bean instances. Enterprise beans as distributed objects The remote and home interfaces are types of Java RMI Remote interfaces. The java.rmi.Remote interface is used by distributed objects to represent the bean in a different address space (process or machine). An enterprise bean is a distributed object. That means that the bean class is instantiated and lives in the container, but it can be accessed by applications that live in other address spaces. To make an object instance in one address space available in another requires a little trick involving network sockets. To make the trick work, wrap the instance in a special object called a skeleton that has a network connection to another special object called a stub. The stub implements the remote interface so it looks like a business object. But the stub doesn't contain business logic; it holds a network socket connection to the skeleton. Every time a business method is invoked on the stub's remote interface, the stub sends a network message to the skeleton telling it which method was invoked. When the skeleton receives a network message from the stub, it identifies the method invoked and the arguments, and then invokes the corresponding method on the actual instance. The instance executes the business method and returns the result to the skeleton, which sends it to the stub. The diagram below illustrates this concept: The stub returns the result to the application that invoked its remote interface method. From the perspective of the application using the stub, it looks like the stub does the work locally. Actually, the stub is just a dumb network object that sends the requests across the network to the skeleton, which in turn invokes the method on the actual instance. The instance does all the work; the stub and skeleton just pass the method identity and arguments back and forth across the network. In EJB, the skeletons for the remote and home interfaces are implemented by the container, not the bean class. This is to ensure that every method invoked on these reference types by a client application are first handled by the container and then delegated to the bean instance. The container must intercept these requests intended for the bean so that it can apply persistence (entity beans), transactions, and access control automatically. Distributed object protocols define the format of network messages sent between address spaces. Distributed object protocols get pretty complicated, but luckily you don't see any of it because it's handled automatically. Most EJB servers support either the Java Remote Method Protocol (JRMP) or CORBA's Internet Inter-ORB Protocol (IIOP). The bean and application programmer only see the bean class and its remote interface; the details of the network communication are hidden. With respect to the EJB API, the programmer doesn't care whether the EJB server uses JRMP or IIOP -- the API is the same. The EJB specification requires that you use a specialized version of the Java RMI API, when working with a bean remotely. Java RMI is an API for accessing distributed objects and is somewhat protocol agnostic -- in the same way that JDBC is database agnostic. So, an EJB server can support JRMP or IIOP, but the bean and application developer always uses the same Java RMI API. In order for the EJB server to have the option of supporting IIOP, a specialized version of Java RMI, called Java RMI-IIOP was developed. Java RMI-IIOP uses IIOP as the protocol and the Java RMI API. EJB servers don't have to use IIOP, but they do have to respect Java RMI-IIOP restrictions, so EJB 1.1 uses the specialized Java RMI-IIOP conventions and types, but the underlying protocol can be anything. |