4.5 PayrollEJB Stateless Session Bean

The PayrollEJB session bean provides remote access to PayrollDatabase. Because payroll data is sensitive information, most, if not all, enterprises set up their environments to restrict access to payroll data. The PayrollEJB session bean exists principally to provide applications, such as the Benefits Enrollment application, with restrictive access to PayrollDatabase. In addition, PayrollEJB may implement an audit trail.

An application that wants to access the payroll information cannot access PayrollDatabase directly, such as by using JDBC. Instead, an application must use the PayrollEJB session bean to access the information indirectly. By requiring applications to use the PayrollEJB session bean to access PayrollDatabase, the payroll department restricts the access to the payroll information to the functions defined in the PayrollEJB session bean. In addition, the payroll department can use the EJB declarative security mechanism enforced by the EJB container to restrict access to the individual methods of PayrollEJB to specific applications.

4.5.1 PayrollEJB Stateless Session Bean Parts

Figure 4.11 illustrates the main parts of the PayrollEJB stateless session bean.

Figure 4.11. PayrollEJB Session Bean Parts

graphics/04fig11.gif

The remote interface is called Payroll. The home interface is called PayrollHome. The session bean class is called PayrollBean. The methods of the remote and home interfaces throw the application exception PayrollException.

PayrollEJB Session Bean Remote Interface

The Payroll remote interface defines the business methods that a client may invoke on the individual session objects. Code Example 4.16 shows the definition of the Payroll remote interface:

Code Example 4.16 Payroll Remote Interface
 package com.star.payroll; import javax.ejb.*; import java.rmi.RemoteException; public interface Payroll extends EJBObject {    void setBenefitsDeduction(int emplNumber, double deduction)       throws RemoteException, PayrollException;    double getBenefitsDeduction(int emplNumber)       throws RemoteException, PayrollException;    double getSalary(int emplNumber)       throws RemoteException, PayrollException;    void setSalary(int emplNumber, double salary)       throws RemoteException, PayrollException; } 

The Payroll interface follows the same EJB rules for all enterprise bean remote interfaces.

PayrollEJB Session Bean Home Interface

The PayrollHome home interface defines the create method used by the client to create a session object. Code Example 4.17 shows the definition of this interface:

Code Example 4.17 PayrollHome Home Interface
 import javax.ejb.*; import java.rmi.RemoteException; public interface PayrollHome extends EJBHome {    Payroll create() throws RemoteException, CreateException; } 

Note that PayrollHome defines only one create method and that this method takes no arguments. Note also that PayrollHome defines no other methods. According to the EJB specification, the home interface of a stateless session bean must have a single create method that takes no arguments. The home interface cannot define any other methods.

PayrollEJB Helper Classes

The PayrollEJB session bean uses only one helper class, PayrollException, which defines the payroll-specific exceptions. The Payroll and PayrollHome interfaces are defined to throw the exception PayrollException. Code Example 4.18 shows the definition of the PayrollException class:

