You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2018/06/27 08:08:04 UTC
[isis] 03/04: ISIS-1960: Action background execution built-in
default:
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 <ah...@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();