Unit of Work Options


One of the key features of any application server is support for transactions. Applications use transactions when interacting with resource managers. Transactions are normally started and ended around a set of one or more interactions with a resource manager. These interactions correspond to a Unit of Work for which the business demands that, either all changes are made to the backend resource manager or none are made at all. A single transaction can actually involve one or more resource managers. In the case of more than one resource manager, a global transaction is used. A global transaction means that the transaction is coordinated by an external coordinator rather an individual resource manager.

The application server plays this role of coordination for global transactions. When more than one resource manager is involved, this is also referred to as a two-phase commit transaction, requiring both the underlying resource manager and the application server to support specific interaction protocols. A transaction can involve EJBs that are hosted in more than one application server process. When this occurs, it is referred to as a distributed transaction. A distributed two-phase commit transaction involves both resources from multiple resource managers and multiple application server processes. This is the most complex transaction type that application servers will deal with.

The EJB specification defines a set of transactional policies that must be implemented and enforced by the application server. These describe what occurs upon commit and how to signal the beginning and ending of transactions. Individual beans can be set via the deployment descriptor in ways that allow the container to enforce and manage transactional operations. Transactions are important from the perspective of an application builder, and from the perspective of those who are implementing application servers that are J2EE compliant.

It is normally the case that entity beans, and potentially individual methods on entity beans, will be marked with a transaction attribute setting of Required, RequiresNew, or Mandatory. Stateful session beans with session synchronization follow a similar pattern.

Chapter 5 has some further discussion on transactions and transactional demarcation.

Session beans, or other J2EE code that drives these entity beans, may or may not have transactional settings or code specific to transactions. It is common to have a session bean manage the interactions with entity beans. In this case, the session bean can either be set up using the Bean-Managed Transaction (BMT) model or the Container-Managed Transaction (CMT) model. BMT implies that there is explicit code in the session bean logic to start, commit, and/or roll back transactions. This model involves using the Java Transaction APIs (JTA) directly. In the CMT model, methods on the calling session bean are also marked with transactional settings such as Required or RequiresNew. This model means that the container will start a transaction or cause the session bean to join an existing transaction without having any explicit transaction API calls in the code. BMT versus CMT is a topic for another discussion. For now, realize that in either case, there is an assumption that downstream entities support transactions.

Resource managers and transactions managers must support the JTA XAResource interface to be fully usable in the normal transactional modes described in the previous paragraph. Some resource managers are not fully compliant with the related X/Open XA standards, and are thus incapable of participating in a full two-phase commit distributed transaction. This fact presents a challenge to those wishing to use entity beans and enjoy the benefits of the EJB model as it relates to transactions.

WebSphere defines a fully compliant resource manager to be one that supports XA and full two-phase commit distributed transactions. Fully compliant means that global transactions can involve resources from different resource managers in the same two-phase commit transaction. However, many JDBC drivers and procedural systems do not support full two-phase commit-enabled distributed transactions. Transactions actually work fine for these resource managers and for the transaction settings described above as long as individual transactions do not span resource managers. This is because the transactional semantics required by the application can be honored when only one resource is enlisted in the transaction even when the resource manager does not fully support XA and the two-phase commit protocol. This optimization can be made by the application server.

It is very common, however, to wish to involve multiple resources, each from different resource managers in a single transaction. If the resource managers are not fully compliant, then using global transaction settings will lead to exceptions. Exceptions will arise, indicating that multiple resource managers, that are not two-phase commit compliant, are not allowed in a single global transaction.

Entity beans that are using datastores that are not fully compliant will sometimes have to be marked with transaction attribute settings of Never, NotSupported, or Supports. The EJB 2.0 specification, in section 12.1.6.1 states that:

When the NotSupported transaction attribute is assigned to a component interface method, the corresponding enterprise bean class method executes with an unspecified transaction context (See Subsection 17.6.5). This means that the container does not have any well-defined transaction boundaries to drive the ejbLoad and ejbStore methods on the instance.

It also states in a footnote that the same applies to the Never and Supports attributes.

