Version 2

    The following example uses JBoss AOP to apply a custom interceptor to any Java method, in any runtime environment.


    This is a more flexible alternative to a servlet filter (i.e. the Open Session in View pattern), or most other kinds of interceptors. It wraps a Hibernate Session and a database transaction around any pointcut. Usually you would wrap this interceptor around a service facade method that needs a persistence context, or, in other words, that uses DAOs.


    This AOP interceptor should be used if your hibernate.current_session_context_class configuration option is set to thread and you are not using JTA and/or CMT. However, you could easily rewrite it to work with JTA and programmatic transaction demarcation with the UserTransaction API. If your application uses EJBs and container-managed transactions, you don't need any of this. Sessions and transactions is required reading to understand this interceptor and where it is applicable.


    Note that this filter always propagates a transaction if one wrapped method would call another wrapped method - the "current" Session is also propagated automatically.

    public class SessionTransactionInterceptor
        implements org.jboss.aop.advice.Interceptor {
        private static Log log = LogFactory.getLog(SessionTransactionInterceptor.class);
        private static SessionFactory sf = HibernateUtil.getSessionFactory();
        public String getName() {
            return "SessionTransactionInterceptor";
        public Object invoke(Invocation invocation) throws Throwable {
            try {
                boolean isActive = sf.getCurrentSession().getTransaction().isActive();
                if ( !isActive) {
                   log.debug("Starting a database transaction");
                log.debug("Invoking the aspectized service method");
                Object result = invocation.invokeNext();
                // Commit and cleanup
                if (!isActive) {
                   log.debug("Committing the database transaction");
                return result;
            } catch (StaleObjectStateException staleEx) {
                log.error("This interceptor does not implement optimistic concurrency control!");
                log.error("Your application will not work until you add compensation actions!");
                // Rollback, close everything, possibly compensate for any permanent changes
                // during the conversation, and finally restart business conversation. Maybe
                // give the user of the application a chance to merge some of his work with
                // fresh data... what you do here depends on your applications design.
                throw staleEx;
            } catch (Throwable ex) {
                // Rollback only
                try {
                    log.warn("Trying to rollback database transaction after exception");
                } catch (Throwable rbEx) {
                    log.error("Could not rollback transaction after exception!", rbEx);
                // Let others handle it... maybe another interceptor for exceptions?
                throw ex;

    Now define the AOP pointcuts in your META-INF/jboss-aop.xml descriptor:

            Wrap all execute() methods in all Action (interface) implementors inside a database transaction
            and a thread-bound persistence context. If one execute() method should call another
            execute() method, both transaction and persistence context are propagated.
        <bind pointcut="execution(* $instanceof{my.actions.Action}->execute(..))">
            <interceptor class="my.persistence.SessionTransactionInterceptor"/>

    To weave the interceptor into your bytecode, use either build time instrumentation in your Ant build.xml:

    <taskdef name="aopc" classname="org.jboss.aop.ant.AopC">
        <classpath refid="project.libs"/>
    <target name="instrument.aop" depends="compile"
            description="Run the AOP compiler to weave interception code">
        <aopc classpath="${classes.dir}">
            <compilerclasspath><path refid="project.libs"/></compilerclasspath>
            <src path="${classes.dir}"/>
            <include name="**/*.class"/>

    Or inject the bytecode through a custom boot classloader:

    <target name="" depends="compile"
        description="Run with load-time AOP instrumentation">
        <echo>To run on JDK 1.4 download JBoss AOP and don't use lib/api/jboss-aop-jdk5.jar!</echo>
        <!-- Compile a custom classloader first, for JDK 5.0 (see note above) -->
            <arg value="${build.dir}/custom_aop_loader"/>
            <classpath refid="project.libs"/>
        <!-- Need custom bootclasspath... -->
        <path id="custom.bootclasspath">
            <fileset dir="${lib.dir}">
                <include name="**/jboss-ejb3-all*.jar"/>
                <include name="**/thirdparty-all*.jar"/>
            <pathelement path="${build.dir}/custom_aop_loader"/>
        <property name="bootclasspath" refid="custom.bootclasspath"/>
        <!-- Run TestNG tests with custom classloader in boot classpath, prepended -->
        <mkdir dir="${testng.out.dir}"/>
        <testng outputDir="${testng.out.dir}">
            <jvmarg value="-Xbootclasspath/p:${bootclasspath}"/>
            <jvmarg value="-Djboss.aop.exclude=org.hibernate.impl"/>
            <!-- Ignoring these prevents warnings -->
            <jvmarg value="-Djboss.aop.ignore=*ByCGLIB$$*,*dom4j*,*oracle*,*objectweb*"/>
                <path refid="project.libs"/>
                <pathelement path="${classes.dir}"/>
            <xmlfileset dir="${etc.dir}">
                <include name="testsuite-aop.xml"/>