JCA 1.5, Part 1: Optimizations and life-cycle management

Connections get better and resource adapters take on a life of their own

In the first of a three-part series, Java developer David Currie introduces some Java™ 2 Enterprise Edition (J2EE) Connector Architecture (JCA) 1.5 optimizations that should make your existing or new outbound resource adapters go faster. He also takes a look at some additions that let resource adapters take on a new life of their own. This series is essential if you want to improve the performance of -- or add new functionality to -- existing resource adapters or are considering writing a new JCA 1.5 resource adapter. It should also be of interest if you write applications that use resource adapters and want to know a little more about what goes on behind the scenes.

Share:

David Currie, Staff Software Engineer, IBM UK Ltd.

David CurrieDavid Currie recently joined the IBM Software Services for WebSphere organization based in Hursley in the United Kingdom. Prior to that, he worked on the development of WebSphere Application Server, initially in the area of transactions, and most recently designing and implementing JCA resource adapters for messaging support. You can reach him at david_currie@uk.ibm.com.



05 April 2005

Also available in Russian Japanese

JCA 1.5, the latest version of the J2EE Connector Architecture, includes many important enhancements and some major additions. In this article, the first of a three-part series covering these changes, I'll introduce some optimizations that should make applications using outbound resource adapters run faster, particularly those using transactions. Then I'll take a look at extensions to the life-cycle management contract that should prevent applications from getting broken connections and enable resource adapters to take on a whole new life of their own. This will set the stage for Part 2, which will cover the new work-management and transaction-inflow contracts, and Part 3, which will examine the long-awaited message-inflow contract, better known as message-driven bean (MDB) support.

This article assumes a reasonable understanding of the JCA connection management contract. Everything in the original 1.0 specification still applies, so if you're new to JCA, I recommend that you first work through Willy Farrell's introductory tutorial (see Resources).

Lazy connections go faster

A new version of the JCA specification can't make the connection between an application and the back-end system any quicker, but JCA 1.5 does introduce two sets of interfaces that can make applications using connections run faster. The first set addresses limitations in the way application servers could manage connection handles under previous JCA versions.

As many of you are aware, J2EE supports two models of connection usage, which I'll refer to as get-use-close and cached-handle. A closer look at these models will help you understand the performance improvements JCA 1.5 brings in this area.

Get-use-close