The unspecified transaction context mentioned above is the key to the next part of the story. WebSphere Application Server does support these attributes and does document and support a specific behavior in this area where the specification is not specific. We will start by describing this in the next section and then move on to the ActivitySession Service, describing how this further extends WebSphere's support for resource managers that are not fully two-phase commit capable. We will also describe ActivitySession optimization opportunities. Finally, we will describe additional optimizations supported by the WebSphere Application Server that relate to transactions and resource managers.

Local Transactions Support

In the previous section, the use of the word transaction was generally unqualified. In this section, a distinction will be made. A global transaction is a transaction such as those we described in previous sections. It is the one that the specification for EJBs refers to when talking about demarcation of unit-of-work boundaries. Generally, it is what is expected when settings like Required are used on EJBs. Global transactions are also distributable transactions, meaning they can involve multiple application server processes also.

A local transaction then refers to the mechanism by which programmers, either declaratively or otherwise, deal with resource managers that are not fully two-phase commit enabled. Sometimes this involves programming syntax, as we will see in the upcoming section. Other times, local transactions just happen under the covers as part of how the container manages backend interactions. This section will further clarify and delineate the behavior of local transactions and contrast it to the global transaction concept.

The base WebSphere Application Server introduces the concept of local transaction containment to define the behavior in what the EJB specification calls the "unspecified transaction context". Local transaction containment support is an aggregating concept, encompassing all resources that might be accessed while in the "unspecified transaction context".

WebSphere defines a Resource Manager Local Transaction (RMLT) as a resource adapter's view of a local transaction. A resource adapter is the application server's internal wrapper or layer that talks to an external resource manager such as a database. To a resource adapter, an RMLT represents a unit of recovery on a single connection that is managed by the resource adapter. The resource adapter has interfaces, such as the javax.resource.cci.LocalTransaction that enable a bean or the container to request that the resource adapter commit or roll back its RMLT.

In WebSphere, when a method is being executed by the container in an "unspecified transaction context", there will be a Local Transaction Containment (LTC) in place. This is the container's view of what is going on when RMLTs are being used. The LTC defines the boundary at which all RMLTs must be complete and how any incomplete RMLTs are resolved. An LTC context is always established by the container in the absence of a global transaction, and thus it is the LTC that defines what really happens in the server when it is in "unspecified transaction context". An LTC is local to a bean instance and is not shared across beans even if those beans are managed by the same container, at least until the concept of ActivitySession is introduced.

To fully describe and elaborate upon what local transactions are meant for, we must begin using some examples assuming that there are no entity beans, assuming that there are no container-managed transactions, and that in fact, we are programming directly to the resource manager using connections and local transactions. There are a couple of styles that are prevalent here and usage will vary depending on whether or not this is a JDBC-based resource or one that is integrated into the server using the Java 2 Connector architecture.

Java 2 Connector Architecture (JCA)

The Java 2 Connector specification introduces the javax.resource.cci.LocalTransaction interface, which can be acquired from a connection. Any arbitrary code running in an EJB (session bean), or on the server in general (directly from a servlet perhaps), can make use of the interfaces described here. The key interfaces are:

  • javax.resource.cci.ConnectionFactory

  • javax.resource.cci.Connection

  • javax.resource.cci.ConnectionSpec

  • javax.resource.cci.LocalTransaction

These interfaces represent the basics used for acquiring and using connections via JCA Common Client interface (CCI). The CCI interface is used to communicate with Java 2 Connectors, retrieving, updating, creating, or deleting data from the specific backend that the connector encapsulates.

The general starting pattern for direct usage of the CCI involves something such as the following:

 // Obtain initial Naming Context   MyContext ic = new InitialContext();   javax.resource.cci.ConnectionFactory cf =      (javax.resource.cci.ConnectionFactory)       ic.lookup("java:comp/env/myEIS"); // Get a connection  javax.resource.cci.Connection conn =    (javax.resource.cci.Connection) cf.getConnection(); // Get an interaction    javax.resource.cci.Interaction interaction = conn.createInteraction(); 

The above code acquires the connection factory, gets a connection, and creates an interaction. The creation of an interaction is usually followed by the creation of Record instances using the RecordFactory create methods.

What is important from a unit-of-work perspective is that the work is scoped inside a local transaction. Somewhere after the initial sequence of code shown above there will be a sequence like this:

 javax.resource.cci.LocalTransaction localTran =   conn.getLocalTransaction(); localTran.begin();   // Run various execute() methods on the Interaction   interaction.execute(anInteractionSpec,aRecord);   //... localTran.commit(); // Or maybe  //... localTran.rollback(); 

At some point, when the connection is no longer needed, should be a conn.Close() statement to free up the connection.

JDBC Resources

Programming directly to the JDBC interfaces reveals a pattern similar to that described in the JCA section. The java.sql.Connection interface is used to manage the interactions with the JDBC-based resource manager. The following code snippet shows the acquisition of a connection and the subsequent usage of it:

 private java.sql.DataSource ds; private java.sql.Connection conn; private InitialContext ctx; private Statement stmt; ctx=new InitialContext(); ds=(DataSource)ctx.lookup("java:comp/env/datasource") conn=ds.getConnection();        // get a connection conn.setAutoCommit(false);      // requires user code to commit connection stmt = conn.createStatement(); ResultSet rs =    stmt.executeUpdate("UPDATE X.X SET VALUE = VALUE +10 WHERE \"KEY\"=99"); // additional code could go here dealing with the result set, more  // statements etc.. rs.close(); stmt.close(); if (transactionShouldBeCommitted) {   conn.commit(); } else {   conn.rollback(); } conn.close(); 

The key difference here is that there is no LocalTransaction interface, but rather the commit control is based on the presence of a connection. The local transaction is explicitly committed or rolled back through methods on the connection itself.

In both the JCA and JDBC cases, local transactions are used and the container manages these RMLTs using an LTC as described earlier. Remember that the LTC only spans a specific method and must be committed or completed when that method has completed.

The style of programming described here is one that is used outside the context of global transactions. Both the JCA and JDBC styles follow the same pattern. This pattern is prevalent in the presence of resource managers that do not fully support global transactions. It is also used when the overhead of a global transaction is deemed inappropriate. WebSphere takes some specific steps to ensure that this environment is safe with regards to connection and local transaction management. The next section begins describing WebSphere's specific support for these local transaction environments.

WebSphere Settings for Local Transactions

WebSphere has some very specific settings for ensuring proper management of local transaction environments. Some are applicable for the scenarios above and others are predicated upon ActivitySession semantics, which are described later. We will introduce all the settings here and will proceed to further elaborate upon the ActivitySession-related settings in upcoming sections.

There are extensions for EJBs and for both the EJB and web containers. This means that EJBs and servlets allow the following local transaction settings to be configured:

  • boundary
    The life of the containment boundary for which all RMLTs may be accessed is controlled by this setting. This can be set to either ActivitySession or BeanMethod. So far, we have only talked about local transactions outside the context of ActivitySession. The BeanMethod setting means that all RMLTs such as those shown in the previous examples must be resolved in the same method in which they were started. The ActivitySession setting will be described in upcoming sections of this chapter. The BeanMethod setting is the default setting.

  • resolution-control
    This indicates which component is responsible for initiating and ending the local transactions. The settings can be Application or ContainerAtBoundary. The Application setting means that specific code must be supplied in the application to start and complete the local transactions. In the JCA example described previously, this means that the localTransaction.begin() and localTransaction.commit() must be explicitly invoked in the code. ContainerAtBoundary on the other hand, implies that the container will actually start and complete the local transactions. This becomes useful in the presence of session beans and entity beans where we want to hide the complexity of dealing directly with the local transaction interfaces. This has additional use in the case where the boundary is set to ActivitySession. The default value for this setting depends on the transactional setting for the bean. Beans with CMTs will default the resolution-control setting to ContainerAtBoundary, while beans with a BMT setting will default to Application.

  • unresolved-action
    This can be set to Commit or Rollback. This indicates to the container what to do with methods containing local transactions, which are unresolved at the end of a method. This setting is looked at only when resolution-control is set to Application. A setting for Rollback, for example, would cause any unresolved local transactions left at the end of a method to be rolled back by the container. The default value here is Rollback.

