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 2018/01/18 17:08:40 UTC

[aries-tx-control] branch master updated (a578cf4 -> bdae9a1)

This is an automated email from the ASF dual-hosted git repository.

timothyjward pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/aries-tx-control.git.


    from a578cf4  Marker commit indicating the point at which Transaction Control moved to its own Git Repository
     new a2b1a35  tx-control-service-local spec compliance
     new eb9ec5a  tx-control-service spec compliance No Transaction scope should allow post-completion registrations from inside pre-completion callbacks
     new 46fe11f  tx-control-service spec compliance Post-Completion callback exceptions must be logged, but not re-thrown to the client
     new bdae9a1  tx-control-service spec fixes

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .gitignore                                         |  4 +++
 .../impl/AbstractTransactionContextImpl.java       | 19 ++++++++++---
 .../impl/AbstractTransactionControlImpl.java       | 13 +++++----
 .../common/impl/NoTransactionContextImpl.java      | 21 +++++++++------
 .../common/impl/NoTransactionContextTest.java      | 31 ++++++++++++++++++++++
 .../service/local/impl/TransactionContextImpl.java |  9 ++++---
 .../service/local/impl/TransactionContextTest.java | 18 +++++++++++++
 .../local/impl/TransactionControlRunningTest.java  | 26 ++++++++++++++++++
 .../xa/impl/TransactionControlRunningTest.java     | 26 ++++++++++++++++++
 9 files changed, 146 insertions(+), 21 deletions(-)
 create mode 100644 .gitignore

-- 
To stop receiving notification emails like this one, please contact
['"commits@aries.apache.org" <co...@aries.apache.org>'].

[aries-tx-control] 02/04: tx-control-service spec compliance No Transaction scope should allow post-completion registrations from inside pre-completion callbacks

Posted by ti...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

timothyjward pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/aries-tx-control.git

commit eb9ec5a5f9aa74464b1c8a327b25cd800ca882d4
Author: Tim Ward <ti...@apache.org>
AuthorDate: Thu Jan 18 16:44:33 2018 +0000

    tx-control-service spec compliance
    No Transaction scope should allow post-completion registrations from inside pre-completion callbacks
---
 .../common/impl/NoTransactionContextImpl.java       | 21 +++++++++++++--------
 .../common/impl/NoTransactionContextTest.java       | 15 +++++++++++++++
 2 files changed, 28 insertions(+), 8 deletions(-)

diff --git a/tx-control-services/tx-control-service-common/src/main/java/org/apache/aries/tx/control/service/common/impl/NoTransactionContextImpl.java b/tx-control-services/tx-control-service-common/src/main/java/org/apache/aries/tx/control/service/common/impl/NoTransactionContextImpl.java
index aa3d6d0..c345d64 100644
--- a/tx-control-services/tx-control-service-common/src/main/java/org/apache/aries/tx/control/service/common/impl/NoTransactionContextImpl.java
+++ b/tx-control-services/tx-control-service-common/src/main/java/org/apache/aries/tx/control/service/common/impl/NoTransactionContextImpl.java
@@ -20,7 +20,7 @@ package org.apache.aries.tx.control.service.common.impl;
 
 import static org.osgi.service.transaction.control.TransactionStatus.NO_TRANSACTION;
 
-import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Consumer;
 
 import javax.transaction.xa.XAResource;
@@ -32,7 +32,11 @@ import org.osgi.service.transaction.control.TransactionStatus;
 public class NoTransactionContextImpl extends AbstractTransactionContextImpl
 		implements TransactionContext {
 
-	private final AtomicBoolean finished = new AtomicBoolean(false);
+	private enum Status {
+		WORKING, PRE, POST;
+	}
+	
+	private final AtomicReference<Status> status = new AtomicReference<>(Status.WORKING);
 
 	public NoTransactionContextImpl() {
 		super();
@@ -60,9 +64,9 @@ public class NoTransactionContextImpl extends AbstractTransactionContextImpl
 
 	@Override
 	public void preCompletion(Runnable job) throws IllegalStateException {
-		if (finished.get()) {
+		if (status.get() != Status.WORKING) {
 			throw new IllegalStateException(
-					"The transaction context has finished");
+					"The scoped work has returned. No more pre-completion callbacks can be registered");
 		}
 		
 		preCompletion.add(job);
@@ -71,9 +75,9 @@ public class NoTransactionContextImpl extends AbstractTransactionContextImpl
 	@Override
 	public void postCompletion(Consumer<TransactionStatus> job)
 			throws IllegalStateException {
-		if (finished.get()) {
+		if (status.get() == Status.POST) {
 			throw new IllegalStateException(
-					"The transaction context has finished");
+					"Post completion callbacks have begun. No more post-completion callbacks can be registered");
 		}
 
 		postCompletion.add(job);
@@ -106,13 +110,14 @@ public class NoTransactionContextImpl extends AbstractTransactionContextImpl
 
 	@Override
 	protected boolean isAlive() {
-		return !finished.get();
+		return status.get() == Status.WORKING;
 	}
 	
 	@Override
 	public void finish() {
-		if(finished.compareAndSet(false, true)) {
+		if(status.compareAndSet(Status.WORKING, Status.PRE)) {
 			beforeCompletion(() -> {});
+			status.set(Status.POST);
 			afterCompletion(NO_TRANSACTION);
 		}
 	}
diff --git a/tx-control-services/tx-control-service-common/src/test/java/org/apache/aries/tx/control/service/common/impl/NoTransactionContextTest.java b/tx-control-services/tx-control-service-common/src/test/java/org/apache/aries/tx/control/service/common/impl/NoTransactionContextTest.java
index 4cf4c81..d1e1219 100644
--- a/tx-control-services/tx-control-service-common/src/test/java/org/apache/aries/tx/control/service/common/impl/NoTransactionContextTest.java
+++ b/tx-control-services/tx-control-service-common/src/test/java/org/apache/aries/tx/control/service/common/impl/NoTransactionContextTest.java
@@ -23,6 +23,7 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
+import static org.osgi.service.transaction.control.TransactionStatus.COMMITTED;
 import static org.osgi.service.transaction.control.TransactionStatus.NO_TRANSACTION;
 
 import java.util.concurrent.atomic.AtomicInteger;
@@ -236,6 +237,20 @@ public class NoTransactionContextTest {
 		
 		assertEquals(5, value.get());
 	}
+	
+	@Test
+	public void testPreCompletionRegisterPostCompletion() throws Exception {
+		
+		AtomicInteger value = new AtomicInteger(2);
+		
+		ctx.preCompletion(() -> ctx.postCompletion(t -> value.compareAndSet(1, t.ordinal())));
+		
+		assertEquals(2, value.getAndSet(1));
+		
+		ctx.finish();
+		
+		assertEquals(NO_TRANSACTION.ordinal(), value.get());
+	}
 
 	@Test(expected=IllegalStateException.class)
 	public void testPreCompletionAfterEnd() throws Exception {

-- 
To stop receiving notification emails like this one, please contact
"commits@aries.apache.org" <co...@aries.apache.org>.

[aries-tx-control] 03/04: tx-control-service spec compliance Post-Completion callback exceptions must be logged, but not re-thrown to the client

Posted by ti...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

timothyjward pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/aries-tx-control.git

commit 46fe11f82e0d045a57e7f51f94748afeb57905c1
Author: Tim Ward <ti...@apache.org>
AuthorDate: Thu Jan 18 16:53:31 2018 +0000

    tx-control-service spec compliance
    Post-Completion callback exceptions must be logged, but not re-thrown to the client
---
 .../service/common/impl/AbstractTransactionContextImpl.java    | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/tx-control-services/tx-control-service-common/src/main/java/org/apache/aries/tx/control/service/common/impl/AbstractTransactionContextImpl.java b/tx-control-services/tx-control-service-common/src/main/java/org/apache/aries/tx/control/service/common/impl/AbstractTransactionContextImpl.java
index 5bda0ee..9c8337a 100644
--- a/tx-control-services/tx-control-service-common/src/main/java/org/apache/aries/tx/control/service/common/impl/AbstractTransactionContextImpl.java
+++ b/tx-control-services/tx-control-service-common/src/main/java/org/apache/aries/tx/control/service/common/impl/AbstractTransactionContextImpl.java
@@ -27,9 +27,13 @@ import java.util.function.Consumer;
 
 import org.osgi.service.transaction.control.TransactionContext;
 import org.osgi.service.transaction.control.TransactionStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public abstract class AbstractTransactionContextImpl implements TransactionContext {
 
+	private static final Logger logger = LoggerFactory.getLogger(AbstractTransactionContextImpl.class);
+	
 	protected final AtomicReference<Throwable> firstUnexpectedException = new AtomicReference<>();
 
 	protected final List<Throwable> subsequentExceptions = new ArrayList<>();
@@ -60,7 +64,7 @@ public abstract class AbstractTransactionContextImpl implements TransactionConte
 				} else {
 					subsequentExceptions.add(e);
 				}
-				// TODO log this
+				logger.warn("A pre-completion callback failed with an exception", e);
 			}
 		});
 	}
@@ -70,8 +74,8 @@ public abstract class AbstractTransactionContextImpl implements TransactionConte
 			try {
 				c.accept(status);
 			} catch (Exception e) {
-				recordFailure(e);
-				// TODO log this
+				// Post completion failures do not affect the outcome
+				logger.warn("A post-completion callback failed with an exception", e);
 			}
 		});
 	}

-- 
To stop receiving notification emails like this one, please contact
"commits@aries.apache.org" <co...@aries.apache.org>.

[aries-tx-control] 04/04: tx-control-service spec fixes

Posted by ti...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

timothyjward pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/aries-tx-control.git

commit bdae9a1357c05622abc4ea2298a1f636afbf2c00
Author: Tim Ward <ti...@apache.org>
AuthorDate: Thu Jan 18 17:08:29 2018 +0000

    tx-control-service spec fixes
    
    Users should be able to ignore specific exception instances before they are thrown
---
 .../impl/AbstractTransactionContextImpl.java       |  9 ++++++++
 .../impl/AbstractTransactionControlImpl.java       | 13 +++++------
 .../common/impl/NoTransactionContextTest.java      |  1 -
 .../local/impl/TransactionControlRunningTest.java  | 26 ++++++++++++++++++++++
 .../xa/impl/TransactionControlRunningTest.java     | 26 ++++++++++++++++++++++
 5 files changed, 67 insertions(+), 8 deletions(-)

diff --git a/tx-control-services/tx-control-service-common/src/main/java/org/apache/aries/tx/control/service/common/impl/AbstractTransactionContextImpl.java b/tx-control-services/tx-control-service-common/src/main/java/org/apache/aries/tx/control/service/common/impl/AbstractTransactionContextImpl.java
index 9c8337a..534a4f1 100644
--- a/tx-control-services/tx-control-service-common/src/main/java/org/apache/aries/tx/control/service/common/impl/AbstractTransactionContextImpl.java
+++ b/tx-control-services/tx-control-service-common/src/main/java/org/apache/aries/tx/control/service/common/impl/AbstractTransactionContextImpl.java
@@ -19,9 +19,12 @@
 package org.apache.aries.tx.control.service.common.impl;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Consumer;
 
@@ -38,6 +41,8 @@ public abstract class AbstractTransactionContextImpl implements TransactionConte
 
 	protected final List<Throwable> subsequentExceptions = new ArrayList<>();
 
+	protected final Set<Throwable> ignoredExceptions = Collections.newSetFromMap(new IdentityHashMap<>());
+
 	protected final List<Runnable> preCompletion = new ArrayList<>();
 
 	protected final List<Consumer<TransactionStatus>> postCompletion = new ArrayList<>();
@@ -91,4 +96,8 @@ public abstract class AbstractTransactionContextImpl implements TransactionConte
 	protected abstract void safeSetRollbackOnly();
 
 	public abstract void finish();
+
+	protected void ignoreException(Throwable t) {
+		ignoredExceptions.add(t);
+	}
 }
diff --git a/tx-control-services/tx-control-service-common/src/main/java/org/apache/aries/tx/control/service/common/impl/AbstractTransactionControlImpl.java b/tx-control-services/tx-control-service-common/src/main/java/org/apache/aries/tx/control/service/common/impl/AbstractTransactionControlImpl.java
index 24173dd..f37a06c 100644
--- a/tx-control-services/tx-control-service-common/src/main/java/org/apache/aries/tx/control/service/common/impl/AbstractTransactionControlImpl.java
+++ b/tx-control-services/tx-control-service-common/src/main/java/org/apache/aries/tx/control/service/common/impl/AbstractTransactionControlImpl.java
@@ -161,8 +161,8 @@ public abstract class AbstractTransactionControlImpl implements TransactionContr
 				result = transactionalWork.call();
 
 			} catch (Throwable t) {
-				//TODO handle noRollbackFor
-				if(requiresRollback(t)) {
+				if(!currentTran.ignoredExceptions.contains(t) && 
+						requiresRollback(t)) {
 					currentTran.safeSetRollbackOnly();
 				}
 				if(endTransaction) {
@@ -239,7 +239,7 @@ public abstract class AbstractTransactionControlImpl implements TransactionContr
 	private final ThreadLocal<AbstractTransactionContextImpl> existingTx = new ThreadLocal<>();
 	
 	private final AtomicBoolean closed = new AtomicBoolean();
-
+	
 	protected abstract AbstractTransactionContextImpl startTransaction(boolean readOnly);
 
 	@Override
@@ -291,8 +291,8 @@ public abstract class AbstractTransactionControlImpl implements TransactionContr
 		return getCurrentContext() != null;
 	}
 
-	private TransactionContext getCurrentTranContextChecked() {
-		TransactionContext toUse = getCurrentContext();
+	private AbstractTransactionContextImpl getCurrentTranContextChecked() {
+		AbstractTransactionContextImpl toUse = existingTx.get();
 		if (toUse == null) {
 			throw new IllegalStateException(
 					"There is no applicable transaction context");
@@ -307,8 +307,7 @@ public abstract class AbstractTransactionControlImpl implements TransactionContr
 
 	@Override
 	public void ignoreException(Throwable t) throws IllegalStateException {
-		// TODO Auto-generated method stub
-
+		getCurrentTranContextChecked().ignoreException(t);
 	}
 
 	public void close() {
diff --git a/tx-control-services/tx-control-service-common/src/test/java/org/apache/aries/tx/control/service/common/impl/NoTransactionContextTest.java b/tx-control-services/tx-control-service-common/src/test/java/org/apache/aries/tx/control/service/common/impl/NoTransactionContextTest.java
index d1e1219..bba856e 100644
--- a/tx-control-services/tx-control-service-common/src/test/java/org/apache/aries/tx/control/service/common/impl/NoTransactionContextTest.java
+++ b/tx-control-services/tx-control-service-common/src/test/java/org/apache/aries/tx/control/service/common/impl/NoTransactionContextTest.java
@@ -23,7 +23,6 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
-import static org.osgi.service.transaction.control.TransactionStatus.COMMITTED;
 import static org.osgi.service.transaction.control.TransactionStatus.NO_TRANSACTION;
 
 import java.util.concurrent.atomic.AtomicInteger;
diff --git a/tx-control-services/tx-control-service-local/src/test/java/org/apache/aries/tx/control/service/local/impl/TransactionControlRunningTest.java b/tx-control-services/tx-control-service-local/src/test/java/org/apache/aries/tx/control/service/local/impl/TransactionControlRunningTest.java
index 5564fa5..f43577d 100644
--- a/tx-control-services/tx-control-service-local/src/test/java/org/apache/aries/tx/control/service/local/impl/TransactionControlRunningTest.java
+++ b/tx-control-services/tx-control-service-local/src/test/java/org/apache/aries/tx/control/service/local/impl/TransactionControlRunningTest.java
@@ -140,6 +140,32 @@ public class TransactionControlRunningTest {
 	}
 
 	@Test
+	public void testRequiredIgnoreException() {
+		
+		AtomicReference<TransactionStatus> finalStatus = new AtomicReference<>();
+		
+		Exception userEx = new BindException("Bang!");
+		
+		try {
+			txControl.required(() -> {
+				
+				assertTrue(txControl.activeTransaction());
+				
+				txControl.getCurrentContext().postCompletion(finalStatus::set);
+				
+				txControl.ignoreException(userEx);
+				
+				throw userEx;
+			});
+			fail("Should not be reached");
+		} catch (ScopedWorkException swe) {
+			assertSame(userEx, swe.getCause());
+		}
+		
+		assertEquals(COMMITTED, finalStatus.get());
+	}
+
+	@Test
 	public void testTwoRequiredsNested() {
 
 		AtomicReference<TransactionStatus> finalStatusOuter = new AtomicReference<>();
diff --git a/tx-control-services/tx-control-service-xa/src/test/java/org/apache/aries/tx/control/service/xa/impl/TransactionControlRunningTest.java b/tx-control-services/tx-control-service-xa/src/test/java/org/apache/aries/tx/control/service/xa/impl/TransactionControlRunningTest.java
index dbfa3c7..a7ad5d0 100644
--- a/tx-control-services/tx-control-service-xa/src/test/java/org/apache/aries/tx/control/service/xa/impl/TransactionControlRunningTest.java
+++ b/tx-control-services/tx-control-service-xa/src/test/java/org/apache/aries/tx/control/service/xa/impl/TransactionControlRunningTest.java
@@ -141,6 +141,32 @@ public class TransactionControlRunningTest {
 	}
 
 	@Test
+	public void testRequiredIgnoreException() {
+		
+		AtomicReference<TransactionStatus> finalStatus = new AtomicReference<>();
+		
+		Exception userEx = new BindException("Bang!");
+		
+		try {
+			txControl.required(() -> {
+				
+				assertTrue(txControl.activeTransaction());
+				
+				txControl.getCurrentContext().postCompletion(finalStatus::set);
+				
+				txControl.ignoreException(userEx);
+				
+				throw userEx;
+			});
+			fail("Should not be reached");
+		} catch (ScopedWorkException swe) {
+			assertSame(userEx, swe.getCause());
+		}
+		
+		assertEquals(COMMITTED, finalStatus.get());
+	}
+
+	@Test
 	public void testTwoRequiredsNested() {
 
 		AtomicReference<TransactionStatus> finalStatusOuter = new AtomicReference<>();

-- 
To stop receiving notification emails like this one, please contact
"commits@aries.apache.org" <co...@aries.apache.org>.

[aries-tx-control] 01/04: tx-control-service-local spec compliance

Posted by ti...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

timothyjward pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/aries-tx-control.git

commit a2b1a35cfc4080b1ae890e6e4a88705712d0222a
Author: Tim Ward <ti...@apache.org>
AuthorDate: Thu Jan 18 16:29:22 2018 +0000

    tx-control-service-local spec compliance
    
    Registering a pre-completion callback should throw an IllegalStateException once pre-completion has started
---
 .gitignore                                             |  4 ++++
 .../service/common/impl/NoTransactionContextTest.java  | 17 +++++++++++++++++
 .../service/local/impl/TransactionContextImpl.java     |  9 ++++++---
 .../service/local/impl/TransactionContextTest.java     | 18 ++++++++++++++++++
 4 files changed, 45 insertions(+), 3 deletions(-)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4191720
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+.project
+.settings/
+.classpath
+target/
diff --git a/tx-control-services/tx-control-service-common/src/test/java/org/apache/aries/tx/control/service/common/impl/NoTransactionContextTest.java b/tx-control-services/tx-control-service-common/src/test/java/org/apache/aries/tx/control/service/common/impl/NoTransactionContextTest.java
index 9426bb5..4cf4c81 100644
--- a/tx-control-services/tx-control-service-common/src/test/java/org/apache/aries/tx/control/service/common/impl/NoTransactionContextTest.java
+++ b/tx-control-services/tx-control-service-common/src/test/java/org/apache/aries/tx/control/service/common/impl/NoTransactionContextTest.java
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
 import static org.osgi.service.transaction.control.TransactionStatus.NO_TRANSACTION;
 
 import java.util.concurrent.atomic.AtomicInteger;
@@ -132,6 +133,22 @@ public class NoTransactionContextTest {
 	}
 
 	@Test
+	public void testPreCompletionRegisterPreCompletion() throws Exception {
+		
+		AtomicInteger value = new AtomicInteger(0);
+		
+		ctx.preCompletion(() -> ctx.preCompletion(() -> value.compareAndSet(1, 5)));
+		
+		assertEquals(0, value.getAndSet(1));
+		
+		ctx.finish();
+		
+		assertTrue(ctx.firstUnexpectedException.get() instanceof IllegalStateException);
+		
+		assertEquals(1, value.get());
+	}
+
+	@Test
 	public void testPostCompletion() throws Exception {
 		
 		AtomicInteger value = new AtomicInteger(0);
diff --git a/tx-control-services/tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/TransactionContextImpl.java b/tx-control-services/tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/TransactionContextImpl.java
index 1c6c14e..8d72ee4 100644
--- a/tx-control-services/tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/TransactionContextImpl.java
+++ b/tx-control-services/tx-control-service-local/src/main/java/org/apache/aries/tx/control/service/local/impl/TransactionContextImpl.java
@@ -42,6 +42,8 @@ public class TransactionContextImpl extends AbstractTransactionContextImpl imple
 	final List<LocalResource> resources = new ArrayList<>();
 
 	private final boolean readOnly;
+	
+	private boolean workBodyFinished;
 
 	private AtomicReference<TransactionStatus> tranStatus = new AtomicReference<>(ACTIVE);
 
@@ -115,8 +117,8 @@ public class TransactionContextImpl extends AbstractTransactionContextImpl imple
 
 	@Override
 	public void preCompletion(Runnable job) throws IllegalStateException {
-		if (tranStatus.get().compareTo(MARKED_ROLLBACK) > 0) {
-			throw new IllegalStateException("The current transaction is in state " + tranStatus);
+		if (workBodyFinished) {
+			throw new IllegalStateException("The current transactional work has finished executing so a pre-completion callback can no longer be registered");
 		}
 
 		preCompletion.add(job);
@@ -126,7 +128,7 @@ public class TransactionContextImpl extends AbstractTransactionContextImpl imple
 	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);
+			throw new IllegalStateException("The current transaction is complete so a post-completion callback can no longer be registered");
 		}
 
 		postCompletion.add(job);
@@ -168,6 +170,7 @@ public class TransactionContextImpl extends AbstractTransactionContextImpl imple
 
 	@Override
 	public void finish() {
+		workBodyFinished = true;
 		
 		beforeCompletion(() -> setRollbackOnly());
 
diff --git a/tx-control-services/tx-control-service-local/src/test/java/org/apache/aries/tx/control/service/local/impl/TransactionContextTest.java b/tx-control-services/tx-control-service-local/src/test/java/org/apache/aries/tx/control/service/local/impl/TransactionContextTest.java
index 634bfc9..814804c 100644
--- a/tx-control-services/tx-control-service-local/src/test/java/org/apache/aries/tx/control/service/local/impl/TransactionContextTest.java
+++ b/tx-control-services/tx-control-service-local/src/test/java/org/apache/aries/tx/control/service/local/impl/TransactionContextTest.java
@@ -327,6 +327,24 @@ public class TransactionContextTest {
 		
 		Mockito.verify(localResource).rollback();
 	}
+	
+	@Test
+	public void testLocalResourcePreCompletionRegisterPreCompletion() throws Exception {
+		
+		ctx.registerLocalResource(localResource);
+		
+		Mockito.doAnswer(i -> {
+			assertEquals(ROLLING_BACK, ctx.getTransactionStatus());
+			return null;
+		}).when(localResource).rollback();
+		
+		
+		ctx.preCompletion(() -> ctx.preCompletion(() -> {}));
+		
+		ctx.finish();
+		
+		Mockito.verify(localResource).rollback();
+	}
 
 	@Test
 	public void testLocalResourcePostCommitException() throws Exception {

-- 
To stop receiving notification emails like this one, please contact
"commits@aries.apache.org" <co...@aries.apache.org>.