EntityContext

The first method called by the container after a bean instance is created is setEntityContext(). This method passes the bean instance a reference to its javax.ejb.EntityContext, which is really the instance’s interface to the container.

The setEntityContext() method should be implemented by the entity bean developer so that it places the EntityContext reference in an instance field of the bean where it will be kept for the life of the instance. The definition of EntityContext in EJB 2.0 is as follows:

public interface javax.ejb.EntityContext extends javax.ejb.EJBContext {
    public EJBLocalObject getEJBLocalObject() throws IllegalStateException
    public abstract EJBObject getEJBObject() throws IllegalStateException;
    public abstract Object getPrimaryKey() throws IllegalStateException;
}

EJBLocalObject is new to EJB 2.0 and is not supported by EJB 1.1. The definition of the EntityContext in EJB 1.1 is as follows:

public interface javax.ejb.EntityContext extends javax.ejb.EJBContext {
    public abstract EJBObject getEJBObject() throws IllegalStateException;
    public abstract Object getPrimaryKey() throws IllegalStateException;
}

As the bean instance is swapped from one EJB object to the next, the information obtainable from the EntityContext changes to reflect the EJB object to which the instance is assigned. This change is possible because the EntityContext is an interface, not a static class definition, and it means that the container can implement the EntityContext with a concrete class that it controls. As the entity bean instance is swapped from one EJB object to another, some of the information made available through the EntityContext will also change.

The getEJBObject() method returns a remote reference to the bean instance’s EJB object. The getEJBLocalObject() method (EJB 2.0), on the other hand, returns a local reference to the bean instance’s EJB object.

Tip

Session beans also define the getEJBObject() and getEJBLocalObject() (EJB 2.0) methods in the SessionContext interface; their behavior is exactly the same.

The EJB objects obtained from the EntityContext are the same kinds of references that might be used by an application client, in the case of a remote reference, or another co-located bean, in the case of a local reference. These methods allow the bean instance to get its own EJB object reference, which it can then pass to other beans. Here is an example:

public class A_Bean extends EntityBean {
    public EntityContext context;
    public void someMethod() {
        B_BeanRemote  b = ... // Get a remote reference to B_Bean.
        EJBObject obj = context.getEJBObject();             
        A_BeanRemote mySelf =  (A_BeanRemote)PortableRemoteObject.narrow(obj,A_BeanRemote.class);
        b.aMethod( mySelf );
    }
    ...
}

Tip

It is illegal for a bean instance to pass a this reference to another bean; instead, it passes its remote or local EJB object reference, which the bean instance gets from its EntityContext.

In EJB 2.0, the ability of a bean to obtain an EJB object reference to itself is also useful when establishing relationships with other beans in container-managed persistence. For example, the Customer EJB might implement a business method that allows it to assign itself a Reservation:

public abstract class CustomerBean implements javax.ejb.EntityBean {
    public EntityContext context;

    public void assignToReservation(ReservationLocal reservation) {
        EJBLocalObject localRef = context.getEJBLocalObject();
        Collection customers = reservation.getCustomers();
        customers.add(localRef);
    }
    ...
}

The getPrimaryKey() method allows a bean instance to get a copy of the primary key to which it is currently assigned. Use of this method outside of the ejbLoad() and ejbStore() methods of BMP entity beans is probably rare, but the EntityContext makes the primary key available for those unusual circumstances when it is needed.

As the context in which the bean instance operates changes, some of the information made available through the EntityContext reference will be changed by the container. This is why the methods in the EntityContext throw the java.lang.IllegalStateException. The EntityContext is always available to the bean instance, but the instance is not always assigned to an EJB object. When the bean is between EJB objects (i.e., when it’s in the pool), it has no EJB object or primary key to return. If the getEJBObject(), getEJBLocalObject(), or getPrimaryKey() methods are invoked when the bean is in the pool, they will throw an IllegalStateException. Appendix B provides tables of allowed operations for each bean type describing which EJBContext methods can be invoked at what times.

EJBContext

The EntityContext extends the javax.ejb.EJBContext class, which is also the base class for the SessionContext session beans use. EJBContext defines several methods that provide useful information to a bean at runtime.

Here is the definition of the EJBContext interface:

package javax.ejb;
public interface EJBContext {
   
    // EJB home methods
    public EJBHome getEJBHome();
    // EJB 2.0 only
    public EJBLocalHome getEJBLocalHome();
   
    // security methods
    public java.security.Principal getCallerPrincipal();
    public boolean isCallerInRole(java.lang.String roleName);
   
    // transaction methods
    public javax.transaction.UserTransaction getUserTransaction() 
        throws java.lang.IllegalStateException;
    public boolean getRollbackOnly() 
        throws java.lang.IllegalStateException;
    public void setRollbackOnly() 
        throws java.lang.IllegalStateException;

