Hi.
I have an application, which uses spring (3.0.4) transactional proxies. Application uses org.springframework.transaction.jta.JtaTransaction Manager and runs on Weblogic 10.3.
The problem i run into can be described via the following meta code.
I have defined three transactional services.
Now client of class A calls a.storeThings(someThings) (a is an instance of A). a delegates some work to instance of B calling storeSubThings. If now something goes wrong in storeSubThings, exception is thrown and transactional proxy of instance of B sets transaction to rollback only. storeThings method has a try-catch guard for situations where storeSubThings method throws an exception. In catch branch, c.getErrorText method is called in order to return error message in proper language (application has multilanguage support). Method getErrorText has transaction propagation REQUIRES_NEW in order to work correctly in situations where transaction of the calling code is set rollback only.Code:class A { private B b; private C c; @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) void storeThings(things) { // Do some useful things and register a TransactionSynchronization try { b.storeSubThings(things.getSubThings()); } catch (StoreSubThingsException e) { throw new MyAppException( c.getErrorText("error.getting.subthings")); } } } class B { @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) void storeSubThings(subThings) { // perform checks and store subthings // throw StoreSubThingsException if something goes wrong. } } class C { @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class) String getErrorText(String errorCode) { // Queries db for error text corresponding to given // error code in language specified by context. // Returns found error text. } }
Unfortunately spring encounters a problem on resuming outer transaction when leaving method call c.getErrorText and instead of MyAppException, an IllegalTransactionStateException - "Tried to resume invalid JTA transaction" - is thrown from storeThings. Additional problem is that storeThings method registers a TransactionSynchronization before calling b.storeSubThings and if resuming from c.getErrorText fails, this synchronization will never get executed.
As a quick (but not sure if utterly correct) workaround i modified org.springframework.transaction.jta.JtaTransaction Manager to not throw IllegalTransactionStateException from doResume method if resuming fails. With that fix outer transaction (which is set rollback only and rolls back anyway) is resumed and MyAppException is thrown. Registered TransactionSynchronization is executed as well.
Is there a better workaround for the described problem without modifying spring source code?


Reply With Quote