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 2013/11/15 00:19:37 UTC
svn commit: r1542116 [2/3] - in /onami/sandbox/persist: ./ src/ src/main/
src/main/java/ src/main/java/org/ src/main/java/org/apache/
src/main/java/org/apache/onami/ src/main/java/org/apache/onami/persist/
src/test/ src/test/java/ src/test/java/org/ sr...
Added: 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=1542116&view=auto
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceModule.java (added)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceModule.java Thu Nov 14 23:19:36 2013
@@ -0,0 +1,264 @@
+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.AbstractModule;
+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.any;
+
+/**
+ * Main module of the jpa-persistence guice extension.
+ * <p/>
+ * Add either a {@link ApplicationManagedPersistenceUnitModule} or a
+ * {@link ContainerManagedPersistenceUnitModule} per 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>
+ * </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
+ extends AbstractModule
+{
+
+ // ---- Members
+
+ /**
+ * 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()
+ {
+ if ( configureHasNotBeenExecutedYet() )
+ {
+ 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 );
+ }
+ }
+
+ for ( AbstractPersistenceUnitModule module : modules )
+ {
+ install( module );
+
+ final Matcher<AnnotatedElement> matcher = Matchers.annotatedWith( Transactional.class );
+ final MethodInterceptor transactionInterceptor = module.getTransactionInterceptor( utFacade );
+
+ bindInterceptor( matcher, any(), transactionInterceptor );
+ bindInterceptor( any(), matcher, transactionInterceptor );
+ }
+
+ bind( PersistenceService.class ).annotatedWith( AllPersistenceUnits.class ).toInstance( puContainer );
+ bind( UnitOfWork.class ).annotatedWith( AllPersistenceUnits.class ).toInstance( puContainer );
+ bind( PersistenceFilter.class ).toInstance( new PersistenceFilter( puContainer ) );
+ }
+
+ /**
+ * @return {@code true} if {@link #configure()} has not yet been invoked.
+ */
+ private boolean configureHasNotBeenExecutedYet()
+ {
+ return modules.size() == 0;
+ }
+
+ /**
+ * Make sure that the {@link #configure()} method has not been executed yet.
+ */
+ private void ensureConfigurHasNotYetBeenExecuted()
+ {
+ if ( configureHasNotBeenExecutedYet() )
+ {
+ return;
+ }
+ throw new IllegalStateException( "cannot change a module after creating the injector." );
+ }
+
+ /**
+ * Initializes the field {@link #utFacade} with the {@link UserTransaction} obtained by a
+ * JNDI lookup.
+ */
+ private void initUserTransactionFacade()
+ {
+ 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 );
+ }
+ }
+ }
+
+}
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceModule.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceModule.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceModule.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: 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=1542116&view=auto
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceService.java (added)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceService.java Thu Nov 14 23:19:36 2013
@@ -0,0 +1,56 @@
+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.
+ */
+
+/**
+ * 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.
+ */
+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
+ * method upon initialization of the web application.
+ *
+ * @throws IllegalArgumentException if the service is already running.
+ */
+ void start()
+ throws IllegalArgumentException;
+
+ /**
+ * @return {@code true} if the underlying persistence engine is running.
+ * {@code false} otherwise.
+ */
+ boolean isRunning();
+
+ /**
+ * Stops the underlying persistence engine.
+ * <ul>
+ * <li>If already stopped, calling this method does nothing.</li>
+ * <li>If not yet started, it also does nothing.</li>
+ * </ul>
+ */
+ void stop();
+
+}
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceService.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceService.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceService.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitBuilder.java
URL: http://svn.apache.org/viewvc/onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitBuilder.java?rev=1542116&view=auto
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitBuilder.java (added)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitBuilder.java Thu Nov 14 23:19:36 2013
@@ -0,0 +1,102 @@
+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;
+
+import static org.apache.onami.persist.Preconditions.checkNotNull;
+
+/**
+ * Builder class for configurating a guice-jpa persistence unit.
+ */
+public final class PersistenceUnitBuilder
+{
+
+ // ---- Members
+
+ /**
+ * The module which is built by this instance.
+ */
+ private AbstractPersistenceUnitModule module;
+
+ // ---- Constructors
+
+ /**
+ * Constructor.
+ *
+ * @param module the module which is built by this instance.
+ */
+ PersistenceUnitBuilder( AbstractPersistenceUnitModule module )
+ {
+ this.module = module;
+ }
+
+ // ---- Methods
+
+ /**
+ * Add an annotation to the module. The annotation is used to bind the {@link UnitOfWork} and
+ * the {@link EntityManagerProvider} in guice.
+ *
+ * @param annotation the annotation. May be {@code null}.
+ * @return the builder for method chaining.
+ */
+ public PersistenceUnitBuilder annotatedWith( Class<? extends Annotation> annotation )
+ {
+ checkNotNull( module, "cannot change a module after creating the injector." );
+ module.annotatedWith( annotation );
+ return this;
+ }
+
+ /**
+ * Configure the persistence unit to use local transactions. This means even if the data source
+ * is managed by the container its transaction will not participate in a global container managed
+ * transaction (CMT).
+ */
+ public void useResourceLocalTransaction()
+ {
+ checkNotNull( module, "cannot change a module after creating the injector." );
+ module.setTransactionType( TransactionType.RESOURCE_LOCAL );
+ }
+
+ /**
+ * Configure the persistence unit to use global transactions. This means all transactions on this
+ * data source will participate in a global container managed transaction (CMT)
+ */
+ public void useJtaTransaction()
+ {
+ checkNotNull( module, "cannot change a module after creating the injector." );
+ module.setTransactionType( TransactionType.JTA );
+ }
+
+ /**
+ * Builds the module and also changes the state of the builder.
+ * After calling this method all calls to the builder will result in an exception.
+ *
+ * @return the persistence module.
+ */
+ AbstractPersistenceUnitModule build()
+ {
+ checkNotNull( module, "build() can only be called once." );
+ final AbstractPersistenceUnitModule m = module;
+ module = null;
+ return m;
+ }
+
+}
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitBuilder.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitBuilder.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitBuilder.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: 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=1542116&view=auto
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitContainer.java (added)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitContainer.java Thu Nov 14 23:19:36 2013
@@ -0,0 +1,145 @@
+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.HashSet;
+import java.util.Set;
+
+import static org.apache.onami.persist.Preconditions.checkNotNull;
+
+/**
+ * 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.
+ */
+class PersistenceUnitContainer
+ implements PersistenceService, UnitOfWork
+{
+
+ // ---- Members
+
+ /**
+ * Collection of all known persistence services.
+ */
+ private final Set<PersistenceService> persistenceServices = new HashSet<PersistenceService>();
+
+ /**
+ * Collection of all known units of work.
+ */
+ 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}.
+ */
+ void add( PersistenceService ps, UnitOfWork uow )
+ {
+ checkNotNull( ps );
+ checkNotNull( uow );
+ persistenceServices.add( ps );
+ unitsOfWork.add( uow );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ // @Override
+ public synchronized void start()
+ {
+ for ( PersistenceService ps : persistenceServices )
+ {
+ ps.start();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ // @Override
+ public synchronized boolean isRunning()
+ {
+ for ( PersistenceService ps : persistenceServices )
+ {
+ if ( !ps.isRunning() )
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ // @Override
+ public synchronized void stop()
+ {
+ for ( PersistenceService ps : persistenceServices )
+ {
+ ps.stop();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ // @Override
+ public void begin()
+ {
+ for ( UnitOfWork unitOfWork : unitsOfWork )
+ {
+ unitOfWork.begin();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ // @Override
+ public boolean isActive()
+ {
+ for ( UnitOfWork unitOfWork : unitsOfWork )
+ {
+ if ( !unitOfWork.isActive() )
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ // @Override
+ public void end()
+ {
+ for ( UnitOfWork unitOfWork : unitsOfWork )
+ {
+ unitOfWork.end();
+ }
+
+ }
+
+}
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitContainer.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitContainer.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/PersistenceUnitContainer.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: 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=1542116&view=auto
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/Preconditions.java (added)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/Preconditions.java Thu Nov 14 23:19:36 2013
@@ -0,0 +1,58 @@
+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.
+ */
+
+/**
+ * Checks to ensure arguments are in a valid state.
+ */
+class Preconditions
+{
+
+ /**
+ * Check that a reference is not null.
+ *
+ * @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( );
+ }
+ return reference;
+ }
+
+ /**
+ * Check that a reference is not null.
+ *
+ * @param <T> the type of the reference
+ * @param reference the reference to check.
+ * @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) {
+ throw new NullPointerException( message );
+ }
+ return reference;
+ }
+}
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/Preconditions.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/Preconditions.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/Preconditions.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: onami/sandbox/persist/src/main/java/org/apache/onami/persist/ResourceLocalTxnInterceptor.java
URL: http://svn.apache.org/viewvc/onami/sandbox/persist/src/main/java/org/apache/onami/persist/ResourceLocalTxnInterceptor.java?rev=1542116&view=auto
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/ResourceLocalTxnInterceptor.java (added)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/ResourceLocalTxnInterceptor.java Thu Nov 14 23:19:36 2013
@@ -0,0 +1,166 @@
+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 org.aopalliance.intercept.MethodInterceptor;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityTransaction;
+import java.lang.annotation.Annotation;
+
+import static org.apache.onami.persist.Preconditions.checkNotNull;
+
+/**
+ * {@link MethodInterceptor} for intercepting methods of persistence units of type RESOURCE_LOCAL.
+ */
+class ResourceLocalTxnInterceptor
+ extends AbstractTxnInterceptor
+{
+
+ // ---- Constructor
+
+ /**
+ * Constructor.
+ *
+ * @param emProvider the provider for {@link EntityManager}. Must not be {@code null}.
+ * @param puAnntoation the annotation of the persistence unit this interceptor belongs to.
+ */
+ public ResourceLocalTxnInterceptor( EntityManagerProviderImpl emProvider, Class<? extends Annotation> puAnntoation )
+ {
+ super( emProvider, emProvider, puAnntoation );
+ checkNotNull( emProvider );
+ }
+
+ // ---- Methods
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected TransactionFacade getTransactionFacade( final EntityManager em )
+ {
+ final EntityTransaction txn = em.getTransaction();
+ if ( txn.isActive() )
+ {
+ return new InnerTransaction( txn );
+ }
+ return new OuterTransaction( txn );
+ }
+
+ // ---- Inner Classes
+
+ /**
+ * 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 InnerTransaction
+ implements TransactionFacade
+ {
+ private final EntityTransaction txn;
+
+ InnerTransaction( EntityTransaction txn )
+ {
+ this.txn = txn;
+ }
+
+ /**
+ * {@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 OuterTransaction
+ implements TransactionFacade
+ {
+ private final EntityTransaction txn;
+
+ /**
+ * {@inheritDoc}
+ */
+ OuterTransaction( EntityTransaction txn )
+ {
+ this.txn = txn;
+ }
+
+ /**
+ * {@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/ResourceLocalTxnInterceptor.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/ResourceLocalTxnInterceptor.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/ResourceLocalTxnInterceptor.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: 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=1542116&view=auto
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionFacade.java (added)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionFacade.java Thu Nov 14 23:19:36 2013
@@ -0,0 +1,57 @@
+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 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}.
+ */
+interface TransactionFacade
+{
+
+ /**
+ * Starts a transaction.
+ * <p/>
+ * The first call to begin will start the actual transaction. Subsequent calls will start a
+ * 'nested' transaction.
+ */
+ void begin();
+
+ /**
+ * Commits a transaction.
+ * <p/>
+ * Only the actual transaction can be committed. Calls to commit on nested transactions have
+ * no effect.
+ */
+ void commit();
+
+ /**
+ * Rolls a transaction back.
+ * <p/>
+ * Only the actual transaction can be rolled back. Calls to rollback on nested transactions will
+ * set the onlyRollBack flag on the actual transaction. Setting this flag wil cause an actual
+ * transaction to be rolled back in any case.
+ */
+ void rollback();
+
+}
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionFacade.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionFacade.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionFacade.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionType.java
URL: http://svn.apache.org/viewvc/onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionType.java?rev=1542116&view=auto
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionType.java (added)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionType.java Thu Nov 14 23:19:36 2013
@@ -0,0 +1,37 @@
+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.
+ */
+
+/**
+ * Type of a transaction.
+ */
+enum TransactionType
+{
+
+ /**
+ * A transaction which is local to the application and is not managed by a container.
+ */
+ RESOURCE_LOCAL,
+
+ /**
+ * A transaction which is global and is managed by a container.
+ */
+ JTA
+}
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionType.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionType.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionType.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: 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=1542116&view=auto
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/Transactional.java (added)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/Transactional.java Thu Nov 14 23:19:36 2013
@@ -0,0 +1,76 @@
+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.Injector;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Marks a method or class to be executed within a transaction.
+ * <p/>
+ * This will span a new transaction around the method unless there is already a running transaction.
+ * In the case that there is a running transaction no new transaction is started.
+ * If a rollback happens for a method which did not start the transaction the already existing
+ * 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:
+ * <ul>
+ * <li>
+ * The object on which the method is called has been created by guice.
+ * 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
+ * </li>
+ * </ul>
+ */
+@Target({ ElementType.METHOD, ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+public @interface Transactional
+{
+
+ /**
+ * A List of annotations for persistence units on which to start a transaction.
+ * Default is on all persistence units.
+ */
+ Class<? extends Annotation>[] onUnits() default { };
+
+ /**
+ * A list of exceptions to rollback on. Default is {@link RuntimeException}.
+ */
+ Class<? extends Exception>[] rollbackOn() default RuntimeException.class;
+
+ /**
+ * A list of exceptions to <b>not<b> rollback on. Use this to exclude one ore more subclasses of
+ * the exceptions defined in rollbackOn(). Default is none.
+ */
+ Class<? extends Exception>[] ignore() default { };
+}
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/Transactional.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/Transactional.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/Transactional.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: 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=1542116&view=auto
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionalAnnotationReader.java (added)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionalAnnotationReader.java Thu Nov 14 23:19:36 2013
@@ -0,0 +1,96 @@
+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 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.
+ */
+class TransactionalAnnotationReader
+{
+ private static final Transactional DEFAULT_TRANSACTIONAL = DefaultTransactional.class.getAnnotation( Transactional.class );
+
+ /**
+ * cache for {@link Transactional} annotations per method.
+ */
+ final TransactionalCache transactionalCache = new TransactionalCache();
+
+
+ /**
+ * Reads the @{@link 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}.
+ */
+ 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;
+ result = method.getAnnotation( Transactional.class );
+ if ( null == result )
+ {
+ final Class<?> targetClass = methodInvocation.getThis().getClass();
+ result = targetClass.getAnnotation( Transactional.class );
+ }
+ if ( null == result )
+ {
+ result = DEFAULT_TRANSACTIONAL;
+ }
+ return result;
+ }
+
+ /**
+ * Helper class for obtaining the default of @{@link Transactional}.
+ */
+ @Transactional
+ private static class DefaultTransactional
+ {
+ }
+
+ private static class TransactionalCache
+ {
+ Transactional get( Method method )
+ {
+ return null;
+ }
+
+ void put( Method method, Transactional annotation )
+ {
+ // nop
+ }
+ }
+}
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionalAnnotationReader.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionalAnnotationReader.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/TransactionalAnnotationReader.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: onami/sandbox/persist/src/main/java/org/apache/onami/persist/UnitOfWork.java
URL: http://svn.apache.org/viewvc/onami/sandbox/persist/src/main/java/org/apache/onami/persist/UnitOfWork.java?rev=1542116&view=auto
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/UnitOfWork.java (added)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/UnitOfWork.java Thu Nov 14 23:19:36 2013
@@ -0,0 +1,84 @@
+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 javax.persistence.EntityManager;
+
+/**
+ * The Unit of work correlates with the life cycle of the {@link EntityManager}.
+ * According to JPA every thread should use its own {@link EntityManager}. Therefore the unit of
+ * work will control the life cycle of the {@link EntityManager} on a per thread basis. This means
+ * the UnitOfWork is thread safe.
+ * <p/>
+ * Most of the time it is not recommended to manual control the unit of work.
+ * <p/>
+ * For applications running in a container the {@link PersistenceFilter} is recommended.
+ * It will start a unit of work for every incoming request and properly close it at the end.
+ * <p/>
+ * For stand alone application it is recommended to relay on the @{@link Transactional} annotation.
+ * The transaction handler will automatically span a unit of work around a transaction.
+ * <p/>
+ * The most likely scenario in which one would want to take manual control over the unit of work
+ * is in a background thread within a container (i.e. timer triggered jobs).
+ * <p/>
+ * Recommended pattern:
+ * <pre>
+ * public void someMethod() {
+ * final boolean unitOfWorkWasInactive = ! unitOfWork.isActive();
+ * if (unitOfWorkWasInactive) {
+ * unitOfWork.begin();
+ * }
+ * try {
+ * // do work
+ * }
+ * finally {
+ * if (unitOfWorkWasInactive) {
+ * unitOfWork.end();
+ * }
+ * }
+ * }
+ * </pre>
+ */
+public interface UnitOfWork
+{
+
+ /**
+ * Starts the unit of work.
+ * When the unit of work has already been started for the current thread an
+ * {@link IllegalStateException} is thrown.
+ *
+ * @throws IllegalStateException if the unit of work is already running for this thread.
+ */
+ void begin()
+ throws IllegalStateException;
+
+ /**
+ * @return {@code true} if the unit of work is already running for this thread
+ * {@code false} otherwise.
+ */
+ boolean isActive();
+
+ /**
+ * Stops the unit of work.
+ * When the unit of work is not active this method will do nothing.
+ */
+ void end();
+
+}
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/UnitOfWork.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/UnitOfWork.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/UnitOfWork.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: 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=1542116&view=auto
==============================================================================
--- onami/sandbox/persist/src/main/java/org/apache/onami/persist/UserTransactionFacade.java (added)
+++ onami/sandbox/persist/src/main/java/org/apache/onami/persist/UserTransactionFacade.java Thu Nov 14 23:19:36 2013
@@ -0,0 +1,195 @@
+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 javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+import javax.transaction.UserTransaction;
+
+import static org.apache.onami.persist.Preconditions.checkNotNull;
+
+/**
+ * Facade to the {@link UserTransaction} which wraps all checked exception into runtime exceptions.
+ */
+class UserTransactionFacade
+{
+
+ // ---- Members
+
+ private final UserTransaction txn;
+
+ // ---- Constructor
+
+ /**
+ * Constructor.
+ *
+ * @param txn the actual user transaction to facade. Must not be {@code null}.
+ */
+ UserTransactionFacade( UserTransaction txn )
+ {
+ checkNotNull( txn );
+ this.txn = txn;
+ }
+
+ // ---- Methods
+
+ /**
+ * @see {@link UserTransaction#begin()}.
+ */
+ void begin()
+ {
+ try
+ {
+ txn.begin();
+ }
+ catch ( NotSupportedException e )
+ {
+ throw new RuntimeException( "nested transactions are not supported by the user transaction " + txn, e );
+ }
+ catch ( SystemException e )
+ {
+ throw new RuntimeException( "unexpected error occured", e );
+ }
+ }
+
+ /**
+ * @see {@link UserTransaction#commit()}.
+ */
+ void commit()
+ {
+ try
+ {
+ txn.commit();
+ }
+ catch ( SecurityException e )
+ {
+ throw new RuntimeException( "not allowed to commit the transaction", e );
+ }
+ catch ( IllegalStateException e )
+ {
+ throw new RuntimeException( "no transaction associated with userTransaction", e );
+ }
+ catch ( RollbackException e )
+ {
+ throw new RuntimeException( "rollback during commit", e );
+ }
+ catch ( HeuristicMixedException e )
+ {
+ throw new RuntimeException( "heuristic partial rollback during commit", e );
+ }
+ catch ( HeuristicRollbackException e )
+ {
+ throw new RuntimeException( "heuristic rollback during commit", e );
+ }
+ catch ( SystemException e )
+ {
+ throw new RuntimeException( "unexpected error occured", e );
+ }
+ }
+
+ /**
+ * @see {@link UserTransaction#rollback()}.
+ */
+ void rollback()
+ {
+ try
+ {
+ txn.rollback();
+ }
+ catch ( IllegalStateException e )
+ {
+ throw new RuntimeException( "no transaction associated with userTransaction", e );
+ }
+ catch ( SecurityException e )
+ {
+ throw new RuntimeException( "not allowed to rollback the transaction", e );
+ }
+ catch ( SystemException e )
+ {
+ throw new RuntimeException( "unexpected error occured", e );
+ }
+ }
+
+ /**
+ * @see {@link UserTransaction#setRollbackOnly()}.
+ */
+ void setRollbackOnly()
+ {
+ try
+ {
+ txn.setRollbackOnly();
+ }
+ catch ( IllegalStateException e )
+ {
+ throw new RuntimeException( "no transaction associated with userTransaction", e );
+ }
+ catch ( SystemException e )
+ {
+ throw new RuntimeException( "unexpected error occured", e );
+ }
+ }
+
+ /**
+ * @see {@link UserTransaction#getStatus()}.
+ */
+ int getStatus()
+ {
+ try
+ {
+ int status = txn.getStatus();
+ for ( int i = 0; Status.STATUS_UNKNOWN == status && i < 5; i++ )
+ {
+ try
+ {
+ Thread.sleep( 30L );
+ }
+ catch ( InterruptedException e )
+ {
+ // do nothing
+ }
+ status = txn.getStatus();
+ }
+ return status;
+ }
+ catch ( SystemException e )
+ {
+ throw new RuntimeException( "unexpected error occured", e );
+ }
+ }
+
+ /**
+ * @see {@link UserTransaction#setTransactionTimeout(int)}.
+ */
+ void setTransactionTimeout( int seconds )
+ {
+ try
+ {
+ txn.setTransactionTimeout( seconds );
+ }
+ catch ( SystemException e )
+ {
+ throw new RuntimeException( "unexpected error occured", e );
+ }
+ }
+}
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/UserTransactionFacade.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/UserTransactionFacade.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: onami/sandbox/persist/src/main/java/org/apache/onami/persist/UserTransactionFacade.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: onami/sandbox/persist/src/test/java/org/apache/onami/persist/NestedTransactionTest.java
URL: http://svn.apache.org/viewvc/onami/sandbox/persist/src/test/java/org/apache/onami/persist/NestedTransactionTest.java?rev=1542116&view=auto
==============================================================================
--- onami/sandbox/persist/src/test/java/org/apache/onami/persist/NestedTransactionTest.java (added)
+++ onami/sandbox/persist/src/test/java/org/apache/onami/persist/NestedTransactionTest.java Thu Nov 14 23:19:36 2013
@@ -0,0 +1,432 @@
+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.Guice;
+import com.google.inject.Injector;
+import junit.framework.TestCase;
+import org.apache.onami.persist.testframework.TransactionalTask;
+import org.apache.onami.persist.testframework.TransactionalWorker;
+import org.apache.onami.persist.testframework.tasks.TaskRollingBackOnAnyThrowingNone;
+import org.apache.onami.persist.testframework.tasks.TaskRollingBackOnAnyThrowingRuntimeTestException;
+import org.apache.onami.persist.testframework.tasks.TaskRollingBackOnAnyThrowingTestException;
+import org.apache.onami.persist.testframework.tasks.TaskRollingBackOnNoneThrowingNone;
+import org.apache.onami.persist.testframework.tasks.TaskRollingBackOnNoneThrowingRuntimeTestException;
+import org.apache.onami.persist.testframework.tasks.TaskRollingBackOnNoneThrowingTestException;
+import org.apache.onami.persist.testframework.tasks.TaskRollingBackOnRuntimeTestExceptionThrowingNone;
+import org.apache.onami.persist.testframework.tasks.TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException;
+import org.apache.onami.persist.testframework.tasks.TaskRollingBackOnRuntimeTestExceptionThrowingTestException;
+import org.apache.onami.persist.testframework.tasks.TaskRollingBackOnTestExceptionThrowingNone;
+import org.apache.onami.persist.testframework.tasks.TaskRollingBackOnTestExceptionThrowingRuntimeTestException;
+import org.apache.onami.persist.testframework.tasks.TaskRollingBackOnTestExceptionThrowingTestException;
+
+/**
+ * Tests running nested transactions.
+ * The test make us of the testframework.
+ * Since the test is running a loop only the injector is created directly in the test to ensure
+ * that for every {@link TestVector} a new injector instance is used.
+ */
+public class NestedTransactionTest
+ extends TestCase
+{
+
+ /**
+ * All possible combination of {@link TransactionalTask}s
+ * and if they should have been rolled back.
+ */
+ private static final TestVector[] TEST_VECTORS =
+ { new TestVector( TaskRollingBackOnAnyThrowingNone.class, TaskRollingBackOnAnyThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnAnyThrowingNone.class,
+ TaskRollingBackOnAnyThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnAnyThrowingNone.class, TaskRollingBackOnAnyThrowingTestException.class,
+ true ),
+ new TestVector( TaskRollingBackOnAnyThrowingNone.class, TaskRollingBackOnNoneThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnAnyThrowingNone.class,
+ TaskRollingBackOnNoneThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnAnyThrowingNone.class, TaskRollingBackOnNoneThrowingTestException.class,
+ true ), new TestVector( TaskRollingBackOnAnyThrowingNone.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnAnyThrowingNone.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnAnyThrowingNone.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingTestException.class, true ),
+ new TestVector( TaskRollingBackOnAnyThrowingNone.class, TaskRollingBackOnTestExceptionThrowingNone.class,
+ false ), new TestVector( TaskRollingBackOnAnyThrowingNone.class,
+ TaskRollingBackOnTestExceptionThrowingRuntimeTestException.class,
+ true ), new TestVector( TaskRollingBackOnAnyThrowingNone.class,
+ TaskRollingBackOnTestExceptionThrowingTestException.class,
+ true ),
+
+ new TestVector( TaskRollingBackOnAnyThrowingRuntimeTestException.class,
+ TaskRollingBackOnAnyThrowingNone.class, true ),
+ new TestVector( TaskRollingBackOnAnyThrowingRuntimeTestException.class,
+ TaskRollingBackOnAnyThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnAnyThrowingRuntimeTestException.class,
+ TaskRollingBackOnAnyThrowingTestException.class, true ),
+ new TestVector( TaskRollingBackOnAnyThrowingRuntimeTestException.class,
+ TaskRollingBackOnNoneThrowingNone.class, true ),
+ new TestVector( TaskRollingBackOnAnyThrowingRuntimeTestException.class,
+ TaskRollingBackOnNoneThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnAnyThrowingRuntimeTestException.class,
+ TaskRollingBackOnNoneThrowingTestException.class, true ),
+ new TestVector( TaskRollingBackOnAnyThrowingRuntimeTestException.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingNone.class, true ),
+ new TestVector( TaskRollingBackOnAnyThrowingRuntimeTestException.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnAnyThrowingRuntimeTestException.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingTestException.class, true ),
+ new TestVector( TaskRollingBackOnAnyThrowingRuntimeTestException.class,
+ TaskRollingBackOnTestExceptionThrowingNone.class, true ),
+ new TestVector( TaskRollingBackOnAnyThrowingRuntimeTestException.class,
+ TaskRollingBackOnTestExceptionThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnAnyThrowingRuntimeTestException.class,
+ TaskRollingBackOnTestExceptionThrowingTestException.class, true ),
+
+ new TestVector( TaskRollingBackOnAnyThrowingTestException.class, TaskRollingBackOnAnyThrowingNone.class,
+ true ), new TestVector( TaskRollingBackOnAnyThrowingTestException.class,
+ TaskRollingBackOnAnyThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnAnyThrowingTestException.class,
+ TaskRollingBackOnAnyThrowingTestException.class, true ),
+ new TestVector( TaskRollingBackOnAnyThrowingTestException.class, TaskRollingBackOnNoneThrowingNone.class,
+ true ), new TestVector( TaskRollingBackOnAnyThrowingTestException.class,
+ TaskRollingBackOnNoneThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnAnyThrowingTestException.class,
+ TaskRollingBackOnNoneThrowingTestException.class, true ),
+ new TestVector( TaskRollingBackOnAnyThrowingTestException.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingNone.class, true ),
+ new TestVector( TaskRollingBackOnAnyThrowingTestException.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnAnyThrowingTestException.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingTestException.class, true ),
+ new TestVector( TaskRollingBackOnAnyThrowingTestException.class,
+ TaskRollingBackOnTestExceptionThrowingNone.class, true ),
+ new TestVector( TaskRollingBackOnAnyThrowingTestException.class,
+ TaskRollingBackOnTestExceptionThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnAnyThrowingTestException.class,
+ TaskRollingBackOnTestExceptionThrowingTestException.class, true ),
+
+ new TestVector( TaskRollingBackOnNoneThrowingNone.class, TaskRollingBackOnAnyThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnNoneThrowingNone.class,
+ TaskRollingBackOnAnyThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnNoneThrowingNone.class, TaskRollingBackOnAnyThrowingTestException.class,
+ true ),
+ new TestVector( TaskRollingBackOnNoneThrowingNone.class, TaskRollingBackOnNoneThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnNoneThrowingNone.class,
+ TaskRollingBackOnNoneThrowingRuntimeTestException.class, false ),
+ new TestVector( TaskRollingBackOnNoneThrowingNone.class, TaskRollingBackOnNoneThrowingTestException.class,
+ false ), new TestVector( TaskRollingBackOnNoneThrowingNone.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnNoneThrowingNone.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnNoneThrowingNone.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingTestException.class, false ),
+ new TestVector( TaskRollingBackOnNoneThrowingNone.class, TaskRollingBackOnTestExceptionThrowingNone.class,
+ false ), new TestVector( TaskRollingBackOnNoneThrowingNone.class,
+ TaskRollingBackOnTestExceptionThrowingRuntimeTestException.class,
+ false ), new TestVector( TaskRollingBackOnNoneThrowingNone.class,
+ TaskRollingBackOnTestExceptionThrowingTestException.class,
+ true ),
+
+ new TestVector( TaskRollingBackOnNoneThrowingRuntimeTestException.class,
+ TaskRollingBackOnAnyThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnNoneThrowingRuntimeTestException.class,
+ TaskRollingBackOnAnyThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnNoneThrowingRuntimeTestException.class,
+ TaskRollingBackOnAnyThrowingTestException.class, true ),
+ new TestVector( TaskRollingBackOnNoneThrowingRuntimeTestException.class,
+ TaskRollingBackOnNoneThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnNoneThrowingRuntimeTestException.class,
+ TaskRollingBackOnNoneThrowingRuntimeTestException.class, false ),
+ new TestVector( TaskRollingBackOnNoneThrowingRuntimeTestException.class,
+ TaskRollingBackOnNoneThrowingTestException.class, false ),
+ new TestVector( TaskRollingBackOnNoneThrowingRuntimeTestException.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnNoneThrowingRuntimeTestException.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnNoneThrowingRuntimeTestException.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingTestException.class, false ),
+ new TestVector( TaskRollingBackOnNoneThrowingRuntimeTestException.class,
+ TaskRollingBackOnTestExceptionThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnNoneThrowingRuntimeTestException.class,
+ TaskRollingBackOnTestExceptionThrowingRuntimeTestException.class, false ),
+ new TestVector( TaskRollingBackOnNoneThrowingRuntimeTestException.class,
+ TaskRollingBackOnTestExceptionThrowingTestException.class, true ),
+
+ new TestVector( TaskRollingBackOnNoneThrowingTestException.class, TaskRollingBackOnAnyThrowingNone.class,
+ false ), new TestVector( TaskRollingBackOnNoneThrowingTestException.class,
+ TaskRollingBackOnAnyThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnNoneThrowingTestException.class,
+ TaskRollingBackOnAnyThrowingTestException.class, true ),
+ new TestVector( TaskRollingBackOnNoneThrowingTestException.class, TaskRollingBackOnNoneThrowingNone.class,
+ false ), new TestVector( TaskRollingBackOnNoneThrowingTestException.class,
+ TaskRollingBackOnNoneThrowingRuntimeTestException.class, false ),
+ new TestVector( TaskRollingBackOnNoneThrowingTestException.class,
+ TaskRollingBackOnNoneThrowingTestException.class, false ),
+ new TestVector( TaskRollingBackOnNoneThrowingTestException.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnNoneThrowingTestException.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnNoneThrowingTestException.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingTestException.class, false ),
+ new TestVector( TaskRollingBackOnNoneThrowingTestException.class,
+ TaskRollingBackOnTestExceptionThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnNoneThrowingTestException.class,
+ TaskRollingBackOnTestExceptionThrowingRuntimeTestException.class, false ),
+ new TestVector( TaskRollingBackOnNoneThrowingTestException.class,
+ TaskRollingBackOnTestExceptionThrowingTestException.class, true ),
+
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingNone.class,
+ TaskRollingBackOnAnyThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingNone.class,
+ TaskRollingBackOnAnyThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingNone.class,
+ TaskRollingBackOnAnyThrowingTestException.class, true ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingNone.class,
+ TaskRollingBackOnNoneThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingNone.class,
+ TaskRollingBackOnNoneThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingNone.class,
+ TaskRollingBackOnNoneThrowingTestException.class, false ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingNone.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingNone.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingNone.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingTestException.class, false ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingNone.class,
+ TaskRollingBackOnTestExceptionThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingNone.class,
+ TaskRollingBackOnTestExceptionThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingNone.class,
+ TaskRollingBackOnTestExceptionThrowingTestException.class, true ),
+
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException.class,
+ TaskRollingBackOnAnyThrowingNone.class, true ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException.class,
+ TaskRollingBackOnAnyThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException.class,
+ TaskRollingBackOnAnyThrowingTestException.class, true ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException.class,
+ TaskRollingBackOnNoneThrowingNone.class, true ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException.class,
+ TaskRollingBackOnNoneThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException.class,
+ TaskRollingBackOnNoneThrowingTestException.class, false ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingNone.class, true ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingTestException.class, false ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException.class,
+ TaskRollingBackOnTestExceptionThrowingNone.class, true ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException.class,
+ TaskRollingBackOnTestExceptionThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException.class,
+ TaskRollingBackOnTestExceptionThrowingTestException.class, true ),
+
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingTestException.class,
+ TaskRollingBackOnAnyThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingTestException.class,
+ TaskRollingBackOnAnyThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingTestException.class,
+ TaskRollingBackOnAnyThrowingTestException.class, true ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingTestException.class,
+ TaskRollingBackOnNoneThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingTestException.class,
+ TaskRollingBackOnNoneThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingTestException.class,
+ TaskRollingBackOnNoneThrowingTestException.class, false ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingTestException.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingTestException.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingTestException.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingTestException.class, false ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingTestException.class,
+ TaskRollingBackOnTestExceptionThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingTestException.class,
+ TaskRollingBackOnTestExceptionThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnRuntimeTestExceptionThrowingTestException.class,
+ TaskRollingBackOnTestExceptionThrowingTestException.class, true ),
+
+ new TestVector( TaskRollingBackOnTestExceptionThrowingNone.class, TaskRollingBackOnAnyThrowingNone.class,
+ false ), new TestVector( TaskRollingBackOnTestExceptionThrowingNone.class,
+ TaskRollingBackOnAnyThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingNone.class,
+ TaskRollingBackOnAnyThrowingTestException.class, true ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingNone.class, TaskRollingBackOnNoneThrowingNone.class,
+ false ), new TestVector( TaskRollingBackOnTestExceptionThrowingNone.class,
+ TaskRollingBackOnNoneThrowingRuntimeTestException.class, false ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingNone.class,
+ TaskRollingBackOnNoneThrowingTestException.class, true ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingNone.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingNone.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingNone.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingTestException.class, true ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingNone.class,
+ TaskRollingBackOnTestExceptionThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingNone.class,
+ TaskRollingBackOnTestExceptionThrowingRuntimeTestException.class, false ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingNone.class,
+ TaskRollingBackOnTestExceptionThrowingTestException.class, true ),
+
+ new TestVector( TaskRollingBackOnTestExceptionThrowingRuntimeTestException.class,
+ TaskRollingBackOnAnyThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingRuntimeTestException.class,
+ TaskRollingBackOnAnyThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingRuntimeTestException.class,
+ TaskRollingBackOnAnyThrowingTestException.class, true ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingRuntimeTestException.class,
+ TaskRollingBackOnNoneThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingRuntimeTestException.class,
+ TaskRollingBackOnNoneThrowingRuntimeTestException.class, false ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingRuntimeTestException.class,
+ TaskRollingBackOnNoneThrowingTestException.class, true ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingRuntimeTestException.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingRuntimeTestException.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingRuntimeTestException.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingTestException.class, true ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingRuntimeTestException.class,
+ TaskRollingBackOnTestExceptionThrowingNone.class, false ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingRuntimeTestException.class,
+ TaskRollingBackOnTestExceptionThrowingRuntimeTestException.class, false ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingRuntimeTestException.class,
+ TaskRollingBackOnTestExceptionThrowingTestException.class, true ),
+
+ new TestVector( TaskRollingBackOnTestExceptionThrowingTestException.class,
+ TaskRollingBackOnAnyThrowingNone.class, true ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingTestException.class,
+ TaskRollingBackOnAnyThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingTestException.class,
+ TaskRollingBackOnAnyThrowingTestException.class, true ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingTestException.class,
+ TaskRollingBackOnNoneThrowingNone.class, true ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingTestException.class,
+ TaskRollingBackOnNoneThrowingRuntimeTestException.class, false ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingTestException.class,
+ TaskRollingBackOnNoneThrowingTestException.class, true ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingTestException.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingNone.class, true ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingTestException.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingRuntimeTestException.class, true ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingTestException.class,
+ TaskRollingBackOnRuntimeTestExceptionThrowingTestException.class, true ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingTestException.class,
+ TaskRollingBackOnTestExceptionThrowingNone.class, true ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingTestException.class,
+ TaskRollingBackOnTestExceptionThrowingRuntimeTestException.class, false ),
+ new TestVector( TaskRollingBackOnTestExceptionThrowingTestException.class,
+ TaskRollingBackOnTestExceptionThrowingTestException.class, true ), };
+
+ /**
+ * Test which iterates over ALL possible combinations of inner and outer tasks.
+ */
+ public void testNestedTransactions()
+ {
+ final StringBuilder msg = new StringBuilder();
+ for ( TestVector v : TEST_VECTORS )
+ {
+ try
+ {
+ doTestNestedTransaction( v );
+ }
+ catch ( AssertionError e )
+ {
+ msg.append( "\n" );
+ msg.append( e.getMessage() );
+ }
+ }
+ if ( msg.length() > 0 )
+ {
+ fail( msg.toString() );
+ }
+ }
+
+ private void doTestNestedTransaction( TestVector testVector )
+ {
+ final PersistenceModule pm = new PersistenceModule();
+ pm.addApplicationManagedPersistenceUnit( "testUnit" );
+ final Injector injector = Guice.createInjector( pm );
+ final PersistenceService persistService = injector.getInstance( PersistenceService.class );
+ persistService.start();
+ try
+ {
+ // given
+ final TransactionalWorker worker = injector.getInstance( TransactionalWorker.class );
+ worker.scheduleTask( testVector.getOuterTask() );
+ worker.scheduleTask( testVector.getInnerTask() );
+
+ // when
+ worker.doTasks();
+
+ // then
+ if ( testVector.shouldRollBack() )
+ {
+ worker.assertNoEntityHasBeenPersisted();
+ }
+ else
+ {
+ worker.assertAllEntitesHaveBeenPersisted();
+ }
+ }
+ finally
+ {
+ persistService.stop();
+ }
+
+ }
+
+ private static class TestVector
+ {
+ private final Class<? extends TransactionalTask> outerTask;
+
+ private final Class<? extends TransactionalTask> innerTask;
+
+ private final boolean shouldRollBack;
+
+ public TestVector( Class<? extends TransactionalTask> outerTask, Class<? extends TransactionalTask> innerTask,
+ boolean shouldRollBack )
+ {
+ this.outerTask = outerTask;
+ this.innerTask = innerTask;
+ this.shouldRollBack = shouldRollBack;
+ }
+
+ public Class<? extends TransactionalTask> getOuterTask()
+ {
+ return outerTask;
+ }
+
+ public Class<? extends TransactionalTask> getInnerTask()
+ {
+ return innerTask;
+ }
+
+ public boolean shouldRollBack()
+ {
+ return shouldRollBack;
+ }
+ }
+}
Propchange: onami/sandbox/persist/src/test/java/org/apache/onami/persist/NestedTransactionTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: onami/sandbox/persist/src/test/java/org/apache/onami/persist/NestedTransactionTest.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: onami/sandbox/persist/src/test/java/org/apache/onami/persist/NestedTransactionTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain