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).
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.
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
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.
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
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
} |
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.
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
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.
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
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.
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.
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
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.
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 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 interfacepublic 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.
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.
- Don't miss the other articles in this series, which cover work management and transaction flow and life-cycle management and message-inflow contract.
- You can download the J2EE Platform, EJB 2.1, J2EE Connector 1.5, and Java Message Service specifications from Sun Microsystems' J2EE 1.4 Documentation page.
- Download the trial version of WebSphere Application Server to experiment with JCA 1.5 for yourself.
- Introduction to the J2EE Connector Architecture (developerWorks, November 2002) is an informative tutorial by Willy Farrell covering the original JCA specification on which version 1.5 builds.
- J2EE Connector Architecture Extensions in WebSphere Application Server V5 (developerWorks, February 2003) details two IBM innovations that became part of the JCA 1.5 specification.
- Understanding JCA transactions (developerWorks, October 2004) explains how different enterprise information systems can participate in transactions via the JCA.
- Developing applications with JCA-based tools (developerWorks, January 2002) introduces the practical aspects of the JCA by using tools from IBM to build, test, deploy, and run a J2EE EJB application (excerpted from J2EE Connector Architecture and Enterprise Application Integration by Rahul Sharma, Beth Stearns, and Tony Ng; Addison-Wesley, 2001).
- Build JCA-compliant resource adapters with WebSphere Studio Application Developer (developerWorks, August 2003) shows you how to write your own JCA-compliant resource adapter.
- Getting started with EJB technology (developerWorks, April 2003) is a comprehensive tutorial introducing the basics of EJB programming and the J2EE environment.
- You'll find articles about every aspect of Java programming in the developerWorks Java technology zone.
- Get involved in the developerWorks community by participating in developerWorks blogs.
- Browse for books on these and other technical topics.
- Also see the Java technology zone tutorials for a complete listing of free Java-focused tutorials from developerWorks.

David 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.
Comments (Undergoing maintenance)