If you have an EJB that is making direct and explicit calls to backend systems and managing local transactions directly, the following snippet would appear in the deployment descriptor extensions for the bean:

 <local-transaction>   <boundary>BeanMethod</boundary>   <resolution-control>Application</resolution-control>   <unresolved-action>Rollback</unresolved-action>   ... </local-transaction> 

This shows up in the AAT as follows:

click to expand

The Local Transactions settings are shown above for a session bean that is managing its own connections.

The WAS local transaction containment support, and its configurability through these three extended deployment descriptors (which are a part of the base application server), give the WAS application programmer who is using this direct style of programming to connections one key advantage: any local transactions that are not committed will be cleaned up by the container. This cleanup will happen according to the resolution control setting described above.

We will describe additional combinations of these settings and additional advantages in upcoming sections.

Container-Managed Interactions

The previous sections on JCA resources and JDBC resources have focused on a very direct and manual interaction style. The code segments that deal with these resource managers are very explicit and certainly not something that is desirable if we can get the container to manage some of this for us. A container-managed entity bean is in fact intended to transparently handle things like connections and transactions. Let's see how the container-managed concept might apply to EJBs that use these resource managers but do not fully support all of the necessary transactional semantics to let the standard global transaction based model assist us.

If an entity bean is marked NotSupported in WebSphere, then the local transaction containment support provided by the container will be used. Each method on a container-managed entity bean will have a local transaction containment environment in place during the execution of a method. This means that the programming style for entity beans shown below will work just fine.

  1. Find the home for the CMP entity

  2. Create a bean using the home

  3. Update CMP field x on the bean

  4. Update CMP field y on the bean

The good part of this style is that we treat these entities like all other container-managed entities. Transactions are not specifically started, connections are not programmatically acquired, and specific backend interactions are not observable in the Java code. The server does this work of getting connections, starting transactions, and managing the backend interactions.

The concern is that this style of interaction will involve two connections and effectively three local transactions for the sequence above. The first local transaction is for the create and there will be one each for the updates. Now you can see why you might be led back to the more manual interaction model that was previously described. Too many transactions will affect performance of the system. We want better support in the application server for CMP entities backed by these special resource managers.

In the above sequence, there is no global transaction started because the bean is not marked with a transactional setting that will cause the creation of a global transaction. This is good in this case, as there is no need for a global transaction. However, often there is a need to do interactions of the following pattern:

Globaltransaction.begin()   Touch bean1 of type1   Touch bean2 of type1 GlobalTransaction.commit()

If this is the case, then we can mark the type1 bean with a transactional setting of Required, RequiresNew, or Mandatory. As there is only a single resource manager being enlisted as part of a global transaction, this will work, even though the resource manager does not fully support the necessary transactional protocol. A single connection ends up being used in this case and things are once again looking as we want them.

Note

If we did not demarcate the above sequence with a global transaction then it would still probably work. There are many possible ways to configure applications to use global or local transactions. We cannot cover them all here.

However, not all is yet as flexible as we might want it to be. The following pattern, involving two CMP beans, each of a different type and thus having different connection factories or data sources, neither of which are fully transactional, demonstrates the next level of challenge in this area:

  CallingMethod begin      Touch bean1 of type1     Touch bean2 of type 2   CallingMethod end

Now if the beans are set with a transactional setting of Requires, then a global transaction could be started in the code or implicitly started by the calling method. In either case, involving a global transaction, we are heading for trouble. The execution of the method on the second bean will cause an exception to be thrown. This exception will indicate that we cannot have two bean types that do not fully support transactions in a single global transaction. The previous example worked because there was only a single resource manager involved in the transaction, and the global transaction was just a wrapper around what turned out to be a local transaction-based interaction to the backend systems. This example will not work with global transactions.

