X-Git-Url: http://wamblee.org/gitweb/?a=blobdiff_plain;f=test%2Fenterprise%2Fsrc%2Fmain%2Fjava%2Forg%2Fwamblee%2Fsupport%2Fpersistence%2FTransactionProxyFactory.java;h=548a3cdaebc1a8279ebaef779854807387925a99;hb=f9ccadb956bac942258d9892c66e481ac2aec446;hp=4e72f4845d4a377b7075f62a11e0b8856b0e6783;hpb=4c4b45259c4af24c2551c40df72ad776dd037cbe;p=utils diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/TransactionProxyFactory.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/TransactionProxyFactory.java index 4e72f484..548a3cda 100644 --- a/test/enterprise/src/main/java/org/wamblee/support/persistence/TransactionProxyFactory.java +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/TransactionProxyFactory.java @@ -15,6 +15,7 @@ */ package org.wamblee.support.persistence; + import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -27,10 +28,24 @@ import org.wamblee.support.persistence.JpaBuilder.JpaUnitOfWork; /** * This utility makes sure that each invocation on a certain interface is - * carried out within a JPA unit of work. + * carried out within a JPA unit of work. Note that this is equivalent + * to the sementics of a requiresNew transaction attribute. + * + * Use {@link #getTransactionScopedEntityManager()} to get the transaction + * scoped entity manager to pass to services. * - * Use {@link #getTransactionScopedEntityManager()} to get the transaction scoped - * entity manager to pass to services. + * + * For example: + *
+ *     JpaBuilder builder = ...
+ *     TransactionProxyFactory factory = new TransactionProxyFactory(
+ *           builder, Service.class);
+ *     Service service = new JpaService(factory.getTransactionScopedEntityManager());
+ *     Service proxy = factory.getProxy(service);
+ *     proxy.executeMethod(...); 
+ * 
+ * The above example executes the executeMethod() call on the service object within an active transaction. + * In the constructor of the service a transaction scoped entity manager is passed. * * @param T * Type of interface to proxy. @@ -39,6 +54,13 @@ import org.wamblee.support.persistence.JpaBuilder.JpaUnitOfWork; */ public class TransactionProxyFactory { + /** + * Executes the call on the service within a new transaction. + * + * @author Erik Brakkee + * + * @param Type of the service interface. + */ private class UnitOfWorkInvocationHandler implements InvocationHandler { private T service; @@ -54,13 +76,21 @@ public class TransactionProxyFactory { .execute(new JpaUnitOfWork() { @Override public Object execute(EntityManager aEm) throws Exception { + EntityManager oldEm = ENTITY_MANAGER.get(); try { ENTITY_MANAGER.set(aEm); return aMethod.invoke(service, aArgs); } catch (InvocationTargetException e) { - throw (Exception)e.getCause(); - } finally { - ENTITY_MANAGER.set(null); + Throwable cause = e.getCause(); + if (cause instanceof Exception) { + throw (Exception) cause; + } else if (cause instanceof Error) { + throw (Error) cause; + } + // last resort. + throw new RuntimeException(e); + } finally { + ENTITY_MANAGER.set(oldEm); } } }); @@ -68,9 +98,9 @@ public class TransactionProxyFactory { } - private static final ThreadSpecificProxyFactory ENTITY_MANAGER = - new ThreadSpecificProxyFactory(EntityManager.class); - + private static final ThreadSpecificProxyFactory ENTITY_MANAGER = new ThreadSpecificProxyFactory( + EntityManager.class); + private JpaBuilder jpaBuilder; private Class clazz; @@ -83,8 +113,8 @@ public class TransactionProxyFactory { jpaBuilder = aJpaBuilder; clazz = aClass; } - - public EntityManager getTransactionScopedEntityManager() { + + public EntityManager getTransactionScopedEntityManager() { return ENTITY_MANAGER.getProxy(); } @@ -98,8 +128,9 @@ public class TransactionProxyFactory { new Class[] { InvocationHandler.class }).newInstance( new Object[] { handler }); return proxy; - } catch (Exception e) { - throw new RuntimeException("Could not create proxy for " + clazz.getName(), e); + } catch (Exception e) { + throw new RuntimeException("Could not create proxy for " + + clazz.getName(), e); } } }