This section explains how the EJB container manages the session bean at runtime. We use object interaction diagrams (OIDs) to illustrate the interactions among the client, the distributed objects implemented by the container, and the instances of the session bean class. Some of the examples that follow use the remote interface and the remote home interface to illustrate the interactions. Keep in mind that similar interactions happen for local interfaces, too, except that local objects have no distributed objects and hence no network activity. 5.2.1 EJB Home Interface LookupRecall that a client program uses the following code to locate a session bean's home interface: ... Context ictx = new InitialContext(); Object h = ictx.lookup("java:comp/env/ejb/PayrollEJB"); PayrollHome payrollHome = (payrollHome) PortableRemoteObject.narrow(h, PayrollHome.class); ... This code performs a JNDI lookup operation and casts the found object to the PayrollHome home interface type. The OID in Figure 5.2 illustrates the EJB container actions that occur "under the covers" when the client initiates a lookup operation.
Figure 5.2. Home Interface Lookup OIDThe container returns the PayrollHomeRMI home object to the client. The client program obtains a reference to the RMI stub for the PayrollHomeRMI object. The stub implements the PayrollHome interface, which allows the client to subsequently invoke the methods defined in the PayrollHome interface on the stub. Note that the EJB specification requires the client to convert the result of the lookup operation by using the PortableRemoteObject.narrow method. The reason is that the home object is a remote object. If the client uses a simple Java cast to convert the result of the lookup operation, the cast operation could fail with some EJB container implementations. 5.2.2 Session Object CreationLet's look at what happens when the client program invokes the create method on the session bean home object with the following line of code: payroll = payrollHome.create(); The OID diagram (Figure 5.3) illustrates how the container performs this operation.
Figure 5.3. Create a Session Object OIDWhen these operations are complete, the container returns a remote object reference of the PayrollRMI distributed object to the client program. The stub implements the Payroll remote interface. The create operation does not run in the client's transaction context. Therefore, if a client's transaction rolls back after the client creates a session object, the container does not remove the new session object, such as PayrollRMI, in our example; nor does it undo the work of the ejbCreate method. The client can use the session object. 5.2.3 Business Method InvocationThis section discusses how the container manages the execution of the client-invoked business methods. This is probably the heart of an EJB application. The OID for the business method invocations is the most complex of the OIDs. It is important to keep in mind that these diagrams illustrate what the container is doing for the application. Because the container is responsible for these actions, the application developer's job is greatly simplified. To put it another way, the application developer merely invokes one business method, but the container must manage this with approximately 14 separate operations. Without the EJB container and environment, the application developer would have to write the code for these 14 operations, a far-from-easy task. In addition, the case we are examining here is rather simple. Two session beans use two databases in a transaction. Although one session bean does call another enterprise bean within a transaction, the session bean does not import a client's transactions; nor does it use the SessionSynchronization interface. Many real situations are much more complex, involving multiple databases, other enterprise beans, multiple transactions, transaction synchronization, and so forth. In these cases, the container's job is even more complex and involves many more steps. For our example, let's consider the case when the client, the EnrollmentWeb application, invokes the following business method on the Enrollment object: enrollment.commitSelections(selection); The OID diagram in Figure 5.4 illustrates the sequence of actions the container takes.
Figure 5.4. Business Method Invocation OIDAfter the transaction manager commits the transaction, the EnrollmentLocalObject object sends the reply to the client. If the commit fails for any reason, the EnrollmentLocalObject object throws javax.ejb.EJBException to the client. 5.2.4 Session Bean Passivation and ActivationLet's assume that the user invoked a business method, such as the getMedicalOptions method, and then decided to interrupt the session with the EnrollmentWeb application. For example, the user starts the enrollment process, gets to the page displaying the available medical options, and then, realizing that it is time to go to lunch, locks the workstation screen, leaving the application where it is to resume it later. Shortly thereafter, the container detects that the Enrollment session object recall that the Enrollment session bean is stateful has been idle for a while. At that point, the container may decide to reclaim the memory resources by passivating the session object. The OID diagram in Figure 5.5 illustrates the actions that the container takes to passivate the session object.
Figure 5.5. Passivation OIDLater, when the user comes back from lunch and resumes the session with the EnrollmentWeb application, the container activates the passivated object. It does this by taking the actions illustrated in Figure 5.6.
Figure 5.6. Activation OID5.2.5 Session Object RemovalThe client invokes the remove method on the EnrollmentLocalObject object to remove the session bean instance. This is shown in the following code segment: enrollment.remove(); The client call to the remove method causes the container to invoke the following sequence of actions, as illustrated in Figure 5.7.
Figure 5.7. Session Bean Removal OIDIf a client attempts to invoke a business method on a local session object after the object has been removed, the client receives javax.ejb.NoSuchObjectLocalException. (For remote objects, the client receives java.rmi.NoSuchObjectException.) A client cannot remove a session object while the object is participating in a transaction. That is, the remove method cannot be called when the object is participating in a transaction; this throws javax.ejb.RemoveException to the client. For session objects having a remote interface, a client may also remove the session object, using the EJBHome.remove(Handle handle) method. Handles are discussed in Chapter 4. The container has the option of invoking the ejbRemove method on an instance after the life of the session bean instance has expired, even without a prior remove method call from the client. See Section 5.2.6, Session Bean Timeout, which follows. Finally, the remove operation does not run in the client's transaction context. Therefore, if a client's transaction rolls back after the client removed a session object, the container does not restore the removed session object, such as EnrollmentLocalObject in our example; nor does it undo the work of the ejbRemove method. 5.2.6 Session Bean TimeoutIn some cases, a client may create a session object but then never call the remove method on this object. To handle these occurrences, the container typically uses a timeout mechanism to automatically remove session objects that are no longer used by clients. The deployer usually sets the timeout. The container must be able to remove a session bean without waiting for the remove method invocation, because it needs, eventually, to deallocate the resources that it allocated for the session object, such as the space on secondary storage, to store the serialized image of the session bean instance. Essentially, if a client has not invoked the session object for a specified period of time, the container implicitly removes the session object. Keep in mind, however, that a session bean timeout never occurs while a session object is in a transaction. When it removes the session object because of the timeout, the container may or may not choose to call the ejbRemove method on the session bean instance. The state of the session object determines whether the container invokes the ejbRemove method. If a session object is not in the "passive" state, the container invokes the ejbRemove method. If the session object has been passivated by the container, the container may simply reclaim the secondary storage allocated for the session object and not call the ejbRemove method. Therefore, the developer must design the application to tolerate the case in which the ejbRemove method is not called when a session object is removed. |