In the get-use-close model, an application always obtains a new connection when it needs one, uses it, then closes it again, as shown in Listing 1. (For clarity, I haven't included exception-processing logic in the sample listings.)

Listing 1. An Enterprise JavaBean (EJB) using the get-use-close model
public class GetUseCloseEJB implements SessionBean {

    ...

    public void businessMethod() {

       InitialContext context = new InitialContext();
       DataSource dataSource = (DataSource)context.lookup("java:comp/env/jdbc/mydatasource");
       Connection connection = datasource.getConnection();

       ...

       connection.close();

    }

}

The get-use-close model might sound inefficient, but the connection pooling the application server implements should make the "get" operation cheap. And because the application holds on to the connection for only as long as it's needed, different instances or parts of the application can reuse the connection, thereby reducing the total resource usage. This is illustrated in Figure 1.

Figure 1. The get-use-close model in action
The get-use-close model in action

As Figure 1 shows, each time the bean method calls getConnection, the connection manager reuses a managed connection from the pool and creates only a new connection handle. When the connection handle notifies the connection manager that it has been closed, the managed connection is cleaned up and returned to the pool. The time that the managed connection is tied up with this instance of the application is indicated in Figure 1 by the green bars.

Cached-handle

In the cached-handle model, the application obtains the connection once up-front and caches a reference to it in an instance field, as illustrated in Listing 2.

Listing 2. The cached-handle model
public class CachedHandleEJB implements SessionBean {

    private Connection _connection;

    ...

    public void ejbCreate() {

       InitialContext context = new InitialContext();
       DataSource dataSource = (DataSource)context.lookup("java:comp/env/jdbc/mydatasource");
       _connection = datasource.getConnection();

    }

    public void businessMethod() {

       ...

    }

}

Application writers typically use the cached-handle approach because they believe the application will perform better. But because of the benefits of connection pooling under the get-use-close model, there's generally little performance difference between the two usage models. Although the cached-handle model makes the logic in the business method simpler, additional logic is required to close the connection on passivation and recreate it on activation. The possibility also exists that, if the bean should get destroyed by the container (for example, because a method has thrown a run-time exception) an open connection might be left dangling.

The biggest problem with the cached-handle model is that while one instance of the bean or servlet is holding on to the connection, another instance can't use it -- so you end up with at least as many connections as instances. This is shown in Figure 2.

Figure 2. The cached-handle model in action
The cached-handle model in action

You can see in Figure 2 that the managed connection is associated with the connection handle when the EJB is created (the start of the green bar) and is unusable by anything other than that bean instance thereafter. (The green bar continues indefinitely.)

The JCA 1.5 specification has addressed this issue by introducing the two new interfaces, shown in Listing 3.

Listing 3. Interfaces for dissociation and lazy association
public interface DissociatableManagedConnection {

    void dissociateConnections() throws ResourceException;

}

public interface LazyAssociatableConnectionManager {

    void associateConnection(Object connection,
                             ManagedConnectionFactory mcf,
                             ConnectionRequestInfo cxReqInfo)
            throws ResourceException

}

Dissociation

A resource adapter's managed connections implement the first interface -- the interface for dissociation -- to indicate to the connection manager that the adapter supports this optimization. When a connection goes temporarily out of scope (that is, when the bean or servlet method exits) the connection manager can, if it also supports the optimization, dissociate the connection handle held by the application from the managed connection that represents the physical resource. This lets the managed connection be returned to the pool for use by other parts of the application.

Lazy association

Rather than reassociating the connection handle with the managed connection the next time a method is called, the optimization uses lazy association. If the method doesn't use the connection, or it only calls simple methods on the connection handle that don't require access to the back end, a managed connection isn't removed from the pool unnecessarily. Instead, when the connection handle determines that it does need to be reassociated to a managed connection, it can cast the connection manager to a LazyAssociatableConnectionManager and call the associateConnection method. This method takes the connection handle as the first parameter, followed by the managed-connection factory, and requests information passed on the initial call to allocateConnection. The connection manager then finds another suitable managed connection from the pool and uses the managed connection's associateConnection method to tie it to the connection handle.

Figure 3 shows the effect this optimization has on the cached-handle usage you saw in Figure 2.

Figure 3. Lazy association reduces resource usage
Lazy association reduces resource usage

The dashed arrows in Figure 3 indicate the notification of the connection manager by the EJB container when a method completes. At these points, the managed connection is dissociated from the connection handle, and only when a method attempts to use the handle is the managed connection reassociated. The short green bars show how the managed connection is now tied to the EJB for less time and can, consequently, be reused elsewhere.


To enlist, or not to enlist

Everyone knows that transactions are expensive -- particularly XA (global) transactions. This makes it all the more important for a transaction not to do more work than necessary. Another pair of new interfaces in JCA 1.5 prevents unnecessary enlistment of XAResource objects.

Let's look more closely at the issues this enhancement addresses. Suppose you take the EJB from Listing 1 and deploy it using container-managed transactions and a transactional attribute of RequiresNew for the business method. A new transaction begins when the method is invoked. When the connection is created, the connection manager has no idea how it will be used, so it must obtain an XAResource from the associated managed connection and enlist it in the transaction. The connection might be used only to query the database or might not be used at all, but the connection manager must enlist the connection anyway, in case an insert or update is performed. This means that, at a minimum, the resource adapter must make start, commit or rollback, and end flows to the back end. Figure 4 illustrates this flow of events.

Figure 4. Eager transactional enlistment
Eager transactional enlistment

You can see in Figure 4 that the XAResource is enlisted in the transaction (that is, receives a start flow) immediately after the connection is obtained. This means that completion needs to be flowed to the resource when the transactional method ends, even if the method didn't use the connection transactionally.

WebSphere lays JCA 1.5 groundwork

IBM WebSphere® Application Server V5 addressed the drawbacks of the cached-handle connection model with an extension to the JCA 1.0 specification known as smart connection handles. The JCA 1.5 specification took this extension on board in a modified form with the two interfaces in Listing 3

JCA 1.5 also adopted WebSphere Application Server V5's deferred transaction enlistment extension in its lazy-enlistment support.

Read more about these WebSphere extensions in a developerWorks article by Kevin Kelle et al (see Resources).

If another resource becomes involved in the transaction, you have forced an unnecessary two-phase commit, causing an additional prepare flow. The only saving grace here is that the resource manager can still return XA_RDONLY (for "read only") from the prepare call to indicate that it has not actually done any work. The transaction manager does not then need to flow the completion call to that resource manager and, if only one resource manager actually did any work in the transaction, the transaction manager might be able to avoid a slow write to its log file.

Lazy enlistment

By now you should have the idea that you don't want to enlist in the transaction unless absolutely necessary. The JCA 1.5 specification has a solution: lazy enlistment. Listing 4 shows the two interfaces introduced to support this optimization.

Listing 4. Interfaces for lazy enlistment
public interface LazyEnlistableManagedConnection {

}

public interface LazyEnlistableConnectionManager {

    void lazyEnlist(ManagedConnection mc)
            throws ResourceException;

}

The LazyEnlistableManagedConnection interface is a marker interface implemented by the managed connection to indicate to the connection manager that it doesn't need to eagerly enlist the managed connection in an existing transaction when a new connection is created in a transaction or in a new transaction started when a connection already exists. If a connection handle is about to perform some work that should be part of any transaction, and its managed connection hasn't already been enlisted, it should determine whether the connection manager implements the LazyEnlistableConnectionManager interface. If it does, it should call the lazyEnlist method passing the managed connection. This method returns nothing, but if a transaction is associated with the calling thread, the XAResource from the managed connection is enlisted at that point. If the connection isn't enlisted, it needs to call lazyEnlist again before each subsequent piece of work in order to check that a transaction hasn't been started since the last time it called the method.

Figure 5 shows this new sequence of events.

Figure 5. Lazy transactional enlistment
Lazy transactional enlistment

You can see in Figure 5 that the XAResource is no longer enlisted eagerly when the connection is obtained. Instead, the connection manager waits until the connection indicates with the lazyEnlist call that it is about to do some transactional work before enlisting the XAResource.


When things go wrong

The first version of the JCA specification provided a mechanism for a resource adapter to indicate to the connection manager when something has gone badly wrong with a connection. This was the connectionErrorOccurred method on the ConnectionEventListener interface. On receiving this notification, the connection manager destroys the managed connection that sent the event so that it isn't used again. This is all very well. But if, for example, the connection to the back end has been lost, it's quite likely that many of the pooled managed connections are also unusable.

JCA 1.5 introduces an elegant solution to this problem in the form of the ValidatingManagedConnectionFactory interface, shown in Listing 5.

Listing 5. Interface for determining invalid connections
public interface ValidatingManagedConnectionFactory {

    Set getInvalidConnections(Set connectionSet)
            throws ResourceException;

}

Implemented by a managed-connection factory, the ValidatingManagedConnectionFactory interface contains a single method -- getInvalidConnections -- which takes a set of managed connections and returns the subset that the resource adapter considers to be invalid. The validation the resource adapter performs can take any form, but would typically involve some form of "ping" operation to the back end in order to test the connection. The connection manager can then call this method when the resource adapter indicates a connection error, or even periodically to remove broken connections from the pool.


The beginning and the end

The initial JCA release provided a detailed life-cycle model for managed connections and their associated connection handles, but it included no such concept for the resource adapter as a whole. The first moment a deployed resource adapter was aware it even existed in an application server was when a managed-connection factory was created. This has been rectified in JCA 1.5 with the introduction of the ResourceAdapter interface, shown in Listing 6.

Listing 6. Life-cycle methods on the new resource-adapter interface
public interface ResourceAdapter {

    void start(BootstrapContext ctx)
            throws ResourceAdapterInternalException;

    void stop();

    ...

}

A resource adapter can give the name of a class implementing this interface in the resourceadapter-class element of its deployment descriptor (ra.xml). In addition to implementing the ResourceAdapter interface, the class can support a number of properties via the JavaBean pattern. As with managed-connection factories, you declare these properties in the deployment descriptor along with their default values, as illustrated in Listing 7. When the resource adapter is installed, the application server should let the administrator override these defaults.

Listing 7. Example resource-adapter deployment descriptor
<connector>
  ...
  <resourceadapter>
    <resourceadapter-class>
      example.ExampleResourceAdapterImpl
    </resourceadapter-class>
    <config-property>
      <config-property-name>ServerName</config-property-name>
      <config-property-type>java.lang.String</config-property-type>
      <config-property-value>MyServer</config-property-value>
    </config-property>
    <config-property>
      <config-property-name>PortNumber</config-property-name>
      <config-property-type>java.lang.String</config-property-type>
      <config-property-value>1976</config-property-value>
    </config-property>
  </resourceadapter>
  ...
</connector>

At startup, the application server creates an instance of the class specified in the deployment descriptor and sets the properties the administrator has provided. The class must implement an equals method based on these properties so the application server can ensure that it doesn't create more than one equivalent instance. The start method is then called, passing in an object implementing the BootstrapContext interface. You can use this object to create timers, schedule work on other threads, and control imported transactions, all of which I'll cover in more detail in Part 2 of this series. The method should not block and should return in a timely fashion.

The application server typically calls the stop method on the resource adapter before the application server is shut down or the resource adapter is undeployed. The JCA 1.5 specification describes two phases to this process. First, the application server ensures that all applications that depend on the resource adapter have stopped. This guarantees that application threads are no longer using resource-adapter objects and that all transactions have completed. The application server then calls the stop method. At this point, the resource adapter should perform an orderly shutdown (for example, releasing network and application-server resources and forcing any cached data to the back end). Once stop has been called, the application server won't reuse the resource-adapter instance.

The ManagedConnectionFactory interface remains unchanged to preserve backward compatibility, but if you want outbound resources to have access to the capabilities provided to the resource adapter, also implement the new ResourceAdapterAssociation interface shown in Listing 8.

Listing 8. ResourceAdapterAssociation interface
public interface ResourceAdapterAssociation {

    ResourceAdapter getResourceAdapter();
    void setResourceAdapter(ResourceAdapter ra)
            throws ResourceException;

}

After constructing a managed-connection factory, the application server will call the setResourceAdapter method to associate it with its resource adapter. This association is then fixed for the lifetime of the managed-connection factory. The method will be called only once.


Conclusion

In this article, I've shown you four enhancements that JCA 1.5 brings to existing outbound contracts. The lazy association and enlistment optimizations should increase the performance of applications using connections, and the validating managed-connection factory should improve processing in the failure cases. The introduction of life-cycle management at the resource-adapter level opens the door to lots of interesting new opportunities for resource adapters. Part 2 of this series will look at how the new work-management and transaction-inflow contracts build off this basis.

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Java technology on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Java technology
ArticleID=57767
ArticleTitle=JCA 1.5, Part 1: Optimizations and life-cycle management
publish-date=04052005