I have an OSGi bundle in which I declare a service and inject into it a transaction with blueprint:
<bean id="MyServiceImpl"
class="com.test.impl.MyServiceImpl">
<jpa:context property="em" unitname="mypu" />
<tx:transaction method="*" value="Required" />
</bean>
<service id="MyService" ref="MyServiceImpl" interface="com.test.api.MyService" />
In this service I have two methods each one of which is writing data in the database, something like the following:
public void createParent() throws MyException {
Parent parent = new Parent();
... // Set parent fields
em.persist(parent);
createChild();
// Checks that could throw MyException
}
public void createChild() throws MyException {
Child child = new Child();
... // Set child fields
em.persist(child);
// Checks that could throw MyException
}
My problems are the following:
- If I throw a runtime exception in the createParent method between
em.persist(parent);
andcreateChild();
the transaction rolls back (as I would expect) and parent is not persisted in the DB. However if at the same point I throw MyException (which is a checked exception) the transaction commits and parent is persisted. I saw in the Aries mailing list that a declared (checked) exception in a blueprint declarative transaction does not trigger a rollback. Is there a way to configure this behavior and specify that I want my exception to rollback the transaction when thrown? - If I throw a runtime exception in the createChild method (after
em.persist(child);
) child is not persisted in the database, however parent is persisted, as if the two methods are running in two different transactions. Why is that? Shouldn't createChild join in the transaction started by createParent? - If I throw a runtime exception in the createParent method after the call to createChild I get the same behavior as in point 2 (ie. parent is persisted and child is not persisted) which confuses me even more since even if I assume that createChild starts a new transaction then this should not get rolled back when an exception is thrown in createParent.
- If in points 2 and 3 above the two methods are in different services then everything works as expected, ie. a runtime exception thrown in any of the methods rolls back the whole transaction.
Can someone please explain the above behavior?
After getting some help form the Aries mailing list it turns out the problem was in the datasource configuration and not in the blueprint configuration. Although I was using MysqlXADataSource
as a driver class the datasource service was registered as a javax.sql.DataSource
instead of javax.sql.XADataSource
which is what was messing up my transactions.
1: A couple of years ago I asked the same. While in Spring you can specify that some transactions should cause rollback and some not, in blueprint you cannot do this. After a while I found the book "Clean code" and read the chapter "Error handling". And I got enlightened. I do not really try to write down the same as the book says. I think after you read it you will get some useful basic thoughts to build up your opinion if this is a right behaviour.
2: There can be two options:
- You throw the exception before the persist function. You catch the exception in the parent. The child function is only wrapped with intercepting logic if the function is called from outside of there is not rollback when the call from child goes back to parent in whatever way. Just think of class wrapping. At least if you do not use bytecode manipulation or runtime class inheritance (but only java proxy classes) you cannot write wrap a class in a way that it intercepts function calls between functions inside. Probably Aries with ASM tries to do the trick (is ASM-4 is present) but personally I do not like this kind of tricks.
- You found a bug
3: That confuses me, too :). Are you sure you do not throw the exception after persisting in the parent but before calling the child? Probably ASM is present and if that is there jta-blueprint has a bug... Debugging would be necessary to find out what happens.
4: Nice to hear that it can work somehow :)
来源:https://stackoverflow.com/questions/19031360/transaction-rollback-in-osgi