There are four ways to deal with this apparent problem with container-managed entities. These are:

  • Go back to the direct programming style of using connections and local transactions, and give up on container-managed entities for these kinds of resources.

  • Leave out the global transaction and let two separate local transactions run. Handling the exceptions or rollbacks here would be tricky, but doable.

  • Leverage the ActivitySession service described in the next section instead of the global transaction to get past the error and get more control over the error handling and coordination over the two local transactions.

  • Leverage Last Participant Support, which is described in an upcoming section.

The third and the fourth options are obviously desirable as they continue to allow us to use a higher level programming model and deal with container-managed entities instead of direct connections to the backend resource managers and have a centralized place to handle potential failures that occur when committing changes to the backend resource manager.

The ActivitySession Service

The ActivitySession service of WebSphere Application Server Enterprise introduces interfaces, which allow explicit programmatic or declarative scoping of units of work, which involve multiple non-two-phase capable resource managers. The ActivitySession service extends the WebSphere support for local transactions. An ActivitySession will allow an LTC to live longer than the enterprise-bean method in which it is started.

The ActivitySession service enables a different lifecycle for the EJB from that with existing J2EE mechanisms. ActivitySession becomes a new activation boundary. Normally, an entity EJB will be active in the EJB container for the duration of a transaction and then will be stored and passiviated at the end of a transaction. Subsequent interactions with the same bean will necessitate a reactivation and a reload in the EJB container. The ActivitySession Service changes this when it is active. It separates the load and store timing from the activation and passivation timing. Transactions still control the load and store, but now an ActivitySession controls the activation and passivation. This will be described in more detail, as we get further into this section. For now, realize that this has a number of ramifications and opportunities. From a unit-of-work perspective, you can have zero or more transactions executing within the scope of the ActivitySession. Resources may access data as part of a global transaction or an RMLT. The RMLT boundary can be either determined by the bean method or the ActivitySession. A new set of attributes for ActivitySessions is introduced for EJBs that look like transactional settings in many ways.

There is an <activity-session-type> deployment descriptor extension that can be set to either Bean or Container. This determines whether or not the container should be starting ActivitySessions, or relying upon the application code to do so.

The <activity-session-attribute> element can be at the bean or method level and can have the following settings that apply when the <activity-session-type> is contained:

  • Supports
    Any received ActivitySession context is retained on the thread of execution for method dispatch. If no ActivitySession is received, none will be created.

  • NotSupported
    Any received ActivitySession context is suspended for the duration of the method and resumed thereafter.

  • Never
    Any received ActivitySession context results in the InvalidActivityException being thrown.

  • Required
    Any received ActivitySession context is retained on the thread of execution for method dispatch. If no ActivitySession is received, one is created by the container.

  • RequiresNew
    Any received ActivitySession context is suspended for the duration of the method and resumed thereafter. A new ActivitySession is created for the method invocation.

  • Mandatory
    Any received ActivitySession context is retained on the thread of execution for method dispatch. If no ActivitySession is received, the exception InvalidActivityException is thrown.

The com.ibm.websphere.ActivitySession package defines the key interfaces that are used to programmatically leverage the ActivitySession service. The primary programming interface is the UserActivitySession and the key methods are beginSession() and endSession(). The endSession() method takes a parameter to indicated whether the session is to be check-pointed or reset. This will become clearer in the examples that will follow.

The following screenshot shows specifying ActivitySessions on a CMP entity bean in the AAT:

click to expand

Each method can have a different value. The example above shows all methods on the Order bean's remote interface being set to a value of ActivitySession Supports.

ActivitySession Programming – Implicit Local Transactions

This usage pattern for the ActivitySession Service is the one to consider if you are coming from a global transactions perspective and wish to enjoy the abstraction and simplicity of a global transaction type of model when dealing with resource managers that do not fully support the two-phase commit protocol. The following sequence of code is from a session bean. It uses the ActivitySession Service to scope a number of calls to a container-managed entity bean that is set with the following settings:

  • Activation policy set to ActivitySession – We will come back to this later with more details on this

  • The <boundary> for <local-transaction> is set to ActivitySession

  • The <resolution-control> for <local-transaction> is set to ContainerAtBoundary

  • The normal transactional policy is set to NotSupported

  • The <activity-session-type> is set to Container

  • The <activity-session-attribute> is set to Supports

