AOP Connection
Resin 3.0

Features
Installation
Configuration
Web Applications
IOC/AOP
Resources
JSP
Servlets and Filters
Portlets
Databases
Admin (JMX)
CMP
EJB
EJB 3.0
Security
XML and XSLT
XTP
JMS
Performance
Protocols
Third-party
Troubleshooting/FAQ

bean
misc
Tutorials

AOP Conn
Tutorials
Tutorials
Resources

Find this tutorial in: /usr/local/resin/resin-3.0.12/webapps/resin-doc/ioc/tutorial/aop-connection
Try the Tutorial

Using AOP to handle JDBC connection management simplifies the tedious and error-prone JDBC connection pattern.

  1. Files in this tutorial
  2. Using the ConnectionRequired interceptor
  3. ConnectionInterceptor: Implementing the Interceptor
    1. MethodInterceptor.invoke(): JDBC Connection Pattern
  4. @RequireConnection
  5. Configuration
  6. Compatibility

Files in this tutorial

WEB-INF/web.xml web.xml configuration
WEB-INF/classes/example/RequireConnection.java The method annotation
WEB-INF/classes/example/ConnectionInterceptor.java The interceptor
WEB-INF/classes/example/SampleServlet.java A sample servlet using the annotation

Using the ConnectionRequired interceptor

If a method needs a connection, it adds a @ConnectionRequired annotation with the JNDI name of the data source. The method can assume the connection is always passed as the argument. If the caller sets the conn, the interceptor uses the specified connection, i.e. the method acts as normal. If conn is null, the interceptor allocates a connection from the data source and passes it to the method.

@ConnectionRequired("jdbc/resin")
void testConnection(Connection conn)
  throws SQLException
{
  ...
}

The application code is pretty basic. It just needs to add an annotation.

ConnectionInterceptor: Implementing the Interceptor

The interceptor needs to do a number of things:

  • Fetch the DataSource from JNDI
  • Find the method's connection argument
  • If the connection is null, get a new connection and set the argument
  • If there's a new connection, protect the conn.close() in a finally block

MethodInterceptor.invoke(): JDBC Connection Pattern

The interceptor implements the standard JDBC connection pattern: getting a connection, using it in a protected block, and closing it in a finally block. Instead of running the protected code directly, it calls it through the MethodInvocation's proceed block.

public Object invoke(MethodInvocation inv) throws Throwable
{
  int paramIndex = ...;
  Object []args = inv.getArguments();
  Connection conn = _dataSource.getConnection();
  try {
    args[paramIndex] = conn;
    return inv.proceed();
  } finally {
    conn.close();
  }
}

The MethodInvocation is essentially a closure of the underlying method call. It contains the method to be called and the method arguments. The ConnectionInterceptor fills in the argument corresponding to the connection.

Because the ConnectionInterceptor code is written once, it's straightforward to verify its correctness. Without this code sharing, code using connections must reimplement the connection pattern for each use. As anyone who's tried to debug connection code knows, trying to find the case which forgot to close the connection is a slow, painful process. By using the method interceptor, you can avoid those kinds of hard-to-find bugs.

@RequireConnection

The @RequireConnection annotation is the critical glue tying the application code to the interceptor.

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequireConnection {
  /**
   * The jndi name of the data source.
   */
  String value();
}

Configuration

The <enhancer> tag in the resin.conf connects the annotation to its method enhancer. The <enhancer> belongs to a class loader (since it's implemented by bytecode enhancement), and so can appear at any of the <server>, <host>, or <web-app> levels.

<class-loader>
  <enhancer>
    <method annotation="example.RequireConnection"
            type="example.ConnectionInterceptor"/>
  </enhancer>
<class-loader>

Compatibility

The application code will be entirely compatible with other AOP implementations because it only depends on a JDK 1.5 annotation. Since annotations are the logical place for this kind of information, it's likely that all AOP implementations will eventually provide this support.

Writing the method interceptor depends on the standard aopalliance API. So an interceptor written to the MethodInterceptor API is fully compatible with any other aopalliance AOP implementation such as the Spring framework.

The <enhancer> configuration, of course, is completely Resin-dependent.

Try the Tutorial


Tutorials
Tutorials
Resources
Copyright © 1998-2005 Caucho Technology, Inc. All rights reserved.
Resin® is a registered trademark, and HardCoretm and Quercustm are trademarks of Caucho Technology, Inc.