Chapter 3. Resource Management and the Primary Services

Chapter 2 discussed the basic architecture of Enterprise JavaBeans, including the relationship between the bean class, the component interfaces, the EJB object and EJB home, and the EJB container. These artifacts define a common model for distributed server-side components. But the common model for distributed objects isn’t enough to make EJB interesting or even particularly useful. EJB servers also manage the resources used by beans, and can manage thousands, even millions of distributed objects simultaneously. They must manage how distributed objects use memory, threads, database connections, processing power, and more. Furthermore, the EJB specification defines interfaces that help developers take advantage of these common practices.

In particular, EJB servers support six primary services: concurrency, transaction management, persistence, object distribution, naming, and security. These services provide the kind of infrastructure that is necessary for a successful three-tier system. Enterprise JavaBeans also supports two additional services: asynchronous messaging and a timer service.

This chapter discusses the resource-management facilities and the primary services that are available to Enterprise JavaBeans.

Resource Management

A large business system with many users can easily require thousands of objects—even millions of objects—to be in use simultaneously. As the number of interactions among these objects increases, concurrency and transactional concerns can degrade the system’s response time and frustrate users. EJB servers increase performance by synchronizing object interactions and sharing resources.

There is a relationship between the number of clients and the number of distributed objects that are required to service them. Not surprisingly, the larger the client population, the more distributed objects are needed. At some point, the increase in clients affects performance and diminishes throughput. EJB explicitly supports two mechanisms that make it easier to manage large numbers of beans at runtime: instance pooling and activation. In addition, EJB supports the use of the J2EE Connector Architecture (J2EE Connectors) for managing resource connections. As the number of distributed objects and clients increase, the number of resource connections also increases. J2EE Connectors work with the EJB container to manage connections to databases, enterprise messaging, ERP, legacy systems, and other types of resources.

Instance Pooling

The concept of pooling resources is nothing new. It’s common to pool database connections so that the business objects in the system can share database access. This trick reduces the number of database connections needed, which reduces resource consumption and increases throughput. The J2EE Connector Architecture (J2eeCA) is frequently the mechanism employed by EJB containers when pooling connections to databases and other resources, and is covered a little later. Most EJB containers also apply resource pooling to server-side components; this technique is called instance pooling. Instance pooling reduces the number of component instances—and therefore resources—needed to service client requests. In general, it is also less expensive to reuse pooled instances than to create and destroy instances.

As you already know, clients of session and entity beans interact with the beans through the remote and local interfaces implemented by EJB objects. Client applications never have direct access to the actual bean. Similarly, JMS clients never interact with JMS-based message-driven beans (JMS-MDBs) directly. They send messages that are routed to the EJB container system. The EJB container then delivers these messages to the proper message-driven instance.

Instance pooling is possible because clients never access beans directly. Therefore, there’s no fundamental reason to keep a separate copy of each enterprise bean for each client. The server can keep a much smaller number of enterprise beans around to do the work, reusing each enterprise bean instance to service different requests. Although this sounds like a resource drain, when done correctly, it greatly reduces the resources required to service all the client requests.

The entity bean life cycle

To understand how instance pooling works, let’s examine the life cycle of an entity bean. Entity beans exist in one of three states:

No state

When a bean instance is in this state, it has not yet been instantiated. We identify this state to provide a beginning and an end for the life cycle of a bean instance.

Pooled state

When an instance is in this state, it has been instantiated by the container but has not yet been associated with an EJB object.

Ready state

When a bean instance is in this state, it has been associated with an EJB object and is ready to respond to business method invocations.

Each EJB vendor implements instance pooling differently, but all instance-pooling strategies attempt to manage collections of bean instances so that they are quickly accessible at runtime. To set up an instance pool, the EJB container creates several instances of a bean class and holds them until needed. As clients make business-method requests, bean instances from the pool are assigned to the EJB objects associated with the clients. When the EJB object doesn’t need the instance, it’s returned to the instance pool. An EJB server maintains instance pools for every type of bean deployed. Every instance in an instance pool is equivalent—they are treated equally. Instances are selected arbitrarily from the instance pool and assigned to EJB objects as needed.

