The EJB Server component lifecycle is designed to:
Maximize sharing and reuse of server resources
Minimize the possibility that a client application can monopolize server resources
To achieve these goals, EJB Server supports the concepts of component instance pooling and early deactivation.
Instance pooling allows a single component instance to service multiple clients. The component lifecycle contains activation and deactivation steps: Activation binds an instance to an individual client; deactivation indicates that the instance is unbound. Instance pooling eliminates resource drain from repeated allocation of component instances.
Early deactivation allows a component’s methods to specify when deactivation occurs. Early deactivation prevents a client application from tying up the resources that are associated with a component instance and allows the instance to serve more clients in a given time frame.
A component that is deactivated after each method call and supports instance pooling is said to be a stateless component because the component’s state is reset across the boundary of a transaction and activation. Early deactivation and instance pooling promotes greater scalability by enabling an increasing number of clients to use a static number of instances. An application design based on stateless components offers the greatest scalability.
Generic component lifecycle EJB Server components in any component model follow the state diagram illustrated in this figure:
Figure 5-1: States in the EJB Server component lifecycle
The state transitions are as follows:
New instance The EJB Server runtime allocates a new instance of the component. The instance remains idle in the instance pool waiting for the first method invocation.
Activation Activation prepares a component instance for use by a client. Once an instance is activated, it is bound to one client and can service no other client until it has been deactivated. If a component is transactional, activation also indicates the beginning of the instance’s participation in a transaction.
In method In response to a method invocation request from the client, the EJB Server runtime calls the corresponding method in the component. The next state depends on which of the transaction state primitives the method calls before returning. (The state transition also depends on whether the method returns with an uncaught exception.) See “Using transaction state primitives” for more information.
Deactivation Deactivation indicates that the component is no longer bound to the client. Methods can call either the completeWork or rollbackWork transaction state primitives to cause explicit deactivation of the instance. As discussed in “Using transaction state primitives”, these primitives also affect the transaction’s outcome. Deactivation can also occur automatically, under any of the following circumstances:
If the instance is participating in a transaction, the instance is deactivated when the transaction commits, rolls back, or times out.
If you have configured the component’s Instance Timeout property to a finite setting, an instance is deactivated if the time between consecutive method calls exceeds the timeout value. “Resources tab component properties” describes how to configure this property.
Destruction Destruction occurs if the component instance cannot be recycled. “Supporting instance pooling in your component” describes how to ensure instance reuse. If the component cannot be reused, deactivation is followed by destruction of the instance.
The EJB Server component lifecycle allows component instances to be recycled; idle component instances can be cached when idle and bound to the service of individual clients only as needed. If your component has been coded to support early deactivation, a client holding a reference to the component’s stub or proxy object may be serviced by several different instances of the component. After each deactivation, the next method invocation causes an instance to be activated and bound to the client. Overall server scalability is increased because a new instance does not have to be instantiated each time a client invokes a method.
Instance pooling eliminates resource drain caused by repeated allocation of new component instances.
For Java components, you can implement a lifecycle-control interface to control whether the component instances are pooled. These interfaces also provide activate and deactivate methods that are called to indicate state transitions in a component instance’s lifetime. For more information on these interfaces, see the following sections:
Java components can implement the interface jaguar.beans.enterprise.ServerBean.
To support instance pooling, code that responds to activation events must restore the component to its initial state (that is, as if it were newly created). The Java interface has methods that allow an instance to selectively refuse pooling: canReuse in Java.
When the component Pooling option is set in EJB Server, the Java canReuse method is not called, even if the component implements the ServerBean Java interface.
A component that can remain active between consecutive method invocations is called a stateful component. A component that is deactivated after each method call and that supports instance pooling is said to be a stateless component. Typically, an application built with stateless components offers the greatest scalability.
Stateful components A stateful component remains active across method calls.
Since deactivation happens at the mercy of client applications, you may wish to configure the Instance Timeout property for stateful components so that a client cannot monopolize a component instance indefinitely. See “Resources tab component properties” for more information.
Stateless components In order for a component to be stateless, both of the following must be true:
You have configured or implemented the component to be deactivated after every method invocation. In the Adaptive Server plug-in, you can enable the Automatic deactivation / demarcation property for the component (located on the Transactions tab in the Component Properties window). Alternatively, you can implement the component so that it calls either completeWork or rollbackWork in every method.
You have enabled the Pooling option in the Component Properties window (this option is located on the Instances tab).
Stateless components cannot use instance-specific data to accumulate data between method invocations.
Some situations require that you accumulate data across method invocations. For example, a PurchaseOrder component might have an addItem() method that is called repeatedly to specify the contents of an order. In lieu of instance-specific data, you can use one of these alternatives to accumulate data:
Accumulate data in the database Use connection caching and database commands to accumulate data in the database. This is the preferred technique.
Accumulate data in the client Create a data structure that is passed to each method invocation and contains all accumulated data. This technique is only practical if the amount of data is small. Sending large amounts of data over the network will degrade performance.
Accumulate data in a file If the accumulated data is small and represented by simple data structures, you can store the data in a local file.