The session bean itself is set to <activity-session-type> of Bean. The snippet of code starts a session, runs some methods on the entity bean, and ends the session. Ending the session provides each of the registered resources, in this case the bean1 and bean2 instances, the opportunity to complete or commit open RMLTs:

 InitialContext ctx  = new InitialContext(); UserActivitySession actSess = (UserActivitySession)   ctx.lookup("java:comp/websphere/UserActivitySession"); actSess.beginSession();       // start the session   int v1 = bean1.getValueI();   int v2 = bean2.getValueI();   int v3 = v1 + v2;   bean1.increment(v3);   bean1.setValue(v3); actSess.endSession(UserActivitySession.EndModeCheckPoint); 

The snippet above completes with the UserActivitySession.EndModeCheckPoint being the parameter to the endSession() method. This is one of the options for checkpointing and ending an ActivitySession, and most importantly the one that drives forward and completes any work that has been started during the ActivitySession. Each of the resources registered with the ActivitySession has the opportunity to complete or commit whatever outstanding work had been started. Failures encountered during the completion of the ActivitySession, or more properly, the committing of resources registered with the ActivitySession will cause the MixedOutcomeException to be thrown. The caller then can process the data in this exception to determine which resources succeeded and which failed, and write any necessary additional logic to handle inconsistencies.

UserActivitySession.EndModeReset is the other option for ending an ActivitySession. This causes the ActivitySession to reset or return to the last point of consistency.

ActivitySession Programming – Explicit Local Transactions

While the first "programming pattern" for the ActivitySession service keeps us in the container-managed entity space and achieves the maximum level of abstraction for those building J2EE applications, let's revert back to the direct programming style introduced earlier and observe one more problem and demonstrate how ActivitySessions can help us with this problem also.

If you paid careful attention to the example that described how to program directly to connections and directly to local transactions, you would have observed that these examples always showed direct inline usage of the interfaces necessary to manage and manipulate the backend resource managers. A JDBC example, just to restate it for clarity showed:

  1. Get a connection

  2. Retrieve using the connection

  3. Update using the connection

  4. Commit the connection

Without ActivitySessions, all four steps above, if they are to be in a single local transaction containment boundary, must be executed from a single method within the controlling J2EE application. The default setting, without ActivitySessions being involved at all, is to have boundary = BeanMethod for the local transaction setting.

The above pattern all works fine, but might not be a programming style that is easy to understand or maintain. A better design would involve factoring the steps above into separate methods on the session bean and even providing granular control over connections and local transactions.

Optimally in fact, it would be desirable to have callers (other session beans or perhaps servlets), which would have sequences of code in a method that deals with the resource manager that look something like:

x.GetConnection(...);          // Call method to get the connection x.BeginLT(...);                // Begin the local transaction x.RetrieveX(...);              // Get some data x.UpdateX(...);                // Update some values x.CommitLT(...);               // Commit the local transaction x.CloseConnection(...);        // Close the connection

The above sequence needs to run in an environment where a single ActivitySession covers whichever combination of methods the caller chooses to use. This means that our bean x needs to be configured to run with boundary = ActivitySession. This also implies that the calling code, either when the caller is a session bean or when it explicitly demarcates the ActivitySession boundary, can have the method that drives the interactions on x be set to an <activity-session-attribute> of Required.

This pattern provides additional flexibility over the management of local transactions, enabling the creation of more maintainable and understandable applications, while retaining the advantages of having precise control over backend interactions.

