[ Team LiB ] |
EJB ContainerNow let's look at the heart of the any enterprise bean implementation: the EJB container. Sun's specification for Enterprise JavaBeans deals with the functions of the container provider in detail, and the defined component model is described in terms of the container's responsibilities with respect to each of the enterprise bean type. Container DefinedThe EJB container provides an operational environment for all the enterprise bean types discussed earlier. It represents the EJB runtime holder that resides within the scope of the EJB server, and is more of a logical entity than a physical resource. In the current specification, the server provider isn't differentiated from the container provider. There's no clear demarcation between the responsibility of the container and the server. The responsibility of the container can be summarized as follows:
The EJB component model is built on basic interfaces defined by the specification for different bean types. The EntityBean, SessionBean, and MessageDrivenBean are the respective interfaces for the Entity, Session, and Message-Driven beans. Figure 20.1 lists the bean classes for each of the EJB types and the functions they provide. The base interfaces define callback methods that the container invokes during various events such as the creation of new instance, removal of the bean, and so forth. The callback methods for all the bean interfaces enable bean developers to define application-specific logic to manipulate the bean based on its context. It isn't necessary for the bean developer to implement all the callback methods. All the methods are optional and can be left empty ({ /* do nothing */ }). We'll look at these interfaces and the related classes later in the chapter when we discuss the EJB implementation. Figure 20.1. EJB interfaces.Apart from the basic interfaces, the EJB specifications define a context interface: EJBContext. This interface gives access to the container's properties, the client information, and the bean's metadata. The EJB specification provides detailed subinterfaces for this context interface for each of the bean types: EntityContext for Entity beans, SessionContext for Session beans, and MessageDrivenContext for Message-Driven beans. Figure 20.2 describes the relationship between the EJB context classes and the bean implementations and also lists the available metadata functions. Figure 20.2. EJB context.The bean container contract also talks about the special JNDI namespace known as the environment naming context (ENC). The JNDI ENC forms an important part of the bean container contract. JNDI ENC allows an enterprise bean to interact with other beans and resources, such as JDBC data sources, and also provides access to environment entries (configuration data). We'll take a detailed look at the interfaces and their methods in the next three chapters when we deal with the three bean types in detail. Life Cycle ManagementSo far, we've looked at the different EJB types that cater to different enterprise application requirements and we've also briefly covered about the runtime environment that surrounds Enterprise JavaBeans. Enterprise business applications usually have a high-performance requirement coupled with the fact that there are limited resources at disposal for managing the millions of interactions between the clients and the EJB server. The EJB container has the responsibility for efficiently managing the resources for the EJBs by sharing resources such as threads, TCP socket connections, database resources, and so on. These resources can be increased to a certain extent as the number of clients increase, but doing so reaches a point of diminishing returns at which the resource increase has an adverse effect on the EJB server's performance. Most EJB servers, including WebLogic Server, support instance pooling and activation mechanisms for efficient resource management. The mechanism adopted depends on the bean type. We'll go over each of the mechanisms in this section of the chapter. Instance PoolingThe concept of instance pooling is not new. It has evolved over years of multitier application framework development. The concept provides an excellent answer for enhanced scalability requirements in enterprisewide business applications. A typical multitier enterprise application might involve many resources, including database connections, file handles, TCP IP socket connections, JMS connections, and other components. In an application server such as WebLogic Server, those resources are used by the various components being served by the container. As mentioned earlier, the EJB container, which forms an integral part of the application server, transparently provides all resource management functions to the user. Along with this function, it is also responsible for the life cycle operations of the EJBs deployed in the server environment. In other words, the EJB container is responsible for the instantiating the bean instance, invoking the instance on a client request, and removing the bean from memory. But the process of creation of a new bean instance is an expensive operation, and it therefore increases the performance overhead. This could be avoided if there were a mechanism by which the container could process a client request using a bean instance that's already in memory. Instance pooling allows EJB containers to cache bean instances in memory and use them for servicing client requests as they come, thereby avoiding the cost of creating a bean for every client request. A pool of bean instances can be used to service the client requests, and the number of instances can be fewer than the number of clients. This helps to reduce the resources needed for servicing all client requests. The reuse of EJB components is not limited to any particular bean type and can be used with Stateless Session beans and Message-Driven beans alike. Stateful session beans are not pooled and neither are active Entity beans: They're created as needed. Figure 20.3 describes the life cycle of a Stateless Session bean instance in an instance pool scenario. Figure 20.3. Bean instance pool life cycle.When the bean instance is in a pooled state, it's ready for use to handle a client request because the bean instance has already been instantiated and resides within the container. The pooled instances have no associated identity at this moment. As a response to a client request, a bean instance associated with an identity is linked to a client—this is the ready state of the bean. In this state, the bean instance can respond to client requests. After a client is done with an assigned bean instance, that bean instance is returned to the instance pool and can be used for other client requests. Instance SwappingMost EJB vendors leverage the concept of instance pooling in the implementation of Stateless Session beans. Because Stateless Session beans do not store any client state information, a method invocation corresponds to a complete task. The only dependency between method invocations might be the volatile data common to all Stateless instances, such as a log file handler or a database connection. Because all bean instances are equal, it does not matter to the client which bean instance responds to its request. This allows the container to swap bean instances from the pool between client requests. In a real-world scenario, there is a considerable lapse between the client method invocations that enables the EJB container to share the same bean instances between different clients. This allows for efficient use of bean instances and reduces the inactive periods between client requests. It also keeps the number of bean instances considerably less than the number of clients; that is, fewer bean instances are required to service more requests. WebLogic Server uses the free pool concept to improve the performance of Stateless Session beans and for pooled Entity instances used for home method invocations. The free pool is created from the value set for initial-beans-in-free-pool parameter at server startup. This parameter is configured in the WebLogic-based EJB configuration file (weblogic-ejb-jar.xml). This configuration file is explained in detail later in the chapter. Because this eliminates the creation of a new instance for the first few requests, the initial response time improves noticeably. The upper limit of the free pool is controlled by both the memory available and the max-beans-in-free-pool parameter in weblogic-ejb-jar.xml. The WebLogic EJB container swaps the instances from the pool for handling the client requests, as explained earlier. WebLogic Server processes all requests concurrently until all bean instances in the pool are active and the max-beans-in-free-pool limit has reached. These parameters are not applicable for Stateful Session beans. Message-Driven beans, like Stateless Session beans, can leverage the concepts of instance pooling and instance swapping, which allows them to process multiple requests concurrently. Message-Driven beans process messages from a specific destination that's configured at server startup. For example, messages arriving to a destination X can be processed by instances of the particular Message-Driven bean type at the same time. The EJB container takes responsibility for assigning a bean instance for every message. After the message is processed, the bean instance is returned to the free pool to process other messages. Instance Activation and PassivationStateful Session beans, unlike other bean types, maintain client state information between method invocations. A client-bean conversation may span across multiple method calls, and information about the conversation is stored at the bean instance associated with the specific client. The integrity of the conversational state is important for the successful completion of the client task. Stateful Session beans cannot use instance pooling because a bean instance is tied to a client for the life of the bean's service to the client. For efficient resource management, most EJB containers implement the passivation mechanism when dealing with Stateful Session beans. The passivation mechanism is a two-step process: passivation and activation. In the passivation step, the bean instance is dissociated from the associated EJB object and conversational state is persisted to a secondary storage. The bean has the occasion of cleaning up its state (freeing resources, storing transient data, keeping a handle to retrieve it, and so on) beforehand. Once the bean instance is persisted, the container can use the instance to process another client's request. Because the client executes the methods on the EJB object that communicates with the associated bean instance, the passivation process is totally transparent to the client. In the activation step, the instance is restored to that state relative to the EJB object. Activation happens when a returning client invokes a method on the passivated EJB object. The container has the responsibility of automatically retrieving the client's conversational state from secondary storage and associating it to the EJB object along with the instance variables assigned to the values equal to the data stored when it was passivated. Other state (resources and transient data) can be retrieved when the container notifies the bean of the activation. Sun's specification leaves the implementation of the activation mechanism to the vendor. WebLogic Server uses a caching mechanism for implementing the activation mechanism to improve the performance of Stateful Session beans. The cache stores active EJB instances that include the bean instances currently in use as well as the ones that were in use recently. When the EJB instance is present in the cache, it is still associated with the EJB object it was servicing. The cache size is controlled by the max-beans-in-cache deployment element of the WebLogic EJB configuration file (weblogic-ejb-jar.xml). Along with idle-timeout-seconds, the max-beans-in-cache parameter gives some control to the WebLogic administrator as to when the EJB container will passivate the bean instance to a secondary storage. If there is no pressure on the resources, WebLogic Server might avoid the passivation even if one of the conditions mentioned here is met. But an administrator can force passivation using the cache-type element in the weblogic-ejb-jar.xml file that's explained later in the chapter. The idle-timeout-seconds element controls the removal of the passivated bean; that is, whether it's permanently removed from the secondary storage. If the EJB deployer does not want the passivated bean to be automatically removed, idle-timeout-seconds should be set to 0. Finally, the EJB developer has to make sure that WebLogic Server can save all the instance variables relating to the client's conversational state. The container knows how to save
All variables that are transient are not serialized. The specification provides the ejbPassivate() and ejbActivate() callback methods for performing any custom cleanup operations, such as releasing or activating resources (for example, database connections) before the bean instance's passivation or activation. These resources can be restored in ejbActivate() if their connection attributes, or handles, are saved in ejbPassivate() in serializable variables. TIP In theory, passivation is a good idea. In practice, it's a waste of system resources precisely when the system needs those resources the most. But this has to be weighed against the cost at which this service is provided. Because RAM is cheap, a better idea is to make sure that the application has plenty of heap to work with. Also ensure that the cache settings are comfortably set up and thereby make sure that passivation is not needed. The callback method ejbPassivate() can be used to convey a message to the administrator suggesting to add more memory or look for memory-hogging process or procedures. Basic ServicesThe container is responsible for managing the different bean types that live within its environment from their creation to their eventual eviction. The container provides basic services that include concurrency, transactions, persistence, and security to all the deployed EJBs. The EJB server eliminates the management of these complicated services from EJB developers and enables them to concentrate on the implementation of the business logic. TransactionsIn an enterprise application, tasks are usually completed as units of work. Either all the tasks within a block complete or they are all thrown out. For instance, to execute a funds transfer between two bank accounts, the system should successfully withdraw funds from one account and deposit them into another account. If either of these two operations fails, the system should not make any change permanent to maintain data integrity. In an airline reservation system, the customer should not be charged for the ticket without making sure that she has been allotted a seat. This behavior is achieved by using transactions in enterprise systems. Transactions are dealt with in detail in Chapter 9, "Processing Transactions with the Java Transaction API." Their use is covered in the chapter context of JDBC (see Chapter 10, "Managing Database Connectivity Using JDBC"), Session beans (refer to Chapter 21, "Working with Session Beans"), Entity beans (see Chapter 22, "Working with Entity Beans"), and so on. Transaction support is one of the most important features offered by the EJB container. In this section, we take a detailed look at the transaction features that the WebLogic Server container provides for EJBs and how you can control them. Most of these features are common for all the EJB types, so we'll look at them together. Where relevant, we'll look at them separately to distinguish between behaviors in each case. The container takes care of handling all infrastructure features, such as transactions and security, thus enabling you to concentrate on the business functionality of the bean. If not for these features, you would have to demarcate transactions every time in your code, which is a distraction from the main task for your bean. Beans that make use of this feature of the container are said to have container-managed transactions. Although container management of transactions is a very useful feature, there are some cases in which you might not prefer this behavior. In such cases, you can take complete control of transaction management within the bean. Such beans are said to use bean-managed transactions. Container-Managed TransactionsWhen managing transactions with the container, which is also known as declarative transaction management, the transactional behavior of EJBs is controlled by the transaction deployment elements of the deployment descriptors. The container uses these attributes to provide transactional facilities for each method of the bean. Therefore, when any change is required in the transactional behavior, all you have to do is alter the descriptors—you don't have to change the source code. This provides for easier maintainability of your application. Also, the same bean can now be deployed in different applications with different transactional attributes. A WebLogic Server container enables you to control transactional support within a bean at a method level. Now let's look at the transaction attribute and the predefined values that define transactional behavior. This attribute can take six values in all. They are
The transactional attribute behavior described earlier can be tabularized to provide a clearer perspective. For all cases in which the action states that the client transaction was suspended, the transaction is resumed when the method returns control to the container. Wherever new transactions are started, the scope of the new transaction ends when the method returns to the container. This perspective can be seen in Table 20.2.
In cases where the container begins a transaction for the bean, it monitors your bean method for transactional support. In such cases, the container always commits it, even if there's an application exception, except in these cases:
Alternatively, if the client started the transaction, the container doesn't commit or roll back the transaction. The following rules apply in that case:
As mentioned earlier, transaction attributes can be set at a method level. The attribute used for a method is the most specific attribute that has been defined in the EJB deployment descriptor (ejb-jar.xml). We'll look at how transaction attributes are configured when we cover this deployment descriptor later in the chapter. NOTE WebLogic Server also enables you to define a custom timeout for transactions started by the container. That way, the container isn't waiting forever for the transaction to finish. You can do this by providing the timeout value in the WebLogic EJB configuration file (weblogic-ejb-jar.xml), which is explained later in the chapter. By default, the transaction timeout is set to thirty seconds. Refer to the following link for the BEA documentation on how to configure the <trans-timeout-seconds> element: http://edocs.bea.com/wls/docs81/ejb/reference.html#1072610. Bean-Managed TransactionsIn some occasions, the EJB developer might want to control the transaction management in the bean code and not use container-managed transactions. It is strongly advised that, wherever possible, container-managed transactions should be used rather than bean-managed transactions. This is because container-managed transactions clearly distinguish transactional behavior from business logic, thus enabling EJB developers or deployers to change either without affecting the other. This behavior is managed using the transaction type deployment element in the deployment descriptors. When this is done, the EJB developer should code the bean implementation to take care of transactions within it using the java.transaction.UserTransaction interface. For more information about the UserTransaction interface and how to use the Java Transaction Architecture, refer to Chapter 9. Just a quick note about client-initiated transactions: When a client that is already in an active transaction context invokes a bean-managed transaction, the container first suspends the client's transaction and then invokes the bean implementation. The container does this irrespective of whether the bean implementation starts its own transaction. ConcurrencyAs with other primary services, concurrency is interpreted differently for different bean types. This is mainly because of the nature of the bean types. That is, in the context of a Message-Driven bean, concurrency means processing multiple asynchronous messages simultaneously, whereas in the context of Session and Entity beans, concurrency is defined as multiple clients accessing the same bean at the same time. Session beans do not allow for concurrent access. Stateless Session beans are associated with only one client for the duration of the request being processed. A Stateful Session bean is associated with one client for the duration of the conversation, which could involve multiple interactions between the client and the server. An Entity bean, on the other hand, models real-world objects and has to be accessed concurrently by different clients. For a detailed description of this with respect to Entity beans, see Chapter 22. Concurrency in Message-Driven beans makes these bean types more powerful and enables a high-performance component model. ClusteringIn some critical business applications, system failures even for a little while are not acceptable. Today, most applications are so critical that they're required to be supplemented by multiple copies of the application running in different machines so that even if one copy fails, another copy can take over and complete the task. The process of executing several copies of the same application on more than one machine, with all of them supplementing each other and providing reliable service, is known as clustering. Clustering also plays a vital role in improving the scalability of your enterprise. You can increase the capacity of the cluster at any time by adding more copies of your application and/or more hardware into your cluster. For more information on clustering a WebLogic Server deployment, including the benefits it provides for deployed Enterprise JavaBeans, see Chapter 36, "Installing, Configuring and Deploying WebLogic Server Clusters." NamingSince EJB specification 1.1, a new concept known as the environment naming context has been introduced between the bean and the container. The ENC is a JNDI context, which is specific to each bean, and isn't shared across the server. This ENC defines the environment under which the bean is deployed and is running. The JNDI ENC can be used to access references and environment entries, which contributes to making EJBs portable and flexible. This applies to all bean types. We'll cover some basic examples when we talk about EJB configuration files later in the chapter. The EJB specification requires the use of JNDI to look up the deployed beans. For a detailed explanation of looking up the beans in the JNDI, refer to Chapter 8, "Naming and Directory Services with JNDI". Enterprise JavaBeans require the EJB developer to use the PortableRemoteObject.narrow() method to cast the object returned from the JNDI lookup; that is, cast the remote object references to the appropriate type. We'll look at this function and all the details about the implementation of an EJB in the next three chapters. PersistenceThis primary service offered by the container is mostly linked with Entity beans, although Stateful Session beans need persistence services when a bean instance is passivated. As earlier mentioned, Entity beans, such as customers and gate agents (as in an airline reservation system), need to be stored in a permanent store to satisfy the durability requirements of these entities. An Entity bean, as defined earlier, provides two kinds of persistence: container-managed and bean-managed persistence. In the case of container-managed persistence, the container takes responsibility for synchronizing the Entity bean's fields to the corresponding database fields. When the persistence is bean-managed, the bean developer has to take care of implementing the logic for synchronizing the data fields in the Entity bean to the corresponding database fields. The specification provides two callback methods as part of the Entity bean—ejbStore() and ejbLoad()—for persisting and retrieving durable data, respectively. Figure 20.1 described all the callback methods defined by the Entity bean interface. For container-managed persistence, the specification only imposes the rule on the EJB vendor to support persistence using these methods—the exact mechanism is left to the vendors themselves. The application server uses the ejbStore() and ejbLoad() methods to write and read data, respectively. These callback methods make sure that all transactional clients use the latest data from the persistent store. WebLogic Server provides several configuration elements in the WebLogic Server–specific EJB configuration files (weblogic-ejb-jar.xml and weblogic-cmp-rdbms-jar.xml) that enable you to configure persistence behavior. This is quite useful when for optimizing Entity beans. We'll go into greater detail on persistence in Chapter 22. SecuritySecurity is a key concern in any enterprise class business application. EJB has a transparent security framework that allows for securing EJB components with no or little code. The EJB specification addresses the authorization using deployment descriptor elements and supports authentication as well via IIOP. Authentication validates or verifies the user's identity. One common example of authentication is a username/password combination verified against a persistent data store. Although authentication provides a global verification of the user, it's insufficient if a user must be monitored as he navigates through the different components of the system. With EJB 2.0, the security mechanism can be implemented using the standard Java Authentication and Authorization Service (JAAS)—an integral part of the J2EE platform. This mechanism is in addition to IIOP authentication and is more flexible. Authorization enables EJB deployers to exercise control over the type of permissions that each user has. Authorization can be granular; that is, you can restrict a user's access to particular subsystems, data, and methods. Authorization can be enforced programmatically or declaratively. In the case of programmatic authorization, the security checks are built in the bean's business logic. For declarative security, the container performs the authorization with the help of the deployment descriptor elements defined in the various EJB descriptors. The main difference between the two authorization mechanisms is that the container takes care of verifying the user's authorization and permissions instead of the bean code. The deployment descriptor provides the method-permission element tag for securing the methods. The container takes care of generating security checks and the associated exceptions if the user identity fails the check. As with other services described earlier, declarative security makes a bean easier to maintain in terms of security because the roles and security policies can be changed without touching the bean code. But programmatic security plays a key role for complex security implementations in which certain bean instances have to be controlled separately from other instances belonging to the same class that cannot be done using declarative security. We'll look at some of the elements from the EJB configuration files that are related to security when we discuss them later in this chapter. At that time, we'll cover some of the common tags for all the EJB types. For a complete description of securing WebLogic-based applications including Enterprise JavaBeans, refer to Part VII, "WebLogic Server Security." |
[ Team LiB ] |