Announcement Announcement Module
Collapse
No announcement yet.
Using Hibernate EntityInterceptor with TransactionProxyFactoryBean Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Using Hibernate EntityInterceptor with TransactionProxyFactoryBean

    Hi,

    I found that the Hibernate Interceptor which is set to a HibernateTransactionManager's entityInterceptor was not called when the transactionManager is wired to TransactionProxyFactoryBean. Below shown my Spring config:

    <bean id="dataSource"
    class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName">
    <value>oracle.jdbc.driver.OracleDriver</value>
    </property>
    <property name="url">
    <value>jdbc:oracle:thin:@localhost:1521:XE</value>
    </property>
    <property name="username">
    <value>ap001</value>
    </property>
    <property name="password">
    <value>abcd1234</value>
    </property>
    </bean>

    <bean id="auditLogInterceptor" class="com.koala.audit.hibernate.AuditLogIntercept or"
    singleton="false">
    <property name="auditLogDAO">
    <ref bean="auditLogDAO" />
    </property>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.hibernate3.Hibernat eTransactionManager">
    <property name="sessionFactory">
    <ref bean="sessionFactory" />
    </property>
    <property name="entityInterceptor">
    <ref bean="auditLogInterceptor" />
    </property>
    </bean>

    <bean id="auditSessionFactory" class="org.springframework.orm.hibernate3.LocalSes sionFactoryBean">
    <property name="dataSource">
    <ref bean="dataSource" />
    </property>
    <property name="hibernateProperties">
    <ref bean="hibernateProperties" />
    </property>
    <property name="mappingLocations">
    <list><value>classpath:hibernate-mappings/AuditLogVO.hbm.xml</value></list>
    </property>
    </bean>

    <bean id="auditLogDAO" class="com.koala.audit.dao.impl.AuditLogDAOImpl">
    <property name="sessionFactory">
    <ref bean="auditSessionFactory" />
    </property>
    </bean>

    <bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.LocalSes sionFactoryBean">
    <property name="dataSource">
    <ref bean="dataSource" />
    </property>
    <property name="hibernateProperties">
    <ref bean="hibernateProperties" />
    </property>
    <property name="mappingLocations">
    <list><value>classpath:hibernate-mappings/AccountVO.hbm.xml</value></list>
    </property>
    <property name="entityInterceptor">
    <ref bean="auditLogInterceptor" />
    </property>
    </bean>

    <bean id="hibernateProperties" class="org.springframework.beans.factory.config.Pr opertiesFactoryBean">
    <property name="properties">
    <props>
    <prop key="hibernate.dialect">
    org.hibernate.dialect.OracleDialect
    </prop>
    <prop key="hibernate.show_sql">true</prop>
    <prop key="hibernate.format_sql">true</prop>
    </props>
    </property>
    </bean>

    <bean id="accountDAO" class="com.koala.dao.impl.AccountDAOImpl">
    <property name="sessionFactory">
    <ref bean="sessionFactory" />
    </property>
    </bean>

    <bean id="transactionProxy"
    class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean"
    abstract="true">
    <property name="transactionManager" ref="transactionManager" />
    <property name="transactionAttributes">
    <props>
    <prop key="test*">PROPAGATION_REQUIRED</prop>
    <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
    </props>
    </property>
    </bean>

    <bean id="testBO" parent="transactionProxy">
    <property name="target">
    <bean
    class="com.koala.bo.impl.TestBOImpl">
    <property name="accountDAO">
    <ref bean="accountDAO" />
    </property>
    </bean>
    </property>
    </bean>


    The Java classes are:


    //
    public final class AuditLogInterceptor extends EmptyInterceptor {

    private IAuditLogDAO auditLogDAO;

    public void setAuditLogDAO(IAuditLogDAO auditLogDAO) {
    this.auditLogDAO = auditLogDAO;
    }

    public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames,
    Type[] types) {

    System.out.println("onSave");
    return false;
    }

    public void postFlush(Iterator entities) {
    System.out.println("postFlush");
    }
    }

    // AccountDAOImpl
    public class AccountDAOImpl extends HibernateTemplate implements IAccountDAO {
    public void insert(AccountVO account) {
    this.save(account);
    }
    }

    // TestBOImpl
    public class TestBOImpl implements ITestBO {

    private IAccountDAO dao;

    public void setAccountDAO(IAccountDAO dao) {
    this.dao = dao;
    }

    public void test() {
    AccountVO account = new AccountVO();
    account.setAccountNumber(1);
    account.setAccountSearchName("Koala Lam 2");
    account.setAccountFullName1("KoLaLa 3");
    account.setAccountFullName2("Lam 4");
    account.setLastModifyUser("User2");
    account.setLastModifyDate(new Date());

    dao.insert(account);
    }

    // Main
    public class Main {

    public static void main(String[] args) {

    BeanFactoryLocator bfLocator = SingletonBeanFactoryLocator.getInstance("classpath *:spring/beanRefFactory.xml");
    BeanFactoryReference bfReference = bfLocator.useBeanFactory("context");
    BeanFactory ctx = bfReference.getFactory();

    ITestBO testBO = (ITestBO) ctx.getBean("testBO");
    testBO.test();
    }
    }

    Record was inserted to the db but the interceptor was never called. Can anyone please kindly tell me what goes wrong in the above config?

    Thanks in advance.

    Regards,
    Koala Lam

  • #2
    In our project we put the entityInterceptor in LocalSessionFactoryBean not in HibernateTransactionManager

    Comment


    • #3
      Hi isyak,

      Thanks for your advice.

      I have tried setting the Hibernate Interceptor in LocalSessionFactoryBean as well but failed too. Did you also use TransactionProxyFactoryBean? Can you please share with me your config?

      Regards,
      Koala Lam

      Comment


      • #4
        Sure no problem...
        we also using interceptor for auditlog

        Code:
        <bean id="testAuditLogInterceptor" class="com.xxx.component.auditlog.interceptor.AuditLogInterceptor">
            <property name="auditLogIntegrator">
                <ref bean="auditLogIntegrator"/>
            </property>
        </bean>       
        
        <bean id="auditLogIntegrator" class="com.xxx.component.auditlog.services.impl.AuditLogJMSIntegratorImpl">
            <property name="jmsTemplate">
                <ref bean="auditLogJMSTemplate"/>
            </property>
        </bean>
        
        <bean id="testSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
            <property name="entityInterceptor" ref="testAuditLogInterceptor"/>
            <property name="dataSource">
                <ref bean="testTX"></ref>
            </property>
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
                    <prop key="hibernate.show_sql">false</prop>
                    <prop key="hibernate.format_sql">false</prop>
                </props>
            </property>
            <property name="mappingResources">
            ...
            ...
        </bean>

        Comment


        • #5
          Hi isyak,

          Thanks very much for your sharing. However, I can't find setting for TransactionProxyFactoryBean. Did you use it for declarative transaction handling?

          Thanks a lot.

          Regards,
          Koala Lam

          Comment


          • #6
            yes i use declarative transaction.

            we also implement JMS, so the process of writing to database will perform asynchronously. This the xml to perform writing the database :

            Code:
                <bean id="auditLogService" parent="txProxyTemplate">
                    <property name="target">
                        <bean class="com.xxx.component.auditlog.services.impl.AuditLogServiceImpl">
                            <property name="auditLogDAO" ref="auditLogDAO"/>
                            <property name="auditLogIndexDAO" ref="auditLogIndexDAO"/>
                        </bean>
                    </property>
                </bean>
                
                <bean id="txProxyTemplate" abstract="true"
                    class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
                    <property name="transactionManager" ref="transactionManager"/>
                    <property name="transactionAttributes">
                        <props>
                            <prop key="save*">PROPAGATION_REQUIRED,-Exception</prop>
                        </props>
                    </property>
                </bean>
            
                <bean id="transactionManager"
                    class="org.springframework.transaction.jta.WebLogicJtaTransactionManager"
                    abstract="false" singleton="true" lazy-init="default"
                    autowire="default" dependency-check="default">
                </bean>

            Comment


            • #7
              Hi isyak,

              Thanks so much for sharing with me your config.

              I found one difference between your config and mine. Instead of sending out a JMS message to a JMS destination, an audit log is inserted to the database.

              I tried to run my program at debug level and found that the interceptor did run just no audit record was inserted into the database.

              After that I modified the program like this (config was kept the same):

              public class MainTest {

              public static void main(String[] args) {

              BeanFactoryLocator beanFactoryLocator = SingletonBeanFactoryLocator.getInstance("classpath *:spring/beanRefFactory.xml");
              BeanFactoryReference beanFactoryReference = beanFactoryLocator.useBeanFactory("context");
              BeanFactory factory = beanFactoryReference.getFactory();

              // This one doesn't work.
              //ITestBO test = (ITestBO) factory.getBean("testBO");
              //test.test();

              AccountVO account = new AccountVO();
              account.setAccountNumber((short)1);
              account.setAccountSearchName("Koala Lam 2");
              account.setAccountFullName1("KoLaLa 3");
              account.setAccountFullName2("Lam 4");
              account.setLastModifyUser("User2");
              account.setLastModifyDate(new Date());

              IAccountDAO dao = (IAccountDAO) factory.getBean("accountDAO");
              dao.insert(account);
              }

              It works !! Therefore, I wonder if the problem comes from the use of the Transaction Manager.

              Could anyone please try to give me some advice what's going wrong?

              Thanks a lot.

              Regards,
              Koala Lam

              Comment

              Working...
              X