To summarize, the ActivitySession capability of WebSphere Application Server Enterprise provides two more advantages above those provided by the base WAS support for local transactions:

  • The use of RMLTs (otherwise called local transactions) is restricted, in the J2EE specifications, to single EJB methods. This is because the standard specifications have no scoping device, beyond a container-interposed method boundary, to which an RMLT can be extended. The ActivitySession is a distributed context that can be controlled by a client that provides a longer-than-method boundary over which such RMLTs can extend, reducing the need to use distributed transactions where coordinated operations on multiple resources are not required. This benefit is exploited through the boundary setting. Such extended RMLTs can remain under the control of the application, or remain managed by the container, depending on the use of the resolution control.

  • For resource managers that do not support XA transaction coordination, the exploitation of ActivitySession scoped LTCs gives a client the same ability to control the completion direction of those resource managers' resource updates as it has for transactional resource managers. A client can start a bean-managed ActivitySession and call its entity beans under that context. Those beans can perform their RMLTs within the scope of that ActivitySession and return without completing the RML(s). The client can control, through the UserActivitySession interface, whether those RMLTs should then be committed or rolled back.

Last Participant Support

While the ActivitySession Service provides us power and capabilities for dealing with resource managers that do not support full XA transactions, it does introduce some specific interfaces and requires a specific understanding of the various unit of work patterns that are used to accomplish business tasks. The Last Participant Support feature of WebSphere Application Server Enterprise, offers an additional option for dealing with some of these types of transactions.

The basic transactional capabilities within WebSphere Application Server provide coordination within a global transaction of multiple transactional resources. At transaction commit, if there is more than one resource enlisted in the transaction, or if the transaction has been distributed to another server, a two-phase commit procedure is used. As an optimization, a one-phase protocol is used if there is a single resource in a non-distributed transaction.

There is a clear customer requirement to allow use of these one-phase resources (which include the currently available CICS connector and many other JCA connectors) in transactions that also use true 2PC-capable resources such DB2 and Oracle. Last Participant Support satisfies this requirement.

To use Last Participant Support, it is necessary to:

  • Have WebSphere Application Server Enterprise version 5.0 installed, as this feature only exists in this package

  • Have all resources involved in the unit of work accessed within a global transaction

  • Ensure that the transaction is not distributed across multiple application servers (this restriction is expected to be lifted in future releases of WebSphere)

  • Configure the application to accept heuristic hazards

Heuristic is a term typically used in a transactional situation where a participant transaction manager makes a unilateral decision to commit or rollback, hopefully applying some intelligent heuristic approach to do so. This might happen if a participant transaction manager loses contact with the commit coordinator during commit processing. It knows the commit coordinator will return, but perhaps cannot wait for this happen. If, on a later reconnect, it turns out the participant transaction manager got it wrong, it raises a heuristic exception.

Configuring the application to accept heuristic hazards can be done in the AAT at the application level as shown below:

click to expand

WebSphere Application Server Enterprise Version 5.0 allows resource adapters to be configured as being incapable of accepting 2PC flows. These resource adapters can then be treated exclusively as 1PC resource adapters. Most resource adapter archives should already be properly set. However, if you are building a new resource adapter archive, it can be marked as Local Transaction in the AAT as shown at the bottom of the Resource Adapter screen:

click to expand

By using these settings, we can now enable a single 1PC resource to participate in a 2PC transaction. This allows normal transactional design and programming techniques to be applied to complex transactions that involve multiple resources, including a single 1PC resource.

What happens inside is that, at transaction commit, the 2PC resources will first be prepared using the 2PC protocol, and if this is successful, the 1PC resource will then be called to commit (one-phase). This gives the mechanism its commonly used name of "Last Participant Support" or LPS, where the single 1PC resource is the last agent to participate. The 2PC resources will then be committed or rolled back depending on the response of the 1PC resource. In the case where more than one 1PC resource is registered in the transaction, it will never get to commit processing. An exception is thrown upon attempting to register the second resource stating that you cannot registered multiple single-phase resources in a global transaction. If you have this requirement, then local transaction and ActivitySessions are your options, not global transactions.

Summarizing Transactions and ActivitySessions

