Chapter 2: Understanding Transactions and Component Lifecycles
The EAServer 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, EAServer 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. To achieve early deactivation, you can code or configure your component as described in “Supporting early deactivation in your component”.
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 EAServer components in any component model follow the state diagram illustrated in this figure:
Figure 2-1: States in the EAServer component lifecycle
The state transitions are as follows:
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 EAServer runtime calls the corresponding method in the component. The next state depends on which of the transaction state primitives the method calls before returning. (For Java components, 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. “Component properties: Resources” describes how to configure this property.
If an exception occurs in a user transaction, you must call rollbackWork after catching the exception; otherwise, a transaction deadlock may occur in the database, which can cause client applications to fail.
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 EAServer 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.
Early deactivation prevents a client application from tying up the resources (such as connections) that are associated with a component instance.
EJB stateless session beans and entity beans support early deactivation by design. If you have coded the component according to the EJB specification, no additional code or configuration is required to run in EAServer.
For components of other types, there are several ways to support early deactivation:
Configure the component to implement a control interface as described “Configuring a control interface”. If using the CtsComponents::ObjectControl interface, you can enable the Stateless option on the Instances tab in the EAServer Manager Component Properties dialog box. If using another control interface, enable the Auto demarcation/deactivation option on the Transactions tab of Component Properties window (see “Component properties: Transactions” for more information). With the appropriate option enabled, the component is automatically deactivated after every method invocation.
Code your component to call one of the completeWork or rollbackWork transaction state primitives to cause explicit deactivation of the instance. This technique is useful when your design requires deactivation to occur after some, but not all, method invocations. If the component is transactional, the completeWork and rollbackWork primitives also affect the outcome of the transaction in which the component is participating. See “Using transaction state primitives” for more information.
Instance pooling eliminates resource drain caused by repeated allocation of new component instances.
For Java and ActiveX 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:
C++ or Java CORBA components can implement a control interface as described “Configuring a control interface”.
EJB components must implement EntityBean or SessionBean interface for lifecycle control. For more information, see Chapter 6, “Enterprise JavaBeans Overview.”
ActiveX components can implement the IObjectControl interface and the GetObjectContext method. See Chapter 2, “ActiveX C++ Interface Reference,” of the EAServer API Reference for details.
For PowerBuilder components, you can enable the Pooling option on the PowerBuilder wizard that you use to create your component. You can then write event scripts that respond to changes in an instance’s lifecycle. See the Application Techniques manual in the PowerBuilder documentation for more information.
For C and C++ components, you can enable instance pooling using EAServer Manager. Display the Instances tab in the Component Properties window, then select the Pooling option. This option also allows you to configure pooling for Java and ActiveX components that do not implement the ServerBean or IObjectControl interfaces, respectively.
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). Both the Java and ActiveX interfaces have methods that allow an instance to selectively refuse pooling: canReuse in Java, canBePooled in ActiveX. For PowerBuilder components, you can script the canBePooled event to selectively refuse pooling.
When the component Pooling option is set in EAServer Manager, the Java canReuse or ActiveX canBePooled method is not called, even if the component implements the ServerBean Java interface or IObjectControl ActiveX interface.
You can configure the component pooling properties to control how many instances are pooled, and to assign different components to a shared pool. For information on tuning these settings, see “Instance pooling” in Chapter 3, “Component Tuning,” in the EAServer Performance and Tuning Guide.
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 “Component properties: Resources” 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 EAServer Manager, 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 a remote database Use connection caching and database commands to accumulate data in a remote database. This is the preferred technique. If you deploy your component to a cluster, it may run on multiple servers and the database provides a central location available from all servers.
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.
|Copyright © 2005. Sybase Inc. All rights reserved.|