This is an automated email from the ASF dual-hosted git repository. ahuber pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/isis.git
commit 9332cdd9a6a536cbe769770808d4e3ca16afbd74 Author: Andi Huber <ahu...@apache.org> AuthorDate: Wed Jun 27 09:31:33 2018 +0200 ISIS-1960: Action background execution built-in default: wait for current thread's transaction to complete before executing background tasks Task-Url: https://issues.apache.org/jira/browse/ISIS-1960 --- .../applib/services/xactn/TransactionService.java | 10 ++- .../PersistenceSessionServiceInternal.java | 11 ++-- .../PersistenceSessionServiceInternalNoop.java | 8 +++ .../services/xactn/TransactionServiceDefault.java | 9 ++- .../background/BackgroundCommandExecution.java | 26 ++------ .../background/ForkingInvocationHandler.java | 12 ++++ .../PersistenceSessionServiceInternalDefault.java | 7 +++ .../system/persistence/PersistenceSessionBase.java | 2 +- .../system/transaction/IsisTransaction.java | 73 ++++++++++------------ .../system/transaction/IsisTransactionManager.java | 14 ++--- 10 files changed, 94 insertions(+), 78 deletions(-) diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/xactn/TransactionService.java b/core/applib/src/main/java/org/apache/isis/applib/services/xactn/TransactionService.java index 124dba5..d6de35b 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/services/xactn/TransactionService.java +++ b/core/applib/src/main/java/org/apache/isis/applib/services/xactn/TransactionService.java @@ -19,6 +19,8 @@ package org.apache.isis.applib.services.xactn; +import java.util.concurrent.CountDownLatch; + import org.apache.isis.applib.annotation.Programmatic; import org.apache.isis.applib.services.command.Command; import org.apache.isis.applib.services.command.CommandContext; @@ -59,7 +61,13 @@ public interface TransactionService { @Programmatic TransactionState getTransactionState(); - + /** + * Return a latch, that allows threads to wait on the current transaction to complete. + */ + @Programmatic + CountDownLatch currentTransactionLatch(); + + /** * Intended only for use by fixture scripts and integration tests. * diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/persistsession/PersistenceSessionServiceInternal.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/persistsession/PersistenceSessionServiceInternal.java index daa1b69..572af70 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/persistsession/PersistenceSessionServiceInternal.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/persistsession/PersistenceSessionServiceInternal.java @@ -17,13 +17,14 @@ package org.apache.isis.core.metamodel.services.persistsession; import java.util.List; +import java.util.concurrent.CountDownLatch; import org.apache.isis.applib.annotation.Programmatic; import org.apache.isis.applib.query.Query; import org.apache.isis.applib.services.bookmark.Bookmark; import org.apache.isis.applib.services.bookmark.BookmarkService; -import org.apache.isis.applib.services.xactn.Transaction; import org.apache.isis.applib.services.command.Command; +import org.apache.isis.applib.services.xactn.Transaction; import org.apache.isis.applib.services.xactn.TransactionState; import org.apache.isis.core.metamodel.adapter.ObjectAdapter; import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager; @@ -120,13 +121,13 @@ public interface PersistenceSessionServiceInternal extends AdapterManager { @Programmatic Transaction currentTransaction(); - + + @Programmatic + CountDownLatch currentTransactionLatch(); @Programmatic TransactionState getTransactionState(); - - // -- makePersistent, remove /** @@ -174,6 +175,4 @@ public interface PersistenceSessionServiceInternal extends AdapterManager { void executeWithinTransaction(TransactionalClosure transactionalClosure); - - } diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/persistsession/PersistenceSessionServiceInternalNoop.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/persistsession/PersistenceSessionServiceInternalNoop.java index 086400b..1016a20 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/persistsession/PersistenceSessionServiceInternalNoop.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/persistsession/PersistenceSessionServiceInternalNoop.java @@ -19,6 +19,7 @@ package org.apache.isis.core.metamodel.services.persistsession; import java.util.List; +import java.util.concurrent.CountDownLatch; import org.apache.isis.applib.annotation.DomainService; import org.apache.isis.applib.annotation.NatureOfService; @@ -145,6 +146,11 @@ public class PersistenceSessionServiceInternalNoop implements PersistenceSession public Transaction currentTransaction() { throw new UnsupportedOperationException("Not supported by this implementation of PersistenceSessionServiceInternal"); } + + @Override + public CountDownLatch currentTransactionLatch() { + throw new UnsupportedOperationException("Not supported by this implementation of PersistenceSessionServiceInternal"); + } @Override public void remove(final ObjectAdapter adapter) { @@ -170,4 +176,6 @@ public class PersistenceSessionServiceInternalNoop implements PersistenceSession public TransactionState getTransactionState() { throw new UnsupportedOperationException("Not supported by this implementation of PersistenceSessionServiceInternal"); } + + } diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/xactn/TransactionServiceDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/xactn/TransactionServiceDefault.java index 0848d8b..d3ddf28 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/xactn/TransactionServiceDefault.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/xactn/TransactionServiceDefault.java @@ -19,11 +19,13 @@ package org.apache.isis.core.metamodel.services.xactn; +import java.util.concurrent.CountDownLatch; + import org.apache.isis.applib.annotation.DomainService; import org.apache.isis.applib.annotation.NatureOfService; +import org.apache.isis.applib.services.command.Command; import org.apache.isis.applib.services.xactn.Transaction; import org.apache.isis.applib.services.xactn.TransactionService; -import org.apache.isis.applib.services.command.Command; import org.apache.isis.applib.services.xactn.TransactionState; import org.apache.isis.core.commons.exceptions.IsisException; import org.apache.isis.core.metamodel.services.persistsession.PersistenceSessionServiceInternal; @@ -87,6 +89,11 @@ public class TransactionServiceDefault implements TransactionService { public Transaction currentTransaction() { return persistenceSessionServiceInternal.currentTransaction(); } + + @Override + public CountDownLatch currentTransactionLatch() { + return persistenceSessionServiceInternal.currentTransactionLatch(); + } @Override public TransactionState getTransactionState() { diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundCommandExecution.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundCommandExecution.java index 0d5ec9d..6ac2ed2 100644 --- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundCommandExecution.java +++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundCommandExecution.java @@ -18,33 +18,15 @@ package org.apache.isis.core.runtime.services.background; import java.util.List; -import com.google.common.collect.Lists; - -import org.apache.isis.applib.services.bookmark.Bookmark; -import org.apache.isis.applib.services.bookmark.BookmarkService; -import org.apache.isis.applib.services.clock.ClockService; import org.apache.isis.applib.services.command.Command; -import org.apache.isis.applib.services.command.Command.Executor; -import org.apache.isis.applib.services.iactn.Interaction; -import org.apache.isis.applib.services.iactn.InteractionContext; -import org.apache.isis.applib.services.jaxb.JaxbService; -import org.apache.isis.core.metamodel.adapter.ObjectAdapter; -import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy; -import org.apache.isis.core.metamodel.facets.actions.action.invocation.CommandUtil; -import org.apache.isis.core.metamodel.spec.ObjectSpecification; -import org.apache.isis.core.metamodel.spec.feature.Contributed; -import org.apache.isis.core.metamodel.spec.feature.ObjectAction; -import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation; -import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation; -import org.apache.isis.core.runtime.sessiontemplate.AbstractIsisSessionTemplate; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import org.apache.isis.applib.services.command.CommandExecutorService; import org.apache.isis.applib.services.command.CommandWithDto; import org.apache.isis.core.runtime.system.persistence.PersistenceSession; import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager; -import org.apache.isis.core.runtime.system.transaction.TransactionalClosure; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.Lists; /** * Intended to be used as a base class for executing queued up {@link Command background action}s. diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/ForkingInvocationHandler.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/ForkingInvocationHandler.java index aa4bbc3..8fa7a34 100644 --- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/ForkingInvocationHandler.java +++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/ForkingInvocationHandler.java @@ -20,9 +20,14 @@ import static org.apache.isis.commons.internal.base._With.requires; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; +import java.util.Optional; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import org.apache.isis.core.runtime.system.context.IsisContext; +import org.apache.isis.core.runtime.system.session.IsisSession; +import org.apache.isis.core.runtime.system.session.IsisSessionFactory; +import org.apache.isis.core.runtime.system.transaction.IsisTransaction; /** * Package private invocation handler that executes actions in the background using a ExecutorService @@ -61,9 +66,16 @@ class ForkingInvocationHandler<T> implements InvocationHandler { domainObject = mixedInIfAny; } + final CountDownLatch countDownLatch = Optional.ofNullable(IsisContext.getSessionFactory()) + .map(IsisSessionFactory::getCurrentSession) + .map(IsisSession::getCurrentTransaction) + .map(IsisTransaction::countDownLatch) + .orElse(new CountDownLatch(0)); + backgroundExecutorService.submit(()->{ try { + countDownLatch.await(); // wait for current transaction of the calling thread to complete IsisContext.getSessionFactory().doInSession( ()->proxyMethod.invoke(domainObject, args)); diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/persistsession/PersistenceSessionServiceInternalDefault.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/persistsession/PersistenceSessionServiceInternalDefault.java index 480f440..c26445c 100644 --- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/persistsession/PersistenceSessionServiceInternalDefault.java +++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/persistsession/PersistenceSessionServiceInternalDefault.java @@ -22,6 +22,7 @@ import static java.util.Objects.requireNonNull; import static java.util.Optional.ofNullable; import java.util.List; +import java.util.concurrent.CountDownLatch; import org.apache.isis.applib.NonRecoverableException; import org.apache.isis.applib.annotation.DomainService; @@ -181,6 +182,12 @@ public class PersistenceSessionServiceInternalDefault implements PersistenceSess public Transaction currentTransaction() { return getTransactionManager().getCurrentTransaction(); } + + @Override + public CountDownLatch currentTransactionLatch() { + IsisTransaction transaction = getTransactionManager().getCurrentTransaction(); + return transaction==null ? new CountDownLatch(0) : transaction.countDownLatch(); + } @Override public <T> List<ObjectAdapter> allMatchingQuery(final Query<T> query) { diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionBase.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionBase.java index d10abe5..b75e1b7 100644 --- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionBase.java +++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionBase.java @@ -119,7 +119,7 @@ abstract class PersistenceSessionBase implements PersistenceSession { // sub-components final AdapterManager adapterManager = this; this.persistenceQueryFactory = new PersistenceQueryFactory(adapterManager, this.specificationLoader); - this.transactionManager = new IsisTransactionManager(this, authenticationSession, servicesInjector); + this.transactionManager = new IsisTransactionManager(this, /*authenticationSession,*/ servicesInjector); this.state = State.NOT_INITIALIZED; diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java index 96c9fa2..6ebe65d 100644 --- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java +++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java @@ -21,19 +21,14 @@ package org.apache.isis.core.runtime.system.transaction; import java.util.List; import java.util.UUID; - -import com.google.common.collect.Lists; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import java.util.concurrent.CountDownLatch; import org.apache.isis.applib.annotation.Programmatic; import org.apache.isis.applib.services.HasTransactionId; import org.apache.isis.applib.services.WithTransactionScope; import org.apache.isis.applib.services.xactn.Transaction; import org.apache.isis.applib.services.xactn.TransactionState; -import org.apache.isis.core.commons.authentication.AuthenticationSession; -import org.apache.isis.core.commons.authentication.MessageBroker; +import org.apache.isis.commons.internal.collections._Lists; import org.apache.isis.core.commons.components.TransactionScopedComponent; import org.apache.isis.core.commons.exceptions.IsisException; import org.apache.isis.core.commons.util.ToString; @@ -45,6 +40,10 @@ import org.apache.isis.core.runtime.persistence.objectstore.transaction.DestroyO import org.apache.isis.core.runtime.persistence.objectstore.transaction.PersistenceCommand; import org.apache.isis.core.runtime.services.auditing.AuditingServiceInternal; import org.apache.isis.core.runtime.services.persistsession.PersistenceSessionServiceInternalDefault; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.Lists; /** * Used by the {@link IsisTransactionManager} to captures a set of changes to be @@ -163,11 +162,11 @@ public class IsisTransaction implements TransactionScopedComponent, Transaction private final UUID interactionId; private final int sequence; - private final AuthenticationSession authenticationSession; +// private final AuthenticationSession authenticationSession; - private final List<PersistenceCommand> persistenceCommands = Lists.newArrayList(); + private final List<PersistenceCommand> persistenceCommands = _Lists.newArrayList(); private final IsisTransactionManager transactionManager; - private final MessageBroker messageBroker; +// private final MessageBroker messageBroker; private final PublishingServiceInternal publishingServiceInternal; private final AuditingServiceInternal auditingServiceInternal; @@ -178,18 +177,18 @@ public class IsisTransaction implements TransactionScopedComponent, Transaction public IsisTransaction( final UUID interactionId, final int sequence, - final AuthenticationSession authenticationSession, + /*final AuthenticationSession authenticationSession,*/ final ServicesInjector servicesInjector) { this.interactionId = interactionId; this.sequence = sequence; - this.authenticationSession = authenticationSession; +// this.authenticationSession = authenticationSession; final PersistenceSessionServiceInternalDefault persistenceSessionService = servicesInjector .lookupServiceElseFail(PersistenceSessionServiceInternalDefault.class); this.transactionManager = persistenceSessionService.getTransactionManager(); - this.messageBroker = authenticationSession.getMessageBroker(); +// this.messageBroker = authenticationSession.getMessageBroker(); this.publishingServiceInternal = servicesInjector.lookupServiceElseFail(PublishingServiceInternal.class); this.auditingServiceInternal = servicesInjector.lookupServiceElseFail(AuditingServiceInternal.class); @@ -200,8 +199,6 @@ public class IsisTransaction implements TransactionScopedComponent, Transaction LOG.debug("new transaction {}", this); } - - // -- transactionId @Programmatic @@ -223,6 +220,7 @@ public class IsisTransaction implements TransactionScopedComponent, Transaction } + private final CountDownLatch countDownLatch = new CountDownLatch(1); // -- state @@ -234,6 +232,9 @@ public class IsisTransaction implements TransactionScopedComponent, Transaction private void setState(final State state) { this.state = state; + if(state.isComplete()) { + countDownLatch.countDown(); + } } @Override @@ -251,12 +252,8 @@ public class IsisTransaction implements TransactionScopedComponent, Transaction return transactionState; } - - - // -- commands - /** * Add the non-null command to the list of commands to execute at the end of * the transaction. @@ -320,8 +317,6 @@ public class IsisTransaction implements TransactionScopedComponent, Transaction removeCommand(CreateObjectCommand.class, onObject); } - - // -- flush public final void flush() { @@ -446,9 +441,6 @@ public class IsisTransaction implements TransactionScopedComponent, Transaction setState(State.COMMITTED); } - - - // -- abortCause, markAsAborted /** @@ -494,11 +486,6 @@ public class IsisTransaction implements TransactionScopedComponent, Transaction clearAbortCause(); } - - - - - // -- toString @Override @@ -512,21 +499,29 @@ public class IsisTransaction implements TransactionScopedComponent, Transaction return str; } - - // -- getMessageBroker +// /** +// * The {@link org.apache.isis.core.commons.authentication.MessageBroker} for this transaction. +// * +// * <p> +// * Injected in constructor +// * +// * @deprecated - obtain the {@link org.apache.isis.core.commons.authentication.MessageBroker} instead from the {@link AuthenticationSession}. +// */ +// public MessageBroker getMessageBroker() { +// return messageBroker; +// } + + // -- countDownLatch + /** - * The {@link org.apache.isis.core.commons.authentication.MessageBroker} for this transaction. + * Returns a latch that allows threads to wait on. The latch count drops to zero once this transaction completes. * - * <p> - * Injected in constructor - * - * @deprecated - obtain the {@link org.apache.isis.core.commons.authentication.MessageBroker} instead from the {@link AuthenticationSession}. */ - public MessageBroker getMessageBroker() { - return messageBroker; - } + public CountDownLatch countDownLatch() { + return countDownLatch; + } diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java index 166a4e4..a8b9a87 100644 --- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java +++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java @@ -21,20 +21,18 @@ package org.apache.isis.core.runtime.system.transaction; import java.util.UUID; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import org.apache.isis.applib.services.command.Command; import org.apache.isis.applib.services.command.CommandContext; import org.apache.isis.applib.services.iactn.Interaction; import org.apache.isis.applib.services.iactn.InteractionContext; -import org.apache.isis.core.commons.authentication.AuthenticationSession; import org.apache.isis.core.commons.components.SessionScopedComponent; import org.apache.isis.core.commons.exceptions.IsisException; import org.apache.isis.core.metamodel.services.ServicesInjector; import org.apache.isis.core.runtime.persistence.objectstore.transaction.PersistenceCommand; import org.apache.isis.core.runtime.system.persistence.PersistenceSession; import org.apache.isis.core.runtime.system.session.IsisSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class IsisTransactionManager implements SessionScopedComponent { @@ -52,7 +50,7 @@ public class IsisTransactionManager implements SessionScopedComponent { // -- constructor, fields private final PersistenceSession persistenceSession; - private final AuthenticationSession authenticationSession; + //private final AuthenticationSession authenticationSession; private final ServicesInjector servicesInjector; private final CommandContext commandContext; @@ -60,11 +58,11 @@ public class IsisTransactionManager implements SessionScopedComponent { public IsisTransactionManager( final PersistenceSession persistenceSession, - final AuthenticationSession authenticationSession, + /*final AuthenticationSession authenticationSession,*/ final ServicesInjector servicesInjector) { this.persistenceSession = persistenceSession; - this.authenticationSession = authenticationSession; + //this.authenticationSession = authenticationSession; this.servicesInjector = servicesInjector; this.commandContext = this.servicesInjector.lookupServiceElseFail(CommandContext.class); @@ -239,7 +237,7 @@ public class IsisTransactionManager implements SessionScopedComponent { final UUID transactionId = command.getTransactionId(); this.currentTransaction = new IsisTransaction(transactionId, - interaction.next(Interaction.Sequence.TRANSACTION.id()), authenticationSession, servicesInjector); + interaction.next(Interaction.Sequence.TRANSACTION.id()), /*authenticationSession,*/ servicesInjector); transactionLevel = 0; persistenceSession.startTransaction();