After the bean instance is placed in the pool, it gets a reference to a javax.ejb.EJBContext. The EJBContext provides an interface that the bean can use to communicate with the EJB environment. This EJBContext becomes more useful when the bean instance moves to the Ready state. When a client uses an EJB home to obtain a remote or local reference to a bean, the container responds by creating an EJB object. Once created, the EJB object is assigned a bean instance from the instance pool. When a bean instance is assigned to an EJB object, it officially enters the Ready state. From the Ready state, a bean instance can receive requests from the client and callbacks from the container. Figure 3-1 shows the sequence of events that results in an EJB object wrapping a bean instance and servicing a client.

A bean moves from the instance pool to the Ready state

Figure 3-1. A bean moves from the instance pool to the Ready state

When a bean instance moves into the Ready state, the EJBContext takes on new meaning. The EJBContext provides information about the client that is using the bean. It also provides the instance with access to its own EJB home and EJB object, which is useful when the bean needs to pass references to itself or to other enterprise beans, or when it needs to create, locate, or remove beans of its own class. So the EJBContext is not a static class; it is an interface to the container, and its state changes as the instance is assigned to different EJB objects.

When the client is finished with a bean’s remote reference, either the remote reference passes out of scope or one of the bean’s remove methods is called.[10] At this point, the bean instance is disassociated from the EJB object and returned to the instance pool. Bean instances can also be returned to the pool during lulls between client requests. If a client request is received and no bean instance is associated with the EJB object, an instance is retrieved from the pool and assigned to the EJB object. This is called instance swapping. After the bean instance returns to the instance pool, it is again available to service a new client request. Figure 3-2 illustrates the life cycle of a bean instance.

Life cycle of a bean instance

Figure 3-2. Life cycle of a bean instance

The number of instances in the pool fluctuates as instances are assigned to EJB objects and returned to the pool. The container can also manage the number of instances in the pool, increasing the count when client activity increases and lowering the count during less active periods.

Instance swapping

Stateless session beans offer a particularly powerful opportunity to leverage instance pooling. Because a stateless session bean does not maintain any state between method invocations, every method invocation operates independently, performing its task without relying on instance variables. This means that any stateless session instance can service requests for any EJB object of the proper type. The container can therefore swap bean instances in and out between method invocations.

Figure 3-3 illustrates instance swapping between stateless session bean method invocations. In Figure 3-3 (a), instance A is servicing a business method invocation delegated by EJB object 1. Once instance A has serviced the request, it moves back to the instance pool (Figure 3-3 (b)). When a business method invocation on EJB object 2 is received, instance A is associated with that EJB object for the duration of the operation (Figure 3-3 (c)). While instance A is servicing EJB object 2, another method invocation is received by EJB object 1 from the client and is serviced by instance B (Figure 3-3 (d)).

Stateless session beans in a swapping strategy

Figure 3-3. Stateless session beans in a swapping strategy

Using this swapping strategy allows a few stateless session bean instances to serve hundreds of clients, because the amount of time it takes to perform most method invocations is typically much shorter than the pauses between method invocations. When a bean instance is finished servicing a request for an EJB object, it is immediately made available to any other EJB object that needs it. This allows fewer stateless session instances to service more requests, which decreases resource consumption and improves performance.

Stateless session beans are declared “stateless” in the deployment descriptor. Nothing in the class definition marks a session bean as being stateless or stateful. Once a bean class is deployed as stateless, the container assumes that no conversational state is maintained between method invocations. So a stateless bean can have instance variables, but because bean instances can be servicing several different EJB objects, they should not be used to maintain conversational state.

Message-driven beans and instance pooling

Message-driven beans, like stateless session beans, do not maintain state specific to a client request, which makes them excellent candidates for instance pooling.

In most EJB containers, each type of message-driven bean has its own instance pool that services incoming messages. JMS-MDBs subscribe to a specific message destination, which is a kind of address used when sending and receiving messages. When a JMS client sends an asynchronous message to a destination, the message is delivered to the EJB containers of the beans that subscribe to the destination. The EJB container determines which JMS-MDB subscribes to that destination, then chooses an instance of that type from the instance pool to process the message. Once the JMS-MDB instance has finished processing the message (when the onMessage( ) method returns), the EJB container returns the instance to its instance pool. Figure 3-4 illustrates how client requests are processed by an EJB container.

JMS-MDB instance pooling

Figure 3-4. JMS-MDB instance pooling

In Figure 3-4 (a), the top JMS client delivers a message to Destination A and the bottom JMS client delivers a message to Destination B. The EJB container chooses an instance of MessageDrivenBean_1 to process the message intended for Destination A and an instance of MessageDrivenBean_2 to process the message intended for Destination B. The bean instances are removed from the pool and used to process the messages.

