A nested transaction of a method annotated with @Transactional(value = REQUIRES_NEW) or even with @Transactional(value = REQUIRES_NEW, rollbackOn = Throwable.class) is committed in case of an OutOfMemoryError. This is a serious bug. It should be rolled back!
It makes no difference, whether I cause the OutOfMemoryError by allocating heaps of memory or just write throw new OutOfMemoryError("test"); – the wrong behaviour is the same.
I experimented with multiple Error-subtypes and the same wrong behaviour happens when throwing a StackOverflowError or an IOError. Subtypes of Exception seem to be handled correctly. It only seems to affect subtypes of Error.
I also tested this with PostgreSQL and with H2 – the behaviour is the same.
Note, that this does not happen with the main-transaction. It only affects nested transactions. If I throw an OutOfMemoryError in the main transaction (and don't employ a nested transaction), the transaction is properly rolled back – and no garbage ends up in my DB.
I just experimented further with other types of exceptions. If I throw an IOException, the nested transaction is correctly rolled back, but the main transaction is not – even though I have the following declaration in my ejb-jar.xml:
Are these known problems?
I searched through the tons of "transaction"-related issues, but didn't find any matching the problem that an Error causes a commit instead of a rollback.