1
@Override
    @Transactional(rollbackFor = { RuntimeException.class, Exception.class}, propagation = Propagation.REQUIRED)
    public String upload(ObjectVO vo) throws CustomException {
    .......
    }

In this service, I am inserting in to two tables. If there is an Exception while processing data (like mandatory field check) for the second table which supposed to get inserted after the first table, should it roll back the data inserted in the first table in the same transaction? In my case I am not getting it rolledback. What is the expected behaviour? (And yes, I am not catching the exception, its a custom exception which is included in rollbackFor clause, and is being thrown)
(I am using hibernate) The DAO Layer does getSession().save(entity); (getSession() returns currentSession)

(So the data in the first table remains)

The tables are not related.

<tx:annotation-driven/>

<bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
        lazy-init="true">
        <property name="dataSource" ref="dataSource" />
    </bean>
pratim_b
  • 1,160
  • 10
  • 29
  • Are you sure the Service instance managed by Spring ? – Mani Apr 04 '14 at 12:10
  • 1
    I am assuming your customException is checkedException. And if it is CustomException , if you are not catched explicitly it should be part of method signature( as throw) - am i wrong any where ? – Mani Apr 04 '14 at 12:51
  • yes it does. sory was a typo. Fixed – pratim_b Apr 04 '14 at 12:53
  • not related with your problem but something here is redundant `rollbackFor = { RuntimeException.class, Exception.class, CustomException.class }` your CustomException is either a runtime or a checked (Exception subclass) exception, actually you could even replace everything by `rollbackFor = { Throwable.class} ` – Gab Apr 04 '14 at 13:18
  • yes ..i was just trying with these dirty coding. Thnanks for pointing out – pratim_b Apr 04 '14 at 13:19
  • 1
    Firstly, enable logging using log4j and set the level to debug or trace: The Spring classes will output detailed logging showing transaction creation etc. If you cannot see logging output showing the transaction being created then you have something misconfigured. If it is there and no rollback then a code issue. – Alan Hay Apr 04 '14 at 14:04

3 Answers3

1

Are you sure the proxy actually apply on the method invocation ?

Assuming you use classic dynamic proxies (not aspectJ ones) can you ensure that the method is called from outside of its class ?

[edit] If you're using hibernate switch your transaction manager to HibernateTransactionManager

Gab
  • 7,869
  • 4
  • 37
  • 68
1

First : As suggested , first enable the log by adding the following in your log4j

log4j.category.org.springframework=ALL

Second : if you are calling upload method from another method in the same Servcie class ( say xxxMethod) and the xxxMethod is not annotated by Transaction. then there wont be any rollback. because calls between the method to method in proxy is not handled by Spring context. thus it wont be able to wrap the transaction.

if the Second is not valid, please enable the log verify the log. your logs should show when the transaction starts and when it ends and what are methods are added to the transaction context.

Like below

DEBUG org.springframework.transaction.annotation.AnnotationTransactionAttributeSource - Adding transactional method 'saveDomain' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''


2014-04-04 10:25:24,276 [main] TRACE org.springframework.orm.jpa.JpaTransactionManager - Triggering beforeCompletion synchronization
2014-04-04 10:25:24,276 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Initiating transaction rollback

And so

Note** , if you DAO Layer also annotated with Transaction and with propagation rule as Propagation.REQUIRES_NEW - the Dao method considered as individual UoW . So throwing exception from service layer would not rollback the previous transaction.

In general - it would be advise to keep the transaction in one layer and preferably with Service - Layer

Community
  • 1
  • 1
Mani
  • 3,274
  • 2
  • 17
  • 27
  • Thnx for the valuable info on spring context. But the problem was with transaction manager. Fixed it – pratim_b Apr 04 '14 at 16:20
0

I remember I also had such a problem. My problem was connected with a proper configuration. For instance: Did you specify in the TransactionManager declaration something like this:

transactionManager.setRollbackOnCommitFailure(true);

you may also use a debugger and catch the execution in your implementation of TransactionManager. You have there a method like rollback and you will see what is the reason that this operation is ommited.

Marek Raki
  • 3,056
  • 3
  • 27
  • 50
  • i don't see a place where i need to specify transactionManager.setRollbackOnCommitFailure(true); Is nt it default to true? – pratim_b Apr 04 '14 at 13:08
  • I am using as a provider: JpaTransactionManager and the method is specified in AbstractPlatformTransactionManager. If you are using something else. Just use a debugger and check if there is no additional conditions for rollback. – Marek Raki Apr 04 '14 at 13:15
  • I would like to just add: by default this value is false: private boolean rollbackOnCommitFailure = false; and in the code of processCommit is: if (isRollbackOnCommitFailure()) { doRollbackOnCommitException(status, ex); } – Marek Raki Apr 04 '14 at 13:18
  • You're using hibernate ?? so you should use HibernateTransactionManager instead – Gab Apr 04 '14 at 13:21
  • so, sorry I don't know how to help :( but If I may guess the problem is with the configuration -> debugger will tell you the true. You can also try JpaTransactionManager I am using this with Hibernate as well. – Marek Raki Apr 04 '14 at 13:22