As you saw earlier in this chapter, when accessing an enterprise bean, a client always uses the component interface to invoke operations on the bean. The type of interface depends on whether you are using local or remote clients to access the bean. If local clients will be accessing your enterprise bean, you must create an interface that extends the javax.ejb.EJBLocalObject interface. This interface provides the local client view of the EJB object and defines the business methods that are available to the local client. Table 3.1 displays the methods defined in the EJBLocalObject interface. Table 3.1. The Methods Defined in the EJBLocalObject Interface
On the other hand, if your enterprise bean will be accessed by remote clients, the component interface for the bean must extend the javax.ejb.EJBObject interface. Table 3.2 displays the methods defined in the EJBObject interface. Table 3.2. The Methods Defined in the EJBObject Interface
Note Some of the methods in Table 3.2 have different behaviors depending on which type of enterprise bean it's invoked on. For example, session beans do not have a primary key, so the getPrimaryKey method would not be valid to call on it. Also, the remove method acts differently whether you are calling it on a session bean or an entity bean. Don't worry if this doesn't makes sense yet, it will shortly. It's enough to realize for now that methods called on enterprise beans can act differently depending on the type of enterprise bean. The enterprise bean class does not actually implement its own component interface, but it must contain the same business methods that the component interface defines. You probably are wondering why this is. There are two key reasons for this behavior. The first reason is that the component interface either extends the EJBLocalObject interface or EJBOjbect interface, depending on the type of client. Both of these interfaces contain method signatures that should be handled by the container and not the bean instance itself. Take another look at the method signatures in Tables 3.1 and 3.2. If an enterprise bean implemented the component interface directly, it would have to define these methods in the bean class. The container will never invoke these methods if they're implemented by the instance. The second reason why a bean should not implement its component interface has to do with letting the compiler help you detect when you are incorrectly passing references to the bean instances in method calls or as return values. As it was mentioned at the top of this section, EJB clients should never access the enterprise bean instance directly. Instead, clients should always perform method calls on the component interface. This ensures that the container performs all system-level services, such as transactions, concurrency, and security, before the bean instance is called. If a client, whether local or remote client, made a call directly to the bean instance, these services would be bypassed. To prevent this from happening, your bean class should not implement the component interface. This way, if you were to pass your bean instance, rather than the object that implements the component interface to another object, the compiler will catch it because it would be the incorrect type. To get the object that implements your component interface, you can get it from either the javax.ejb.SessionContext or the javax.ejb.EntityContext , depending on your enterprise bean type. Both interfaces have the methods getEJBLocalObject and getEJBObject , which return an instance of the local or remote interface respectively. It sounds confusing that a bean should not implement its own component interface, but it will be explained further in Chapter 16, "Patterns and Strategies in EJB Design." If you just cant wait, see "Using a Business Method Interface," p . 448 . With all this talk of the local and remote component interfaces, maybe it would help to see a small example of each. Listings 3.6 and 3.7 show examples of using a local and remote interface, respectively, for an enterprise bean called OrderFulfillmentProcessorBean . Both interfaces declare a single method called completeOrder . This is the only method available to the client for this basic example. Listing 3.6 The Local Interface for an OrderFulfillmentProcessorBeanimport javax.ejb.EJBLocalObject; public interface OrderFulfillmentProcessorLocal extends EJBLocalObject { /** * Completes an order and prepares it for shipping. * * @param orderId String Order identifier * @return void */ public void completeOrder (String orderId); } Notice how the component interface for the local client extends the EJBLocalObject interface in Listing 3.6. On the other hand, the remote interface for the same enterprise bean extends the EJBObject interface. You can see this in Listing 3.7. Listing 3.7 The Remote Interface for an OrderFulfillmentProcessorBeanimport java.rmi.RemoteException; import javax.ejb.EJBObject; public interface OrderFulfillmentProcessor extends EJBObject { /** * Completes an order and prepares it for shipping. * * @param orderId String Order identifier * @return void * @exception RemoteException if there is * a communications or systems failure */ public void completeOrder (String orderId) throws RemoteException; } The EJB specification describes the EJBLocalObject and EJBObject interfaces and indicates that the container generates an object that implements one of these interfaces for every bean instance, depending on the type of client accessing the bean instance. The container performs the prerequisite services, such as checking security, possibly starting a transaction, getting an instance of the bean from the pool, and so on. The vendors have some flexibility in how they implement this functionality. A question that comes up very often is, does the container create an EJBLocalObject or EJBObject for every bean instance? If it does, how will an EJB application scale? Well, the answer to this question is the one that EJB developers hear all the time, it depends on the vendor's implementation. For example, the EJB servers from JBoss and Sybase don't create EJBObject s at all. The container intercepts the call from the stub using a type of dispatch design (like the dispatcher from OMG's portable object adapter [POA] specification) and handles the call without using an EJBObject for the bean. If there are 10,000 clients, there will not be 10,000 EJBObject s. In fact, there might be no EBObject s at all with certain vendors. Of course these are details that a typical EJB developer should not be concerned with, other than evaluating performance results for the vendor. The point to get clear is that certain concepts that seem concrete in the EJB specification are meant to be abstract, and the vendors have wiggle room to optimize as they see fit. |