A moment later in Figure 3-4 (b), the middle JMS client sends a message to Destination B. At this point, the first two messages have already been processed and the container is returning the instances to their respective pools. As the new message comes in, the container chooses a new instance of MessageDrivenBean_2 to process the message.

JMS-MDBs are always deployed to process messages from a specific destination. In the above example, instances of MessageDrivenBean_1 process messages only for Destination A, while instances of MessageDrivenBean_2 process messages only for Destination B. Several messages for the same destination can be processed at the same time. If, for example, a hundred messages for Destination A arrive at the same time, the EJB container simply chooses a hundred instances of MessageDrivenBean_1 to process the incoming messages; each instance is assigned a message.

EJB 2.1 has expanded the role of message-driven beans beyond JMS so that they can support other messaging services and APIs. This opens the message-driven bean up to just about any kind of resource, including messaging systems other than JMS, ERP systems like SAP, and legacy systems like IMS. Regardless of the type of resource represented by the message-driven bean, the instances of the bean type will be pooled in the same way as the JMS-MDBs.

The Activation Mechanism

Unlike other enterprise beans, stateful session beans maintain state between method invocations. Conversational state represents the continuing conversation with the stateful session bean’s client. The integrity of this conversational state needs to be maintained for the life of the bean’s service to the client. Stateful session beans, unlike stateless session, entity, and message-driven beans, do not participate in instance pooling. Instead, stateful session beans use activation to conserve resources. When an EJB server needs to conserve resources, it can evict stateful session beans from memory. When a bean is evicted, its conversational state is serialized to a secondary storage. When a client invokes a method on the EJB object, a new stateful instance is instantiated and populated with the state from the initial bean.

Passivation is the act of disassociating a stateful bean instance from its EJB object and saving its state. Passivation requires that the bean instance’s state be held relative to its EJB object. After the bean has been passivated, it is safe to remove the bean instance from the EJB object and evict it from memory. Clients are unaware of the deactivation process. Remember that the client uses the bean’s remote reference, which is implemented by an EJB object, and therefore does not directly communicate with the bean instance. As a result, the client’s connection to the EJB object can be maintained while the bean is passivated.

Activating a bean is the act of restoring a stateful bean instance’s state relative to its EJB object. When a method on the passivated EJB object is invoked, the container automatically creates a new instance and sets its fields equal to the data stored during passivation. The EJB object can then delegate the method invocation to the bean as normal. Figure 3-5 shows activation and passivation of a stateful bean. In Figure 3-5 (a), the bean is being passivated. The state of instance B is read and held relative to the EJB object it was serving. In Figure 3-5 (b), the bean has been passivated and its state preserved. Here, the EJB object is not associated with a bean instance. In Figure 3-5 (c), the bean is being activated. A new instance, instance C, has been instantiated and associated with the EJB object and is in the process of having its state populated with the state held relative to the EJB object.

The passivation and activation processes

Figure 3-5. The passivation and activation processes

The exact mechanism for activating and passivating stateful beans is up to the vendor. Each stateful bean is serializable and thus provides at least one way of preserving its state, but vendors are free to choose other serialization techniques. Note that the transient property is not treated as you might expect when activating a passivated bean. In Java serialization, transient fields are always set to the initial value for that field type when the object is deserialized. Integers are set to 0, Booleans to false, object references to null, and so on. In EJB, transient fields are not necessarily set back to their initial values but can maintain their original values, or any arbitrary value, after being activated. Take care when using transient fields, since their state following activation is implementation-specific.

The activation process is supported by the life-cycle callback methods discussed in Chapter 2. The ejbActivate( ) method i activation callback methodss called immediately following the successful activation of a bean instance, and can be used to reset transient fields to an initial value. ejbPassivate( ) is called immediately prior to passivation of the bean instance. These two methods are especially helpful if the bean instance maintains connections to resources that need to be closed or freed prior to passivation and reobtained following activation. Because the stateful bean instance is evicted from memory, open connections to resources are not maintained. The exceptions are remote references to other beans and the SessionContext, which must be maintained with the serialized state of the bean and reconstructed when the bean is activated. EJB also requires that the references to the JNDI environment context, component interfaces, and the UserTransaction object be maintained through passivation.