How do we apply all of this functionality and information to our design and implementation of EJB applications? Well, there are some basic rules to follow:

  • Global Transactions
    Global transactions are good in many situations. They provide a consistent and simplified unit-of-work scoping mechanism that can be programmatically or declaratively described. They should be used whenever multiple operations need to be coordinated, assuming the underlying resource managers support the necessary transactional interfaces. Global transactions should generally be started either in session beans using BMT or via declaration in the session bean deployment descriptors. Using global transactions reduces the complexity of the application programming and abstracts away specific transaction programming styles. Global transactions cannot be used when it is expected that coordinating resources from multiple resource managers do not support full XA transactional semantics. Using Last Participant Support, the utility and elegance of global transactions can extend to include transactions that involve multiple resource managers where one and no more than one of those resource managers does not support full XA semantics.

  • Local Transaction Explicit Programming
    Use local transactions and explicit programming to backend systems, when encapsulation is not possible. Local transactions and direct programming to connections is complex. The WebSphere Application Server provides the <local-transaction> deployment descriptor extensions to provide some additional safety for these kinds of environments. Use ActivitySessions to factor these kinds of programs into layers of session beans and methods within beans. The ActivitySession can be declared in the deployment descriptor or directly programmed to support this explicit local transaction model.

  • ActivitySession Programming Model
    Use this style of interaction when maximum abstraction from resource managers is desired and global transactions are not possible or not necessary. Using the ActivitySession-based model lets programmers avoid knowledge of the local transaction programming model while still enabling a level of grouping of interactions to backend systems that is similar to that achievable in the presence of global transactions. The <local-transaction> settings of boundary being set to ActivitySession combined with the ActivitySession settings on the bean, servlet, or method level enable this style of programming. When a global transaction model is possible, but the full recoverable, distributed capability of global transactions is not necessary, the ActivitySession model can also be leveraged with expected performance gains.

Additional ActivitySession Service Opportunities

The ActivitySession service has been described so far in terms of unit-of-work scoping and how it can be leveraged in a variety of situations related to units of work. The ActivitySession Service also has utility as a performance improving technique within the application server. These situations are described in this section.

The ActivitySession service describes to the EJB container a lifecycle for components that differ from those that are generally found. Take the following scenario:

  1. ActivitySession begins (either declaratively or programmatically)

  2. Global Transaction1 begins (either declaratively or programmatically)

  3. Entity EJB1 is accessed or updated (forces an activate and load)

  4. Entity EJB2 is accessed or updated (forces an activate and load)

  5. Global Transaction1 is committed

  6. Global Transaction2 is begun

  7. Entity EJB1 is accessed or updated (forces a load but not an activate)

  8. Entity EJB2 is accessed or updated (forces a load but not an activate)

  9. Global Transaction2 is committed

  10. ActivitySession ends

Without the ActivitySession in place, the scenario above would involve the loading and activation of EJB1 and EJB2 for each global transaction. With the ActivitySession in place, EJB1 and EJB2 are activated only once and remain activated throughout the course of the ActivitySession. They are reloaded for Global Transaction2, but are not reactivated as they are still in the memory when Global Transaction2 starts. This will improve the performance of the application while maintaining the same transactional control over the underlying resources.

A number of application scenarios exist where a set of objects are activated in one transaction and perhaps updated in another. We are always taught to keep the duration of global transactions short, but this often means more transactions, and thus the possible inefficiency of reactivating objects multiple times to accomplish some piece of business function. ActivitySessions let us keep transactional units of work short while letting us gain the efficiency of relating resources used across multiple transactions.

Setting an EJB to have a passivation lifetime that exceeds a transactional boundary is done in the AAT as shown below:

click to expand

You can see that we have called this Commit option C+ to indicate that it is like option C, but that the beans will remain activated in the EJB container for the duration of the ActivitySession instead of the normal transaction boundary.

In applications that are driven by servlets or inbound HTTP requests, it is desirable to associate the length of the ActivitySession with the length of the HTTP Session. This is also possible, declaratively, with WebSphere. The following shows how to have an ActivitySession created for each HTTP Session:

click to expand

Setting the ActivtySession control kind to Container will cause an ActivitySession to automatically be created for each HTTP session. The default is None. Application means that the programmatic APIs for activity will be honored.




Professional IBM WebSphere 5. 0 Applicationa Server
Professional IBM WebSphere 5. 0 Applicationa Server
ISBN: N/A
EAN: N/A
Year: 2001
Pages: 135

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net