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
    The error message appears twice inside your logs - the second time because you are printing it out. Try to add another statement inside the catch block or add some sort of marker to prove that the exception is not 'eaten'.
    at $Proxy0.saveUser(Unknown Source)
    This happens due to the AOP services you are enabling - however if you look closely at the full-stack trace you'll see that it's fairly easy to find out the method and the object.
    I haven't investigated this but I think if you are using CGLIB (you are proxying classes not interfaces) there are some options to enable line numbering inside stacktraces.[/quote]

    P.S. corrected some mispells.

    Comment


    • #3
      Thanks for the remind.

      I am not sure if I AOP a real class or a interface.

      And I also open this topic in AOP section. Someone said the reason is:
      If you don't flush, your DataIntegrityViolationException may not be raised in your target implementation code, but in it's transactional proxy.
      I tried it but it still seems unworkable.

      Reference:

      Comment


      • #4
        I'm guessing your SaveEntityException is not a run-time exception. IIRC, Spring by default will still try to commit the transaction upon catching a non run-time exception.

        Comment

        Working...
        X