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 2020/12/31 13:01:28 UTC
[isis] branch 2033-Spring_Data_Integration updated: ISIS-2033:
re-implement transaction events on top of spring transaction infra.
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch 2033-Spring_Data_Integration
in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/2033-Spring_Data_Integration by this push:
new b68d990 ISIS-2033: re-implement transaction events on top of spring transaction infra.
b68d990 is described below
commit b68d9900ffac6011b7017d583d05b199b96fe55e
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Dec 31 14:01:04 2020 +0100
ISIS-2033: re-implement transaction events on top of spring transaction
infra.
---
...InteractionScope.java => InteractionScope.java} | 14 +--
.../applib/services/xactn/TransactionState.java | 4 +
.../interaction/IsisModuleCoreInteraction.java | 4 +-
...leEvent.java => InteractionLifecycleEvent.java} | 2 +-
.../interaction/integration/IsisRequestCycle.java | 40 +------
...InteractionScope.java => InteractionScope.java} | 19 ++--
... InteractionScopeBeanFactoryPostProcessor.java} | 20 ++--
....java => InteractionScopeLifecycleHandler.java} | 5 +-
.../interaction/session/InteractionFactory.java | 5 -
.../core/runtime/context/IsisAppCommonContext.java | 8 --
.../runtime/events/AppLifecycleEventService.java | 17 ++-
.../publish/ExecutionPublisherDefault.java | 4 +-
.../QueryResultsCacheDefault.java | 17 ++-
.../scratchpad/ScratchpadDefault.java | 8 +-
.../session/InteractionFactoryDefault.java | 34 ++----
.../xactn/TransactionServiceSpring.java | 11 +-
.../changetracking/EntityChangeTrackerDefault.java | 54 ++++-----
.../transaction/events/TransactionBeginEvent.java} | 17 +--
.../transaction/events/TransactionEndedEvent.java} | 16 +--
.../events/TransactionEndingEvent.java} | 16 +--
.../events/TransactionEventAbstract.java | 41 +++----
.../ApplicationLayerAwareTransactionManager.java | 64 +++++++++++
.../viewer/javafx/ui/main/UiBuilderFx.java | 15 ++-
.../config/DnEntityDiscoveryListener.java | 7 +-
.../jdo/integration/IsisModuleJdoIntegration.java | 11 +-
.../lifecycles/JdoPersistenceLifecycleService.java | 12 +-
.../metamodel/facets/entity/JdoEntityFacet.java | 8 +-
.../persistence/JdoPersistenceSession5.java | 122 +++++++++++++--------
.../jdo/lightweight/IsisModuleJdoLightweight.java | 11 +-
.../applayer/ApplicationLayerTestFactory.java | 47 ++++----
.../testdomain/conf/Configuration_headless.java | 45 +-------
.../util/interaction/InteractionBoundaryProbe.java | 57 ++++++----
.../isis/JdoIsisEntityChangesPublishingTest.java | 17 ++-
.../jdo/spring/JdoSpringBootstrappingTest.java | 12 +-
.../JdoSpringTransactionScopeListenerTest.java | 11 ++
.../acceptheader/AcceptHeaderServiceForRest.java | 14 +--
.../viewer/integration/WebRequestCycleForIsis.java | 3 +-
37 files changed, 419 insertions(+), 393 deletions(-)
diff --git a/api/applib/src/main/java/org/apache/isis/applib/annotation/IsisInteractionScope.java b/api/applib/src/main/java/org/apache/isis/applib/annotation/InteractionScope.java
similarity index 80%
rename from api/applib/src/main/java/org/apache/isis/applib/annotation/IsisInteractionScope.java
rename to api/applib/src/main/java/org/apache/isis/applib/annotation/InteractionScope.java
index f69da06..b47ea45 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/annotation/IsisInteractionScope.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/annotation/InteractionScope.java
@@ -27,13 +27,13 @@ import java.lang.annotation.Target;
import org.springframework.context.annotation.Scope;
/**
- * {@code @IsisInteractionScope} is a specialization of {@link Scope @Scope} for a
- * component whose lifecycle is bound to the current top-level IsisInteraction.
+ * {@code @InteractionScope} is a specialization of {@link Scope @Scope} for a
+ * component whose lifecycle is bound to the current top-level Interaction.
*
- * <p>Specifically, {@code @IsisInteractionScope} is a <em>composed annotation</em> that
- * acts as a shortcut for {@code @Scope("isis-interaction")}.
+ * <p>Specifically, {@code @InteractionScope} is a <em>composed annotation</em> that
+ * acts as a shortcut for {@code @Scope("interaction")}.
*
- * <p>{@code @IsisInteractionScope} may be used as a meta-annotation to create custom
+ * <p>{@code @InteractionScope} may be used as a meta-annotation to create custom
* composed annotations.
*
* @since 2.0 {@index}
@@ -46,7 +46,7 @@ import org.springframework.context.annotation.Scope;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
-@Scope("isis-interaction")
-public @interface IsisInteractionScope {
+@Scope("interaction")
+public @interface InteractionScope {
}
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/xactn/TransactionState.java b/api/applib/src/main/java/org/apache/isis/applib/services/xactn/TransactionState.java
index 05d23e5..3acb14f 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/xactn/TransactionState.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/xactn/TransactionState.java
@@ -92,6 +92,10 @@ public enum TransactionState {
return this == COMMITTED || this == ABORTED;
}
+ public boolean isInProgress() {
+ return this == IN_PROGRESS;
+ }
+
public boolean mustAbort() {
return this == MUST_ABORT;
}
diff --git a/core/interaction/src/main/java/org/apache/isis/core/interaction/IsisModuleCoreInteraction.java b/core/interaction/src/main/java/org/apache/isis/core/interaction/IsisModuleCoreInteraction.java
index b99c8c7..ea85fe2 100644
--- a/core/interaction/src/main/java/org/apache/isis/core/interaction/IsisModuleCoreInteraction.java
+++ b/core/interaction/src/main/java/org/apache/isis/core/interaction/IsisModuleCoreInteraction.java
@@ -3,12 +3,12 @@ package org.apache.isis.core.interaction;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
-import org.apache.isis.core.interaction.scope.IsisInteractionScopeBeanFactoryPostProcessor;
+import org.apache.isis.core.interaction.scope.InteractionScopeBeanFactoryPostProcessor;
@Configuration
@Import({
- IsisInteractionScopeBeanFactoryPostProcessor.class
+ InteractionScopeBeanFactoryPostProcessor.class
})
public class IsisModuleCoreInteraction {
diff --git a/core/interaction/src/main/java/org/apache/isis/core/interaction/events/IsisInteractionLifecycleEvent.java b/core/interaction/src/main/java/org/apache/isis/core/interaction/events/InteractionLifecycleEvent.java
similarity index 96%
rename from core/interaction/src/main/java/org/apache/isis/core/interaction/events/IsisInteractionLifecycleEvent.java
rename to core/interaction/src/main/java/org/apache/isis/core/interaction/events/InteractionLifecycleEvent.java
index fb6a868..b98a7d5 100644
--- a/core/interaction/src/main/java/org/apache/isis/core/interaction/events/IsisInteractionLifecycleEvent.java
+++ b/core/interaction/src/main/java/org/apache/isis/core/interaction/events/InteractionLifecycleEvent.java
@@ -25,7 +25,7 @@ import lombok.ToString;
import lombok.Value;
@Value(staticConstructor="of") @ToString(of = "eventType")
-public class IsisInteractionLifecycleEvent {
+public class InteractionLifecycleEvent {
public enum EventType {
HAS_STARTED,
diff --git a/core/interaction/src/main/java/org/apache/isis/core/interaction/integration/IsisRequestCycle.java b/core/interaction/src/main/java/org/apache/isis/core/interaction/integration/IsisRequestCycle.java
index ee8caa4..1a2b39b 100644
--- a/core/interaction/src/main/java/org/apache/isis/core/interaction/integration/IsisRequestCycle.java
+++ b/core/interaction/src/main/java/org/apache/isis/core/interaction/integration/IsisRequestCycle.java
@@ -18,16 +18,10 @@
*/
package org.apache.isis.core.interaction.integration;
-import org.springframework.transaction.PlatformTransactionManager;
-import org.springframework.transaction.TransactionStatus;
-import org.springframework.transaction.support.TransactionTemplate;
-
-import org.apache.isis.commons.internal.exceptions._Exceptions;
import org.apache.isis.core.interaction.session.InteractionFactory;
import org.apache.isis.core.security.authentication.Authentication;
import lombok.RequiredArgsConstructor;
-import lombok.val;
/**
*
@@ -36,55 +30,23 @@ import lombok.val;
@RequiredArgsConstructor(staticName = "next")
public class IsisRequestCycle {
- // -- SUPPORTING ISIS TRANSACTION FILTER FOR RESTFUL OBJECTS ...
-
private final InteractionFactory isisInteractionFactory;
- private final TransactionTemplate transactionTemplate;
- private TransactionStatus txStatus;
// -- SUPPORTING WEB REQUEST CYCLE FOR ISIS ...
public void onBeginRequest(Authentication authentication) {
isisInteractionFactory.openInteraction(authentication);
-
- txStatus = getTransactionManager().getTransaction(null);
-
}
public void onRequestHandlerExecuted() {
- if(txStatus==null) {
- return;
- }
-
- txStatus.flush();
}
public void onEndRequest() {
- if(txStatus==null) {
- return;
- }
+ isisInteractionFactory.closeSessionStack();
- try {
-
- getTransactionManager().commit(txStatus);
-
- } finally {
- isisInteractionFactory.closeSessionStack();
- }
-
- }
-
- // -- HELPER
-
- private PlatformTransactionManager getTransactionManager() {
- val txMan = transactionTemplate.getTransactionManager();
- if(txMan == null) {
- throw _Exceptions.illegalState("IsisRequestCycle needs a PlatformTransactionManager (Spring)");
- }
- return txMan;
}
diff --git a/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/IsisInteractionScope.java b/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/InteractionScope.java
similarity index 89%
rename from core/interaction/src/main/java/org/apache/isis/core/interaction/scope/IsisInteractionScope.java
rename to core/interaction/src/main/java/org/apache/isis/core/interaction/scope/InteractionScope.java
index d98c066..6dfed09 100644
--- a/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/IsisInteractionScope.java
+++ b/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/InteractionScope.java
@@ -38,7 +38,7 @@ import lombok.extern.log4j.Log4j2;
* @since 2.0
*/
@Log4j2
-class IsisInteractionScope implements Scope, IsisInteractionScopeCloseListener {
+class InteractionScope implements Scope, InteractionScopeLifecycleHandler {
@Inject private InteractionTracker isisInteractionTracker;
@@ -61,13 +61,13 @@ class IsisInteractionScope implements Scope, IsisInteractionScopeCloseListener {
public Object get(String name, ObjectFactory<?> objectFactory) {
if(isisInteractionTracker==null) {
- throw _Exceptions.illegalState("Creation of bean %s with @IsisInteractionScope requires the "
- + "IsisInteractionScopeBeanFactoryPostProcessor registered and initialized.", name);
+ throw _Exceptions.illegalState("Creation of bean %s with @InteractionScope requires the "
+ + "InteractionScopeBeanFactoryPostProcessor registered and initialized.", name);
}
if(!isisInteractionTracker.isInInteractionSession()) {
- throw _Exceptions.illegalState("Creation of bean %s with @IsisInteractionScope requires the "
- + "calling %s to have an open IsisInteraction on the thread-local stack. Running into "
+ throw _Exceptions.illegalState("Creation of bean %s with @InteractionScope requires the "
+ + "calling %s to have an open Interaction on the thread-local stack. Running into "
+ "this issue might be caused by use of ... @Inject MyScopedBean bean ..., instead of "
+ "... @Inject Provider<MyScopedBean> provider ...", name, _Probe.currentThreadId());
}
@@ -113,11 +113,12 @@ class IsisInteractionScope implements Scope, IsisInteractionScopeCloseListener {
}
@Override
- public void preTopLevelIsisInteractionClose() {
- removeAll();
+ public void onTopLevelInteractionOpened() {
+ // nothing to do
}
-
- private void removeAll() {
+
+ @Override
+ public void onTopLevelInteractionClosing() {
try {
scopedObjects.get().values().forEach(ScopedObject::preDestroy);
} finally {
diff --git a/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/IsisInteractionScopeBeanFactoryPostProcessor.java b/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/InteractionScopeBeanFactoryPostProcessor.java
similarity index 67%
rename from core/interaction/src/main/java/org/apache/isis/core/interaction/scope/IsisInteractionScopeBeanFactoryPostProcessor.java
rename to core/interaction/src/main/java/org/apache/isis/core/interaction/scope/InteractionScopeBeanFactoryPostProcessor.java
index 6f0695e..221b234 100644
--- a/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/IsisInteractionScopeBeanFactoryPostProcessor.java
+++ b/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/InteractionScopeBeanFactoryPostProcessor.java
@@ -33,21 +33,21 @@ import lombok.val;
* @since 2.0
*/
@Component
-public class IsisInteractionScopeBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
+public class InteractionScopeBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
- val isisInteractionScope = new IsisInteractionScope();
- // scope name as defined in annotation @IsisInteractionScope
- beanFactory.registerScope("isis-interaction", isisInteractionScope);
- _Context.put(IsisInteractionScope.class, isisInteractionScope, true);
+ val interactionScope = new InteractionScope();
+ // scope name as defined in annotation @InteractionScope
+ beanFactory.registerScope("interaction", interactionScope);
+ _Context.put(InteractionScope.class, interactionScope, true);
}
- public static IsisInteractionScopeCloseListener initIsisInteractionScopeSupport(
+ public static InteractionScopeLifecycleHandler initIsisInteractionScopeSupport(
@NonNull final ServiceInjector serviceInjector) {
- val isisInteractionScope = _Context.getElseFail(IsisInteractionScope.class);
- serviceInjector.injectServicesInto(isisInteractionScope);
- _Context.remove(IsisInteractionScope.class); // cleanup
- return isisInteractionScope;
+ val interactionScope = _Context.getElseFail(InteractionScope.class);
+ serviceInjector.injectServicesInto(interactionScope);
+ _Context.remove(InteractionScope.class); // cleanup
+ return interactionScope;
}
}
diff --git a/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/IsisInteractionScopeCloseListener.java b/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/InteractionScopeLifecycleHandler.java
similarity index 87%
copy from core/interaction/src/main/java/org/apache/isis/core/interaction/scope/IsisInteractionScopeCloseListener.java
copy to core/interaction/src/main/java/org/apache/isis/core/interaction/scope/InteractionScopeLifecycleHandler.java
index 1518af9..82ad852 100644
--- a/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/IsisInteractionScopeCloseListener.java
+++ b/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/InteractionScopeLifecycleHandler.java
@@ -21,8 +21,9 @@ package org.apache.isis.core.interaction.scope;
/**
* @since 2.0
*/
-public interface IsisInteractionScopeCloseListener {
+public interface InteractionScopeLifecycleHandler {
- void preTopLevelIsisInteractionClose();
+ void onTopLevelInteractionOpened();
+ void onTopLevelInteractionClosing();
}
diff --git a/core/interaction/src/main/java/org/apache/isis/core/interaction/session/InteractionFactory.java b/core/interaction/src/main/java/org/apache/isis/core/interaction/session/InteractionFactory.java
index 6935825..66db00c 100644
--- a/core/interaction/src/main/java/org/apache/isis/core/interaction/session/InteractionFactory.java
+++ b/core/interaction/src/main/java/org/apache/isis/core/interaction/session/InteractionFactory.java
@@ -64,11 +64,6 @@ public interface InteractionFactory {
* @return whether the calling thread is within the context of an open {@link InteractionSession}
*/
boolean isInInteractionSession();
-
- /**
- * @return whether the calling thread is within the context of an open IsisTransactionSession
- */
- boolean isInTransaction();
/**
* Executes a block of code with a new or reused {@link InteractionSession} using a new or
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/context/IsisAppCommonContext.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/context/IsisAppCommonContext.java
index fcf4174..cf37fd3 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/context/IsisAppCommonContext.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/context/IsisAppCommonContext.java
@@ -22,9 +22,6 @@ import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
-import org.springframework.transaction.PlatformTransactionManager;
-import org.springframework.transaction.support.TransactionTemplate;
-
import org.apache.isis.applib.services.inject.ServiceInjector;
import org.apache.isis.applib.services.menu.MenuBarsService;
import org.apache.isis.applib.services.registry.ServiceRegistry;
@@ -103,11 +100,6 @@ public class IsisAppCommonContext implements HasMetaModelContext {
return getMetaModelContext().getServiceInjector().injectServicesInto(pojo);
}
- public TransactionTemplate createTransactionTemplate() {
- val txMan = lookupServiceElseFail(PlatformTransactionManager.class);
- return new TransactionTemplate(txMan);
- }
-
public ObjectMemento mementoFor(ManagedObject adapter) {
return getMementoService().mementoForObject(adapter);
}
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/events/AppLifecycleEventService.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/events/AppLifecycleEventService.java
index a110056..688e7b7 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/events/AppLifecycleEventService.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/events/AppLifecycleEventService.java
@@ -28,7 +28,8 @@ import org.springframework.stereotype.Service;
import org.apache.isis.applib.annotation.OrderPrecedence;
import org.apache.isis.applib.services.eventbus.EventBusService;
-import org.apache.isis.core.interaction.events.IsisInteractionLifecycleEvent;
+import org.apache.isis.commons.internal.debug._Probe;
+import org.apache.isis.core.interaction.events.InteractionLifecycleEvent;
import org.apache.isis.core.interaction.session.InteractionSession;
import org.apache.isis.core.interaction.session.InteractionTracker;
import org.apache.isis.core.transaction.changetracking.events.PostStoreEvent;
@@ -65,17 +66,23 @@ public class AppLifecycleEventService {
// -- INTERACTION
public void fireInteractionHasStarted(InteractionSession interactionSession) {
+
+ _Probe.errOut("fireInteractionHasStarted");
+
val conversationId = interactionTracker.getConversationId().orElse(null);
eventBusService.post(
- IsisInteractionLifecycleEvent
- .of(conversationId, interactionSession, IsisInteractionLifecycleEvent.EventType.HAS_STARTED));
+ InteractionLifecycleEvent
+ .of(conversationId, interactionSession, InteractionLifecycleEvent.EventType.HAS_STARTED));
}
public void fireInteractionIsEnding(InteractionSession interactionSession) {
+
+ _Probe.errOut("fireInteractionIsEnding");
+
val conversationId = interactionTracker.getConversationId().orElse(null);
eventBusService.post(
- IsisInteractionLifecycleEvent
- .of(conversationId, interactionSession, IsisInteractionLifecycleEvent.EventType.IS_ENDING));
+ InteractionLifecycleEvent
+ .of(conversationId, interactionSession, InteractionLifecycleEvent.EventType.IS_ENDING));
}
// -- PERSISTENT OBJECT EVENTS
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/publish/ExecutionPublisherDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/publish/ExecutionPublisherDefault.java
index 2d6474c..75ce1d3 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/publish/ExecutionPublisherDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/publish/ExecutionPublisherDefault.java
@@ -32,7 +32,7 @@ import org.springframework.context.annotation.Primary;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
-import org.apache.isis.applib.annotation.IsisInteractionScope;
+import org.apache.isis.applib.annotation.InteractionScope;
import org.apache.isis.applib.annotation.OrderPrecedence;
import org.apache.isis.applib.services.iactn.Interaction;
import org.apache.isis.applib.services.publishing.spi.ExecutionSubscriber;
@@ -48,7 +48,7 @@ import lombok.val;
@Order(OrderPrecedence.MIDPOINT)
@Primary
@Qualifier("Default")
-@IsisInteractionScope
+@InteractionScope
@RequiredArgsConstructor(onConstructor_ = {@Inject})
//@Log4j2
public class ExecutionPublisherDefault
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/queryresultscache/QueryResultsCacheDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/queryresultscache/QueryResultsCacheDefault.java
index 323d2e9..75d6b95 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/queryresultscache/QueryResultsCacheDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/queryresultscache/QueryResultsCacheDefault.java
@@ -29,20 +29,19 @@ import org.springframework.context.annotation.Primary;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
-import org.apache.isis.applib.annotation.IsisInteractionScope;
+import org.apache.isis.applib.annotation.InteractionScope;
import org.apache.isis.applib.annotation.OrderPrecedence;
-import org.apache.isis.applib.services.TransactionScopeListener;
-import org.apache.isis.applib.services.queryresultscache.QueryResultCacheControl;
-import org.apache.isis.applib.services.queryresultscache.QueryResultsCache;
-import org.apache.isis.commons.internal.base._Casts;
-import org.apache.isis.commons.internal.base._NullSafe;
-import org.apache.isis.commons.internal.collections._Maps;
import org.apache.isis.applib.services.MethodReferences.Call0;
import org.apache.isis.applib.services.MethodReferences.Call1;
import org.apache.isis.applib.services.MethodReferences.Call2;
import org.apache.isis.applib.services.MethodReferences.Call3;
import org.apache.isis.applib.services.MethodReferences.Call4;
import org.apache.isis.applib.services.MethodReferences.Call5;
+import org.apache.isis.applib.services.queryresultscache.QueryResultCacheControl;
+import org.apache.isis.applib.services.queryresultscache.QueryResultsCache;
+import org.apache.isis.commons.internal.base._Casts;
+import org.apache.isis.commons.internal.base._NullSafe;
+import org.apache.isis.commons.internal.collections._Maps;
import lombok.extern.log4j.Log4j2;
@@ -59,10 +58,10 @@ import lombok.extern.log4j.Log4j2;
@Named("isisRuntime.QueryResultsCacheDefault")
@Order(OrderPrecedence.EARLY)
@Primary
-@IsisInteractionScope
+@InteractionScope
@Qualifier("Default")
@Log4j2
-public class QueryResultsCacheDefault implements QueryResultsCache, TransactionScopeListener {
+public class QueryResultsCacheDefault implements QueryResultsCache {
private final Map<Key, Value<?>> cache = _Maps.newHashMap();
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/scratchpad/ScratchpadDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/scratchpad/ScratchpadDefault.java
index 1f8afdd..3a6821c 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/scratchpad/ScratchpadDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/scratchpad/ScratchpadDefault.java
@@ -27,13 +27,11 @@ import org.springframework.context.annotation.Primary;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
-import org.apache.isis.applib.annotation.IsisInteractionScope;
+import org.apache.isis.applib.annotation.InteractionScope;
import org.apache.isis.applib.annotation.OrderPrecedence;
import org.apache.isis.applib.services.scratchpad.Scratchpad;
import org.apache.isis.commons.internal.collections._Maps;
-import lombok.extern.log4j.Log4j2;
-
/**
* This service (API and implementation) provides a mechanism to interchange information between multiple objects invoked in the same
* interaction. Most commonly this will be as the result of invoking a {@link org.apache.isis.applib.annotation.Bulk}
@@ -49,8 +47,8 @@ import lombok.extern.log4j.Log4j2;
@Order(OrderPrecedence.EARLY)
@Primary
@Qualifier("Default")
-@IsisInteractionScope
-@Log4j2
+@InteractionScope
+//@Log4j2
public class ScratchpadDefault implements Scratchpad {
/**
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/session/InteractionFactoryDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/session/InteractionFactoryDefault.java
index 44503d0..7e217c9 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/session/InteractionFactoryDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/session/InteractionFactoryDefault.java
@@ -19,6 +19,8 @@
package org.apache.isis.core.runtimeservices.session;
+import static org.apache.isis.commons.internal.base._With.requires;
+
import java.io.File;
import java.sql.Timestamp;
import java.util.Objects;
@@ -37,7 +39,6 @@ import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
-import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.apache.isis.applib.annotation.OrderPrecedence;
import org.apache.isis.applib.services.clock.ClockService;
@@ -51,8 +52,8 @@ import org.apache.isis.commons.internal.concurrent._ConcurrentTaskList;
import org.apache.isis.commons.internal.debug._Probe;
import org.apache.isis.commons.internal.exceptions._Exceptions;
import org.apache.isis.core.config.IsisConfiguration;
-import org.apache.isis.core.interaction.scope.IsisInteractionScopeBeanFactoryPostProcessor;
-import org.apache.isis.core.interaction.scope.IsisInteractionScopeCloseListener;
+import org.apache.isis.core.interaction.scope.InteractionScopeBeanFactoryPostProcessor;
+import org.apache.isis.core.interaction.scope.InteractionScopeLifecycleHandler;
import org.apache.isis.core.interaction.session.AuthenticationLayer;
import org.apache.isis.core.interaction.session.InteractionFactory;
import org.apache.isis.core.interaction.session.InteractionSession;
@@ -65,8 +66,6 @@ import org.apache.isis.core.runtime.events.AppLifecycleEventService;
import org.apache.isis.core.security.authentication.Authentication;
import org.apache.isis.core.security.authentication.manager.AuthenticationManager;
-import static org.apache.isis.commons.internal.base._With.requires;
-
import lombok.NonNull;
import lombok.SneakyThrows;
import lombok.val;
@@ -101,11 +100,12 @@ implements InteractionFactory, InteractionTracker {
@Inject ClockService clockService;
@Inject CommandPublisher commandPublisher;
- private IsisInteractionScopeCloseListener isisInteractionScopeCloseListener;
+ private InteractionScopeLifecycleHandler interactionScopeLifecycleHandler;
@PostConstruct
public void initIsisInteractionScopeSupport() {
- this.isisInteractionScopeCloseListener = IsisInteractionScopeBeanFactoryPostProcessor.initIsisInteractionScopeSupport(serviceInjector);
+ this.interactionScopeLifecycleHandler = InteractionScopeBeanFactoryPostProcessor
+ .initIsisInteractionScopeSupport(serviceInjector);
}
//@PostConstruct .. too early, needs services to be provisioned first
@@ -221,23 +221,6 @@ implements InteractionFactory, InteractionTracker {
return !authenticationStack.get().isEmpty();
}
- @Override
- public boolean isInTransaction() {
-
- return TransactionSynchronizationManager.isActualTransactionActive();
-
-// return currentInteractionSession().map(isisInteraction->{
-// if (isisInteraction.getCurrentTransactionId() != null) {
-// if (!isisInteraction.getCurrentTransactionState().isComplete()) {
-// return true;
-// }
-// }
-// return false;
-// })
-// .orElse(false);
-
- }
-
// -- AUTHENTICATED EXECUTION
@Override
@@ -319,13 +302,14 @@ implements InteractionFactory, InteractionTracker {
private void postSessionOpened(InteractionSession session) {
conversationId.set(UUID.randomUUID());
+ interactionScopeLifecycleHandler.onTopLevelInteractionOpened();
runtimeEventService.fireInteractionHasStarted(session); // only fire on top-level session
}
private void preSessionClosed(InteractionSession session) {
completeAndPublishCurrentCommand();
runtimeEventService.fireInteractionIsEnding(session); // only fire on top-level session
- isisInteractionScopeCloseListener.preTopLevelIsisInteractionClose(); // cleanup the isis-session scope
+ interactionScopeLifecycleHandler.onTopLevelInteractionClosing(); // cleanup the isis-session scope
session.close(); // do this last
}
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/xactn/TransactionServiceSpring.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/xactn/TransactionServiceSpring.java
index 30ef4a4..7959ada 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/xactn/TransactionServiceSpring.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/xactn/TransactionServiceSpring.java
@@ -87,6 +87,7 @@ public class TransactionServiceSpring implements TransactionService {
public void nextTransaction() {
val txManager = singletonTransactionManagerElseFail();
+
val txTemplate = new TransactionTemplate(txManager);
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
@@ -126,19 +127,15 @@ public class TransactionServiceSpring implements TransactionService {
return currentTransactionStatus()
.map(txStatus->{
- if(txStatus.isNewTransaction()) {
- return txStatus.isRollbackOnly()
- ? TransactionState.MUST_ABORT
- : TransactionState.IN_PROGRESS;
- }
-
if(txStatus.isCompleted()) {
return txStatus.isRollbackOnly()
? TransactionState.ABORTED
: TransactionState.COMMITTED;
}
- throw _Exceptions.unexpectedCodeReach();
+ return txStatus.isRollbackOnly()
+ ? TransactionState.MUST_ABORT
+ : TransactionState.IN_PROGRESS;
})
.orElse(TransactionState.NONE);
diff --git a/core/transaction/src/main/java/org/apache/isis/core/transaction/changetracking/EntityChangeTrackerDefault.java b/core/transaction/src/main/java/org/apache/isis/core/transaction/changetracking/EntityChangeTrackerDefault.java
index 39b2889..76f40f5 100644
--- a/core/transaction/src/main/java/org/apache/isis/core/transaction/changetracking/EntityChangeTrackerDefault.java
+++ b/core/transaction/src/main/java/org/apache/isis/core/transaction/changetracking/EntityChangeTrackerDefault.java
@@ -32,12 +32,12 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.event.TransactionalEventListener;
import org.apache.isis.applib.annotation.EntityChangeKind;
-import org.apache.isis.applib.annotation.IsisInteractionScope;
+import org.apache.isis.applib.annotation.InteractionScope;
import org.apache.isis.applib.annotation.OrderPrecedence;
import org.apache.isis.applib.events.lifecycle.AbstractLifecycleEvent;
-import org.apache.isis.applib.services.TransactionScopeListener;
import org.apache.isis.applib.services.eventbus.EventBusService;
import org.apache.isis.applib.services.iactn.Interaction;
import org.apache.isis.applib.services.iactn.InteractionContext;
@@ -71,6 +71,7 @@ import org.apache.isis.core.metamodel.spec.feature.MixedIn;
import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
import org.apache.isis.core.transaction.changetracking.events.IsisTransactionPlaceholder;
+import org.apache.isis.core.transaction.events.TransactionEndedEvent;
import lombok.AccessLevel;
import lombok.Getter;
@@ -86,11 +87,10 @@ import lombok.extern.log4j.Log4j2;
@Order(OrderPrecedence.EARLY)
@Primary
@Qualifier("Default")
-@IsisInteractionScope
+@InteractionScope
@Log4j2
public class EntityChangeTrackerDefault
implements
- TransactionScopeListener,
MetricsService,
EntityChangeTracker,
HasEnlistedEntityPropertyChanges,
@@ -175,26 +175,28 @@ implements
/**
* @apiNote intended to be called during pre-commit of a transaction by the framework internally
*/
- @Override
- public void onPreCommit(PreCommitPhase preCommitPhase) {
- switch (preCommitPhase) {
- case WHILE_PUBLISHING:
- log.debug("about to publish entity changes");
- prepareCommandPublishing();
- entityPropertyChangePublisher.publishChangedProperties(this);
- entityChangesPublisher.publishChangingEntities(this);
- break;
- case POST_PUBLISHING:
- log.debug("purging entity change records");
- enlistedEntityPropertiesForAuditing.clear();
- changeKindByEnlistedAdapter.clear();
- changedObjectPropertiesRef.clear();
- entityChangeEventCount.reset();
- numberEntitiesLoaded.reset();
- break;
- default:
- break;
- }
+
+ /** TRANSACTION END BOUNDARY */
+ @TransactionalEventListener(TransactionEndedEvent.class)
+ public void onPreCommit(TransactionEndedEvent event) {
+ whilePublishing();
+ postPublishing();
+ }
+
+ private void whilePublishing() {
+ log.debug("about to publish entity changes");
+ prepareCommandPublishing();
+ entityPropertyChangePublisher.publishChangedProperties(this);
+ entityChangesPublisher.publishChangingEntities(this);
+ }
+
+ private void postPublishing() {
+ log.debug("purging entity change records");
+ enlistedEntityPropertiesForAuditing.clear();
+ changeKindByEnlistedAdapter.clear();
+ changedObjectPropertiesRef.clear();
+ entityChangeEventCount.reset();
+ numberEntitiesLoaded.reset();
}
private void prepareCommandPublishing() {
@@ -416,8 +418,8 @@ implements
final TransactionId txId) {
return getPropertyChangeRecords().stream()
- .map(propertyChangeRecord->EntityPropertyChangeFactory
- .createEntityPropertyChange(timestamp, userName, txId, propertyChangeRecord));
+ .map(propertyChangeRecord->EntityPropertyChangeFactory
+ .createEntityPropertyChange(timestamp, userName, txId, propertyChangeRecord));
}
}
diff --git a/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/IsisInteractionScopeCloseListener.java b/core/transaction/src/main/java/org/apache/isis/core/transaction/events/TransactionBeginEvent.java
similarity index 71%
copy from core/interaction/src/main/java/org/apache/isis/core/interaction/scope/IsisInteractionScopeCloseListener.java
copy to core/transaction/src/main/java/org/apache/isis/core/transaction/events/TransactionBeginEvent.java
index 1518af9..be8a28c 100644
--- a/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/IsisInteractionScopeCloseListener.java
+++ b/core/transaction/src/main/java/org/apache/isis/core/transaction/events/TransactionBeginEvent.java
@@ -16,13 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.isis.core.interaction.scope;
+package org.apache.isis.core.transaction.events;
-/**
- * @since 2.0
- */
-public interface IsisInteractionScopeCloseListener {
+import org.springframework.transaction.TransactionStatus;
+
+public class TransactionBeginEvent extends TransactionEventAbstract {
+
+ private static final long serialVersionUID = 1L;
+
+ public TransactionBeginEvent(final TransactionStatus source) {
+ super(source);
+ }
- void preTopLevelIsisInteractionClose();
-
}
diff --git a/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/IsisInteractionScopeCloseListener.java b/core/transaction/src/main/java/org/apache/isis/core/transaction/events/TransactionEndedEvent.java
similarity index 71%
copy from core/interaction/src/main/java/org/apache/isis/core/interaction/scope/IsisInteractionScopeCloseListener.java
copy to core/transaction/src/main/java/org/apache/isis/core/transaction/events/TransactionEndedEvent.java
index 1518af9..190a0b2 100644
--- a/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/IsisInteractionScopeCloseListener.java
+++ b/core/transaction/src/main/java/org/apache/isis/core/transaction/events/TransactionEndedEvent.java
@@ -16,13 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.isis.core.interaction.scope;
+package org.apache.isis.core.transaction.events;
-/**
- * @since 2.0
- */
-public interface IsisInteractionScopeCloseListener {
+import org.springframework.transaction.TransactionStatus;
+
+public class TransactionEndedEvent extends TransactionEventAbstract {
- void preTopLevelIsisInteractionClose();
+ private static final long serialVersionUID = 1L;
-}
+ public TransactionEndedEvent(final TransactionStatus source) {
+ super(source);
+ }
+}
\ No newline at end of file
diff --git a/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/IsisInteractionScopeCloseListener.java b/core/transaction/src/main/java/org/apache/isis/core/transaction/events/TransactionEndingEvent.java
similarity index 71%
rename from core/interaction/src/main/java/org/apache/isis/core/interaction/scope/IsisInteractionScopeCloseListener.java
rename to core/transaction/src/main/java/org/apache/isis/core/transaction/events/TransactionEndingEvent.java
index 1518af9..b17ebc9 100644
--- a/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/IsisInteractionScopeCloseListener.java
+++ b/core/transaction/src/main/java/org/apache/isis/core/transaction/events/TransactionEndingEvent.java
@@ -16,13 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.isis.core.interaction.scope;
+package org.apache.isis.core.transaction.events;
-/**
- * @since 2.0
- */
-public interface IsisInteractionScopeCloseListener {
+import org.springframework.transaction.TransactionStatus;
+
+public class TransactionEndingEvent extends TransactionEventAbstract {
- void preTopLevelIsisInteractionClose();
+ private static final long serialVersionUID = 1L;
-}
+ public TransactionEndingEvent(final TransactionStatus source) {
+ super(source);
+ }
+}
\ No newline at end of file
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/TransactionScopeListener.java b/core/transaction/src/main/java/org/apache/isis/core/transaction/events/TransactionEventAbstract.java
similarity index 50%
rename from api/applib/src/main/java/org/apache/isis/applib/services/TransactionScopeListener.java
rename to core/transaction/src/main/java/org/apache/isis/core/transaction/events/TransactionEventAbstract.java
index 3fe562a..e77dfed 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/TransactionScopeListener.java
+++ b/core/transaction/src/main/java/org/apache/isis/core/transaction/events/TransactionEventAbstract.java
@@ -16,35 +16,26 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.isis.core.transaction.events;
-package org.apache.isis.applib.services;
+import java.util.EventObject;
-import org.apache.isis.applib.annotation.IsisInteractionScope;
+import org.springframework.transaction.TransactionStatus;
-/**
- * Domain services that need to be aware of transaction boundaries can
- * implement this interface.
- *
- * @apiNote Implementing services most likely need to be scoped in a way that
- * binds the scope to the current thread (eg. {@link IsisInteractionScope})
- *
- * @since 2.0 (renamed from WithTransactionScope) {@index}
- */
-public interface TransactionScopeListener {
-
- enum PreCommitPhase {
- PRE_PUBLISHING,
- WHILE_PUBLISHING,
- POST_PUBLISHING
- }
+import lombok.Getter;
+
+public abstract class TransactionEventAbstract extends EventObject {
+
+ private static final long serialVersionUID = 1L;
- default void onTransactionStarted() {
- // default: do nothing
- }
+ /**
+ * Same as {@link #getSource()}.
+ */
+ @Getter private final TransactionStatus transactionStatus;
- /** triggered during the pre-commit phase in a transaction*/
- default void onPreCommit(PreCommitPhase preCommitPhase) {
- // default: do nothing
+ public TransactionEventAbstract(final TransactionStatus source) {
+ super(source);
+ this.transactionStatus = source;
}
-
+
}
diff --git a/core/transaction/src/main/java/org/apache/isis/core/transaction/manager/ApplicationLayerAwareTransactionManager.java b/core/transaction/src/main/java/org/apache/isis/core/transaction/manager/ApplicationLayerAwareTransactionManager.java
new file mode 100644
index 0000000..b1d4b15
--- /dev/null
+++ b/core/transaction/src/main/java/org/apache/isis/core/transaction/manager/ApplicationLayerAwareTransactionManager.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.isis.core.transaction.manager;
+
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionException;
+import org.springframework.transaction.TransactionStatus;
+
+import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.apache.isis.core.transaction.events.TransactionBeginEvent;
+import org.apache.isis.core.transaction.events.TransactionEndedEvent;
+import org.apache.isis.core.transaction.events.TransactionEndingEvent;
+
+import lombok.RequiredArgsConstructor;
+import lombok.val;
+
+@RequiredArgsConstructor
+public class ApplicationLayerAwareTransactionManager
+implements PlatformTransactionManager {
+
+ private final PlatformTransactionManager txManager;
+ private final EventBusService eventBusService;
+
+ @Override
+ public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
+ val txStatus = txManager.getTransaction(definition);
+ if(txStatus.isNewTransaction()) {
+ eventBusService.post(new TransactionBeginEvent(txStatus));
+ }
+ return txStatus;
+ }
+
+ @Override
+ public void commit(TransactionStatus txStatus) throws TransactionException {
+ eventBusService.post(new TransactionEndingEvent(txStatus));
+ txManager.commit(txStatus);
+ eventBusService.post(new TransactionEndedEvent(txStatus));
+ }
+
+ @Override
+ public void rollback(TransactionStatus txStatus) throws TransactionException {
+ eventBusService.post(new TransactionEndingEvent(txStatus));
+ txManager.rollback(txStatus);
+ eventBusService.post(new TransactionEndedEvent(txStatus));
+ }
+
+}
diff --git a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/main/UiBuilderFx.java b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/main/UiBuilderFx.java
index a883037..dfa8626 100644
--- a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/main/UiBuilderFx.java
+++ b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/main/UiBuilderFx.java
@@ -27,19 +27,18 @@ import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.apache.isis.commons.internal.debug._Probe;
-import org.apache.isis.core.interaction.events.IsisInteractionLifecycleEvent;
+import org.apache.isis.core.interaction.events.InteractionLifecycleEvent;
import org.apache.isis.incubator.viewer.javafx.model.events.JavaFxViewerConfig;
import org.apache.isis.incubator.viewer.javafx.model.events.PrimaryStageReadyEvent;
-import lombok.RequiredArgsConstructor;
-import lombok.SneakyThrows;
-import lombok.val;
-import lombok.extern.log4j.Log4j2;
-
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
+import lombok.RequiredArgsConstructor;
+import lombok.SneakyThrows;
+import lombok.val;
+import lombok.extern.log4j.Log4j2;
@Component
@RequiredArgsConstructor(onConstructor_ = {@Inject})
@@ -66,8 +65,8 @@ public class UiBuilderFx {
stage.show();
}
- @EventListener(IsisInteractionLifecycleEvent.class)
- public void onIsisInteractionLifecycleEvent(IsisInteractionLifecycleEvent event) {
+ @EventListener(InteractionLifecycleEvent.class)
+ public void onInteractionLifecycleEvent(InteractionLifecycleEvent event) {
switch(event.getEventType()) {
case HAS_STARTED:
//TODO this would be the place to indicate to the user, that a long running task has started
diff --git a/persistence/jdo/datanucleus/src/main/java/org/apache/isis/persistence/jdo/datanucleus/config/DnEntityDiscoveryListener.java b/persistence/jdo/datanucleus/src/main/java/org/apache/isis/persistence/jdo/datanucleus/config/DnEntityDiscoveryListener.java
index 1a7aad1..0cea8a9 100644
--- a/persistence/jdo/datanucleus/src/main/java/org/apache/isis/persistence/jdo/datanucleus/config/DnEntityDiscoveryListener.java
+++ b/persistence/jdo/datanucleus/src/main/java/org/apache/isis/persistence/jdo/datanucleus/config/DnEntityDiscoveryListener.java
@@ -33,6 +33,7 @@ import org.apache.isis.commons.internal.base._NullSafe;
import org.apache.isis.commons.internal.context._Context;
import org.apache.isis.persistence.jdo.provider.config.JdoEntityDiscoveryListener;
+import lombok.NonNull;
import lombok.val;
@Component
@@ -40,9 +41,9 @@ public class DnEntityDiscoveryListener implements JdoEntityDiscoveryListener {
@Override
public void onEntitiesDiscovered(
- final PersistenceManagerFactory persistenceManagerFactory,
- final Set<Class<?>> entityTypes,
- final Map<String, String> dnSettings) {
+ final @NonNull PersistenceManagerFactory persistenceManagerFactory,
+ final @NonNull Set<Class<?>> entityTypes,
+ final @NonNull Map<String, String> dnSettings) {
if(_NullSafe.isEmpty(entityTypes)) {
return; // skip
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/IsisModuleJdoIntegration.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/IsisModuleJdoIntegration.java
index 9ab6b86..617a8ff 100644
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/IsisModuleJdoIntegration.java
+++ b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/IsisModuleJdoIntegration.java
@@ -25,8 +25,10 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
+import org.apache.isis.applib.services.eventbus.EventBusService;
import org.apache.isis.core.metamodel.context.MetaModelContext;
import org.apache.isis.core.runtime.IsisModuleCoreRuntime;
+import org.apache.isis.core.transaction.manager.ApplicationLayerAwareTransactionManager;
import org.apache.isis.persistence.jdo.applib.IsisModulePersistenceJdoApplib;
import org.apache.isis.persistence.jdo.datanucleus.IsisModuleJdoProviderDatanucleus;
import org.apache.isis.persistence.jdo.datanucleus.config.DnSettings;
@@ -94,12 +96,15 @@ public class IsisModuleJdoIntegration {
return lpmfBean;
}
- @Bean @Primary
- public JdoTransactionManager getJdoTransactionManager(LocalPersistenceManagerFactoryBean localPmfBean) {
+ @Bean @Primary @Named("jdo-platform-transaction-manager")
+ public ApplicationLayerAwareTransactionManager getApplicationLayerAwareTransactionManager(
+ LocalPersistenceManagerFactoryBean localPmfBean,
+ EventBusService eventBusService) {
val pmf = localPmfBean.getObject(); // created once per application lifecycle
- return new JdoTransactionManager(pmf);
+ return new ApplicationLayerAwareTransactionManager(
+ new JdoTransactionManager(pmf), eventBusService);
}
}
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/lifecycles/JdoPersistenceLifecycleService.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/lifecycles/JdoPersistenceLifecycleService.java
index b997178..3dd6880 100644
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/lifecycles/JdoPersistenceLifecycleService.java
+++ b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/lifecycles/JdoPersistenceLifecycleService.java
@@ -29,11 +29,12 @@ import org.springframework.context.annotation.Primary;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.PlatformTransactionManager;
import org.apache.isis.applib.annotation.OrderPrecedence;
import org.apache.isis.commons.internal.exceptions._Exceptions;
import org.apache.isis.core.config.beans.IsisBeanTypeRegistry;
-import org.apache.isis.core.interaction.events.IsisInteractionLifecycleEvent;
+import org.apache.isis.core.interaction.events.InteractionLifecycleEvent;
import org.apache.isis.core.interaction.session.InteractionSession;
import org.apache.isis.core.metamodel.context.MetaModelContext;
import org.apache.isis.core.runtime.events.AppLifecycleEvent;
@@ -58,6 +59,9 @@ public class JdoPersistenceLifecycleService {
//@Inject LocalPersistenceManagerFactoryBean localPmfBean;
@Inject TransactionAwarePersistenceManagerFactoryProxy txAwarePmfProxy;
+ @Named("jdo-platform-transaction-manager")
+ @Inject PlatformTransactionManager txManager;
+
@Inject IsisBeanTypeRegistry isisBeanTypeRegistry;
@Inject DnSettings dnSettings;
@@ -87,8 +91,8 @@ public class JdoPersistenceLifecycleService {
}
- @EventListener(IsisInteractionLifecycleEvent.class)
- public void onInteractionLifecycleEvent(IsisInteractionLifecycleEvent event) {
+ @EventListener(InteractionLifecycleEvent.class)
+ public void onInteractionLifecycleEvent(InteractionLifecycleEvent event) {
val eventType = event.getEventType();
val interactionSession = event.getInteractionSession();
@@ -114,7 +118,7 @@ public class JdoPersistenceLifecycleService {
// -- HELPER
private void onInteractionStarted(final InteractionSession interactionSession) {
- val persistenceSession = new JdoPersistenceSession5(metaModelContext, txAwarePmfProxy.getObject());
+ val persistenceSession = new JdoPersistenceSession5(metaModelContext, txManager, txAwarePmfProxy);
interactionSession.putAttribute(JdoPersistenceSession.class, persistenceSession);
persistenceSession.open();
}
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/metamodel/facets/entity/JdoEntityFacet.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/metamodel/facets/entity/JdoEntityFacet.java
index ab07a31..de736ca 100644
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/metamodel/facets/entity/JdoEntityFacet.java
+++ b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/metamodel/facets/entity/JdoEntityFacet.java
@@ -67,7 +67,6 @@ implements EntityFacet {
@Inject private TransactionAwarePersistenceManagerFactoryProxy pmf;
@Inject private TransactionService txService;
- @Inject private EntityChangeTracker entityChangeTracker;
@Inject private ObjectManager objectManager;
public JdoEntityFacet(
@@ -351,14 +350,17 @@ implements EntityFacet {
// -- HELPER
private Can<ManagedObject> fetchWithinTransaction(Supplier<List<?>> fetcher) {
+
+ val entityChangeTracker = getFacetHolder().getServiceRegistry().lookupServiceElseFail(EntityChangeTracker.class);
+
return getTransactionalProcessor().callWithinCurrentTransactionElseCreateNew(
()->_NullSafe.stream(fetcher.get())
- .map(fetchedObject->adopt(fetchedObject))
+ .map(fetchedObject->adopt(entityChangeTracker, fetchedObject))
.collect(Can.toCan()))
.orElseFail();
}
- private ManagedObject adopt(final Object fetchedObject) {
+ private ManagedObject adopt(final EntityChangeTracker entityChangeTracker, final Object fetchedObject) {
// handles lifecycle callbacks and injects services
// ought not to be necessary, however for some queries it seems that the
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/JdoPersistenceSession5.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/JdoPersistenceSession5.java
index 544417f..7c5bdf3 100644
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/JdoPersistenceSession5.java
+++ b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/JdoPersistenceSession5.java
@@ -18,15 +18,23 @@
*/
package org.apache.isis.persistence.jdo.integration.persistence;
+import java.util.ArrayList;
+import java.util.List;
+
import javax.enterprise.inject.Vetoed;
import javax.jdo.PersistenceManager;
-import javax.jdo.PersistenceManagerFactory;
+
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.support.TransactionTemplate;
import org.apache.isis.core.metamodel.context.MetaModelContext;
import org.apache.isis.core.transaction.changetracking.EntityChangeTracker;
import org.apache.isis.persistence.jdo.integration.lifecycles.IsisLifecycleListener;
import org.apache.isis.persistence.jdo.integration.lifecycles.JdoStoreLifecycleListenerForIsis;
import org.apache.isis.persistence.jdo.integration.lifecycles.LoadLifecycleListenerForIsis;
+import org.apache.isis.persistence.jdo.spring.integration.TransactionAwarePersistenceManagerFactoryProxy;
import lombok.Getter;
import lombok.val;
@@ -45,8 +53,10 @@ implements
@Getter(onMethod_ = {@Override}) private PersistenceManager persistenceManager;
@Getter(onMethod_ = {@Override}) private final MetaModelContext metaModelContext;
- private final PersistenceManagerFactory pmf;
- private Runnable unregisterLifecycleListeners;
+ private final PlatformTransactionManager txManager;
+ private final TransactionAwarePersistenceManagerFactoryProxy pmf;
+ private final List<Runnable> onCloseTasks = new ArrayList<>();
+ private TransactionStatus nonParticipatingTransactionalBoundary;
// -- CONSTRUCTOR
@@ -57,13 +67,15 @@ implements
*/
public JdoPersistenceSession5(
final MetaModelContext metaModelContext,
- final PersistenceManagerFactory pmf) {
+ final PlatformTransactionManager txManager,
+ final TransactionAwarePersistenceManagerFactoryProxy pmf) {
if (log.isDebugEnabled()) {
log.debug("creating {}", this);
}
this.metaModelContext = metaModelContext;
+ this.txManager = txManager;
this.pmf = pmf;
this.state = State.NOT_INITIALIZED;
@@ -102,38 +114,27 @@ implements
log.debug("opening {}", this);
}
- this.persistenceManager = pmf.getPersistenceManager();
-
- val entityChangeTracker = metaModelContext.getServiceRegistry()
- .lookupServiceElseFail(EntityChangeTracker.class);
-
- val entityChangeEmitter =
- new JdoEntityChangeEmitter(getMetaModelContext(), persistenceManager, entityChangeTracker);
-
- val isisLifecycleListener = new IsisLifecycleListener(entityChangeEmitter);
- persistenceManager.addInstanceLifecycleListener(isisLifecycleListener, (Class[]) null);
+ val txTemplate = new TransactionTemplate(txManager);
+ txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
- // install JDO specific entity change listeners ...
-
- val loadLifecycleListener = new LoadLifecycleListenerForIsis();
- val storeLifecycleListener = new JdoStoreLifecycleListenerForIsis();
+ // either reuse existing or create new
+ val txStatus = txManager.getTransaction(txTemplate);
+ if(txStatus.isNewTransaction()) {
+ // we have created a new transaction,
+ nonParticipatingTransactionalBoundary = txStatus;
+ } else {
+ // we are participating in an exiting transaction
+ }
- getServiceInjector().injectServicesInto(loadLifecycleListener);
- getServiceInjector().injectServicesInto(storeLifecycleListener);
-
- persistenceManager.addInstanceLifecycleListener(loadLifecycleListener, (Class[]) null);
- persistenceManager.addInstanceLifecycleListener(storeLifecycleListener, (Class[]) null);
+ this.persistenceManager = integrateWithApplicationLayer(pmf.getPersistenceManager());
- this.unregisterLifecycleListeners = ()->{
- persistenceManager.removeInstanceLifecycleListener(loadLifecycleListener);
- persistenceManager.removeInstanceLifecycleListener(storeLifecycleListener);
- };
-
this.state = State.OPEN;
}
// -- CLOSE
+
+
@Override
public void close() {
@@ -142,31 +143,66 @@ implements
return;
}
- unregisterLifecycleListeners.run();
- unregisterLifecycleListeners = null;
-
try {
-// if (!participate) {
-//
-// val pmf = pmf;
-//
-// PersistenceManagerHolder pmHolder = (PersistenceManagerHolder)
-// TransactionSynchronizationManager.unbindResource(pmf);
-// log.debug("Closing JDO PersistenceManager in PersistenceSession");
-// PersistenceManagerFactoryUtils.releasePersistenceManager(pmHolder.getPersistenceManager(), pmf);
-// }
-
- persistenceManager = null; // detach
+ if (nonParticipatingTransactionalBoundary!=null) {
+
+ if(nonParticipatingTransactionalBoundary.isRollbackOnly()) {
+ txManager.rollback(nonParticipatingTransactionalBoundary);
+ } else {
+ txManager.commit(nonParticipatingTransactionalBoundary);
+ }
+ }
+
+ onCloseTasks.removeIf(task->{
+ if(!persistenceManager.isClosed()) {
+ task.run();
+ }
+ return true;
+ });
} catch(final Throwable ex) {
// ignore
log.error(
- "close: failed to close JDO persistenceManager; continuing to avoid memory leakage");
+ "close: failed to close JDO persistenceManager; continuing to avoid memory leakage", ex);
}
+
+ persistenceManager = null; // detach
this.state = State.CLOSED;
}
+
+ // -- HELPER
+
+ private PersistenceManager integrateWithApplicationLayer(final PersistenceManager persistenceManager) {
+
+ val entityChangeTracker = metaModelContext.getServiceRegistry()
+ .lookupServiceElseFail(EntityChangeTracker.class);
+
+ val entityChangeEmitter =
+ new JdoEntityChangeEmitter(getMetaModelContext(), persistenceManager, entityChangeTracker);
+
+ val isisLifecycleListener = new IsisLifecycleListener(entityChangeEmitter);
+ persistenceManager.addInstanceLifecycleListener(isisLifecycleListener, (Class[]) null);
+
+ // install JDO specific entity change listeners ...
+
+ val loadLifecycleListener = new LoadLifecycleListenerForIsis();
+ val storeLifecycleListener = new JdoStoreLifecycleListenerForIsis();
+
+ getServiceInjector().injectServicesInto(loadLifecycleListener);
+ getServiceInjector().injectServicesInto(storeLifecycleListener);
+
+ persistenceManager.addInstanceLifecycleListener(loadLifecycleListener, (Class[]) null);
+ persistenceManager.addInstanceLifecycleListener(storeLifecycleListener, (Class[]) null);
+
+ onCloseTasks.add(()->{
+ persistenceManager.removeInstanceLifecycleListener(loadLifecycleListener);
+ persistenceManager.removeInstanceLifecycleListener(storeLifecycleListener);
+ });
+
+ return persistenceManager;
+ }
}
diff --git a/persistence/jdo/lightweight/src/main/java/org/apache/isis/persistence/jdo/lightweight/IsisModuleJdoLightweight.java b/persistence/jdo/lightweight/src/main/java/org/apache/isis/persistence/jdo/lightweight/IsisModuleJdoLightweight.java
index 0d51281..d07683f 100644
--- a/persistence/jdo/lightweight/src/main/java/org/apache/isis/persistence/jdo/lightweight/IsisModuleJdoLightweight.java
+++ b/persistence/jdo/lightweight/src/main/java/org/apache/isis/persistence/jdo/lightweight/IsisModuleJdoLightweight.java
@@ -27,9 +27,11 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
+import org.apache.isis.applib.services.eventbus.EventBusService;
import org.apache.isis.commons.internal.base._NullSafe;
import org.apache.isis.core.config.beans.IsisBeanTypeRegistry;
import org.apache.isis.core.runtime.IsisModuleCoreRuntime;
+import org.apache.isis.core.transaction.manager.ApplicationLayerAwareTransactionManager;
import org.apache.isis.persistence.jdo.applib.IsisModulePersistenceJdoApplib;
import org.apache.isis.persistence.jdo.datanucleus.IsisModuleJdoProviderDatanucleus;
import org.apache.isis.persistence.jdo.datanucleus.config.DnSettings;
@@ -97,9 +99,12 @@ public class IsisModuleJdoLightweight {
return lpmfBean;
}
- @Bean @Primary
- public JdoTransactionManager getJdoTransactionManager(LocalPersistenceManagerFactoryBean localPmf) {
- return new JdoTransactionManager(localPmf.getObject());
+ @Bean @Primary @Named("jdo-platform-transaction-manager")
+ public ApplicationLayerAwareTransactionManager getApplicationLayerAwareTransactionManager(
+ LocalPersistenceManagerFactoryBean localPmf,
+ EventBusService eventBusService) {
+ return new ApplicationLayerAwareTransactionManager(
+ new JdoTransactionManager(localPmf.getObject()), eventBusService);
}
}
diff --git a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/applayer/ApplicationLayerTestFactory.java b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/applayer/ApplicationLayerTestFactory.java
index 37091c0..896064a 100644
--- a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/applayer/ApplicationLayerTestFactory.java
+++ b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/applayer/ApplicationLayerTestFactory.java
@@ -18,6 +18,11 @@
*/
package org.apache.isis.testdomain.applayer;
+import static org.apache.isis.applib.services.wrapper.control.AsyncControl.returningVoid;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.fail;
+import static org.junit.jupiter.api.DynamicTest.dynamicTest;
+
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
@@ -28,34 +33,27 @@ import javax.inject.Inject;
import org.junit.jupiter.api.DynamicTest;
import org.springframework.context.annotation.Import;
+import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.fail;
-import static org.junit.jupiter.api.DynamicTest.dynamicTest;
-
import org.apache.isis.applib.annotation.Where;
-import org.apache.isis.applib.services.TransactionScopeListener;
import org.apache.isis.applib.services.repository.RepositoryService;
import org.apache.isis.applib.services.wrapper.DisabledException;
import org.apache.isis.applib.services.wrapper.WrapperFactory;
import org.apache.isis.applib.services.wrapper.control.SyncControl;
import org.apache.isis.applib.services.xactn.TransactionService;
-import org.apache.isis.applib.services.xactn.TransactionState;
import org.apache.isis.commons.internal.collections._Lists;
import org.apache.isis.commons.internal.exceptions._Exceptions;
import org.apache.isis.core.interaction.session.InteractionFactory;
import org.apache.isis.core.metamodel.interactions.managed.PropertyInteraction;
import org.apache.isis.core.metamodel.objectmanager.ObjectManager;
import org.apache.isis.core.metamodel.spec.ManagedObject;
+import org.apache.isis.core.transaction.events.TransactionEndingEvent;
import org.apache.isis.testdomain.jdo.JdoTestDomainPersona;
import org.apache.isis.testdomain.jdo.entities.JdoBook;
import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScripts;
-import static org.apache.isis.applib.services.wrapper.control.AsyncControl.returningVoid;
-
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.val;
@@ -85,20 +83,15 @@ public class ApplicationLayerTestFactory {
}
@Service
- public static class PreCommitListener implements TransactionScopeListener {
+ public static class PreCommitListener {
@Setter private Consumer<VerificationStage> verifier;
- @Override
- public void onPreCommit(PreCommitPhase preCommitPhase) {
- switch (preCommitPhase) {
- case PRE_PUBLISHING:
- if(verifier!=null) {
- verifier.accept(VerificationStage.PRE_COMMIT);
- }
- break;
- default:
- break;
+ /** TRANSACTION END BOUNDARY */
+ @EventListener(TransactionEndingEvent.class)
+ public void onPreCommit(TransactionEndingEvent event) {
+ if(verifier!=null) {
+ verifier.accept(VerificationStage.PRE_COMMIT);
}
}
}
@@ -107,8 +100,8 @@ public class ApplicationLayerTestFactory {
final Runnable given,
final Consumer<VerificationStage> verifier) {
return _Lists.of(
- dynamicTest("No initial Transaction with Test Execution",
- this::no_initial_tx_context),
+// dynamicTest("No initial Transaction with Test Execution",
+// this::no_initial_tx_context),
programmaticTest("Programmatic Execution",
given, verifier, this::programmaticExecution),
interactionTest("Interaction Api Execution",
@@ -172,11 +165,11 @@ public class ApplicationLayerTestFactory {
// -- TESTS - ENSURE TESTS ARE CORRECTLY INVOKED
- boolean no_initial_tx_context() {
- val txState = transactionService.currentTransactionState();
- assertEquals(TransactionState.NONE, txState);
- return true;
- }
+// boolean no_initial_tx_context() {
+// val txState = transactionService.currentTransactionState();
+// assertEquals(TransactionState.NONE, txState);
+// return true;
+// }
// -- TESTS - WRAPPER SYNC
diff --git a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/conf/Configuration_headless.java b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/conf/Configuration_headless.java
index d74981a..efdc873 100644
--- a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/conf/Configuration_headless.java
+++ b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/conf/Configuration_headless.java
@@ -38,7 +38,7 @@ import org.apache.isis.applib.annotation.OrderPrecedence;
import org.apache.isis.applib.services.metrics.MetricsService;
import org.apache.isis.commons.internal.debug._Probe;
import org.apache.isis.core.config.presets.IsisPresets;
-import org.apache.isis.core.interaction.events.IsisInteractionLifecycleEvent;
+import org.apache.isis.core.interaction.events.InteractionLifecycleEvent;
import org.apache.isis.core.runtimeservices.IsisModuleCoreRuntimeServices;
import org.apache.isis.extensions.modelannotation.metamodel.IsisModuleExtModelAnnotation;
import org.apache.isis.security.bypass.IsisModuleSecurityBypass;
@@ -59,45 +59,6 @@ import lombok.RequiredArgsConstructor;
})
public class Configuration_headless {
-// @Bean @Singleton
-// public TransactionService transactionService() {
-// return new TransactionService() {
-//
-// @Override
-// public TransactionId currentTransactionId() {
-// return null;
-// }
-//
-// @Override
-// public void flushTransaction() {
-// }
-//
-// @Override
-// public TransactionState currentTransactionState() {
-// return null;
-// }
-//
-// @Override
-// public void executeWithinTransaction(Runnable task) {
-// }
-//
-// @Override
-// public <T> T executeWithinTransaction(Supplier<T> task) {
-// return null;
-// }
-//
-// @Override
-// public void executeWithinNewTransaction(Runnable task) {
-// }
-//
-// @Override
-// public <T> T executeWithinNewTransaction(Supplier<T> task) {
-// return null;
-// }
-//
-// };
-// }
-
@Service
@Order(OrderPrecedence.MIDPOINT)
@RequiredArgsConstructor(onConstructor_ = {@Inject})
@@ -107,8 +68,8 @@ public class Configuration_headless {
// private final CommandDispatcher commandDispatcher;
- @EventListener(IsisInteractionLifecycleEvent.class)
- public void onIsisInteractionLifecycleEvent(IsisInteractionLifecycleEvent event) {
+ @EventListener(InteractionLifecycleEvent.class)
+ public void onIsisInteractionLifecycleEvent(InteractionLifecycleEvent event) {
switch(event.getEventType()) {
case HAS_STARTED:
_Probe.errOut("Interaction HAS_STARTED conversationId=%s", event.getConversationId());
diff --git a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/util/interaction/InteractionBoundaryProbe.java b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/util/interaction/InteractionBoundaryProbe.java
index dac6bbf..a19f465 100644
--- a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/util/interaction/InteractionBoundaryProbe.java
+++ b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/util/interaction/InteractionBoundaryProbe.java
@@ -20,53 +20,64 @@ package org.apache.isis.testdomain.util.interaction;
import java.util.function.Supplier;
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
import javax.inject.Inject;
import org.junit.jupiter.api.Assertions;
-import org.springframework.stereotype.Component;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Service;
-import org.apache.isis.applib.annotation.IsisInteractionScope;
-import org.apache.isis.applib.services.TransactionScopeListener;
+import org.apache.isis.core.interaction.events.InteractionLifecycleEvent;
+import org.apache.isis.core.transaction.events.TransactionBeginEvent;
+import org.apache.isis.core.transaction.events.TransactionEndingEvent;
import org.apache.isis.testdomain.util.kv.KVStoreForTesting;
import lombok.val;
+import lombok.extern.log4j.Log4j2;
-@Component
-@IsisInteractionScope
-public class InteractionBoundaryProbe implements TransactionScopeListener {
+@Service
+@Log4j2
+public class InteractionBoundaryProbe {
@Inject private KVStoreForTesting kvStoreForTesting;
+
+
+ @EventListener(InteractionLifecycleEvent.class)
+ public void onIsisInteractionLifecycleEvent(InteractionLifecycleEvent event) {
+ switch(event.getEventType()) {
+ case HAS_STARTED:
+ onIaStarted();
+ break;
+ case IS_ENDING:
+ onIaEnded();
+ break;
+ default:
+ break;
+ }
+ }
/** INTERACTION BEGIN BOUNDARY */
- @PostConstruct
- public void init() {
+ public void onIaStarted() {
+ log.debug("iaStarted");
kvStoreForTesting.incrementCounter(InteractionBoundaryProbe.class, "iaStarted");
}
/** INTERACTION END BOUNDARY */
- @PreDestroy
- public void destroy() {
+ public void onIaEnded() {
+ log.debug("iaEnded");
kvStoreForTesting.incrementCounter(InteractionBoundaryProbe.class, "iaEnded");
}
/** TRANSACTION BEGIN BOUNDARY */
- @Override
- public void onTransactionStarted() {
+ @EventListener(TransactionBeginEvent.class)
+ public void onTransactionStarted(TransactionBeginEvent event) {
+ log.debug("txStarted");
kvStoreForTesting.incrementCounter(InteractionBoundaryProbe.class, "txStarted");
}
/** TRANSACTION END BOUNDARY */
- @Override
- public void onPreCommit(PreCommitPhase preCommitPhase) {
- switch (preCommitPhase) {
- case POST_PUBLISHING:
- kvStoreForTesting.incrementCounter(InteractionBoundaryProbe.class, "txEnding");
- break;
- default:
- break;
- }
+ @EventListener(TransactionEndingEvent.class)
+ public void onPreCommit(TransactionEndingEvent event) {
+ kvStoreForTesting.incrementCounter(InteractionBoundaryProbe.class, "txEnding");
}
// -- ACCESS TO COUNTERS
diff --git a/regressiontests/stable/src/test/java/org/apache/isis/testdomain/applayer/publishing/jdo/isis/JdoIsisEntityChangesPublishingTest.java b/regressiontests/stable/src/test/java/org/apache/isis/testdomain/applayer/publishing/jdo/isis/JdoIsisEntityChangesPublishingTest.java
index 94ed007..171421e 100644
--- a/regressiontests/stable/src/test/java/org/apache/isis/testdomain/applayer/publishing/jdo/isis/JdoIsisEntityChangesPublishingTest.java
+++ b/regressiontests/stable/src/test/java/org/apache/isis/testdomain/applayer/publishing/jdo/isis/JdoIsisEntityChangesPublishingTest.java
@@ -18,6 +18,14 @@
*/
package org.apache.isis.testdomain.applayer.publishing.jdo.isis;
+import static org.apache.isis.testdomain.applayer.publishing.EntityChangesSubscriberForTesting.clearPublishedEntries;
+import static org.apache.isis.testdomain.applayer.publishing.EntityChangesSubscriberForTesting.getCreated;
+import static org.apache.isis.testdomain.applayer.publishing.EntityChangesSubscriberForTesting.getDeleted;
+import static org.apache.isis.testdomain.applayer.publishing.EntityChangesSubscriberForTesting.getLoaded;
+import static org.apache.isis.testdomain.applayer.publishing.EntityChangesSubscriberForTesting.getModified;
+import static org.apache.isis.testdomain.applayer.publishing.EntityChangesSubscriberForTesting.getUpdated;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
import java.util.List;
import javax.inject.Inject;
@@ -28,8 +36,6 @@ import org.junit.jupiter.api.TestFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
import org.apache.isis.core.config.presets.IsisPresets;
import org.apache.isis.testdomain.applayer.ApplicationLayerTestFactory;
import org.apache.isis.testdomain.applayer.ApplicationLayerTestFactory.VerificationStage;
@@ -38,13 +44,6 @@ import org.apache.isis.testdomain.conf.Configuration_usingJdoIsis;
import org.apache.isis.testdomain.util.kv.KVStoreForTesting;
import org.apache.isis.testing.integtestsupport.applib.IsisIntegrationTestAbstract;
-import static org.apache.isis.testdomain.applayer.publishing.EntityChangesSubscriberForTesting.clearPublishedEntries;
-import static org.apache.isis.testdomain.applayer.publishing.EntityChangesSubscriberForTesting.getCreated;
-import static org.apache.isis.testdomain.applayer.publishing.EntityChangesSubscriberForTesting.getDeleted;
-import static org.apache.isis.testdomain.applayer.publishing.EntityChangesSubscriberForTesting.getLoaded;
-import static org.apache.isis.testdomain.applayer.publishing.EntityChangesSubscriberForTesting.getModified;
-import static org.apache.isis.testdomain.applayer.publishing.EntityChangesSubscriberForTesting.getUpdated;
-
@SpringBootTest(
classes = {
Configuration_usingJdoIsis.class,
diff --git a/regressiontests/stable/src/test/java/org/apache/isis/testdomain/persistence/jdo/spring/JdoSpringBootstrappingTest.java b/regressiontests/stable/src/test/java/org/apache/isis/testdomain/persistence/jdo/spring/JdoSpringBootstrappingTest.java
index 42f8624..2cd7b95 100644
--- a/regressiontests/stable/src/test/java/org/apache/isis/testdomain/persistence/jdo/spring/JdoSpringBootstrappingTest.java
+++ b/regressiontests/stable/src/test/java/org/apache/isis/testdomain/persistence/jdo/spring/JdoSpringBootstrappingTest.java
@@ -18,6 +18,11 @@
*/
package org.apache.isis.testdomain.persistence.jdo.spring;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Optional;
@@ -38,11 +43,6 @@ import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
import org.apache.isis.applib.services.repository.RepositoryService;
import org.apache.isis.core.config.presets.IsisPresets;
import org.apache.isis.core.metamodel.facets.object.entity.EntityFacet;
@@ -99,7 +99,7 @@ class JdoSpringBootstrappingTest extends IsisIntegrationTestAbstract {
void platformTransactionManager_shouldBeAvailable() {
assertTrue(platformTransactionManager.isPresent());
platformTransactionManager.ifPresent(ptm->{
- assertEquals("JdoTransactionManager", ptm.getClass().getSimpleName());
+ assertEquals("ApplicationLayerAwareTransactionManager", ptm.getClass().getSimpleName());
});
}
diff --git a/regressiontests/stable/src/test/java/org/apache/isis/testdomain/transactions/jdo/spring/JdoSpringTransactionScopeListenerTest.java b/regressiontests/stable/src/test/java/org/apache/isis/testdomain/transactions/jdo/spring/JdoSpringTransactionScopeListenerTest.java
index a5cc41e..845db60 100644
--- a/regressiontests/stable/src/test/java/org/apache/isis/testdomain/transactions/jdo/spring/JdoSpringTransactionScopeListenerTest.java
+++ b/regressiontests/stable/src/test/java/org/apache/isis/testdomain/transactions/jdo/spring/JdoSpringTransactionScopeListenerTest.java
@@ -26,7 +26,9 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
+import org.springframework.transaction.annotation.Transactional;
+import org.apache.isis.applib.services.registry.ServiceRegistry;
import org.apache.isis.applib.services.repository.RepositoryService;
import org.apache.isis.applib.services.xactn.TransactionService;
import org.apache.isis.core.config.presets.IsisPresets;
@@ -42,13 +44,19 @@ import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScripts;
classes = {
Configuration_usingJdoSpring.class,
InteractionBoundaryProbe.class
+ },
+ properties = {
+ "logging.level.org.apache.isis.testdomain.util.interaction.InteractionBoundaryProbe=DEBUG",
+ "logging.level.org.apache.isis.core.interaction.scope.IsisInteractionScope=DEBUG",
})
@TestPropertySource(IsisPresets.UseLog4j2Test)
+@Transactional
/**
* With this test we manage IsisInteractions ourselves. (not sub-classing IsisIntegrationTestAbstract)
*/
class JdoSpringTransactionScopeListenerTest {
+ @Inject private ServiceRegistry serviceRegistry;
@Inject private FixtureScripts fixtureScripts;
@Inject private TransactionService transactionService;
@Inject private RepositoryService repository;
@@ -67,6 +75,9 @@ class JdoSpringTransactionScopeListenerTest {
@BeforeEach
void setUp() {
+ // request a InteractionBoundaryProbe for the current interaction
+ serviceRegistry.lookupServiceElseFail(InteractionBoundaryProbe.class);
+
// new IsisInteractionScope with a new transaction (#1)
isisInteractionFactory.runAnonymous(()->{
diff --git a/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/acceptheader/AcceptHeaderServiceForRest.java b/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/acceptheader/AcceptHeaderServiceForRest.java
index 10fa052..2d50479 100644
--- a/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/acceptheader/AcceptHeaderServiceForRest.java
+++ b/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/acceptheader/AcceptHeaderServiceForRest.java
@@ -18,12 +18,12 @@
*/
package org.apache.isis.viewer.restfulobjects.rendering.service.acceptheader;
+import static org.apache.isis.commons.internal.base._NullSafe.stream;
+
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
import javax.inject.Named;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
@@ -38,22 +38,18 @@ import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
+import org.apache.isis.applib.annotation.InteractionScope;
import org.apache.isis.applib.annotation.OrderPrecedence;
-import org.apache.isis.applib.annotation.IsisInteractionScope;
import org.apache.isis.applib.services.acceptheader.AcceptHeaderService;
import org.apache.isis.commons.internal.base._NullSafe;
-import static org.apache.isis.commons.internal.base._NullSafe.stream;
-
-import lombok.extern.log4j.Log4j2;
-
@Service
@Named("isisRoRendering.AcceptHeaderServiceForRest")
@Order(OrderPrecedence.MIDPOINT)
@Primary
@Qualifier("ForRest")
-@IsisInteractionScope
-@Log4j2
+@InteractionScope
+//@Log4j2
public class AcceptHeaderServiceForRest implements AcceptHeaderService {
private static ThreadLocal<List<MediaType>> mediaTypesByThread = new ThreadLocal<>();
diff --git a/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/WebRequestCycleForIsis.java b/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/WebRequestCycleForIsis.java
index e9311ce..c4001fe 100644
--- a/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/WebRequestCycleForIsis.java
+++ b/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/WebRequestCycleForIsis.java
@@ -105,8 +105,7 @@ public class WebRequestCycleForIsis implements IRequestCycleListener {
}
val isisRequestCycle = IsisRequestCycle.next(
- commonContext.lookupServiceElseFail(InteractionFactory.class),
- commonContext.createTransactionTemplate());
+ commonContext.lookupServiceElseFail(InteractionFactory.class));
requestCycle.setMetaData(REQ_CYCLE_HANDLE_KEY, isisRequestCycle);