You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@onami.apache.org by sc...@apache.org on 2014/04/07 16:12:21 UTC

svn commit: r1585487 [2/5] - in /onami/sandbox/persist: ./ src/main/java/org/apache/onami/persist/ src/sandbox/ src/test/java/org/apache/onami/persist/ src/test/java/org/apache/onami/persist/test/ src/test/java/org/apache/onami/persist/test/transaction...

Modified: onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceModule.java
URL: http://svn.apache.org/viewvc/onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceModule.java?rev=1585487&r1=1585486&r2=1585487&view=diff
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceModule.java (original)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceModule.java Mon Apr  7 14:12:18 2014
@@ -20,245 +20,146 @@ package org.apache.onami.persist;
  */
 
 import com.google.inject.AbstractModule;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
 import com.google.inject.matcher.Matcher;
-import com.google.inject.matcher.Matchers;
-import org.aopalliance.intercept.MethodInterceptor;
 
-import javax.naming.InitialContext;
-import javax.naming.NamingException;
-import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
-import javax.transaction.UserTransaction;
 import java.lang.reflect.AnnotatedElement;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Properties;
 
-import static org.apache.onami.persist.Preconditions.checkNotNull;
+import static com.google.inject.matcher.Matchers.annotatedWith;
 import static com.google.inject.matcher.Matchers.any;
+import static org.apache.onami.persist.Preconditions.checkNotNull;
 
 /**
- * Main module of the jpa-persistence guice extension.
+ * Main module of the onami persist guice extension.
  * <p/>
- * Add either a {@link ApplicationManagedPersistenceUnitModule} or a
- * {@link ContainerManagedPersistenceUnitModule} per persistence unit using the methods
+ * Add persistence unit using the methods
  * <ul>
- * <li>{@link #add(ApplicationManagedPersistenceUnitModule)}</li>
  * <li>{@link #addApplicationManagedPersistenceUnit(String)}</li>
- * <li>{@link #addApplicationManagedPersistenceUnit(String, Properties)}</li>
- * <li>{@link #add(ContainerManagedPersistenceUnitModule)}</li>
- * <li>{@link #addContainerManagedPersistenceUnit(String)}</li>
- * <li>{@link #addContainerManagedPersistenceUnit(String, Properties)}</li>
+ * <li>{@link #addContainerManagedPersistenceUnitWithJndiName(String)}</li>
+ * <li>{@link #addContainerManagedPersistenceUnit(EntityManagerFactory)}</li>
+ * <li>{@link #addContainerManagedPersistenceUnitProvidedBy(Provider<EntityManagerFactory>)}</li>
  * </ul>
- * <p/>
- * If container managed persistence units have been added and JTA transactions are supported.
- * Use {@link #setUserTransactionJndiName(String)} to define the JNDI name of the
- * {@link UserTransaction} provided by the container.
  */
-public final class PersistenceModule
+public abstract class PersistenceModule
     extends AbstractModule
 {
 
-    // ---- Members
+    private List<PersistenceUnitModule> puModules;
+
+    private final PersistenceUnitContainer container = new PersistenceUnitContainer();
+    private final Matcher<AnnotatedElement> transactionalMatcher = annotatedWith( Transactional.class );
+    private final Matcher<Object> anyMatcher = any();
 
-    /**
-     * List of all module builders.
-     */
-    private final List<PersistenceUnitBuilder> moduleBuilders = new ArrayList<PersistenceUnitBuilder>();
-
-    /**
-     * List of all persistence unit modules.
-     * If this list is empty it means that configure has not yet been called
-     */
-    private final List<AbstractPersistenceUnitModule> modules = new ArrayList<AbstractPersistenceUnitModule>();
-
-    /**
-     * Container for holding all registered persistence units.
-     */
-    private final PersistenceUnitContainer puContainer = new PersistenceUnitContainer();
-
-    /**
-     * The JNDI name to lookup the {@link UserTransaction}.
-     */
-    private String utJndiName;
-
-    /**
-     * The {@link UserTransactionFacade}.
-     */
-    private UserTransactionFacade utFacade = null;
-
-    // ---- Methods
-
-    /**
-     * Adds an application managed persistence unit.
-     *
-     * @param puName the name of the persistence unit as specified in the persistence.xml. Must not be {@code null}.
-     * @return a builder to further configure the persistence unit.
-     */
-    public PersistenceUnitBuilder addApplicationManagedPersistenceUnit( String puName )
-    {
-        checkNotNull( puName );
-        return add( new ApplicationManagedPersistenceUnitModule( puName ) );
-    }
-
-    /**
-     * Adds an application managed persistence unit.
-     *
-     * @param puName     the name of the persistence unit as specified in the persistence.xml. Must not be {@code null}.
-     * @param properties the properties to pass to the {@link EntityManagerFactory}. Must not be {@code null}.
-     * @return a builder to further configure the persistence unit.
-     */
-    public PersistenceUnitBuilder addApplicationManagedPersistenceUnit( String puName, Properties properties )
-    {
-        checkNotNull( puName );
-        checkNotNull( properties );
-        return add( new ApplicationManagedPersistenceUnitModule( puName, properties ) );
-    }
-
-    /**
-     * Adds an application managed persistence unit.
-     *
-     * @param module the module of the persistence unit. Must not be {@code null}.
-     * @return a builder to further configure the persistence unit.
-     */
-    public PersistenceUnitBuilder add( ApplicationManagedPersistenceUnitModule module )
-    {
-        ensureConfigurHasNotYetBeenExecuted();
-        checkNotNull( module );
-        final PersistenceUnitBuilder builder = new PersistenceUnitBuilder( module );
-        moduleBuilders.add( builder );
-        return builder;
-    }
-
-    /**
-     * Adds an container managed persistence unit.
-     *
-     * @param emfJndiName the JNDI name of the {@link EntityManagerFactory}. Must not be {@code null}.
-     * @return a builder to further configure the persistence unit.
-     */
-    public PersistenceUnitBuilder addContainerManagedPersistenceUnit( String emfJndiName )
-    {
-        checkNotNull( emfJndiName );
-        return add( new ContainerManagedPersistenceUnitModule( emfJndiName ) );
-    }
-
-    /**
-     * Adds an container managed persistence unit.
-     *
-     * @param emfJndiName the JNDI name of the {@link EntityManagerFactory}. Must not be {@code null}.
-     * @param properties  the properties to pass to the {@link EntityManager}. Must not be {@code null}.
-     * @return a builder to further configure the persistence unit.
-     */
-    public PersistenceUnitBuilder addContainerManagedPersistenceUnit( String emfJndiName, Properties properties )
-    {
-        checkNotNull( emfJndiName );
-        checkNotNull( properties );
-        return add( new ContainerManagedPersistenceUnitModule( emfJndiName, properties ) );
-    }
-
-    /**
-     * Adds an container managed persistence unit.
-     *
-     * @param module the module of the persistence unit. Must not be {@code null}.
-     * @return a builder to further configure the persistence unit.
-     */
-    public PersistenceUnitBuilder add( ContainerManagedPersistenceUnitModule module )
-    {
-        ensureConfigurHasNotYetBeenExecuted();
-        checkNotNull( module );
-        final PersistenceUnitBuilder builder = new PersistenceUnitBuilder( module );
-        moduleBuilders.add( builder );
-        return builder;
-    }
-
-    /**
-     * Setter for defining the JNDI name of the container managed {@link UserTransaction}.
-     *
-     * @param utJndiName the JNDI name of the container managed {@link UserTransaction}.
-     */
-    public void setUserTransactionJndiName( String utJndiName )
-    {
-        ensureConfigurHasNotYetBeenExecuted();
-        this.utJndiName = utJndiName;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
     @Override
-    protected void configure()
+    protected final void configure()
     {
-        if ( configureHasNotBeenExecutedYet() )
+        if ( puModules != null )
         {
-            if ( 0 == moduleBuilders.size() )
-            {
-                addError( "no persistence units defined. At least one persistence unit is required." );
-                return;
-            }
-            initUserTransactionFacade();
-            for ( PersistenceUnitBuilder builder : moduleBuilders )
-            {
-                final AbstractPersistenceUnitModule module = builder.build();
-                puContainer.add( module.getPersistenceService(), module.getUnitOfWork() );
-                modules.add( module );
-            }
+            throw new RuntimeException( "cannot reenter the configure method" );
         }
-
-        for ( AbstractPersistenceUnitModule module : modules )
+        try {
+            puModules = new ArrayList<PersistenceUnitModule>();
+            doConfigure();
+        }
+        finally
         {
-            install( module );
+            puModules = null;
+        }
+    }
 
-            final Matcher<AnnotatedElement> matcher = Matchers.annotatedWith( Transactional.class );
-            final MethodInterceptor transactionInterceptor = module.getTransactionInterceptor( utFacade );
+    private void doConfigure()
+    {
+        configurePersistence();
 
-            bindInterceptor( matcher, any(), transactionInterceptor );
-            bindInterceptor( any(), matcher, transactionInterceptor );
+        for(PersistenceUnitModule pu : puModules)
+        {
+            final TxnInterceptor txnInterceptor = new TxnInterceptor();
+            pu.setPersistenceUnitContainer( container );
+            pu.setTransactionInterceptor( txnInterceptor );
+            install( pu );
+            bindInterceptor( anyMatcher, transactionalMatcher, txnInterceptor );
+            bindInterceptor( transactionalMatcher, anyMatcher, txnInterceptor );
         }
+    }
 
-        bind( PersistenceService.class ).annotatedWith( AllPersistenceUnits.class ).toInstance( puContainer );
-        bind( UnitOfWork.class ).annotatedWith( AllPersistenceUnits.class ).toInstance( puContainer );
-        bind( PersistenceFilter.class ).toInstance( new PersistenceFilter( puContainer ) );
+    protected abstract void configurePersistence();
+
+    protected UnannotatedPersistenceUnitBuilder addApplicationManagedPersistenceUnit( String puName )
+    {
+        checkNotNull( puModules,
+                      "calling addApplicationManagedPersistenceUnit outside of configurePersistence is not supported" );
+        final PersistenceUnitModuleConfigurator configurator = createAndAddPuModule();
+        configurator.setPuName(puName);
+        return configurator;
     }
 
-    /**
-     * @return {@code true} if {@link #configure()} has not yet been invoked.
-     */
-    private boolean configureHasNotBeenExecutedYet()
+    protected UnannotatedPersistenceUnitBuilder addContainerManagedPersistenceUnit( EntityManagerFactory emf )
     {
-        return modules.size() == 0;
+        checkNotNull( puModules,
+                      "calling addContainerManagedPersistenceUnit outside of configurePersistence is not supported" );
+        final PersistenceUnitModuleConfigurator configurator = createAndAddPuModule();
+        configurator.setEmf( emf );
+        return configurator;
     }
 
-    /**
-     * Make sure that the {@link #configure()} method has not been executed yet.
-     */
-    private void ensureConfigurHasNotYetBeenExecuted()
+    protected UnannotatedPersistenceUnitBuilder addContainerManagedPersistenceUnitWithJndiName( String jndiName )
     {
-        if ( configureHasNotBeenExecutedYet() )
-        {
-            return;
-        }
-        throw new IllegalStateException( "cannot change a module after creating the injector." );
+        checkNotNull( puModules,
+                      "calling addContainerManagedPersistenceUnit outside of configurePersistence is not supported" );
+        final PersistenceUnitModuleConfigurator configurator = createAndAddPuModule();
+        configurator.setEmfJndiName( jndiName );
+        return configurator;
     }
 
-    /**
-     * Initializes the field {@link #utFacade} with the {@link UserTransaction} obtained by a
-     * JNDI lookup.
-     */
-    private void initUserTransactionFacade()
+    protected UnannotatedPersistenceUnitBuilder addContainerManagedPersistenceUnitProvidedBy(
+        Provider<EntityManagerFactory> emfProvider )
     {
-        if ( null != utJndiName )
-        {
-            try
-            {
-                final InitialContext ctx = new InitialContext();
-                final UserTransaction txn = (UserTransaction) ctx.lookup( utJndiName );
-                utFacade = new UserTransactionFacade( txn );
-            }
-            catch ( NamingException e )
-            {
-                addError( "lookup for UserTransaction with JNDI name '%s' failed", utJndiName );
-            }
-        }
+        checkNotNull( puModules,
+                      "calling addContainerManagedPersistenceUnit outside of configurePersistence is not supported" );
+        final PersistenceUnitModuleConfigurator configurator = createAndAddPuModule();
+        configurator.setEmfProvider( emfProvider );
+        return configurator;
+    }
+
+    protected UnannotatedPersistenceUnitBuilder addContainerManagedPersistenceUnitProvidedBy(
+        Class<? extends Provider<EntityManagerFactory>> emfProviderClass )
+    {
+        checkNotNull( puModules,
+                      "calling addContainerManagedPersistenceUnit outside of configurePersistence is not supported" );
+        final PersistenceUnitModuleConfigurator configurator = createAndAddPuModule();
+        configurator.setEmfProviderClass( emfProviderClass );
+        return configurator;
+    }
+
+    protected UnannotatedPersistenceUnitBuilder addContainerManagedPersistenceUnitProvidedBy(
+        TypeLiteral<? extends Provider<EntityManagerFactory>> emfProviderType )
+    {
+        checkNotNull( puModules,
+                      "calling addContainerManagedPersistenceUnit outside of configurePersistence is not supported" );
+        final PersistenceUnitModuleConfigurator configurator = createAndAddPuModule();
+        configurator.setEmfProviderType( emfProviderType );
+        return configurator;
     }
 
+    protected UnannotatedPersistenceUnitBuilder addContainerManagedPersistenceUnitProvidedBy(
+        Key<? extends Provider<EntityManagerFactory>> emfProviderKey )
+    {
+        checkNotNull( puModules,
+                      "calling addContainerManagedPersistenceUnit outside of configurePersistence is not supported" );
+        final PersistenceUnitModuleConfigurator configurator = createAndAddPuModule();
+        configurator.setEmfProviderKey( emfProviderKey );
+        return configurator;
+    }
+
+    private PersistenceUnitModuleConfigurator createAndAddPuModule()
+    {
+        final PersistenceUnitModuleConfigurator configurator = new PersistenceUnitModuleConfigurator();
+        puModules.add( configurator.getPuModule() );
+        return configurator;
+    }
 }

Modified: onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceService.java
URL: http://svn.apache.org/viewvc/onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceService.java?rev=1585487&r1=1585486&r2=1585487&view=diff
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceService.java (original)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceService.java Mon Apr  7 14:12:18 2014
@@ -22,15 +22,15 @@ package org.apache.onami.persist;
 /**
  * This is the main control to the entire persistence engine. Before calling any other method
  * of either {@link UnitOfWork}, {@link EntityManagerProvider}, or any method annotated with
- * @{@link Transactional} the persistence service must be started.
+ * {@link Transactional @Transactional} the persistence service must be started.
  */
 public interface PersistenceService
 {
 
     /**
-     * Starts the underlying persistence engine and makes jpa-persist ready for use.
-     * This method must be called by your code prior to using any other jpa-persist artifacts.
-     * If you are using jpa-persist in a web container {@link PersistenceFilter} will call this
+     * Starts the underlying persistence engine and makes onami-persist ready for use.
+     * This method must be called by your code prior to using any other onami-persist artifacts.
+     * If you are using onami-persist in a web container {@link PersistenceFilter} will call this
      * method upon initialization of the web application.
      *
      * @throws IllegalArgumentException if the service is already running.

Modified: onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitContainer.java
URL: http://svn.apache.org/viewvc/onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitContainer.java?rev=1585487&r1=1585486&r2=1585487&view=diff
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitContainer.java (original)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitContainer.java Mon Apr  7 14:12:18 2014
@@ -19,6 +19,9 @@ package org.apache.onami.persist;
  * under the License.
  */
 
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
 import java.util.HashSet;
 import java.util.Set;
 
@@ -26,15 +29,13 @@ import static org.apache.onami.persist.P
 
 /**
  * Container of persistence units. This is a convenience wrapper for multiple
- * persistence units. calling any method of either {@link PersistenceService} or
- * {@link UnitOfWork} will propagate this call to all added persistence units.
+ * persistence units.
  */
+@Singleton
 class PersistenceUnitContainer
-    implements PersistenceService, UnitOfWork
+    implements AllPersistenceServices, AllUnitsOfWork
 {
 
-    // ---- Members
-
     /**
      * Collection of all known persistence services.
      */
@@ -45,14 +46,13 @@ class PersistenceUnitContainer
      */
     private final Set<UnitOfWork> unitsOfWork = new HashSet<UnitOfWork>();
 
-    // ---- Methods
-
     /**
      * Adds a persistence service and a unit of work to this container.
      *
      * @param ps  the persistence service to add. Must not be {@code null}.
      * @param uow the unit of work to add. Must not be {@code null}.
      */
+    @Inject
     void add( PersistenceService ps, UnitOfWork uow )
     {
         checkNotNull( ps );
@@ -65,81 +65,94 @@ class PersistenceUnitContainer
      * {@inheritDoc}
      */
     // @Override
-    public synchronized void start()
-    {
-        for ( PersistenceService ps : persistenceServices )
-        {
-            ps.start();
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    // @Override
-    public synchronized boolean isRunning()
+    public void startAllStoppedPersistenceServices()
     {
+        AggregatedException.Builder exceptionBuilder = new AggregatedException.Builder();
         for ( PersistenceService ps : persistenceServices )
         {
-            if ( !ps.isRunning() )
+            try
             {
-                return false;
+                if(! ps.isRunning())
+                {
+                    ps.start();
+                }
+            }
+            catch ( Exception e )
+            {
+                exceptionBuilder.add( e );
             }
         }
-        return true;
+        exceptionBuilder.throwRuntimeExceptionIfHasCauses(
+            "multiple exception occurred while starting the persistence service" );
     }
 
     /**
      * {@inheritDoc}
      */
     // @Override
-    public synchronized void stop()
+    public void stopAllRunningPersistenceServices()
     {
+        AggregatedException.Builder exceptionBuilder = new AggregatedException.Builder();
         for ( PersistenceService ps : persistenceServices )
         {
-            ps.stop();
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    // @Override
-    public void begin()
-    {
-        for ( UnitOfWork unitOfWork : unitsOfWork )
-        {
-            unitOfWork.begin();
+            try
+            {
+                ps.stop();
+            }
+            catch ( Exception e )
+            {
+                exceptionBuilder.add( e );
+            }
         }
+        exceptionBuilder.throwRuntimeExceptionIfHasCauses(
+            "multiple exception occurred while stopping the persistence service" );
     }
 
     /**
      * {@inheritDoc}
      */
     // @Override
-    public boolean isActive()
+    public void beginAllInactiveUnitsOfWork()
     {
+        AggregatedException.Builder exceptionBuilder = new AggregatedException.Builder();
         for ( UnitOfWork unitOfWork : unitsOfWork )
         {
-            if ( !unitOfWork.isActive() )
+            try
             {
-                return false;
+                if(! unitOfWork.isActive())
+                {
+                    unitOfWork.begin();
+                }
+            }
+            catch ( Exception e )
+            {
+                exceptionBuilder.add( e );
             }
         }
-        return true;
+        exceptionBuilder.throwRuntimeExceptionIfHasCauses(
+            "multiple exception occurred while starting the unit of work" );
     }
 
     /**
      * {@inheritDoc}
      */
     // @Override
-    public void end()
+    public void endAllUnitsOfWork()
     {
+        AggregatedException.Builder exceptionBuilder = new AggregatedException.Builder();
         for ( UnitOfWork unitOfWork : unitsOfWork )
         {
-            unitOfWork.end();
+            try
+            {
+                unitOfWork.end();
+            }
+            catch ( Exception e )
+            {
+                exceptionBuilder.add( e );
+            }
         }
-
+        exceptionBuilder.throwRuntimeExceptionIfHasCauses(
+            "multiple exception occurred while ending the unit of work" );
     }
 
 }

Added: onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitModule.java
URL: http://svn.apache.org/viewvc/onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitModule.java?rev=1585487&view=auto
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitModule.java (added)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitModule.java Mon Apr  7 14:12:18 2014
@@ -0,0 +1,258 @@
+package org.apache.onami.persist;
+
+import com.google.inject.Key;
+import com.google.inject.PrivateModule;
+import com.google.inject.util.Providers;
+
+import javax.persistence.EntityManagerFactory;
+import javax.transaction.UserTransaction;
+import java.util.Properties;
+
+import static org.apache.onami.persist.Preconditions.checkNotNull;
+
+/**
+ * Module for configuring a single persistence unit.
+ *
+ * @see PersistenceModule
+ */
+class PersistenceUnitModule
+    extends PrivateModule
+{
+
+    /**
+     * The configuration for the persistence unit.
+     */
+    private final PersistenceUnitModuleConfigurator config;
+
+    /**
+     * Transaction interceptor which can be passed in from the outside for injecting dependencies
+     */
+    private TxnInterceptor transactionInterceptor;
+
+    /**
+     * Persistence unit container which can be passed in from the outside for adding this persistence unit to it.
+     */
+    private PersistenceUnitContainer container;
+
+    /**
+     * Constructor.
+     *
+     * @param configurator the configuration holding all configs.
+     */
+    PersistenceUnitModule( PersistenceUnitModuleConfigurator configurator )
+    {
+        this.config = checkNotNull( configurator, "config is mandatory!" );
+    }
+
+    /**
+     * Sets the transaction interceptor for injection of dependencies.
+     *
+     * @param transactionInterceptor the interceptor into which to inject dependencies.
+     */
+    void setTransactionInterceptor( TxnInterceptor transactionInterceptor )
+    {
+        this.transactionInterceptor = transactionInterceptor;
+    }
+
+    /**
+     * Sets the persistence unit container for adding this persistence unit to it.
+     *
+     * @param container the container to which to add the persistence unit.
+     */
+    void setPersistenceUnitContainer( PersistenceUnitContainer container )
+    {
+        this.container = container;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void configure()
+    {
+        bind( AnnotationHolder.class ).toInstance( config.getAnnotationHolder() );
+
+        bindPersistenceServiceAndEntityManagerFactoryProviderAndProperties();
+        bindTransactionFacadeFactory();
+
+        bind( EntityManagerProvider.class ).to( EntityManagerProviderImpl.class );
+        bind( UnitOfWork.class ).to( EntityManagerProviderImpl.class );
+
+        exposePersistenceServiceAndEntityManagerProviderAndUnitOfWork();
+
+        // request injection into transaction interceptor - this adds the required dependencies to the interceptor.
+        if ( transactionInterceptor != null )
+        {
+            requestInjection( transactionInterceptor );
+        }
+
+        // request injection into persistence unit container - this adds the current persistence unit to the container.
+        if ( container != null )
+        {
+            requestInjection( container );
+        }
+    }
+
+    /**
+     * exposes the following interfaces (optionally annotated if an annotation is defined in the configuration).
+     * <ul>
+     * <li>{@link PersistenceService}</li>
+     * <li>{@link EntityManagerProvider}</li>
+     * <li>{@link UnitOfWork}</li>
+     * </ul>
+     */
+    private void exposePersistenceServiceAndEntityManagerProviderAndUnitOfWork()
+    {
+        if ( config.isAnnotated() )
+        {
+            bindAndExposedAnnotated( PersistenceService.class );
+            bindAndExposedAnnotated( EntityManagerProvider.class );
+            bindAndExposedAnnotated( UnitOfWork.class );
+        }
+        else
+        {
+            expose( PersistenceService.class );
+            expose( EntityManagerProvider.class );
+            expose( UnitOfWork.class );
+        }
+    }
+
+    /**
+     * helper to expose a binding with annotation added.
+     *
+     * @param type the type to expose.
+     * @param <T>  the type to expose.
+     */
+    private <T> void bindAndExposedAnnotated( Class<T> type )
+    {
+        bind( type ).annotatedWith( config.getAnnotation() ).to( Key.get( type ) );
+        expose( type ).annotatedWith( config.getAnnotation() );
+    }
+
+    private void bindPersistenceServiceAndEntityManagerFactoryProviderAndProperties()
+    {
+        if ( config.isApplicationManagedPersistenceUnit() )
+        {
+            bindApplicationManagedPersistenceServiceAndEntityManagerFactoryProviderAndProperties();
+        }
+        else
+        {
+            bindContainerManagedPersistenceServiceAndEntityManagerFactoryProviderAndProperties();
+        }
+    }
+
+    private void bindApplicationManagedPersistenceServiceAndEntityManagerFactoryProviderAndProperties()
+    {
+        bind( PersistenceService.class ).to( ApplicationManagedEntityManagerFactoryProvider.class );
+        bind( EntityManagerFactoryProvider.class ).to( ApplicationManagedEntityManagerFactoryProvider.class );
+        bind( Properties.class ).annotatedWith( ForContainerManaged.class ).toProvider(
+            Providers.<Properties>of( null ) );
+        bind( Properties.class ).annotatedWith( ForApplicationManaged.class ).toProvider(
+            Providers.of( config.getProperties() ) );
+
+        // required in ApplicationManagedEntityManagerFactoryProvider
+        bind( EntityManagerFactoryFactory.class );
+        // required in EntityManagerFactoryFactory
+        bind( String.class ).annotatedWith( ForApplicationManaged.class ).toInstance( config.getPuName() );
+    }
+
+    private void bindContainerManagedPersistenceServiceAndEntityManagerFactoryProviderAndProperties()
+    {
+        bind( PersistenceService.class ).to( ContainerManagedEntityManagerFactoryProvider.class );
+        bind( EntityManagerFactoryProvider.class ).to( ContainerManagedEntityManagerFactoryProvider.class );
+        bind( Properties.class ).annotatedWith( ForContainerManaged.class ).toProvider(
+            Providers.of( config.getProperties() ) );
+        bind( Properties.class ).annotatedWith( ForApplicationManaged.class ).toProvider(
+            Providers.<Properties>of( null ) );
+
+        // required in ContainerManagedEntityManagerFactoryProvider
+        bindEntityManagerFactorySource();
+    }
+
+    private void bindEntityManagerFactorySource()
+    {
+        if ( config.isEmfProvidedByJndiLookup() )
+        {
+            bind( EntityManagerFactorySource.class ).to( EntityManagerFactorySourceByJndiLookup.class );
+
+            // required in EntityManagerFactorySourceByJndiLookup
+            bind( String.class ).annotatedWith( ForContainerManaged.class ).toInstance( config.getEmfJndiName() );
+        }
+        else
+        {
+            bind( EntityManagerFactorySource.class ).to( EntityManagerFactorySourceViaProvider.class );
+
+            // required in EntityManagerFactorySourceViaProvider
+            bindInternalEntityManagerFactoryProvider();
+        }
+    }
+
+    private void bindInternalEntityManagerFactoryProvider()
+    {
+        if ( config.isEmfProvidedByInstance() )
+        {
+            bind( EntityManagerFactory.class ).annotatedWith( ForContainerManaged.class ).toInstance( config.getEmf() );
+        }
+        else if ( config.isEmfProvidedByProvider() )
+        {
+            bind( EntityManagerFactory.class ).annotatedWith( ForContainerManaged.class ).toProvider(
+                config.getEmfProvider() );
+        }
+        else if ( config.isEmfProvidedByProviderKey() )
+        {
+            bind( EntityManagerFactory.class ).annotatedWith( ForContainerManaged.class ).toProvider(
+                config.getEmfProviderKey() );
+        }
+        else
+        {
+            throw new RuntimeException( "EntityManager is improperly configured" );
+        }
+    }
+
+    private void bindTransactionFacadeFactory()
+    {
+        if ( config.isJta() )
+        {
+            bindJtaTransactionFacadeFactory();
+        }
+        else
+        {
+            bind( TransactionFacadeFactory.class ).to( ResourceLocalTransactionFacadeFactory.class );
+        }
+    }
+
+    private void bindJtaTransactionFacadeFactory()
+    {
+        bind( TransactionFacadeFactory.class ).to( JtaTransactionFacadeFactory.class );
+
+        // required in JtaTransactionFacadeFactory
+        binInternalUserTransactionProvider();
+    }
+
+    private void binInternalUserTransactionProvider()
+    {
+        if ( config.isUserTransactionProvidedByInstance() )
+        {
+            bind( UserTransaction.class ).toInstance( config.getUserTransaction() );
+        }
+        else if ( config.isUserTransactionProvidedByJndiLookup() )
+        {
+            bind( UserTransaction.class ).toProvider( UserTransactionProviderByJndiLookup.class );
+
+            // required in UserTransactionProviderByJndiLookup
+            bind( String.class ).annotatedWith( UserTransactionJndiName.class ).toInstance( config.getUtJndiName() );
+        }
+        else if ( config.isUserTransactionProvidedByProvider() )
+        {
+            bind( UserTransaction.class ).toProvider( config.getUtProvider() );
+        }
+        else if ( config.isUserTransactionProvidedByProviderKey() )
+        {
+            bind( UserTransaction.class ).toProvider( config.getUtProviderKey() );
+        }
+        else
+        {
+            throw new RuntimeException( "UserTransaction is improperly configured" );
+        }
+    }
+}

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitModule.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitModule.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitModule.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitModuleConfigurator.java
URL: http://svn.apache.org/viewvc/onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitModuleConfigurator.java?rev=1585487&view=auto
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitModuleConfigurator.java (added)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitModuleConfigurator.java Mon Apr  7 14:12:18 2014
@@ -0,0 +1,249 @@
+package org.apache.onami.persist;
+
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
+
+import javax.persistence.EntityManagerFactory;
+import javax.transaction.UserTransaction;
+import java.lang.annotation.Annotation;
+import java.util.Properties;
+
+class PersistenceUnitModuleConfigurator
+    implements UnannotatedPersistenceUnitBuilder, AnnotatedPersistenceUnitBuilder, UnconfiguredPersistenceUnitBuilder
+{
+    private Class<? extends Annotation> annotation;
+
+    private UserTransaction userTransaction;
+
+    private String utJndiName;
+
+    private Provider<UserTransaction> utProvider;
+
+    private Key<? extends Provider<UserTransaction>> utProviderKey;
+
+    private Properties properties;
+
+    private String puName;
+
+    private EntityManagerFactory emf;
+
+    private String emfJndiName;
+
+    private Provider<EntityManagerFactory> emfProvider;
+
+    private Key<? extends Provider<EntityManagerFactory>> emfProviderKey;
+
+    PersistenceUnitModule getPuModule()
+    {
+        return new PersistenceUnitModule( this );
+    }
+
+    public AnnotatedPersistenceUnitBuilder annotatedWith( Class<? extends Annotation> annotation )
+    {
+        this.annotation = annotation;
+        return this;
+    }
+
+    public UnconfiguredPersistenceUnitBuilder useLocalTransaction()
+    {
+        // does nothing
+        return this;
+    }
+
+    public UnconfiguredPersistenceUnitBuilder useGlobalTransaction( UserTransaction userTransaction )
+    {
+        this.userTransaction = userTransaction;
+        return this;
+    }
+
+    public UnconfiguredPersistenceUnitBuilder useGlobalTransactionWithJndiName( String utJndiName )
+    {
+        this.utJndiName = utJndiName;
+        return this;
+    }
+
+    public UnconfiguredPersistenceUnitBuilder useGlobalTransactionProvidedBy( Provider<UserTransaction> utProvider )
+    {
+        this.utProvider = utProvider;
+        return this;
+    }
+
+    public UnconfiguredPersistenceUnitBuilder useGlobalTransactionProvidedBy(
+        Class<? extends Provider<UserTransaction>> utProviderClass )
+    {
+        utProviderKey = Key.get( utProviderClass );
+        return this;
+    }
+
+    public UnconfiguredPersistenceUnitBuilder useGlobalTransactionProvidedBy(
+        TypeLiteral<? extends Provider<UserTransaction>> utProviderType )
+    {
+        utProviderKey = Key.get( utProviderType );
+        return this;
+    }
+
+    public UnconfiguredPersistenceUnitBuilder useGlobalTransactionProvidedBy(
+        Key<? extends Provider<UserTransaction>> utProviderKey )
+    {
+        this.utProviderKey = utProviderKey;
+        return this;
+    }
+
+    public void addProperties( Properties properties )
+    {
+        this.properties = properties;
+    }
+
+    public void setPuName( String puName )
+    {
+        this.puName = puName;
+    }
+
+    public void setEmf( EntityManagerFactory emf )
+    {
+        this.emf = emf;
+    }
+
+    public void setEmfJndiName( String emfJndiName )
+    {
+        this.emfJndiName = emfJndiName;
+    }
+
+    public void setEmfProvider( Provider<EntityManagerFactory> emfProvider )
+    {
+        this.emfProvider = emfProvider;
+    }
+
+    public void setEmfProviderClass( Class<? extends Provider<EntityManagerFactory>> emfProviderClass )
+    {
+        this.emfProviderKey = Key.get( emfProviderClass );
+    }
+
+    public void setEmfProviderType( TypeLiteral<? extends Provider<EntityManagerFactory>> emfProviderType )
+    {
+        this.emfProviderKey = Key.get( emfProviderType );
+    }
+
+    public void setEmfProviderKey( Key<? extends Provider<EntityManagerFactory>> emfProviderKey )
+    {
+        this.emfProviderKey = emfProviderKey;
+    }
+
+    public boolean isApplicationManagedPersistenceUnit()
+    {
+        return puName != null;
+    }
+
+
+    UserTransaction getUserTransaction()
+    {
+        return userTransaction;
+    }
+
+    String getUtJndiName()
+    {
+        return utJndiName;
+    }
+
+    Provider<UserTransaction> getUtProvider()
+    {
+        return utProvider;
+    }
+
+    Key<? extends Provider<UserTransaction>> getUtProviderKey()
+    {
+        return utProviderKey;
+    }
+
+    Properties getProperties()
+    {
+        return properties;
+    }
+
+    String getPuName()
+    {
+        return puName;
+    }
+
+    EntityManagerFactory getEmf()
+    {
+        return emf;
+    }
+
+    String getEmfJndiName()
+    {
+        return emfJndiName;
+    }
+
+    Provider<EntityManagerFactory> getEmfProvider()
+    {
+        return emfProvider;
+    }
+
+    Key<? extends Provider<EntityManagerFactory>> getEmfProviderKey()
+    {
+        return emfProviderKey;
+    }
+
+    public boolean isEmfProvidedByJndiLookup()
+    {
+        return emfJndiName != null;
+    }
+
+    public boolean isEmfProvidedByInstance()
+    {
+        return emf != null;
+    }
+
+    public boolean isEmfProvidedByProvider()
+    {
+        return emfProvider != null;
+    }
+
+    public boolean isEmfProvidedByProviderKey()
+    {
+        return emfProviderKey != null;
+    }
+
+    public boolean isJta()
+    {
+        return utJndiName != null || userTransaction != null || utProvider != null || utProviderKey != null;
+    }
+
+    public boolean isUserTransactionProvidedByJndiLookup()
+    {
+        return utJndiName != null;
+    }
+
+
+    public boolean isUserTransactionProvidedByInstance()
+    {
+        return userTransaction != null;
+    }
+
+    public boolean isUserTransactionProvidedByProvider()
+    {
+        return utProvider != null;
+    }
+
+    public boolean isUserTransactionProvidedByProviderKey()
+    {
+        return utProviderKey != null;
+    }
+
+    public boolean isAnnotated()
+    {
+        return annotation != null;
+    }
+
+    public AnnotationHolder getAnnotationHolder()
+    {
+        return new AnnotationHolder( annotation );
+    }
+
+    Class<? extends Annotation> getAnnotation()
+    {
+        return annotation;
+    }
+}

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitModuleConfigurator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitModuleConfigurator.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitModuleConfigurator.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: onami/sandbox/persist/src/main/java/org/apache/onami/persist/Preconditions.java
URL: http://svn.apache.org/viewvc/onami/sandbox/persist/src/main/java/org/apache/onami/persist/Preconditions.java?rev=1585487&r1=1585486&r2=1585487&view=diff
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/Preconditions.java (original)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/Preconditions.java Mon Apr  7 14:12:18 2014
@@ -28,14 +28,16 @@ class Preconditions
     /**
      * Check that a reference is not null.
      *
-     * @param <T> the type of the reference
+     * @param <T>       the type of the reference
      * @param reference the reference to check.
      * @return the reference itself.
      * @throws NullPointerException if the reference is null.
      */
-    static <T> T checkNotNull(T reference) {
-        if (reference == null) {
-            throw new NullPointerException(  );
+    static <T> T checkNotNull( T reference )
+    {
+        if ( reference == null )
+        {
+            throw new NullPointerException();
         }
         return reference;
     }
@@ -43,14 +45,16 @@ class Preconditions
     /**
      * Check that a reference is not null.
      *
-     * @param <T> the type of the reference
+     * @param <T>       the type of the reference
      * @param reference the reference to check.
-     * @param message the message of the NullPointerException if one is thrown.
+     * @param message   the message of the NullPointerException if one is thrown.
      * @return the reference itself.
      * @throws NullPointerException if the reference is null.
      */
-    static <T> T checkNotNull(T reference, String message) {
-        if (reference == null) {
+    static <T> T checkNotNull( T reference, String message )
+    {
+        if ( reference == null )
+        {
             throw new NullPointerException( message );
         }
         return reference;

Added: onami/sandbox/persist/src/main/java/org/apache/onami/persist/ResourceLocalTransactionFacadeFactory.java
URL: http://svn.apache.org/viewvc/onami/sandbox/persist/src/main/java/org/apache/onami/persist/ResourceLocalTransactionFacadeFactory.java?rev=1585487&view=auto
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/ResourceLocalTransactionFacadeFactory.java (added)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/ResourceLocalTransactionFacadeFactory.java Mon Apr  7 14:12:18 2014
@@ -0,0 +1,168 @@
+package org.apache.onami.persist;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+import javax.persistence.EntityTransaction;
+
+import static org.apache.onami.persist.Preconditions.checkNotNull;
+
+/**
+ * Factory for transaction facades in case of resource local transactions.
+ */
+@Singleton
+class ResourceLocalTransactionFacadeFactory
+    implements TransactionFacadeFactory
+{
+
+    /**
+     * The provider for the entity manager.
+     */
+    private final EntityManagerProvider emProvider;
+
+    /**
+     * Constructor.
+     *
+     * @param emProvider the provider for the entity manager
+     */
+    @Inject
+    ResourceLocalTransactionFacadeFactory( EntityManagerProvider emProvider )
+    {
+        this.emProvider = checkNotNull( emProvider, "emProvider is mandatory!" );
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    // @Override
+    public TransactionFacade createTransactionFacade()
+    {
+        final EntityTransaction txn = emProvider.get().getTransaction();
+        if ( txn.isActive() )
+        {
+            return new Inner( txn );
+        }
+        else
+        {
+            return new Outer( txn );
+        }
+    }
+
+    /**
+     * TransactionFacade representing an inner (nested) transaction.
+     * Starting and committing a transaction has no effect.
+     * This Facade will set the rollbackOnly flag in case of a roll back.
+     */
+    private static class Inner
+        implements TransactionFacade
+    {
+        private final EntityTransaction txn;
+
+        Inner( EntityTransaction txn )
+        {
+            this.txn = checkNotNull( txn, "txn is mandatory!" );
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        // @Override
+        public void begin()
+        {
+            // Do nothing
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        // @Override
+        public void commit()
+        {
+            // Do nothing
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        // @Override
+        public void rollback()
+        {
+            txn.setRollbackOnly();
+        }
+    }
+
+    /**
+     * TransactionFacade representing an outer transaction.
+     * This Facade starts and ends the transaction.
+     * If an inner transaction has set the rollbackOnly flag the transaction will be rolled back
+     * in any case.
+     */
+    private static class Outer
+        implements TransactionFacade
+    {
+        private final EntityTransaction txn;
+
+        /**
+         * {@inheritDoc}
+         */
+        Outer( EntityTransaction txn )
+        {
+            this.txn = checkNotNull( txn, "txn is mandatory!" );
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        // @Override
+        public void begin()
+        {
+            txn.begin();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        // @Override
+        public void commit()
+        {
+            if ( txn.getRollbackOnly() )
+            {
+                txn.rollback();
+            }
+            else
+            {
+                txn.commit();
+            }
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        // @Override
+        public void rollback()
+        {
+            txn.rollback();
+        }
+    }
+
+}

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/ResourceLocalTransactionFacadeFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/ResourceLocalTransactionFacadeFactory.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/ResourceLocalTransactionFacadeFactory.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionFacade.java
URL: http://svn.apache.org/viewvc/onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionFacade.java?rev=1585487&r1=1585486&r2=1585487&view=diff
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionFacade.java (original)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionFacade.java Mon Apr  7 14:12:18 2014
@@ -19,12 +19,9 @@ package org.apache.onami.persist;
  * under the License.
  */
 
-import javax.persistence.EntityTransaction;
-import javax.transaction.UserTransaction;
-
 /**
  * Interface which hides away the details of inner (nested) and outer transactions as well
- * as the details between {@link EntityTransaction} and {@link UserTransaction}.
+ * as the details between {@link javax.persistence.EntityTransaction} and {@link javax.transaction.UserTransaction}.
  */
 interface TransactionFacade
 {

Added: onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionFacadeFactory.java
URL: http://svn.apache.org/viewvc/onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionFacadeFactory.java?rev=1585487&view=auto
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionFacadeFactory.java (added)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionFacadeFactory.java Mon Apr  7 14:12:18 2014
@@ -0,0 +1,34 @@
+package org.apache.onami.persist;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Factory for {@link TransactionFacade}.
+ */
+interface TransactionFacadeFactory
+{
+
+    /**
+     * Creates a new transaction facade.
+     *
+     * @return the transaction facade
+     */
+    TransactionFacade createTransactionFacade();
+}

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionFacadeFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionFacadeFactory.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionFacadeFactory.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: onami/sandbox/persist/src/main/java/org/apache/onami/persist/Transactional.java
URL: http://svn.apache.org/viewvc/onami/sandbox/persist/src/main/java/org/apache/onami/persist/Transactional.java?rev=1585487&r1=1585486&r2=1585487&view=diff
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/Transactional.java (original)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/Transactional.java Mon Apr  7 14:12:18 2014
@@ -39,20 +39,20 @@ import java.lang.annotation.Target;
  * transaction will be marked as rollbackOnly.
  * <p/>
  * Guice uses AOP to enhance a method annotated with @{@link Transactional} with a wrapper.
- * This means the @{@link Transactional} only works as expected when:
+ * This means the {@link Transactional @Transactional} only works as expected when:
  * <ul>
  * <li>
- * The object on which the method is called has been created by guice.
+ * The object on which the method is called has been created by guice.<br/>
  * This can be achieved by having it (or a {@link Provider}) injected into your class
  * or by calling {@link Injector#getInstance(Class)} or {@link Injector#getInstance(Key)}.
  * </li>
  * <li>
- * The method which should be run transactional is not private and not final
+ * The method which should be run transactional is not private, not static and not final.
  * </li>
  * </ul>
  */
-@Target({ ElementType.METHOD, ElementType.TYPE })
-@Retention(RetentionPolicy.RUNTIME)
+@Target( { ElementType.METHOD, ElementType.TYPE } )
+@Retention( RetentionPolicy.RUNTIME )
 @Inherited
 public @interface Transactional
 {

Added: onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionalAnnotationHelper.java
URL: http://svn.apache.org/viewvc/onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionalAnnotationHelper.java?rev=1585487&view=auto
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionalAnnotationHelper.java (added)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionalAnnotationHelper.java Mon Apr  7 14:12:18 2014
@@ -0,0 +1,161 @@
+package org.apache.onami.persist;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import org.aopalliance.intercept.MethodInvocation;
+
+import java.lang.annotation.Annotation;
+
+import static java.util.Arrays.asList;
+import static org.apache.onami.persist.Preconditions.checkNotNull;
+
+/**
+ * Helper class for working with {@link Transactional @Transactional} annotations.
+ */
+@Singleton
+class TransactionalAnnotationHelper
+{
+
+    /**
+     * Annotation of the persistence unit.
+     */
+    private final Class<? extends Annotation> puAnntoation;
+
+    /**
+     * Reader for {@link Transactional @Transactional} annotations.
+     */
+    private final TransactionalAnnotationReader txnAnnoReader;
+
+    /**
+     * Constructor.
+     *
+     * @param annotationHolder Holder of teh annotation of the persistence unit.
+     * @param txnAnnoReader    reader for {@link Transactional @Transactional} annotations.
+     */
+    @Inject
+    TransactionalAnnotationHelper( AnnotationHolder annotationHolder, TransactionalAnnotationReader txnAnnoReader )
+    {
+        this.puAnntoation = annotationHolder.getAnnotation();
+        this.txnAnnoReader = checkNotNull( txnAnnoReader, "txnAnnoReader is mandatory!" );
+    }
+
+    /**
+     * Decides if the current persistence unit participates in a transaction for the given method invocation.
+     * For a detailed description of when a persistence unit participates see the documentation at the
+     * {@link Transactional @Transactional} annotation.
+     *
+     * @param methodInvocation the method invocation which may be wrapped in a transaction.
+     * @return {@code true} if the current persistence unit participates in a transaction for the given method.
+     */
+    public boolean persistenceUnitParticipatesInTransactionFor( MethodInvocation methodInvocation )
+    {
+        return puAnntoation == null || participates( methodInvocation );
+    }
+
+    /**
+     * Decides if the current persistence unit participates in a transaction for the given method invocation.
+     * The persistence unit has is annotated.
+     *
+     * @param methodInvocation the method invocation which may be wrapped in a transaction.
+     * @return {@code true} if the current persistence unit participates in a transaction for the given method.
+     */
+    private boolean participates( MethodInvocation methodInvocation )
+    {
+        final Transactional transactional = txnAnnoReader.readAnnotationFrom( methodInvocation );
+        final Class<? extends Annotation>[] onUnits = transactional.onUnits();
+        return isEmpty( onUnits ) || contains( onUnits, puAnntoation );
+    }
+
+    /**
+     * Returns {@code true} if the given array is empty.
+     *
+     * @param array the array to test for emptiness.
+     * @return {@code true} if the the given array has is {@code null} or has length 0.
+     */
+    private boolean isEmpty( Object[] array )
+    {
+        return array == null || array.length == 0;
+    }
+
+    /**
+     * Returns {@code true} if the given array contains the specified element.
+     *
+     * @param array the array in which to search for the specified element.
+     * @param key   the element to look for.
+     * @return {@code true} if the given array contains the specified element.
+     */
+    private boolean contains( Object[] array, Object key )
+    {
+        return asList( array ).contains( key );
+    }
+
+    /**
+     * Decides if a rollback is necessary for the given method invocation and a thrown exception.
+     *
+     * @param methodInvocation the method invocation during which an exception was thrown.
+     * @param exc              the exception which was thrown
+     * @return {@code true} if the transaction needs to be rolled back.
+     */
+    public boolean isRollbackNecessaryFor( MethodInvocation methodInvocation, Throwable exc )
+    {
+        final Transactional transactional = txnAnnoReader.readAnnotationFrom( methodInvocation );
+        return isRollbackNecessaryFor( transactional, exc );
+    }
+
+    /**
+     * Decides if a rollback is necessary for the given transactional annotation and a thrown exception.
+     *
+     * @param transactional the transactional annotation of the method during which an exception was thrown.
+     * @param exc           the exception which was thrown
+     * @return {@code true} if the transaction needs to be rolled back.
+     */
+    private boolean isRollbackNecessaryFor( Transactional transactional, Throwable exc )
+    {
+        for ( Class<? extends Exception> rollbackOn : transactional.rollbackOn() )
+        {
+            if ( rollbackOn.isInstance( exc ) )
+            {
+                return isNotIgnoredForRollback( transactional, exc );
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Decides if a rollback is not performed for the given transactional annotation and a thrown exception.
+     *
+     * @param transactional the transactional annotation of the method during which an exception was thrown.
+     * @param exc           the exception which was thrown
+     * @return {@code true} if the transaction needs to be rolled back.
+     */
+    private boolean isNotIgnoredForRollback( Transactional transactional, Throwable exc )
+    {
+        for ( Class<? extends Exception> ignore : transactional.ignore() )
+        {
+            if ( ignore.isInstance( exc ) )
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+}

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionalAnnotationHelper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionalAnnotationHelper.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionalAnnotationHelper.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionalAnnotationReader.java
URL: http://svn.apache.org/viewvc/onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionalAnnotationReader.java?rev=1585487&r1=1585486&r2=1585487&view=diff
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionalAnnotationReader.java (original)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionalAnnotationReader.java Mon Apr  7 14:12:18 2014
@@ -19,47 +19,33 @@ package org.apache.onami.persist;
  * under the License.
  */
 
+import com.google.inject.Singleton;
 import org.aopalliance.intercept.MethodInvocation;
 
 import java.lang.reflect.Method;
 
 /**
- * Reader which obtains the concrete @{@link Transactional} annotation on a method. The reader may use some sort of
- * caching.
+ * Reader which obtains the concrete {@link Transactional @Transactional} annotation of a method.
  */
+@Singleton
 class TransactionalAnnotationReader
 {
-    private static final Transactional DEFAULT_TRANSACTIONAL = DefaultTransactional.class.getAnnotation( Transactional.class );
-
     /**
-     * cache for {@link Transactional} annotations per method.
+     * Constant holding the a transactional instance with all default values.
      */
-    final TransactionalCache transactionalCache = new TransactionalCache();
-
+    private static final Transactional DEFAULT_TRANSACTIONAL =
+        DefaultTransactional.class.getAnnotation( Transactional.class );
 
     /**
-     * Reads the @{@link Transactional} of a given method invocation.
+     * Reads the {@link Transactional @Transactional} of a given method invocation.
      *
-     * @param methodInvocation the method invocation for which to obtain the @{@link Transactional}.
-     * @return the @{@link Transactional} of the given method invocation. Never {@code null}.
+     * @param methodInvocation the method invocation for which to obtain the {@link Transactional @Transactional}.
+     * @return the {@link Transactional @Transactional} of the given method invocation. Never {@code null}.
      */
     Transactional readAnnotationFrom( MethodInvocation methodInvocation )
     {
-        final Method method = methodInvocation.getMethod();
-        Transactional result;
-
-        result = transactionalCache.get( method );
-        if ( null == result )
-        {
-            result = getTransactional( methodInvocation, method );
-            transactionalCache.put( method, result );
-        }
-        return result;
-    }
-
-    private Transactional getTransactional( MethodInvocation methodInvocation, Method method )
-    {
         Transactional result;
+        final Method method = methodInvocation.getMethod();
         result = method.getAnnotation( Transactional.class );
         if ( null == result )
         {
@@ -74,23 +60,10 @@ class TransactionalAnnotationReader
     }
 
     /**
-     * Helper class for obtaining the default of @{@link Transactional}.
+     * Helper class for obtaining the default of {@link Transactional @Transactional}.
      */
     @Transactional
     private static class DefaultTransactional
     {
     }
-
-    private static class TransactionalCache
-    {
-        Transactional get( Method method )
-        {
-            return null;
-        }
-
-        void put( Method method, Transactional annotation )
-        {
-            // nop
-        }
-    }
 }

Added: onami/sandbox/persist/src/main/java/org/apache/onami/persist/TxnInterceptor.java
URL: http://svn.apache.org/viewvc/onami/sandbox/persist/src/main/java/org/apache/onami/persist/TxnInterceptor.java?rev=1585487&view=auto
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/TxnInterceptor.java (added)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/TxnInterceptor.java Mon Apr  7 14:12:18 2014
@@ -0,0 +1,213 @@
+package org.apache.onami.persist;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import com.google.inject.Inject;
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+/**
+ * Interceptor for methods and classes annotated with @{@link Transactional} annotation.
+ */
+class TxnInterceptor
+    implements MethodInterceptor
+{
+
+    /**
+     * Unit of work.
+     */
+    @Inject
+    @VisibleForTesting
+    UnitOfWork unitOfWork;
+
+    /**
+     * Factory for {@link TransactionFacade}.
+     */
+    @Inject
+    @VisibleForTesting
+    TransactionFacadeFactory tfProvider;
+
+    /**
+     * Helper for working with the concrete transactional annotations on methods and classes.
+     */
+    @Inject
+    @VisibleForTesting
+    TransactionalAnnotationHelper txnAnnotationHelper;
+
+    /**
+     * {@inheritDoc}
+     */
+    // @Override
+    public final Object invoke( MethodInvocation methodInvocation )
+        throws Throwable
+    {
+        if ( persistenceUnitParticipatesInTransactionFor( methodInvocation ) )
+        {
+            return invokeInTransactionAndUnitOfWork( methodInvocation );
+        }
+        else
+        {
+            return methodInvocation.proceed();
+        }
+
+    }
+
+    private boolean persistenceUnitParticipatesInTransactionFor( MethodInvocation methodInvocation )
+    {
+        return txnAnnotationHelper.persistenceUnitParticipatesInTransactionFor( methodInvocation );
+    }
+
+    /**
+     * Invokes the original method within a unit of work and a transaction.
+     *
+     * @param methodInvocation the method to be executed within the transaction
+     * @return the result of the invocation of the original method.
+     * @throws Throwable if an exception occurs during the call to the original method.
+     */
+    private Object invokeInTransactionAndUnitOfWork( MethodInvocation methodInvocation )
+        throws Throwable
+    {
+        final boolean weStartedTheUnitOfWork = !unitOfWork.isActive();
+        if ( weStartedTheUnitOfWork )
+        {
+            unitOfWork.begin();
+        }
+
+        Throwable originalException = null;
+        try
+        {
+            return invokeInTransaction( methodInvocation );
+        }
+        catch ( Throwable exc )
+        {
+            originalException = exc;
+            throw exc;
+        }
+        finally
+        {
+            if ( weStartedTheUnitOfWork )
+            {
+                endUnitOfWorkAndThrow( originalException );
+            }
+        }
+    }
+
+    /**
+     * Ends the unit of work and throws the original exception if not null.
+     *
+     * @param originalException the original transaction to throw if not null.
+     * @throws Throwable the original exception or an exception which occurred when closing the unit of work.
+     */
+    private void endUnitOfWorkAndThrow( Throwable originalException )
+        throws Throwable
+    {
+        try
+        {
+            unitOfWork.end();
+        }
+        catch ( Throwable exc )
+        {
+            if ( originalException != null )
+            {
+                throw originalException;
+            }
+            else
+            {
+                throw exc;
+            }
+        }
+    }
+
+    /**
+     * Invoke the original method within a transaction.
+     *
+     * @param methodInvocation the original method invocation.
+     * @return the result of the invocation of the original method.
+     * @throws Throwable if an exception occurs during the call to the original method.
+     */
+    private Object invokeInTransaction( MethodInvocation methodInvocation )
+        throws Throwable
+    {
+        final TransactionFacade transactionFacade = tfProvider.createTransactionFacade();
+        transactionFacade.begin();
+        final Object result = invokeAndHandleException( methodInvocation, transactionFacade );
+        transactionFacade.commit();
+
+        return result;
+    }
+
+    /**
+     * Invoke the original method assuming a transaction has already been started.
+     * This method is responsible of calling rollback if necessary.
+     *
+     * @param methodInvocation  the original method invocation.
+     * @param transactionFacade the facade to the underlying resource local or jta transaction.
+     * @return the result of the invocation of the original method.
+     * @throws Throwable if an exception occurs during the call to the original method.
+     */
+    private Object invokeAndHandleException( MethodInvocation methodInvocation, TransactionFacade transactionFacade )
+        throws Throwable
+    {
+        try
+        {
+            return methodInvocation.proceed();
+        }
+        catch ( Throwable exc )
+        {
+            handleException( methodInvocation, transactionFacade, exc );
+            throw exc;
+        }
+    }
+
+    /**
+     * Handles the case that an exception was thrown by the original method.
+     *
+     * @param methodInvocation  the original method invocation.
+     * @param transactionFacade the facade to the underlying resource local or jta transaction.
+     * @param exc               the exception thrown by the original method.
+     */
+    private void handleException( MethodInvocation methodInvocation, TransactionFacade transactionFacade,
+                                  Throwable exc )
+        throws Throwable
+    {
+        try
+        {
+            if ( isRollbackNecessaryFor( methodInvocation, exc ) )
+            {
+                transactionFacade.rollback();
+            }
+            else
+            {
+                transactionFacade.commit();
+            }
+        }
+        catch ( Exception swallowedException )
+        {
+            // swallow exception from transaction facade in favor of th exception thrown by the original method.
+            throw exc;
+        }
+    }
+
+    private boolean isRollbackNecessaryFor( MethodInvocation methodInvocation, Throwable exc )
+    {
+        return txnAnnotationHelper.isRollbackNecessaryFor( methodInvocation, exc );
+    }
+
+}

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/TxnInterceptor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/TxnInterceptor.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/TxnInterceptor.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: onami/sandbox/persist/src/main/java/org/apache/onami/persist/UnannotatedPersistenceUnitBuilder.java
URL: http://svn.apache.org/viewvc/onami/sandbox/persist/src/main/java/org/apache/onami/persist/UnannotatedPersistenceUnitBuilder.java?rev=1585487&view=auto
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/UnannotatedPersistenceUnitBuilder.java (added)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/UnannotatedPersistenceUnitBuilder.java Mon Apr  7 14:12:18 2014
@@ -0,0 +1,28 @@
+package org.apache.onami.persist;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.lang.annotation.Annotation;
+
+public interface UnannotatedPersistenceUnitBuilder
+    extends AnnotatedPersistenceUnitBuilder
+{
+    AnnotatedPersistenceUnitBuilder annotatedWith( Class<? extends Annotation> annotation );
+}

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/UnannotatedPersistenceUnitBuilder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/UnannotatedPersistenceUnitBuilder.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/UnannotatedPersistenceUnitBuilder.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: onami/sandbox/persist/src/main/java/org/apache/onami/persist/UnconfiguredPersistenceUnitBuilder.java
URL: http://svn.apache.org/viewvc/onami/sandbox/persist/src/main/java/org/apache/onami/persist/UnconfiguredPersistenceUnitBuilder.java?rev=1585487&view=auto
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/UnconfiguredPersistenceUnitBuilder.java (added)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/UnconfiguredPersistenceUnitBuilder.java Mon Apr  7 14:12:18 2014
@@ -0,0 +1,27 @@
+package org.apache.onami.persist;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.Properties;
+
+public interface UnconfiguredPersistenceUnitBuilder
+{
+    void addProperties( Properties properties );
+}

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/UnconfiguredPersistenceUnitBuilder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/UnconfiguredPersistenceUnitBuilder.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/UnconfiguredPersistenceUnitBuilder.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: onami/sandbox/persist/src/main/java/org/apache/onami/persist/UserTransactionFacade.java
URL: http://svn.apache.org/viewvc/onami/sandbox/persist/src/main/java/org/apache/onami/persist/UserTransactionFacade.java?rev=1585487&r1=1585486&r2=1585487&view=diff
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/UserTransactionFacade.java (original)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/UserTransactionFacade.java Mon Apr  7 14:12:18 2014
@@ -19,6 +19,8 @@ package org.apache.onami.persist;
  * under the License.
  */
 
+import com.google.inject.Singleton;
+
 import javax.transaction.HeuristicMixedException;
 import javax.transaction.HeuristicRollbackException;
 import javax.transaction.NotSupportedException;
@@ -26,36 +28,44 @@ import javax.transaction.RollbackExcepti
 import javax.transaction.Status;
 import javax.transaction.SystemException;
 import javax.transaction.UserTransaction;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
 
 import static org.apache.onami.persist.Preconditions.checkNotNull;
 
+
 /**
- * Facade to the {@link UserTransaction} which wraps all checked exception into runtime exceptions.
+ * Facade to the {@link javax.transaction.UserTransaction} which wraps all checked exception into runtime exceptions.
+ * Adds some convenience methods.
  */
+@Singleton
 class UserTransactionFacade
 {
 
-    // ---- Members
+    /**
+     * Transaction states in which only a rollback is possible
+     */
+    private static final Set<Integer> ROLLBACK_ONLY_STATES = new HashSet<Integer>(
+        Arrays.asList( Status.STATUS_MARKED_ROLLBACK, Status.STATUS_ROLLING_BACK, Status.STATUS_ROLLEDBACK ) );
 
+    /**
+     * The wrapped user transaction.
+     */
     private final UserTransaction txn;
 
-    // ---- Constructor
-
     /**
      * Constructor.
      *
-     * @param txn the actual user transaction to facade. Must not be {@code null}.
+     * @param txn the actual user transaction to wrap. Must not be {@code null}.
      */
     UserTransactionFacade( UserTransaction txn )
     {
-        checkNotNull( txn );
-        this.txn = txn;
+        this.txn = checkNotNull( txn, "txn is mandatory!" );
     }
 
-    // ---- Methods
-
     /**
-     * @see {@link UserTransaction#begin()}.
+     * @see {@link javax.transaction.UserTransaction#begin()}.
      */
     void begin()
     {
@@ -74,7 +84,7 @@ class UserTransactionFacade
     }
 
     /**
-     * @see {@link UserTransaction#commit()}.
+     * @see {@link javax.transaction.UserTransaction#commit()}.
      */
     void commit()
     {
@@ -109,7 +119,7 @@ class UserTransactionFacade
     }
 
     /**
-     * @see {@link UserTransaction#rollback()}.
+     * @see {@link javax.transaction.UserTransaction#rollback()}.
      */
     void rollback()
     {
@@ -132,7 +142,7 @@ class UserTransactionFacade
     }
 
     /**
-     * @see {@link UserTransaction#setRollbackOnly()}.
+     * @see {@link javax.transaction.UserTransaction#setRollbackOnly()}.
      */
     void setRollbackOnly()
     {
@@ -151,18 +161,37 @@ class UserTransactionFacade
     }
 
     /**
-     * @see {@link UserTransaction#getStatus()}.
+     * @return {@code true} if this transaction may onl roll back. {@code false} otherwise.
+     */
+    boolean getRollbackOnly()
+    {
+        return ROLLBACK_ONLY_STATES.contains( getStatus() );
+    }
+
+    /**
+     * @return {@code true} if there is already a transaction active. {@code false} otherwise.
+     */
+    boolean isActive()
+    {
+        return getStatus() != Status.STATUS_NO_TRANSACTION;
+    }
+
+    /**
+     * @see {@link javax.transaction.UserTransaction#getStatus()}.
+     *      <p/>
+     *      Retries several times when the status is {@link Status#STATUS_UNKNOWN}.
+     *      Will abort retrying after aproximatly one second.
      */
-    int getStatus()
+    private int getStatus()
     {
         try
         {
             int status = txn.getStatus();
-            for ( int i = 0; Status.STATUS_UNKNOWN == status && i < 5; i++ )
+            for ( int i = 0; status == Status.STATUS_UNKNOWN && i < 8; i++ )
             {
                 try
                 {
-                    Thread.sleep( 30L );
+                    Thread.sleep( ( 30L * i ) + 30L );
                 }
                 catch ( InterruptedException e )
                 {

Added: onami/sandbox/persist/src/main/java/org/apache/onami/persist/UserTransactionJndiName.java
URL: http://svn.apache.org/viewvc/onami/sandbox/persist/src/main/java/org/apache/onami/persist/UserTransactionJndiName.java?rev=1585487&view=auto
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/UserTransactionJndiName.java (added)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/UserTransactionJndiName.java Mon Apr  7 14:12:18 2014
@@ -0,0 +1,38 @@
+package org.apache.onami.persist;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import com.google.inject.BindingAnnotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+/**
+ * Annotation to mark bindings which are specific for container managed persistence units.
+ */
+@Target( { ElementType.PARAMETER } )
+@Retention( RetentionPolicy.RUNTIME )
+@BindingAnnotation
+@interface UserTransactionJndiName
+{
+}

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/UserTransactionJndiName.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/UserTransactionJndiName.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/UserTransactionJndiName.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: onami/sandbox/persist/src/main/java/org/apache/onami/persist/UserTransactionProviderByJndiLookup.java
URL: http://svn.apache.org/viewvc/onami/sandbox/persist/src/main/java/org/apache/onami/persist/UserTransactionProviderByJndiLookup.java?rev=1585487&view=auto
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/UserTransactionProviderByJndiLookup.java (added)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/UserTransactionProviderByJndiLookup.java Mon Apr  7 14:12:18 2014
@@ -0,0 +1,45 @@
+package org.apache.onami.persist;
+
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+
+import javax.transaction.UserTransaction;
+
+import static org.apache.onami.persist.Preconditions.checkNotNull;
+
+/**
+ * Provider fro {@link UserTransaction} which retrieves the value from the JNDI context.
+ */
+@Singleton
+public class UserTransactionProviderByJndiLookup
+    implements Provider<UserTransaction>
+{
+
+    private final String jndiName;
+
+    private final JndiLookupHelper jndiLookupHelper;
+
+    /**
+     * Constructor.
+     *
+     * @param jndiName jndi name of the entity manager factory. Must not be {@code null}.
+     */
+    UserTransactionProviderByJndiLookup( @UserTransactionJndiName String jndiName, JndiLookupHelper jndiLookupHelper )
+    {
+        this.jndiName = checkNotNull( jndiName, "jndiName is mandatory!" );
+        this.jndiLookupHelper = checkNotNull( jndiLookupHelper, "jndiLookupHelper is mandatory!" );
+    }
+
+    /**
+     * Gets a {@link UserTransaction} by looking it up in the JNDI context.
+     *
+     * @return the found entity user transaction
+     * @throws RuntimeException when no user transaction was found.
+     */
+    //@Override
+    public UserTransaction get()
+    {
+        return jndiLookupHelper.doJndiLookup( UserTransaction.class, jndiName );
+    }
+
+}

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/UserTransactionProviderByJndiLookup.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/UserTransactionProviderByJndiLookup.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/UserTransactionProviderByJndiLookup.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: onami/sandbox/persist/src/main/java/org/apache/onami/persist/VisibleForTesting.java
URL: http://svn.apache.org/viewvc/onami/sandbox/persist/src/main/java/org/apache/onami/persist/VisibleForTesting.java?rev=1585487&view=auto
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/VisibleForTesting.java (added)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/VisibleForTesting.java Mon Apr  7 14:12:18 2014
@@ -0,0 +1,34 @@
+package org.apache.onami.persist;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to mark the intention of increasing the visibility of a method or field so it can be used in a test.
+ */
+@Target( { ElementType.METHOD, ElementType.FIELD } )
+@Retention( RetentionPolicy.SOURCE )
+@interface VisibleForTesting
+{
+}

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/VisibleForTesting.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/VisibleForTesting.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/VisibleForTesting.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain