You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by ti...@apache.org on 2016/02/25 14:36:31 UTC
svn commit: r1732302 - in /aries/trunk/tx-control:
tx-control-itests/src/test/java/org/apache/aries/tx/control/itests/
tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/
tx-control-service-local/src/test/java/org/apa...
Author: timothyjward
Date: Thu Feb 25 13:36:31 2016
New Revision: 1732302
URL: http://svn.apache.org/viewvc?rev=1732302&view=rev
Log:
[tx-control] Throw the correct Exception types on different kinds of error
Modified:
aries/trunk/tx-control/tx-control-itests/src/test/java/org/apache/aries/tx/control/itests/ExceptionManagementTransactionTest.java
aries/trunk/tx-control/tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/AbstractTransactionContextImpl.java
aries/trunk/tx-control/tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/NoTransactionContextImpl.java
aries/trunk/tx-control/tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/TransactionContextImpl.java
aries/trunk/tx-control/tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/TransactionControlImpl.java
aries/trunk/tx-control/tx-control-service-local/src/test/java/org/apache/aries/tx/control/service/local/impl/NoTransactionContextTest.java
aries/trunk/tx-control/tx-control-service-local/src/test/java/org/apache/aries/tx/control/service/local/impl/TransactionContextTest.java
Modified: aries/trunk/tx-control/tx-control-itests/src/test/java/org/apache/aries/tx/control/itests/ExceptionManagementTransactionTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/tx-control/tx-control-itests/src/test/java/org/apache/aries/tx/control/itests/ExceptionManagementTransactionTest.java?rev=1732302&r1=1732301&r2=1732302&view=diff
==============================================================================
--- aries/trunk/tx-control/tx-control-itests/src/test/java/org/apache/aries/tx/control/itests/ExceptionManagementTransactionTest.java (original)
+++ aries/trunk/tx-control/tx-control-itests/src/test/java/org/apache/aries/tx/control/itests/ExceptionManagementTransactionTest.java Thu Feb 25 13:36:31 2016
@@ -39,7 +39,6 @@ import javax.inject.Inject;
import org.apache.aries.itest.AbstractIntegrationTest;
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Configuration;
@@ -49,6 +48,7 @@ import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
import org.ops4j.pax.exam.spi.reactors.PerClass;
import org.osgi.service.jdbc.DataSourceFactory;
+import org.osgi.service.transaction.control.ScopedWorkException;
import org.osgi.service.transaction.control.TransactionControl;
import org.osgi.service.transaction.control.TransactionRolledBackException;
import org.osgi.service.transaction.control.jdbc.JDBCConnectionProviderFactory;
@@ -107,8 +107,8 @@ public class ExceptionManagementTransact
throw toThrow;
});
fail("An exception should occur!");
- } catch (TransactionRolledBackException tre) {
- assertSame(toThrow, tre.getCause());
+ } catch (ScopedWorkException swe) {
+ assertSame(toThrow, swe.getCause());
}
assertRollback();
@@ -127,8 +127,8 @@ public class ExceptionManagementTransact
fail("An exception should occur!");
// We have to catch Exception as the compiler complains
// otherwise
- } catch (TransactionRolledBackException tre) {
- assertSame(toThrow, tre.getCause());
+ } catch (ScopedWorkException swe) {
+ assertSame(toThrow, swe.getCause());
}
assertRollback();
@@ -137,7 +137,6 @@ public class ExceptionManagementTransact
//This test currently fails - the local implementation should probably
//use the coordinator a little differently
@Test
- @Ignore
public void testPreCompletionException() {
RuntimeException toThrow = new RuntimeException("Bang!");
Modified: aries/trunk/tx-control/tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/AbstractTransactionContextImpl.java
URL: http://svn.apache.org/viewvc/aries/trunk/tx-control/tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/AbstractTransactionContextImpl.java?rev=1732302&r1=1732301&r2=1732302&view=diff
==============================================================================
--- aries/trunk/tx-control/tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/AbstractTransactionContextImpl.java (original)
+++ aries/trunk/tx-control/tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/AbstractTransactionContextImpl.java Thu Feb 25 13:36:31 2016
@@ -7,50 +7,70 @@ import java.util.concurrent.atomic.Atomi
import java.util.function.Consumer;
import org.osgi.service.coordinator.Coordination;
+import org.osgi.service.coordinator.Participant;
import org.osgi.service.transaction.control.TransactionContext;
import org.osgi.service.transaction.control.TransactionStatus;
-public abstract class AbstractTransactionContextImpl
- implements TransactionContext {
+public abstract class AbstractTransactionContextImpl implements TransactionContext {
- protected static class TransactionVariablesKey {}
+ protected static class TransactionVariablesKey {
+ }
+
+ protected final AtomicReference<Throwable> firstUnexpectedException = new AtomicReference<>();
+
+ protected final List<Throwable> subsequentExceptions = new ArrayList<>();
- protected final AtomicReference<Exception> firstUnexpectedException = new AtomicReference<>();
-
- protected final List<Exception> subsequentExceptions = new ArrayList<>();
-
protected final Coordination coordination;
-
+
protected final List<Runnable> preCompletion = new ArrayList<>();
-
+
protected final List<Consumer<TransactionStatus>> postCompletion = new ArrayList<>();
-
+
public AbstractTransactionContextImpl(Coordination coordination) {
this.coordination = coordination;
+
+ coordination.addParticipant(new Participant() {
+
+ @Override
+ public void failed(Coordination coordination) throws Exception {
+ Throwable failure = coordination.getFailure();
+ recordFailure(failure);
+ safeSetRollbackOnly();
+ }
+
+ @Override
+ public void ended(Coordination coordination) throws Exception {
+ if (isAlive()) {
+ // TODO log this
+ recordFailure(new IllegalStateException(
+ "The surrounding coordination ended before the transaction completed"));
+ safeSetRollbackOnly();
+
+ }
+ }
+ });
}
@SuppressWarnings("unchecked")
@Override
public Object getScopedValue(Object key) {
- return ((HashMap<Object,Object>) coordination.getVariables()
- .getOrDefault(TransactionVariablesKey.class, new HashMap<>()))
- .get(key);
+ return ((HashMap<Object, Object>) coordination.getVariables().getOrDefault(TransactionVariablesKey.class,
+ new HashMap<>())).get(key);
}
@SuppressWarnings("unchecked")
@Override
public void putScopedValue(Object key, Object value) {
- ((HashMap<Object,Object>) coordination.getVariables().computeIfAbsent(
- TransactionVariablesKey.class, k -> new HashMap<>())).put(key, value);
+ ((HashMap<Object, Object>) coordination.getVariables().computeIfAbsent(TransactionVariablesKey.class,
+ k -> new HashMap<>())).put(key, value);
}
-
-
+
protected void beforeCompletion(Runnable onFirstError) {
preCompletion.stream().forEach(r -> {
try {
r.run();
} catch (Exception e) {
- if(firstUnexpectedException.compareAndSet(null, e)) {
+ if (firstUnexpectedException.compareAndSet(null, e)) {
onFirstError.run();
} else {
subsequentExceptions.add(e);
@@ -59,4 +79,27 @@ public abstract class AbstractTransactio
}
});
}
+
+ protected void afterCompletion(TransactionStatus status) {
+ postCompletion.stream().forEach(c -> {
+ try {
+ c.accept(status);
+ } catch (Exception e) {
+ recordFailure(e);
+ // TODO log this
+ }
+ });
+ }
+
+ protected abstract boolean isAlive();
+
+ protected void recordFailure(Throwable failure) {
+ if (!firstUnexpectedException.compareAndSet(null, failure)) {
+ subsequentExceptions.add(failure);
+ }
+ }
+
+ protected abstract void safeSetRollbackOnly();
+
+ public abstract void finish();
}
Modified: aries/trunk/tx-control/tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/NoTransactionContextImpl.java
URL: http://svn.apache.org/viewvc/aries/trunk/tx-control/tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/NoTransactionContextImpl.java?rev=1732302&r1=1732301&r2=1732302&view=diff
==============================================================================
--- aries/trunk/tx-control/tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/NoTransactionContextImpl.java (original)
+++ aries/trunk/tx-control/tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/NoTransactionContextImpl.java Thu Feb 25 13:36:31 2016
@@ -2,12 +2,12 @@ package org.apache.aries.tx.control.serv
import static org.osgi.service.transaction.control.TransactionStatus.NO_TRANSACTION;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import javax.transaction.xa.XAResource;
import org.osgi.service.coordinator.Coordination;
-import org.osgi.service.coordinator.Participant;
import org.osgi.service.transaction.control.LocalResource;
import org.osgi.service.transaction.control.TransactionContext;
import org.osgi.service.transaction.control.TransactionStatus;
@@ -15,39 +15,10 @@ import org.osgi.service.transaction.cont
public class NoTransactionContextImpl extends AbstractTransactionContextImpl
implements TransactionContext {
- volatile boolean finished = false;
+ private final AtomicBoolean finished = new AtomicBoolean(false);
public NoTransactionContextImpl(Coordination coordination) {
super(coordination);
-
- coordination.addParticipant(new Participant() {
-
- @Override
- public void failed(Coordination coordination) throws Exception {
- finished();
- }
-
- @Override
- public void ended(Coordination coordination) throws Exception {
- finished();
- }
-
- private void finished() {
- beforeCompletion(() -> {});
- afterCompletion();
- }
-
- private void afterCompletion() {
- postCompletion.stream().forEach(c -> {
- try {
- c.accept(NO_TRANSACTION);
- } catch (Exception e) {
- firstUnexpectedException.compareAndSet(null, e);
- // TODO log this
- }
- });
- }
- });
}
@Override
@@ -76,6 +47,7 @@ public class NoTransactionContextImpl ex
throw new IllegalStateException(
"The transaction context has finished");
}
+
preCompletion.add(job);
}
@@ -109,4 +81,21 @@ public class NoTransactionContextImpl ex
public boolean supportsLocal() {
return false;
}
+
+ @Override
+ protected boolean isAlive() {
+ return !finished.get();
+ }
+
+ @Override
+ public void finish() {
+ if(finished.compareAndSet(false, true)) {
+ beforeCompletion(() -> {});
+ afterCompletion(NO_TRANSACTION);
+ }
+ }
+
+ @Override
+ protected void safeSetRollbackOnly() {
+ }
}
Modified: aries/trunk/tx-control/tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/TransactionContextImpl.java
URL: http://svn.apache.org/viewvc/aries/trunk/tx-control/tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/TransactionContextImpl.java?rev=1732302&r1=1732301&r2=1732302&view=diff
==============================================================================
--- aries/trunk/tx-control/tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/TransactionContextImpl.java (original)
+++ aries/trunk/tx-control/tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/TransactionContextImpl.java Thu Feb 25 13:36:31 2016
@@ -1,5 +1,6 @@
package org.apache.aries.tx.control.service.local.impl;
+import static org.osgi.service.transaction.control.TransactionStatus.ACTIVE;
import static org.osgi.service.transaction.control.TransactionStatus.COMMITTED;
import static org.osgi.service.transaction.control.TransactionStatus.COMMITTING;
import static org.osgi.service.transaction.control.TransactionStatus.MARKED_ROLLBACK;
@@ -8,107 +9,24 @@ import static org.osgi.service.transacti
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import javax.transaction.xa.XAResource;
import org.osgi.service.coordinator.Coordination;
-import org.osgi.service.coordinator.Participant;
import org.osgi.service.transaction.control.LocalResource;
import org.osgi.service.transaction.control.TransactionContext;
import org.osgi.service.transaction.control.TransactionStatus;
-public class TransactionContextImpl extends AbstractTransactionContextImpl
- implements TransactionContext {
+public class TransactionContextImpl extends AbstractTransactionContextImpl implements TransactionContext {
- final List<LocalResource> resources = new ArrayList<>();
+ final List<LocalResource> resources = new ArrayList<>();
- private volatile TransactionStatus tranStatus;
+ private AtomicReference<TransactionStatus> tranStatus = new AtomicReference<>(ACTIVE);
public TransactionContextImpl(Coordination coordination) {
super(coordination);
-
- tranStatus = TransactionStatus.ACTIVE;
-
- coordination.addParticipant(new Participant() {
-
- @Override
- public void failed(Coordination coordination) throws Exception {
- setRollbackOnly();
-
- beforeCompletion();
-
- vanillaRollback();
-
- afterCompletion();
- }
-
- private void vanillaRollback() {
-
- tranStatus = ROLLING_BACK;
-
- resources.stream().forEach(lr -> {
- try {
- lr.rollback();
- } catch (Exception e) {
- // TODO log this
- }
- });
-
- tranStatus = ROLLED_BACK;
- }
-
- private void beforeCompletion() {
- TransactionContextImpl.this.beforeCompletion(() -> setRollbackOnly());
- }
-
- private void afterCompletion() {
- postCompletion.stream().forEach(c -> {
- try {
- c.accept(tranStatus);
- } catch (Exception e) {
- firstUnexpectedException.compareAndSet(null, e);
- // TODO log this
- }
- });
- }
-
- @Override
- public void ended(Coordination coordination) throws Exception {
- beforeCompletion();
-
- if (getRollbackOnly()) {
- vanillaRollback();
- } else {
- tranStatus = COMMITTING;
-
- List<LocalResource> committed = new ArrayList<>(
- resources.size());
- List<LocalResource> rolledback = new ArrayList<>(0);
-
- resources.stream().forEach(lr -> {
- try {
- if (getRollbackOnly()) {
- lr.rollback();
- rolledback.add(lr);
- } else {
- lr.commit();
- committed.add(lr);
- }
- } catch (Exception e) {
- firstUnexpectedException.compareAndSet(null, e);
- if (committed.isEmpty()) {
- tranStatus = ROLLING_BACK;
- }
- rolledback.add(lr);
- }
- });
- tranStatus = tranStatus == ROLLING_BACK ? ROLLED_BACK
- : COMMITTED;
- }
- afterCompletion();
- }
- });
}
@Override
@@ -118,63 +36,74 @@ public class TransactionContextImpl exte
@Override
public boolean getRollbackOnly() throws IllegalStateException {
- switch (tranStatus) {
- case MARKED_ROLLBACK :
- case ROLLING_BACK :
- case ROLLED_BACK :
+ switch (tranStatus.get()) {
+ case MARKED_ROLLBACK:
+ case ROLLING_BACK:
+ case ROLLED_BACK:
return true;
- default :
+ default:
return false;
}
}
@Override
public void setRollbackOnly() throws IllegalStateException {
- switch (tranStatus) {
- case ACTIVE :
- case MARKED_ROLLBACK :
- tranStatus = MARKED_ROLLBACK;
+ TransactionStatus status = tranStatus.get();
+ switch (status) {
+ case ACTIVE:
+ case MARKED_ROLLBACK:
+ if(!tranStatus.compareAndSet(status, MARKED_ROLLBACK))
+ setRollbackOnly();
break;
- case COMMITTING :
+ case COMMITTING:
// TODO something here? If it's the first resource then it might
// be ok to roll back?
- throw new IllegalStateException(
- "The transaction is already being committed");
- case COMMITTED :
- throw new IllegalStateException(
- "The transaction is already committed");
-
- case ROLLING_BACK :
- case ROLLED_BACK :
+ throw new IllegalStateException("The transaction is already being committed");
+ case COMMITTED:
+ throw new IllegalStateException("The transaction is already committed");
+
+ case ROLLING_BACK:
+ case ROLLED_BACK:
// A no op
break;
- default :
- throw new IllegalStateException(
- "The transaction is in an unkown state");
+ default:
+ throw new IllegalStateException("The transaction is in an unkown state");
+ }
+ }
+
+ @Override
+ protected void safeSetRollbackOnly() {
+ TransactionStatus status = tranStatus.get();
+ switch (status) {
+ case ACTIVE:
+ case MARKED_ROLLBACK:
+ if(!tranStatus.compareAndSet(status, MARKED_ROLLBACK))
+ safeSetRollbackOnly();
+ break;
+ default:
+ break;
}
}
@Override
public TransactionStatus getTransactionStatus() {
- return tranStatus;
+ return tranStatus.get();
}
@Override
public void preCompletion(Runnable job) throws IllegalStateException {
- if (tranStatus.compareTo(MARKED_ROLLBACK) > 0) {
- throw new IllegalStateException(
- "The current transaction is in state " + tranStatus);
+ if (tranStatus.get().compareTo(MARKED_ROLLBACK) > 0) {
+ throw new IllegalStateException("The current transaction is in state " + tranStatus);
}
preCompletion.add(job);
}
@Override
- public void postCompletion(Consumer<TransactionStatus> job)
- throws IllegalStateException {
- if (tranStatus == COMMITTED || tranStatus == ROLLED_BACK) {
- throw new IllegalStateException(
- "The current transaction is in state " + tranStatus);
+ public void postCompletion(Consumer<TransactionStatus> job) throws IllegalStateException {
+ TransactionStatus status = tranStatus.get();
+ if (status == COMMITTED || status == ROLLED_BACK) {
+ throw new IllegalStateException("The current transaction is in state " + tranStatus);
}
postCompletion.add(job);
@@ -187,9 +116,8 @@ public class TransactionContextImpl exte
@Override
public void registerLocalResource(LocalResource resource) {
- if (tranStatus.compareTo(MARKED_ROLLBACK) > 0) {
- throw new IllegalStateException(
- "The current transaction is in state " + tranStatus);
+ if (tranStatus.get().compareTo(MARKED_ROLLBACK) > 0) {
+ throw new IllegalStateException("The current transaction is in state " + tranStatus);
}
resources.add(resource);
}
@@ -203,4 +131,64 @@ public class TransactionContextImpl exte
public boolean supportsLocal() {
return true;
}
+
+ @Override
+ protected boolean isAlive() {
+ TransactionStatus status = tranStatus.get();
+ return status != COMMITTED && status != ROLLED_BACK;
+ }
+
+ @Override
+ public void finish() {
+
+ beforeCompletion(() -> setRollbackOnly());
+
+ TransactionStatus status;
+
+ if (getRollbackOnly()) {
+ vanillaRollback();
+ status = ROLLED_BACK;
+ } else {
+ tranStatus.set(COMMITTING);
+
+ List<LocalResource> committed = new ArrayList<>(resources.size());
+ List<LocalResource> rolledback = new ArrayList<>(0);
+
+ resources.stream().forEach(lr -> {
+ try {
+ if (getRollbackOnly()) {
+ lr.rollback();
+ rolledback.add(lr);
+ } else {
+ lr.commit();
+ committed.add(lr);
+ }
+ } catch (Exception e) {
+ firstUnexpectedException.compareAndSet(null, e);
+ if (committed.isEmpty()) {
+ tranStatus.set(ROLLING_BACK);
+ }
+ rolledback.add(lr);
+ }
+ });
+ status = tranStatus.updateAndGet(ts -> ts == ROLLING_BACK ? ROLLED_BACK : COMMITTED);
+ }
+ afterCompletion(status);
+ }
+
+ private void vanillaRollback() {
+
+ tranStatus.set(ROLLING_BACK);
+
+ resources.stream().forEach(lr -> {
+ try {
+ lr.rollback();
+ } catch (Exception e) {
+ // TODO log this
+ recordFailure(e);
+ }
+ });
+
+ tranStatus.set(ROLLED_BACK);
+ }
}
Modified: aries/trunk/tx-control/tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/TransactionControlImpl.java
URL: http://svn.apache.org/viewvc/aries/trunk/tx-control/tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/TransactionControlImpl.java?rev=1732302&r1=1732301&r2=1732302&view=diff
==============================================================================
--- aries/trunk/tx-control/tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/TransactionControlImpl.java (original)
+++ aries/trunk/tx-control/tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/TransactionControlImpl.java Thu Feb 25 13:36:31 2016
@@ -2,12 +2,14 @@ package org.apache.aries.tx.control.serv
import static java.util.Optional.ofNullable;
import static org.osgi.service.transaction.control.TransactionStatus.NO_TRANSACTION;
+import static org.osgi.service.transaction.control.TransactionStatus.ROLLED_BACK;
import java.util.concurrent.Callable;
import org.osgi.service.coordinator.Coordination;
import org.osgi.service.coordinator.CoordinationException;
import org.osgi.service.coordinator.Coordinator;
+import org.osgi.service.transaction.control.ScopedWorkException;
import org.osgi.service.transaction.control.TransactionBuilder;
import org.osgi.service.transaction.control.TransactionContext;
import org.osgi.service.transaction.control.TransactionControl;
@@ -50,18 +52,19 @@ public class TransactionControlImpl impl
throw re;
}
- return doWork(work, currentCoord, endCoordination);
+ return doWork(work, currentTran, currentCoord, endCoordination);
}
@Override
public <T> T requiresNew(Callable<T> work)
throws TransactionException, TransactionRolledBackException {
Coordination currentCoord = null;
+ AbstractTransactionContextImpl currentTran;
try {
currentCoord = coordinator.begin(
"Resource-Local-Transaction.REQUIRES_NEW", 30000);
- AbstractTransactionContextImpl currentTran = new TransactionContextImpl(
+ currentTran = new TransactionContextImpl(
currentCoord);
currentCoord.getVariables().put(TransactionContextKey.class,
currentTran);
@@ -71,7 +74,7 @@ public class TransactionControlImpl impl
throw re;
}
- return doWork(work, currentCoord, true);
+ return doWork(work, currentTran, currentCoord, true);
}
@Override
@@ -101,7 +104,7 @@ public class TransactionControlImpl impl
throw re;
}
- return doWork(work, currentCoord, endCoordination);
+ return doWork(work, currentTran, currentCoord, endCoordination);
}
@Override
@@ -133,36 +136,71 @@ public class TransactionControlImpl impl
}
throw re;
}
- return doWork(work, currentCoord, endCoordination);
+ return doWork(work, currentTran, currentCoord, endCoordination);
}
private <R> R doWork(Callable<R> transactionalWork,
- Coordination currentCoord, boolean endCoordination) {
+ AbstractTransactionContextImpl currentTran, Coordination currentCoord, boolean endCoordination) {
+ R result;
try {
- R result = transactionalWork.call();
+ result = transactionalWork.call();
- if (endCoordination) {
- currentCoord.end();
- }
- return result;
} catch (Throwable t) {
//TODO handle noRollbackFor
currentCoord.fail(t);
+ try {
+ currentTran.finish();
+ } catch (Exception e) {
+ currentTran.recordFailure(e);
+ }
if (endCoordination) {
try {
currentCoord.end();
} catch (CoordinationException ce) {
- if(ce.getType() == CoordinationException.FAILED) {
- throw new TransactionRolledBackException("The transaction was rolled back due to a failure", ce.getCause());
- } else {
- throw ce;
+ if(ce.getType() != CoordinationException.FAILED) {
+ currentTran.recordFailure(ce);
}
}
}
- TransactionControlImpl.<RuntimeException> throwException(t);
+ ScopedWorkException workException = new ScopedWorkException("The scoped work threw an exception", t,
+ endCoordination ? null : currentTran);
+ Throwable throwable = currentTran.firstUnexpectedException.get();
+ if(throwable != null) {
+ workException.addSuppressed(throwable);
+ }
+ currentTran.subsequentExceptions.stream().forEach(workException::addSuppressed);
+
+ throw workException;
+ }
+
+ try {
+ currentTran.finish();
+ } catch (Exception e) {
+ currentTran.recordFailure(e);
+ currentCoord.fail(e);
+ }
+ try {
+ if (endCoordination) {
+ currentCoord.end();
+ }
+ } catch (CoordinationException ce) {
+ if(ce.getType() != CoordinationException.FAILED) {
+ currentTran.recordFailure(ce);
+ }
+ }
+
+ Throwable throwable = currentTran.firstUnexpectedException.get();
+ if(throwable != null) {
+ TransactionException te = currentTran.getTransactionStatus() == ROLLED_BACK ?
+ new TransactionRolledBackException("The transaction rolled back due to a failure", throwable) :
+ new TransactionException("There was an error in the Transaction completion.", throwable);
+
+ currentTran.subsequentExceptions.stream().forEach(te::addSuppressed);
+
+ throw te;
}
- throw new TransactionException(
- "The code here should never be reached");
+
+ return result;
}
}
@@ -244,21 +282,6 @@ public class TransactionControlImpl impl
return toUse;
}
- /**
- * Borrowed from the netty project as a way to avoid wrapping checked
- * exceptions Viewable at https://github.com/netty/netty/
- * netty/common/src/main/java/io/netty/util/internal/PlatformDependent.java
- *
- * @param t
- * @return
- * @throws T
- */
- @SuppressWarnings("unchecked")
- private static <T extends Throwable> T throwException(Throwable t)
- throws T {
- throw (T) t;
- }
-
@Override
public void ignoreException(Throwable t) throws IllegalStateException {
// TODO Auto-generated method stub
Modified: aries/trunk/tx-control/tx-control-service-local/src/test/java/org/apache/aries/tx/control/service/local/impl/NoTransactionContextTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/tx-control/tx-control-service-local/src/test/java/org/apache/aries/tx/control/service/local/impl/NoTransactionContextTest.java?rev=1732302&r1=1732301&r2=1732302&view=diff
==============================================================================
--- aries/trunk/tx-control/tx-control-service-local/src/test/java/org/apache/aries/tx/control/service/local/impl/NoTransactionContextTest.java (original)
+++ aries/trunk/tx-control/tx-control-service-local/src/test/java/org/apache/aries/tx/control/service/local/impl/NoTransactionContextTest.java Thu Feb 25 13:36:31 2016
@@ -22,7 +22,6 @@ import org.mockito.runners.MockitoJUnitR
import org.osgi.service.coordinator.Coordination;
import org.osgi.service.coordinator.Participant;
import org.osgi.service.transaction.control.LocalResource;
-import org.osgi.service.transaction.control.TransactionContext;
@RunWith(MockitoJUnitRunner.class)
public class NoTransactionContextTest {
@@ -36,7 +35,7 @@ public class NoTransactionContextTest {
Map<Class<?>, Object> variables;
- TransactionContext ctx;
+ AbstractTransactionContextImpl ctx;
@Before
public void setUp() {
@@ -97,7 +96,7 @@ public class NoTransactionContextTest {
}
@Test
- public void testPreCompletionEnd() throws Exception {
+ public void testPreCompletion() throws Exception {
AtomicInteger value = new AtomicInteger(0);
@@ -105,8 +104,7 @@ public class NoTransactionContextTest {
assertEquals(0, value.getAndSet(1));
- Participant participant = getParticipant();
- participant.ended(coordination);
+ ctx.finish();
assertEquals(5, value.get());
}
@@ -123,11 +121,13 @@ public class NoTransactionContextTest {
Participant participant = getParticipant();
participant.failed(coordination);
+ ctx.finish();
+
assertEquals(5, value.get());
}
@Test
- public void testPostCompletionEnd() throws Exception {
+ public void testPostCompletion() throws Exception {
AtomicInteger value = new AtomicInteger(0);
@@ -138,8 +138,7 @@ public class NoTransactionContextTest {
assertEquals(0, value.getAndSet(1));
- Participant participant = getParticipant();
- participant.ended(coordination);
+ ctx.finish();
assertEquals(5, value.get());
}
@@ -159,11 +158,13 @@ public class NoTransactionContextTest {
Participant participant = getParticipant();
participant.failed(coordination);
+ ctx.finish();
+
assertEquals(5, value.get());
}
@Test
- public void testPostCompletionIsAfterPreCompletionEnd() throws Exception {
+ public void testPostCompletionIsAfterPreCompletion() throws Exception {
AtomicInteger value = new AtomicInteger(0);
@@ -173,8 +174,7 @@ public class NoTransactionContextTest {
value.compareAndSet(3, 5);
});
- Participant participant = getParticipant();
- participant.ended(coordination);
+ ctx.finish();
assertEquals(5, value.get());
}
@@ -193,6 +193,8 @@ public class NoTransactionContextTest {
Participant participant = getParticipant();
participant.failed(coordination);
+ ctx.finish();
+
assertEquals(5, value.get());
}
@@ -210,8 +212,7 @@ public class NoTransactionContextTest {
value.compareAndSet(3, 5);
});
- Participant participant = getParticipant();
- participant.ended(coordination);
+ ctx.finish();
assertEquals(5, value.get());
}
Modified: aries/trunk/tx-control/tx-control-service-local/src/test/java/org/apache/aries/tx/control/service/local/impl/TransactionContextTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/tx-control/tx-control-service-local/src/test/java/org/apache/aries/tx/control/service/local/impl/TransactionContextTest.java?rev=1732302&r1=1732301&r2=1732302&view=diff
==============================================================================
--- aries/trunk/tx-control/tx-control-service-local/src/test/java/org/apache/aries/tx/control/service/local/impl/TransactionContextTest.java (original)
+++ aries/trunk/tx-control/tx-control-service-local/src/test/java/org/apache/aries/tx/control/service/local/impl/TransactionContextTest.java Thu Feb 25 13:36:31 2016
@@ -29,7 +29,6 @@ import org.mockito.runners.MockitoJUnitR
import org.osgi.service.coordinator.Coordination;
import org.osgi.service.coordinator.Participant;
import org.osgi.service.transaction.control.LocalResource;
-import org.osgi.service.transaction.control.TransactionContext;
import org.osgi.service.transaction.control.TransactionException;
@RunWith(MockitoJUnitRunner.class)
@@ -44,7 +43,7 @@ public class TransactionContextTest {
Map<Class<?>, Object> variables;
- TransactionContext ctx;
+ AbstractTransactionContextImpl ctx;
@Before
public void setUp() {
@@ -107,7 +106,7 @@ public class TransactionContextTest {
}
@Test
- public void testPreCompletionEnd() throws Exception {
+ public void testPreCompletion() throws Exception {
AtomicInteger value = new AtomicInteger(0);
@@ -118,10 +117,7 @@ public class TransactionContextTest {
assertEquals(0, value.getAndSet(1));
- ArgumentCaptor<Participant> captor = ArgumentCaptor.forClass(Participant.class);
- Mockito.verify(coordination).addParticipant(captor.capture());
-
- captor.getValue().ended(coordination);
+ ctx.finish();
assertEquals(5, value.get());
}
@@ -138,16 +134,19 @@ public class TransactionContextTest {
assertEquals(0, value.getAndSet(1));
+
ArgumentCaptor<Participant> captor = ArgumentCaptor.forClass(Participant.class);
Mockito.verify(coordination).addParticipant(captor.capture());
captor.getValue().failed(coordination);
+ ctx.finish();
+
assertEquals(5, value.get());
}
@Test
- public void testPostCompletionEnd() throws Exception {
+ public void testPostCompletion() throws Exception {
AtomicInteger value = new AtomicInteger(0);
@@ -158,10 +157,7 @@ public class TransactionContextTest {
assertEquals(0, value.getAndSet(1));
- ArgumentCaptor<Participant> captor = ArgumentCaptor.forClass(Participant.class);
- Mockito.verify(coordination).addParticipant(captor.capture());
-
- captor.getValue().ended(coordination);
+ ctx.finish();
assertEquals(5, value.get());
}
@@ -183,6 +179,8 @@ public class TransactionContextTest {
captor.getValue().failed(coordination);
+ ctx.finish();
+
assertEquals(5, value.get());
}
@@ -200,10 +198,7 @@ public class TransactionContextTest {
value.compareAndSet(3, 5);
});
- ArgumentCaptor<Participant> captor = ArgumentCaptor.forClass(Participant.class);
- Mockito.verify(coordination).addParticipant(captor.capture());
-
- captor.getValue().ended(coordination);
+ ctx.finish();
assertEquals(5, value.get());
}
@@ -222,10 +217,7 @@ public class TransactionContextTest {
value.compareAndSet(3, 5);
});
- ArgumentCaptor<Participant> captor = ArgumentCaptor.forClass(Participant.class);
- Mockito.verify(coordination).addParticipant(captor.capture());
-
- captor.getValue().ended(coordination);
+ ctx.finish();
assertEquals(5, value.get());
}
@@ -241,9 +233,8 @@ public class TransactionContextTest {
@Test(expected=IllegalStateException.class)
public void testPreCompletionAfterEnd() throws Exception {
- getParticipant().ended(coordination);
+ ctx.finish();
- Mockito.when(coordination.isTerminated()).thenReturn(true);
ctx.preCompletion(() -> {});
}
@@ -252,16 +243,16 @@ public class TransactionContextTest {
getParticipant().failed(coordination);
- Mockito.when(coordination.isTerminated()).thenReturn(true);
+ ctx.finish();
+
ctx.preCompletion(() -> {});
}
@Test(expected=IllegalStateException.class)
public void testPostCompletionAfterEnd() throws Exception {
- getParticipant().ended(coordination);
+ ctx.finish();
- Mockito.when(coordination.isTerminated()).thenReturn(true);
ctx.postCompletion(x -> {});
}
@@ -270,12 +261,13 @@ public class TransactionContextTest {
getParticipant().failed(coordination);
- Mockito.when(coordination.isTerminated()).thenReturn(true);
+ ctx.finish();
+
ctx.postCompletion(x -> {});
}
@Test
- public void testLocalResourceEnd() throws Exception {
+ public void testLocalResource() throws Exception {
ctx.registerLocalResource(localResource);
Mockito.doAnswer(i -> {
@@ -283,13 +275,29 @@ public class TransactionContextTest {
return null;
}).when(localResource).commit();
- getParticipant().ended(coordination);
+ ctx.finish();
Mockito.verify(localResource).commit();
}
+
+ @Test
+ public void testLocalResourceEarlyEnd() throws Exception {
+ ctx.registerLocalResource(localResource);
+
+ Mockito.doAnswer(i -> {
+ assertEquals(COMMITTING, ctx.getTransactionStatus());
+ return null;
+ }).when(localResource).commit();
+
+ getParticipant().ended(coordination);
+
+ ctx.finish();
+
+ Mockito.verify(localResource).rollback();
+ }
@Test
- public void testLocalResourceEndRollbackOnly() throws Exception {
+ public void testLocalResourceRollbackOnly() throws Exception {
ctx.registerLocalResource(localResource);
ctx.setRollbackOnly();
@@ -298,7 +306,7 @@ public class TransactionContextTest {
return null;
}).when(localResource).rollback();
- getParticipant().ended(coordination);
+ ctx.finish();
Mockito.verify(localResource).rollback();
}
@@ -314,11 +322,13 @@ public class TransactionContextTest {
getParticipant().failed(coordination);
+ ctx.finish();
+
Mockito.verify(localResource).rollback();
}
@Test
- public void testLocalResourceEndPreCommitException() throws Exception {
+ public void testLocalResourcePreCommitException() throws Exception {
ctx.registerLocalResource(localResource);
Mockito.doAnswer(i -> {
@@ -328,13 +338,13 @@ public class TransactionContextTest {
ctx.preCompletion(() -> { throw new IllegalArgumentException(); });
- getParticipant().ended(coordination);
+ ctx.finish();
Mockito.verify(localResource).rollback();
}
@Test
- public void testLocalResourceEndPostCommitException() throws Exception {
+ public void testLocalResourcePostCommitException() throws Exception {
ctx.registerLocalResource(localResource);
Mockito.doAnswer(i -> {
@@ -347,7 +357,7 @@ public class TransactionContextTest {
throw new IllegalArgumentException();
});
- getParticipant().ended(coordination);
+ ctx.finish();
Mockito.verify(localResource).commit();
}
@@ -370,7 +380,7 @@ public class TransactionContextTest {
return null;
}).when(localResource2).rollback();
- getParticipant().ended(coordination);
+ ctx.finish();
Mockito.verify(localResource).commit();
Mockito.verify(localResource2).rollback();