aries-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Tim Jones <>
Subject Enhance Aries JPA to be able to specify exception types to rollback on and not rollback on
Date Tue, 13 Oct 2015 20:43:45 GMT
I have been looking at modifying the Aries JPA code to add the Ability to be able to specify
exception types to rollback on and not rollback on 

The current org.apache.aries.jpa.template.JpaTemplate has the following 

public interface JpaTemplate { 
<R> R txExpr(TransactionType type, EmFunction<R> code); 
void tx(TransactionType type, EmConsumer code); 

<R> R txExpr(EmFunction<R> code); 
void tx(EmConsumer code); 

which allows a client to use a Lambda expression e.g. 

em -> { 

What is the best way to specify/pass the list of exceptions to rollback on and not rollback
on to the underlying implementations of the JpaTemplate (currently XAJpaTemplate and ResourceLocalJpaTemplate
in the jpa-support project)? 

I have added extra methods to accept 2 new arguments to the JpaTemplate e.g. 

<R> R txExpr(TransactionType type, 
Class<? extends Throwable>[] exceptionTypesToRollBackOn, 
Class<? extends Throwable>[] exceptionTypesToNotRollBackOn, 
EmFunction<R> code); 

opinions/criticisms? Are there any standards from specs that need to be adhered to? 

Upon modifying the code it became apparent I was running into the issue with throwing checked
exceptions within the Lambda body. 


e.g. consider the snippet below 

public void addTasks(Task1 task1, Task2 task2) throws ParseException { 

new Class[]{ParseException.class}, <--- exceptions to rollback on 
new Class[]{UnsupportedOperationException.class}, <--- exceptions to not rollback on 
em -> { 

dummyCheckedExceptionThrow(); <--- assume this method throws a checked ParseException which
we don't want to wrap in a Runtime exception 




I don't think this is possible to write without further enhancement to the EmConsumer class
which I changed to sneakily throw checked exceptions (see

public interface EmConsumer { 

default void accept(EntityManager em) { 

try { 


} catch (final Exception e) { 



void acceptThrows(EntityManager em) throws Exception; 

public static <T extends Throwable> T sneakyThrow(Throwable t) throws T { 

// Cast to the parameterized type T, in this case that type is RuntimeException. However 
// at runtime the generic types are erased, so that there is no T type anymore to cast to,

// so the cast disappears. So the compiler sees the code with the cast e.g. throw (RuntimeException)
// so it allows the now-unchecked exception to propagate, but the runtime doesn't see the
generic types, 
// so it sees no cast e.g. throw t and therefore it doesn’t complain about a ClassCastException.

// (credit where credit is due -

throw (T) t; 



Unfortunately this change requires that Aries JPA is compiled with 1.8 as the EmConsumer interface
now contains a default method (>= 1.8). 

An unsatisfactory (I think) alternative is for the client to put a try catch block around
the method e.g. dummyCheckedExceptionThrow() that throws the checked exception and wrap the
exception in a Runtime exception and then perhaps unwrap the exception afterwards and rethrow.

Can anyone see other better alternatives? 

Is it possible/advisable to maintain an extra 1.8 branch as is done with the Postgres JDBC


Tim Jones 
Floor 1, 100 McLeod St, Hastings 4120, New Zealand 
PO Box 2006, Hastings 4153, New Zealand 
P: +64 6 871 5700 F: +64 6 871 5709 E: 

View raw message