Code Example 4.18 PayrollException Helper Class
 package com.star.payroll; public class PayrollException extends Exception {    // error codes    public static int UNKNOWN = 0;    public static int INVAL_EMPL_NUMBER = 1;    static String[] defaultMessage = {       "unknown error code",       "invalid employee number"    };    int errorCode;    public PayrollException() { super(); }    public PayrollException(String s) { super(s); }    public PayrollException(int errorCode, String s) {       super(s);       this.errorCode = errorCode;    }    public PayrollException(int errorCode) {       super(errorCode >= 0 && errorCode < defaultMessage.length ?          defaultMessage[errorCode] : "");       this.errorCode = errorCode;    } } 
PayrollEJB Session Bean Class

The PayrollBean class, the PayrollEJB's session bean class, is defined as shown in Code Example A.3 on page 378. The PayrollBean session bean class is a Java class that defines the implementation of the PayrollEJB session bean. Specifically, this class defines

  • The business methods that are defined in the Payroll remote interface

  • The ejbCreate method, which corresponds to the create method defined in the PayrollHome interface

  • The methods defined in the javax.ejb.SessionBean interface

PayrollEJB Business Methods Implementation

The PayrollEJB session bean defines four business methods. The implementations of these business methods setSalary, getSalary, setBenefitsDeduction, and getBenefitsDeduction use JDBC to read or update the underlying PayrollDatabase.

The PayrollBean bean instance acquires a database connection at the start of each business method and releases the connection at the end of the business method. In this example, the bean developer chose not to hold the database connection across business method invocations; the developer did this to allow the application server's connection pooling mechanism to maximize the reuse of database connections. However, it is also legal to hold the database connection across all business method invocations that is, to acquire the database connection in the ejbCreate method, use it in the business methods, and then release it in the ejbRemove method.

Recall that a stateless session bean instance does not maintain state for a specific client. The PayrollBean class does not keep any state that is specific to a client: conversational state. The EJB container can use a stateless session bean instance to process serially the requests from multiple clients. The container can also route each request occurrence from a given client to a different instance, even if that client is running within the context of a transaction. Therefore, instances of a stateless session bean class must not hold any conversational state. (However, they can contain objects that are not specific to a client, such as JDBC data sources, as illustrated in our example.) The client must pass all the state necessary to process a request in the business method arguments.

As the example code illustrates, the paradigm provided by a stateless session bean is essentially procedural programming. This is in contrast to a stateful session bean and an entity bean, both of which provide the object-oriented programming paradigm.

The ejbCreate Method Implementation

Note that the PayrollBean class leaves the implementation of the ejbCreate method empty. The container invokes the ejbCreate method after creating the instance of the PayrollBean class and invoking the setSessionContext method on the instance. The bean developer needs to keep in mind that the container may create instances of a stateless session bean class in no direct relationship to the client-invoked create methods. This differs from a stateful session bean, in which the container creates the instance when a client invokes a create method through the session bean's home interface.

For example, the container may choose to create a fixed number of instances of the stateless session bean when the container starts and then use these instances to handle all subsequent client-invoked methods. Therefore, the ejbCreate method does not execute in a client context. Therefore, it would be an error for the ejbCreate method to invoke, for example, the getCallerPrincipal method on the associated SessionContext interface.

A stateless session bean typically uses the ejbCreate method to acquire various resources that will be used across subsequently invoked business methods. An example of such a resource would be a TCP/IP connection or a JDBC data source.

The SessionBean Method Implementation

The PayrollBean class defines empty implementations of the setSessionContext, ejbRemove, ejbActivate, and ejbPassivate SessionBean interface methods. PayrollBean is really a simple, uncomplicated bean, and as such does not need the functionality provided by the setSessionContext and ejbRemove container-invoked methods. (The ejbActivate and ejbPassivate methods are not called on stateless session beans.)

The container calls the setSessionContext method after creating the PayrollBean instance and before invoking the ejbCreate method on the instance. If it needs to invoke any of the methods that relate to SessionContext during its lifetime, the instance should save the passed SessionContext reference in an instance variable and should do this from within the setSessionContext method.

The ejbRemove Method Implementation

The container invokes the ejbRemove method before discarding the instance. Once it invokes the ejbRemove method on an instance, the container does not invoke any further business methods in the instance. The ejbRemove method is typically used to release any resources acquired in the ejbCreate method.

Note the comments in the PayrollBean code for the ejbActivate and ejbPassivate methods, which indicate that the container never calls the ejbActivate and ejbPassivate methods. The concept of passivation and activation applies only to stateful session beans; the container thus never calls these methods on a stateless session bean.

Data Access

The PayrollBean class makes direct use of JDBC in its business methods to access the database. Some application developers may prefer encapsulating the data access by using command beans (see the section Data Access Command Beans on page 100).

If a JDBC call throws an exception, the PayrollBean instance catches the exception and throws EJBException. You may notice that the instance does not close the JDBC connection before throwing EJBException, even though closing the connection is considered good programming practice. (For example, we always close the JDBC connection in the command beans used by EnrollmentBean. We do so by calling the release method in the finally clause.) However, because the container manages resources for bean instances, not closing the JDBC connection does not result in a leak of resources. The container catches EJBException and closes all the resources, including JDBC connections, that are held by the instance. Management of resources is one of the services that the EJB container provides on behalf of the enterprise bean instances. The JDBC driver collaborates with the container to achieve the management of resources.

4.5.2 Client Developer's Perspective

In our example application, the EnrollmentEJB session bean is the client of the PayrollEJB session bean. EnrollmentEJB creates a stateless session object as follows:

 ... PayrollHome payrollHome = (PayrollHome) PortableRemoteObject.narrow(    ictx.lookup("java:comp/env/ejb/PayrollEJB"),    PayrollHome.class); payroll = (Payroll)payrollHome.create(); ... 

A client uses the same API to create a stateless session bean as it does to create a stateful session bean. However, as discussed in the section The ejbCreate Method Implementation on page 115, invoking the create method on the home interface of a stateless session bean does not necessarily create a new instance of the session bean class. The implementation of the session bean's home interface create method may simply produce an object reference to the existing distributed object that implements the session bean's remote interface and then may return the reference to the client.

After it creates a stateless session object, the client can invoke the object's business methods through the remote interface. For example, EnrollmentBean invokes the setBenefitsDeduction method through the DeductionUpdateBean command bean as follows:

 ... // Update information in the payroll system. try {    payroll.setBenefitsDeduction(employeeNumber, payrollDeduction); } catch (PayrollException ex) {    ... } catch (RemoteException ex) {    ... } ... 

Finally, when finished using the Payroll object, the client releases it by invoking the remove method, as follows:

 ... try {    payroll.remove(); } catch (Exception ex) { } ... 

Note that all stateless session objects within the same home interface have the same object identity. (However, objects from different home interfaces have different identities.) The following code example shows that two Payroll bean objects have the same identity, with the isIdentical method returning true:

 Payroll payroll = (Payroll)payrollHome.create(); Payroll payroll2 = (Payroll)payrollHome.create(); if (payroll.isIdentical(payroll2)) {// this test returns true    ... } else {    ... } 

This is in contrast to a stateful session bean. Every stateful session object has a unique identity.

Use of Object Handles

The EJB architecture allows a session bean client to store an object reference of a session bean's home or remote interface in persistent storage. To do this, a client uses the object's handle. The handle is needed because the home or remote interface references are not guaranteed to be serializable. The EJB specification defines two interfaces for working with handles:

  1. The javax.ejb.Handle interface for the handles of enterprise bean objects

  2. The javax.ejb.HomeHandle interface for the handles of the enterprise bean home objects

Code Example 4.19 illustrates the use of a session object handle:

Code Example 4.19 Using a Session Bean Handle
 ... ObjectOutputStream outputStream = ...; ... Handle handle = payroll.getHandle(); outputStream.writeObject(handle); ... 

Note in this example that the client first obtains the handle by invoking the getHandle method on the session object. The client then serializes the handle into ObjectOutputStream.

At a later point, another client program running in the same client environment can deserialize the handle and create an object from the session object reference. Code Example 4.20 shows how this is done:

Code Example 4.20 Deserializing a Handle
 ... ObjectInputStream inputStream = ...; ... Handle handle = (Handle)inputStream.readObject(); Payroll payroll = (Payroll)       PortableRemoteObject.narrow(handle.getEJBObject(),                Payroll.class); // invoke business methods on payroll session object payroll.setBenefitsDeduction(); 

Note that the PortableRemoteObject.narrow mechanism, although complicated to use, ensures that the client code works with all EJB containers.

The Benefits Enrollment application does not use handles directly. Clients, such as application clients and Web applications, however, may use the handle mechanism in several ways, as follows:

  • Maintain a reference to the session object A Web application may maintain a reference to the session object in its HTTP session state. If it needs to swap the HTTP session state to secondary storage, the Web container may use the handle mechanism to retain the reference to the session object.

  • Migrate the HTTP session to another process The Web container may choose to migrate the HTTP session to another process on the same or a different machine. The Web container may use the handle mechanism to migrate the session object reference from one process to another.

  • Store HTTP session data The Web container may choose to implement the Web application as stateless by storing all the HTTP session data in an HTTP cookie. The Web container may use the handle to externalize the session object reference and store it in the cookie.

Note that a container crash invalidates any session handles for session objects that were stored in persistent storage.



Applying Enterprise Javabeans
Applying Enterprise JavaBeans(TM): Component-Based Development for the J2EE(TM) Platform
ISBN: 0201702673
EAN: 2147483647
Year: 2003
Pages: 110

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net