Announcement Announcement Module
Collapse
No announcement yet.
SOS: can't catch exceptions after I enabled AOP transaction Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • SOS: can't catch exceptions after I enabled AOP transaction

    Generally speaing I think I can't catch the exceptions after I enabled transaction management via AOP.

    I get a bean just before AOP transaction management is enabled, I can catch my exceptions.
    After AOP transaction management is enabled, I can't catch my exceptions and when use debug to trace it said:

    $Proxy0.saveUser(User, User) line: not available
    and source not found.
    Anyone hasing similiar experience please help.

    Great Thanks

    The Story and Scenario:

    Initially I create a class:
    public class Entity implements Serializable {
    private long objID;
    public long getObjID() {
    return objID;
    }
    public void setObjID(long objID) {
    this.objID = objID;
    }

    private String entityID;
    public String getEntityID() {
    return entityID;
    }
    public void setEntityID(String entityID) {
    this.entityID = entityID;
    }
    }
    I persist it into mySQL DB.

    And I defined my Hibernate dao to access it (I only leave the save method here).

    public class HibernateDao extends HibernateDaoSupport {
    public void saveEntity(Object obj) throws SaveEntityException {
    try {
    getHibernateTemplate().saveOrUpdate(obj);
    } catch ( DataAccessException e) {
    throw new SaveEntityException(e.getMessage(),e.getCause());
    };
    }
    }
    OK, Now I defined Application Context to start my service. Application Context definition.

    <bean id="pdServiceTarget" class="service.PdServer" init-method="initialize">
    <property name="dao"><ref local="mesDao"/></property>
    </bean>

    <bean id="pdService" class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
    <property name="transactionManager"><ref local="transactionManager"/></property>
    <property name="target"><ref local="pdServiceTarget"/></property>
    <property name="transactionAttributes">
    <props>
    <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
    <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
    <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
    <prop key="save*">PROPAGATION_REQUIRED</prop>
    <prop key="delete*">PROPAGATION_REQUIRED</prop>
    <prop key="acquire*">PROPAGATION_REQUIRED</prop>
    <prop key="operation*">PROPAGATION_REQUIRED</prop>
    <prop key="release*">PROPAGATION_REQUIRED</prop>
    </props>
    </property>
    </bean>
    Now I begin to test my dao acess service.

    Scenario A. I use the service before AOP Transaction is enabled. The entityID must be unique in the table and in DB there is already a record with entityID=="A", so there must be a duplicated key error.

    I can catch my exception. It works fine.

    public static void main(String[] args) {
    ApplicationContext context =
    new FileSystemXmlApplicationContext("applicationContex t-pdServer.xml");

    if(! (context == null)) System.out.print("AppContext Is Created");
    PdService pdServer = (PdService) context.getBean("pdServiceTarget");

    Entity myEntity = new Entity();
    myUser.setEntityID("A");

    try {
    pdServer.saveEntity(myEntity);
    } catch (SaveEntityException e) {
    System.out.print(e.getMessage());
    }
    }
    Then I test Scenario B, I use the service after AOP transaction is enabled.
    Note: I just change the line to following line
    PdService pdServer = (PdService) context.getBean("pdService");
    And all codes are
    public static void main(String[] args) {
    ApplicationContext context =
    new FileSystemXmlApplicationContext("applicationContex t-pdServer.xml");

    if(! (context == null)) System.out.print("AppContext Is Created");
    PdService pdServer = (PdService) context.getBean("pdService");

    Entity myEntity = new Entity();
    myUser.setEntityID("A");

    try {
    pdServer.saveEntity(myEntity);
    } catch (SaveEntityException e) {
    System.out.print(e.getMessage());
    }
    }
    But this time I can't catch the exception any more it print following logs:
    AppContext Is Created
    service.PdServer@682406
    18-May-2005 00:57:21 org.springframework.jdbc.datasource.JdbcTransactio nObjectSupport <clinit>
    INFO: JDBC 3.0 Savepoint class is available
    Hibernate: select user0_.objID as objID1_, user0_.userName as userName1_, user0_.password as password1_, user0_.editStatus as editStatus1_, user0_.created_by as created_by1_, user0_.created_at as created_at1_, user0_.lastEdit_by as lastEdit7_1_, user0_.lastEdit_at as lastEdit8_1_, user0_.lastReleased_by as lastRele9_1_, user0_.lastReleased_at as lastRel10_1_, user0_.entityID as entityID1_, user0_.entityDescription as entityD12_1_, user1_.objID as objID0_, user1_.userName as userName0_, user1_.password as password0_, user1_.editStatus as editStatus0_, user1_.created_by as created_by0_, user1_.created_at as created_at0_, user1_.lastEdit_by as lastEdit7_0_, user1_.lastEdit_at as lastEdit8_0_, user1_.lastReleased_by as lastRele9_0_, user1_.lastReleased_at as lastRel10_0_, user1_.entityID as entityID0_, user1_.entityDescription as entityD12_0_ from User user0_ left outer join User user1_ on user0_.created_by=user1_.objID where user0_.objID=?
    Hibernate: insert into User (userName, password, editStatus, created_by, created_at, lastEdit_by, lastEdit_at, lastReleased_by, lastReleased_at, entityID, entityDescription) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    18-May-2005 00:57:21 net.sf.hibernate.util.JDBCExceptionReporter logExceptions
    WARNING: SQL Error: 1062, SQLState: 23000
    18-May-2005 00:57:21 net.sf.hibernate.util.JDBCExceptionReporter logExceptions
    SEVERE: Duplicate key or integrity constraint violation message from server: "Duplicate entry 'A' for key 2"
    18-May-2005 00:57:21 net.sf.hibernate.AssertionFailure <init>
    SEVERE: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
    net.sf.hibernate.AssertionFailure: null id in entry (don't flush the Session after an exception occurs)
    at net.sf.hibernate.impl.SessionImpl.checkId(SessionI mpl.java:2669)
    at net.sf.hibernate.impl.SessionImpl.flushEntity(Sess ionImpl.java:2493)
    at net.sf.hibernate.impl.SessionImpl.flushEntities(Se ssionImpl.java:2486)
    at net.sf.hibernate.impl.SessionImpl.flushEverything( SessionImpl.java:2281)
    at net.sf.hibernate.impl.SessionImpl.flush(SessionImp l.java:2260)
    at net.sf.hibernate.transaction.JDBCTransaction.commi t(JDBCTransaction.java:61)
    at org.springframework.orm.hibernate.HibernateTransac tionManager.doCommit(HibernateTransactionManager.j ava:472)
    at org.springframework.transaction.support.AbstractPl atformTransactionManager.commit(AbstractPlatformTr ansactionManager.java:397)
    at org.springframework.transaction.interceptor.Transa ctionAspectSupport.doCloseTransactionAfterThrowing (TransactionAspectSupport.java:279)
    at org.springframework.transaction.interceptor.Transa ctionInterceptor.invoke(TransactionInterceptor.jav a:60)
    at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :144)
    at org.springframework.aop.framework.JdkDynamicAopPro xy.invoke(JdkDynamicAopProxy.java:174)
    at $Proxy0.saveUser(Unknown Source)
    at test.PdServiceTest.main(PdServiceTest.java:41)
    Exception in thread "main" net.sf.hibernate.AssertionFailure: null id in entry (don't flush the Session after an exception occurs)
    at net.sf.hibernate.impl.SessionImpl.checkId(SessionI mpl.java:2669)
    at net.sf.hibernate.impl.SessionImpl.flushEntity(Sess ionImpl.java:2493)
    at net.sf.hibernate.impl.SessionImpl.flushEntities(Se ssionImpl.java:2486)
    at net.sf.hibernate.impl.SessionImpl.flushEverything( SessionImpl.java:2281)
    at net.sf.hibernate.impl.SessionImpl.flush(SessionImp l.java:2260)
    at net.sf.hibernate.transaction.JDBCTransaction.commi t(JDBCTransaction.java:61)
    at org.springframework.orm.hibernate.HibernateTransac tionManager.doCommit(HibernateTransactionManager.j ava:472)
    at org.springframework.transaction.support.AbstractPl atformTransactionManager.commit(AbstractPlatformTr ansactionManager.java:397)
    at org.springframework.transaction.interceptor.Transa ctionAspectSupport.doCloseTransactionAfterThrowing (TransactionAspectSupport.java:279)
    at org.springframework.transaction.interceptor.Transa ctionInterceptor.invoke(TransactionInterceptor.jav a:60)
    at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :144)
    at org.springframework.aop.framework.JdkDynamicAopPro xy.invoke(JdkDynamicAopProxy.java:174)
    at $Proxy0.saveUser(Unknown Source)
    at test.PdServiceTest.main(PdServiceTest.java:41)

  • #2
    But this time I can't catch the exception any more
    This is because the changes may not be flushed - the AOP proxy will do this, which is why you get the error source as being in $Proxy0.saveUser.

    You can try adding a flush. E.g.
    Code:
    public class HibernateDao extends HibernateDaoSupport &#123;
      public void saveEntity&#40;Object obj&#41; throws SaveEntityException &#123;
        try &#123;
          getHibernateTemplate&#40;&#41;.saveOrUpdate&#40;obj&#41;;
          getHibernateTemplate&#40;&#41;.flush&#40;&#41;;
        &#125; catch &#40; DataAccessException e&#41; &#123;
          throw new SaveEntityException&#40;e.getMessage&#40;&#41;,e.getCause&#40;&#41;&#41;;
        &#125;;
      &#125;
    &#125;
    I noted this previously in this post.

    Comment


    • #3
      Hi KatenTim, great thanks for the remind.
      I expected the AOP can pass the original exceptions since normally we assume AOP aspects as a shadow functions and extert no impact on business logics.

      And after the dao service is enabled by an AOP advisor, I can't debug/trace down to my native codes. So how can I trace down to my native implementation code?

      I tried it and but it seems doesn't work.

      First using:
      getHibernateTemplate().saveOrUpdate(obj);
      try {
      getHibernateTemplate().flush();
      } catch ( DataAccessException e) {
      throw new SaveEntityException(e.getMessage(),e.getCause());
      }
      And following are logs:
      ppContext Is Created
      service.PdServer@2006a0
      Hibernate: select user0_.objID as objID1_, user0_.userName as userName1_, user0_.password as password1_, user0_.editStatus as editStatus1_, user0_.created_by as created_by1_, user0_.created_at as created_at1_, user0_.lastEdit_by as lastEdit7_1_, user0_.lastEdit_at as lastEdit8_1_, user0_.lastReleased_by as lastRele9_1_, user0_.lastReleased_at as lastRel10_1_, user0_.entityID as entityID1_, user0_.entityDescription as entityD12_1_, user1_.objID as objID0_, user1_.userName as userName0_, user1_.password as password0_, user1_.editStatus as editStatus0_, user1_.created_by as created_by0_, user1_.created_at as created_at0_, user1_.lastEdit_by as lastEdit7_0_, user1_.lastEdit_at as lastEdit8_0_, user1_.lastReleased_by as lastRele9_0_, user1_.lastReleased_at as lastRel10_0_, user1_.entityID as entityID0_, user1_.entityDescription as entityD12_0_ from User user0_ left outer join User user1_ on user0_.created_by=user1_.objID where user0_.objID=?
      Hibernate: insert into User (userName, password, editStatus, created_by, created_at, lastEdit_by, lastEdit_at, lastReleased_by, lastReleased_at, entityID, entityDescription) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
      18-May-2005 09:31:54 net.sf.hibernate.util.JDBCExceptionReporter logExceptions
      WARNING: SQL Error: 1062, SQLState: 23000
      18-May-2005 09:31:54 net.sf.hibernate.util.JDBCExceptionReporter logExceptions
      SEVERE: Duplicate key or integrity constraint violation message from server: "Duplicate entry 'A' for key 2"
      Exception in thread "main" org.springframework.dao.DataIntegrityViolationExce ption: Hibernate operation: Duplicate key or integrity constraint violation message from server: "Duplicate entry 'A' for key 2"; nested exception is java.sql.SQLException: Duplicate key or integrity constraint violation message from server: "Duplicate entry 'A' for key 2"
      java.sql.SQLException: Duplicate key or integrity constraint violation message from server: "Duplicate entry 'A' for key 2"
      at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.ja va:1997)
      at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:11 67)
      at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java :1278)
      at com.mysql.jdbc.Connection.execSQL(Connection.java: 2247)
      at com.mysql.jdbc.PreparedStatement.executeUpdate(Pre paredStatement.java:1772)
      at com.mysql.jdbc.PreparedStatement.executeUpdate(Pre paredStatement.java:1619)
      at net.sf.hibernate.persister.EntityPersister.insert( EntityPersister.java:518)
      at net.sf.hibernate.persister.EntityPersister.insert( EntityPersister.java:426)
      at net.sf.hibernate.impl.ScheduledIdentityInsertion.e xecute(ScheduledIdentityInsertion.java:28)
      at net.sf.hibernate.impl.SessionImpl.execute(SessionI mpl.java:2449)
      at net.sf.hibernate.impl.SessionImpl.doSave(SessionIm pl.java:943)
      at net.sf.hibernate.impl.SessionImpl.doSave(SessionIm pl.java:868)
      at net.sf.hibernate.impl.SessionImpl.saveWithGenerate dIdentifier(SessionImpl.java:786)
      at net.sf.hibernate.impl.SessionImpl.save(SessionImpl .java:749)
      at net.sf.hibernate.impl.SessionImpl.saveOrUpdate(Ses sionImpl.java:1398)
      at org.springframework.orm.hibernate.HibernateTemplat e$16.doInHibernate(HibernateTemplate.java:532)
      at org.springframework.orm.hibernate.HibernateTemplat e.execute(HibernateTemplate.java:312)
      at org.springframework.orm.hibernate.HibernateTemplat e.saveOrUpdate(HibernateTemplate.java:529)
      at dao.HibernateDao.saveEntity(HibernateDao.java:50)
      at service.PdServer.saveEntity(PdServer.java:98)
      at service.PdServer.saveUser(PdServer.java:260)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:585)
      at org.springframework.aop.support.AopUtils.invokeJoi npointUsingReflection(AopUtils.java:284)
      at org.springframework.aop.framework.ReflectiveMethod Invocation.invokeJoinpoint(ReflectiveMethodInvocat ion.java:155)
      at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :122)
      at org.springframework.transaction.interceptor.Transa ctionInterceptor.invoke(TransactionInterceptor.jav a:56)
      at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :144)
      at org.springframework.aop.framework.JdkDynamicAopPro xy.invoke(JdkDynamicAopProxy.java:174)
      at $Proxy0.saveUser(Unknown Source)
      at test.PdServiceTest.main(PdServiceTest.java:41)
      Second using your suggestion
      public void saveEntity(Object obj) throws SaveEntityException {
      try {
      getHibernateTemplate().saveOrUpdate(obj);
      getHibernateTemplate().flush();
      } catch ( DataAccessException e) {
      throw new SaveEntityException(e.getMessage(),e.getCause());
      }
      }
      following are logs
      AppContext Is Created
      service.PdServer@115126e
      18-May-2005 09:40:54 org.springframework.jdbc.datasource.JdbcTransactio nObjectSupport <clinit>
      INFO: JDBC 3.0 Savepoint class is available
      Hibernate: select user0_.objID as objID1_, user0_.userName as userName1_, user0_.password as password1_, user0_.editStatus as editStatus1_, user0_.created_by as created_by1_, user0_.created_at as created_at1_, user0_.lastEdit_by as lastEdit7_1_, user0_.lastEdit_at as lastEdit8_1_, user0_.lastReleased_by as lastRele9_1_, user0_.lastReleased_at as lastRel10_1_, user0_.entityID as entityID1_, user0_.entityDescription as entityD12_1_, user1_.objID as objID0_, user1_.userName as userName0_, user1_.password as password0_, user1_.editStatus as editStatus0_, user1_.created_by as created_by0_, user1_.created_at as created_at0_, user1_.lastEdit_by as lastEdit7_0_, user1_.lastEdit_at as lastEdit8_0_, user1_.lastReleased_by as lastRele9_0_, user1_.lastReleased_at as lastRel10_0_, user1_.entityID as entityID0_, user1_.entityDescription as entityD12_0_ from User user0_ left outer join User user1_ on user0_.created_by=user1_.objID where user0_.objID=?
      Hibernate: insert into User (userName, password, editStatus, created_by, created_at, lastEdit_by, lastEdit_at, lastReleased_by, lastReleased_at, entityID, entityDescription) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
      18-May-2005 09:40:54 net.sf.hibernate.util.JDBCExceptionReporter logExceptions
      WARNING: SQL Error: 1062, SQLState: 23000
      18-May-2005 09:40:54 net.sf.hibernate.util.JDBCExceptionReporter logExceptions
      SEVERE: Duplicate key or integrity constraint violation message from server: "Duplicate entry 'A' for key 2"
      18-May-2005 09:40:54 net.sf.hibernate.AssertionFailure <init>
      SEVERE: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
      net.sf.hibernate.AssertionFailure: null id in entry (don't flush the Session after an exception occurs)
      at net.sf.hibernate.impl.SessionImpl.checkId(SessionI mpl.java:2669)
      at net.sf.hibernate.impl.SessionImpl.flushEntity(Sess ionImpl.java:2493)
      at net.sf.hibernate.impl.SessionImpl.flushEntities(Se ssionImpl.java:2486)
      at net.sf.hibernate.impl.SessionImpl.flushEverything( SessionImpl.java:2281)
      at net.sf.hibernate.impl.SessionImpl.flush(SessionImp l.java:2260)
      at net.sf.hibernate.transaction.JDBCTransaction.commi t(JDBCTransaction.java:61)
      at org.springframework.orm.hibernate.HibernateTransac tionManager.doCommit(HibernateTransactionManager.j ava:472)
      at org.springframework.transaction.support.AbstractPl atformTransactionManager.commit(AbstractPlatformTr ansactionManager.java:397)
      at org.springframework.transaction.interceptor.Transa ctionAspectSupport.doCloseTransactionAfterThrowing (TransactionAspectSupport.java:279)
      at org.springframework.transaction.interceptor.Transa ctionInterceptor.invoke(TransactionInterceptor.jav a:60)
      at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :144)
      at org.springframework.aop.framework.JdkDynamicAopPro xy.invoke(JdkDynamicAopProxy.java:174)
      at $Proxy0.saveUser(Unknown Source)
      at test.PdServiceTest.main(PdServiceTest.java:41)
      Exception in thread "main" net.sf.hibernate.AssertionFailure: null id in entry (don't flush the Session after an exception occurs)
      at net.sf.hibernate.impl.SessionImpl.checkId(SessionI mpl.java:2669)
      at net.sf.hibernate.impl.SessionImpl.flushEntity(Sess ionImpl.java:2493)
      at net.sf.hibernate.impl.SessionImpl.flushEntities(Se ssionImpl.java:2486)
      at net.sf.hibernate.impl.SessionImpl.flushEverything( SessionImpl.java:2281)
      at net.sf.hibernate.impl.SessionImpl.flush(SessionImp l.java:2260)
      at net.sf.hibernate.transaction.JDBCTransaction.commi t(JDBCTransaction.java:61)
      at org.springframework.orm.hibernate.HibernateTransac tionManager.doCommit(HibernateTransactionManager.j ava:472)
      at org.springframework.transaction.support.AbstractPl atformTransactionManager.commit(AbstractPlatformTr ansactionManager.java:397)
      at org.springframework.transaction.interceptor.Transa ctionAspectSupport.doCloseTransactionAfterThrowing (TransactionAspectSupport.java:279)
      at org.springframework.transaction.interceptor.Transa ctionInterceptor.invoke(TransactionInterceptor.jav a:60)
      at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :144)
      at org.springframework.aop.framework.JdkDynamicAopPro xy.invoke(JdkDynamicAopProxy.java:174)
      at $Proxy0.saveUser(Unknown Source)
      at test.PdServiceTest.main(PdServiceTest.java:41)

      Comment


      • #4
        The Hibernate AssertionFailure is a worry. What DB and Hibernate version is it?

        Comment


        • #5
          Same thread on Data Access forum.

          Comment


          • #6
            Spring 1.1.5 and with built-in hibrnate in it, hibernate should be 2.x

            Yes, same topic in Data Access since I am not sure which section is more suitable. I made a reference there to this thread.

            Comment


            • #7
              I get the issue being resolved but it seems it works different from what explained in katentim's previous discussion thread.

              First I add a print to confirm the exception is actually being caught.

              try {
              getHibernateTemplate().saveOrUpdate(obj);
              } catch ( DataIntegrityViolationException e) {
              System.out.print("saveEntity in dao: The Exception is " + e.getClass().getName() + "\n");
              e.printStackTrace();
              throw e;
              }
              Second I find out if I throw myself defined exceptions, there will always error, The AOP always try to commit it so it raise following exceptions.

              Third I change the throw out exception from my dao back to spring dao exceptions, the AOP know it and decide to rollback the call, then it woks.

              This means I must keep spring exception being thrown to keep AOP know when to commit and when to rollback.

              Anyway, Great thanks for your help.

              Comment


              • #8
                Second I find out if I throw myself defined exceptions, there will always error, The AOP always try to commit it so it raise following exceptions.
                OK - this is the problem. SaveEntityException is a checked exception, and won't be rolled back by default. You can either make it unchecked, or define a rollback rule (or use Spring's exception hierarchy - which is unchecked). E.g.
                Code:
                <prop key="save*">PROPAGATION_REQUIRED,-SaveEntityException</prop>

                Comment

                Working...
                X