Unlike stateful beans, entity beans do not have conversational state; instead, the state of each entity bean instance is saved in the database. However, the activation callback methods (ejbActivate( ) and ejbPassivate( ) ) are used to notify the instance when it’s about to be swapped in or out of the instance pool. The ejbActivate( ) method is invoked immediately after the bean instance is swapped into the EJB object, and the ejbPassivate( ) method is invoked just before the instance is swapped out.

J2EE Connector Architecture

The J2EE Connector Architecture defines an interface between Enterprise Information Systems (EISs) and J2EE container systems (i.e., EJB and Servlet containers). EIS is a generic term for any information system, including relational database servers, message-oriented middleware (e.g., MQSeries and SonicMQ), CORBA, ERP systems (e.g., SAP, PeopleSoft, and JD Edwards), and legacy systems (e.g., IMS and CICS).

J2EE defines a number of standard enterprise APIs, including JDBC, JMS, JNDI, Java IDL, and JavaMail, in addition to EJB. Each of these APIs provides a vendor-neutral API for a specific kind of enterprise information system. JDBC is used to exchange information with relational databases; JMS is for message-oriented middleware; JNDI is for naming and directory services; JavaMail is for electronic mail systems; and Java IDL is for CORBA. Requiring support for these APIs ensures that the enterprise beans that use them are portable across EJB vendors.

Although the enterprise APIs are vendor-agnostic, the products behind the APIs are always proprietary. When an enterprise bean uses the enterprise APIs, it’s the responsibility of the EJB container to pool and maintain the EIS connections, enroll the EIS in transactions, propagate security credentials, etc. These tasks often require the EJB container to interact with the underlying EIS in ways not addressed by the generic APIs. In effect, each J2EE vendor had to write proprietary code to manage each brand of EIS. Faced with this situation, J2EE vendors chose which EISs they would support for each standard API. This situation had a significant impact on the brands of EIS an EJB vendor could be expected to support: for example, vendor A might support JDBC connectivity to Oracle, while vendor B supports only DB2.

J2EE Connectors 1.0 for EJB 2.0 and 2.1

EJB 2.0 required support for the new J2EE Connector Architecture, which went a long way to solving this problem. The J2eeCA defines an interface between enterprise information systems and EJB containers. It establishes a set of Java interfaces that the EIS must implement in order to be J2EE Connector-compliant. These interfaces define a very general and portable Service Provider Interface (SPI) for creating EIS connections, managing connections in a pool, enrolling connections into transactions, and exchanging security information. The J2eeCA essentially hides the differences between proprietary infrastructures so that EJB container vendors can develop one set of code to manage all J2eeCA-compliant EISs.

While the J2eeCA standardizes the SPI, it has little or no impact on the APIs that you, the developer, use. A JDBC provider (a.k.a. driver) that is J2eeCA-compliant has the same API as one that’s not. From the perspective of the application developer, nothing’s changed, but under the hood of the EJB container, a single set of code can be used to manage all EISs. The benefit is that you can plug any J2eeCA-compliant EIS into your EJB container system. You don’t have to worry about the EIS vendor you choose: as long as its API is J2EE Connector-compliant, it will work with any EJB 2.0 or 2.1 vendor.

While Version 1.0 of the J2EE Connector Architecture solved some important problems, it didn’t support the push model for messaging. Several EISs push data to clients, without the clients explicitly making a request—for example, JMS. JMS allows clients to receive messages by subscribing to a destination. In this case, the EIS, the message-oriented middleware, is pushing messages to the clients.

J2EE Connectors 1.5 for EJB 2.1

EJB 2.1 requires support for J2EE Connector Architecture 1.5, which also supports the push model. To support the push model, J2eeCA 1.5 uses the message-driven bean programming model. Specifically, it defines a container-connector interface that allows incoming messages, sent asynchronously from the EIS, to be processed by message-driven beans. For example, vendor X could develop a J2EE Connector for a Mail Delivery Agent (MDA), which is software that delivers Internet email. Vendor X defines a message-listening interface, the EmailListener, that can be implemented to create an Email Message-Driven Bean (Email-MDB) for processing email. As the MDA receives email from the Internet, it pushes them to the EJB container, which delegates each message to an instance of the Email-MDB. The application developer then writes an Email-MDB that implements the javax.ejb.MessageDrivenBean interface as well as the com.xvendor.EmailListener interface. Once the Email-MDB is created and deployed, it can process incoming messages.



[10] The EJBHome, EJBLocalHome, EJBObject, and EJBLocalObject interfaces all define methods that can be used to remove a bean.

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

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