views:

91

answers:

3

I am using Transaction management with Spring and Hibernate. My situation is as follow:
I have got bean A which is sorrounded by transaction and it call bean B which is defined with transaction including the attribute 'PROPAGATION_REQUIRED'

B in this case doesn't open new transaction but uses the exsiting one (saw in the logs: 'Participating in existing transaction'). However in case the method in B will throw a runtimeException, on its way back to A it will dirty the transaction and will cause it to be marked for roll-back, even if the external method of A will catch the exception and won't throw it away. I think that this behavior is wrong, in this case I want A to control the transaction and B should not interrupt the transaction in any case.
Is there any way to define B to open transaction if no transaction defined but DO NOTHING if it is already inside an exising transaction and let the upper level make the decision whether to commit or roll-back?

See more responses about this issue in a thread in Spring community here.

A: 

Theoretically it is possible, but not within the standard means of Spring's Transaction aspects. You would need to create your own aspect that duplicates the spring standard functionality, extending it for your special case. Perhaps it will even be possible to extend the original aspect they use.

(Probably you will have to define a custom annotation though, because you can neither override the @Transactional attribute nor extend the Propagation enum.)

Here are some pointers:

Also, you should consider reading the book AspectJ in Action, even if you just want to use Spring AOP, as it gives a very good overview.

A good starting point is to download the sources of the spring-aspects jar, see what they are doing there and provide your own extension of either org.springframework.transaction.aspectj.AbstractTransactionAspect or org.springframework.transaction.aspectj.AnnotationTransactionAspect

To sum it up: I'm sure it can be done, but it will take a lot of work. The Spring Transaction API is pretty good as it is though. Maybe you should learn to live with it's limitations. If not: start hacking (see above)

seanizer
So you are saying that there is no spring out-of-the-box solution for it. I'll still try to look for more generic solution htat requires less work, before mark this answer as the best one.
Spiderman
sure, there is no need to choose the correct answer within one hour of the question. But an upvote would be nice :-)
seanizer
To close this case, I think that no workaround fit my requests. Therefore this behavior by design of Spring seems like a limitation to me.The only real solution is to override Spring's implmentation as suggested here.
Spiderman
yes, but that's a perfectly acceptible suggestion from spring's point of view. That's why there is an `AbstractTransactionAspect` for you to extend.
seanizer
A: 

Maybe using annotation @Transactional in a way shown below will solve your problem? @Transactional( propagation = Propagation.REQUIRED, noRollbackFor = RuntimeException.class)

bob
not good because in case B will be called NOT from A but from somewhere else outside, I want the call to B method to be wrapped with a transaction and that in case of runtimeException it WILL do roll-back.
Spiderman
A: 

One solution is to provide TWO bean definitions in your context.xml.

  • One with PROPAGATION_REQUIRED which you will use when you want the bean to be transactional itself

  • The second with PROPAGATION_SUPPORTS which you will use when you call the bean from inside an existing transaction (Actually, it could even be nontransactional).

If you want to minimise duplication, you can factor common configuration into a parent bean definition.

gpeche