    // deprecated methods
    public java.security.Identity getCallerIdentity();
    public boolean isCallerInRole(java.security.Identity role); 
    public java.util.Properties getEnvironment();

}

The getEJBHome() and getEJBLocalHome() (EJB 2.0) methods return a reference to the bean’s EJB home. This is useful if the bean needs to create or find entity beans of its own type. Access to the EJB home proves more useful in bean-managed entity beans and CMP 1.1 entity beans than in CMP 2.0 entity beans, which have select methods and CMR fields.

As an example, if all of the employees in Titan’s system (including managers) are represented by CMP 1.1 Employee beans, a manager who needs access to subordinate employees can use the getEJBHome() method to get beans representing the appropriate employees:

public class EmployeeBean implements EntityBean {
    int id;
    String firstName;
    ...
    public Enumeration getSubordinates() {            
        Object ref = ejbContext.getEJBHome();
        EmployeeHome home = (EmployeeHome)
            PortableRemoteObject.narrow(ref, EmployeeHome.class);
        Integer primKey = (Integer)context.getPrimaryKey();
        Enumeration subordinates = home.findByManagerID(primKey);
        return subordinates;
    }
    ...
}

The getCallerPrincipal() method is used to obtain the Principal object representing the client that is currently accessing the bean. The Principal object can, for example, be used by the Ship bean to track the identities of clients making updates:

public class ShipBean implements EntityBean {
    String lastModifiedBy;
    EntityContext context;
    ...
    public void setTonnage(double tons) {
        tonnage = tons;
        Principal principal = context.getCallerPrincipal();
        String modifiedBy = principal.getName();
    }
    ...
}

The isCallerInRole() method tells you whether the client accessing the bean is a member of a specific role, identified by a role name. This method is useful when more access control is needed than simple method-based access control can provide. In a banking system, for example, you might allow the Teller role to make most withdrawals but only the Manager role to make withdrawals of over $10,000. This kind of fine-grained access control cannot be addressed through EJB’s security attributes because it involves a business logic problem. Therefore, we can use the isCallerInRole() method to augment the automatic access control provided by EJB. First, let’s assume that all managers are also tellers. The business logic in the withdraw() method uses isCallerInRole() to make sure that only the Manager role can withdraw sums over $10,000.00:

public class AccountBean implements EntityBean {
    int id;
    double balance;
    EntityContext context;

    public void withdraw(Double withdraw) throws AccessDeniedException {
        
        if (withdraw.doubleValue() > 10000) {
            boolean isManager = context.isCallerInRole("Manager");
            if (!isManager) {
                // Only Managers can withdraw more than 10k.
                throw new AccessDeniedException();
            }
        }
        balance = balance - withdraw.doubleValue();

    }
    ...
}

The EJBContext contains some methods that were used in EJB 1.0 but were deprecated in EJB 1.1 and have been abandoned in EJB 2.0. Support for these deprecated methods is optional for EJB 1.1 containers, which can host EJB 1.0 beans. EJB containers that do not support the deprecated security methods will throw a RuntimeException. The deprecated security methods are based on EJB 1.0’s use of the Identity object instead of the Principal object. The semantics of the deprecated methods are basically the same but, because Identity is an abstract class, it has proven to be too difficult to use.

The getEnvironment() method has been replaced by the JNDI environment naming context, which is discussed later in this book. Support for the deprecated getEnvironment() method in EJB 1.1 is discussed in detail in Chapter 12. The transactional methods—getUserTransaction(), setRollbackOnly(), and getRollbackOnly()—are described in detail in Chapter 14.

The material on the EJBContext covered in this section applies equally well to session and message-driven beans. There are some exceptions, however, and these differences are covered in Chapter 12 and Chapter 13.

JNDI ENC

Starting with EJB 1.1, the bean-container contract for entity and stateful beans was expanded beyond the EJBContext using the Java Naming and Directory Interface ( JNDI). A special JNDI name space, which is referred to as the environment naming context (ENC), was added to allow any enterprise bean to access environment entries, other beans, and resources (such as JDBC DataSource objects) specific to that enterprise bean.

The JNDI ENC continues to be an extremely important part of the bean-container contract in EJB 2.0. Although we used the JNDI ENC to access JDBC in the bean-managed persistence chapter (Chapter 10), it’s not specific to entity beans. The JNDI ENC is used by session, entity, and message-driven beans alike. To avoid unnecessary duplication, a detailed discussion of this important facility is left for Chapter 12. What you learn about using the JNDI ENC in Chapter 12 applies equally well to session, entity, and message-driven beans.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset