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/10/05 06:15:21 UTC
[isis] 01/01: ISIS-2441: work on ChangedObjects tests (wip)
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch 2441-auditing
in repository https://gitbox.apache.org/repos/asf/isis.git
commit 4d06bf35e462c8cccb34878b448f7a2b723ebf65
Author: Andi Huber <ah...@apache.org>
AuthorDate: Mon Oct 5 08:15:01 2020 +0200
ISIS-2441: work on ChangedObjects tests (wip)
---
.../applib/services/TransactionScopeListener.java | 7 +-
.../isis/applib/services/iactn/Interaction.java | 2 +-
.../applib/services/iactn/InteractionContext.java | 11 +-
.../transaction/AuditerDispatchService.java | 2 +-
.../transaction/ChangedObjectsService.java | 218 ++++++++++-----------
.../transaction/HasEnlistedForAuditing.java | 26 +--
.../transaction/HasEnlistedForMetrics.java | 24 +--
.../transaction/HasEnlistedForPublishing.java | 31 ++-
.../publish/PublisherDispatchServiceDefault.java | 14 +-
.../datanucleus5/metrics/MetricsServiceForJdo.java | 6 +-
.../persistence/IsisTransactionJdo.java | 11 +-
.../commons/InteractionBoundaryProbe.java | 6 +-
.../entitychangemetrics/ChangedObjectsTest.java | 21 +-
13 files changed, 173 insertions(+), 206 deletions(-)
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/TransactionScopeListener.java b/api/applib/src/main/java/org/apache/isis/applib/services/TransactionScopeListener.java
index 028bf40..85364bb 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/TransactionScopeListener.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/TransactionScopeListener.java
@@ -36,7 +36,12 @@ public interface TransactionScopeListener {
default void onTransactionStarted() {
// default: do nothing
}
+
+ /** triggered during the pre-commit phase in a transaction*/
+ default void onTransactionEnding() {
+ // default: do nothing
+ }
+
- void onTransactionEnded();
}
// end::refguide[]
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/iactn/Interaction.java b/api/applib/src/main/java/org/apache/isis/applib/services/iactn/Interaction.java
index 3e2de34..6a0fc7e 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/iactn/Interaction.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/iactn/Interaction.java
@@ -87,7 +87,7 @@ public class Interaction implements HasUniqueId {
}
@Getter
- private Command command; // <.>
+ private final Command command; // <.>
@Override
public UUID getUniqueId() { // <.>
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/iactn/InteractionContext.java b/api/applib/src/main/java/org/apache/isis/applib/services/iactn/InteractionContext.java
index b6579ea..157e265 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/iactn/InteractionContext.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/iactn/InteractionContext.java
@@ -31,14 +31,11 @@ import org.apache.isis.applib.annotation.DomainService;
import org.apache.isis.applib.annotation.IsisInteractionScope;
import org.apache.isis.applib.annotation.OrderPrecedence;
import org.apache.isis.applib.services.TransactionScopeListener;
-import org.apache.isis.applib.services.command.Command;
-import org.apache.isis.applib.services.inject.ServiceInjector;
import org.apache.isis.applib.services.metrics.MetricsService;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.val;
-import lombok.extern.log4j.Log4j2;
/**
* This service (API and implementation) provides access to context information about any {@link Interaction}.
@@ -55,7 +52,7 @@ import lombok.extern.log4j.Log4j2;
@Qualifier("Default")
@IsisInteractionScope
@RequiredArgsConstructor(onConstructor_ = {@Inject})
-@Log4j2
+//@Log4j2
public class InteractionContext implements TransactionScopeListener, DisposableBean {
// end::refguide[]
@@ -79,11 +76,11 @@ public class InteractionContext implements TransactionScopeListener, DisposableB
@Override
- public void onTransactionEnded() {
+ public void onTransactionEnding() {
val command = getInteraction().getCommand();
command.updater().setSystemStateChanged(
- command.isSystemStateChanged() ||
- metricsService.numberObjectsDirtied() > 0);
+ command.isSystemStateChanged()
+ || metricsService.numberObjectsDirtied() > 0);
}
@Override
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/transaction/AuditerDispatchService.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/transaction/AuditerDispatchService.java
index a15f934..da44da5 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/transaction/AuditerDispatchService.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/transaction/AuditerDispatchService.java
@@ -53,7 +53,7 @@ import lombok.val;
public class AuditerDispatchService {
@Inject private List<AuditerService> auditerServices;
- @Inject private javax.inject.Provider<ChangedObjectsService> changedObjectsProvider;
+ @Inject private javax.inject.Provider<HasEnlistedForAuditing> changedObjectsProvider;
@Inject private UserService userService;
@Inject private ClockService clockService;
@Inject private TransactionService transactionService;
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/transaction/ChangedObjectsService.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/transaction/ChangedObjectsService.java
index ee657bc..212f125 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/transaction/ChangedObjectsService.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/transaction/ChangedObjectsService.java
@@ -21,7 +21,6 @@ package org.apache.isis.core.runtime.persistence.transaction;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
-import java.util.stream.Stream;
import javax.inject.Named;
@@ -30,18 +29,22 @@ 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.OrderPrecedence;
import org.apache.isis.applib.annotation.PublishingChangeKind;
import org.apache.isis.applib.services.HasUniqueId;
import org.apache.isis.applib.services.TransactionScopeListener;
+import org.apache.isis.commons.internal.base._Lazy;
import org.apache.isis.commons.internal.collections._Maps;
import org.apache.isis.commons.internal.collections._Sets;
+import org.apache.isis.commons.internal.exceptions._Exceptions;
import org.apache.isis.core.metamodel.spec.ManagedObject;
import org.apache.isis.core.metamodel.spec.ManagedObjects.EntityUtil;
-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.ObjectAssociation;
+import lombok.Getter;
+import lombok.NonNull;
import lombok.val;
// tag::refguide[]
@@ -50,8 +53,10 @@ import lombok.val;
@Order(OrderPrecedence.EARLY)
@Primary
@Qualifier("Default")
+@IsisInteractionScope
//@Log4j2
-public class ChangedObjectsService implements TransactionScopeListener {
+public class ChangedObjectsService
+implements TransactionScopeListener, HasEnlistedForAuditing, HasEnlistedForPublishing, HasEnlistedForMetrics {
// end::refguide[]
/**
@@ -72,13 +77,15 @@ public class ChangedObjectsService implements TransactionScopeListener {
* Will be null until {@link #getChangedObjectProperties()} is called, thereafter contains the actual changes.
* </p>
*/
- private Set<AuditEntry> changedObjectProperties;
+ private final _Lazy<Set<AuditEntry>> changedObjectPropertiesRef = _Lazy.threadSafe(this::capturePostValuesAndDrain);
// used for publishing
- private final Map<ManagedObject,PublishingChangeKind> changeKindByEnlistedAdapter = _Maps.newLinkedHashMap();
+ @Getter(onMethod_ = {@Override})
+ private final Map<ManagedObject, PublishingChangeKind> changeKindByEnlistedAdapter = _Maps.newLinkedHashMap();
+
- public boolean isEnlisted(ManagedObject adapter) {
+ public boolean isEnlisted(final @NonNull ManagedObject adapter) {
return changeKindByEnlistedAdapter.containsKey(adapter);
}
@@ -93,19 +100,12 @@ public class ChangedObjectsService implements TransactionScopeListener {
* <p>
* Supported by the JDO object store; check documentation for support in other objectstores.
*/
- public void enlistCreated(final ManagedObject adapter) {
-
+ public void enlistCreated(final @NonNull ManagedObject adapter) {
if(shouldIgnore(adapter)) {
return;
}
-
enlistForPublishing(adapter, PublishingChangeKind.CREATE);
-
- final Stream<ObjectAssociation> properties = adapter.getSpecification()
- .streamAssociations(Contributed.EXCLUDED)
- .filter(ObjectAssociation.Predicates.PROPERTIES);
-
- enlist(adapter, properties, aap->PreAndPostValues.pre(IsisTransactionPlaceholder.NEW));
+ enlistForAuditing(adapter, aap->PreAndPostValues.pre(IsisTransactionPlaceholder.NEW));
}
@@ -119,19 +119,12 @@ public class ChangedObjectsService implements TransactionScopeListener {
* <p>
* Supported by the JDO object store; check documentation for support in other objectstores.
*/
- public void enlistUpdating(final ManagedObject adapter) {
-
+ public void enlistUpdating(final @NonNull ManagedObject adapter) {
if(shouldIgnore(adapter)) {
return;
}
-
enlistForPublishing(adapter, PublishingChangeKind.UPDATE);
-
- final Stream<ObjectAssociation> properties = adapter.getSpecification()
- .streamAssociations(Contributed.EXCLUDED)
- .filter(ObjectAssociation.Predicates.PROPERTIES);
-
- enlist(adapter, properties, aap->PreAndPostValues.pre(aap.getPropertyValue()));
+ enlistForAuditing(adapter, aap->PreAndPostValues.pre(aap.getPropertyValue()));
}
/**
@@ -145,30 +138,63 @@ public class ChangedObjectsService implements TransactionScopeListener {
* <p>
* Supported by the JDO object store; check documentation for support in other objectstores.
*/
- public void enlistDeleting(final ManagedObject adapter) {
-
+ public void enlistDeleting(final @NonNull ManagedObject adapter) {
if(shouldIgnore(adapter)) {
return;
}
-
final boolean enlisted = enlistForPublishing(adapter, PublishingChangeKind.DELETE);
if(!enlisted) {
return;
}
+ enlistForAuditing(adapter, aap->PreAndPostValues.pre(aap.getPropertyValue()));
+ }
- final Stream<ObjectAssociation> properties = adapter.getSpecification()
- .streamAssociations(Contributed.EXCLUDED)
- .filter(ObjectAssociation.Predicates.PROPERTIES);
- enlist(adapter, properties, aap->PreAndPostValues.pre(aap.getPropertyValue()));
+ @Override
+ public Set<AuditEntry> getChangedObjectProperties() {
+ return changedObjectPropertiesRef.get();
+ }
+ @Override
+ public int numberObjectPropertiesModified() {
+ return changedObjectPropertiesRef.get().size();
+ }
+
+ @Override
+ public int numberObjectsDirtied() {
+ return changeKindByEnlistedAdapter.size();
+ }
+
+ protected boolean shouldIgnore(final @NonNull ManagedObject adapter) {
+ val spec = adapter.getSpecification();
+ return HasUniqueId.class.isAssignableFrom(spec.getCorrespondingClass());
}
+ // end::refguide[]
+
+ /**
+ * @apiNote intended to be called at the end of a transaction by the framework internally
+ */
+ @Override
+ public void onTransactionEnding() {
+ System.err.println("PRE COMMIT");
+ enlistedObjectProperties.clear();
+ changeKindByEnlistedAdapter.clear();
+ changedObjectPropertiesRef.clear();
+ }
+
+ // -- HELPER
+ static String asString(Object object) {
+ return object != null? object.toString(): null;
+ }
+
/**
* @return <code>true</code> if successfully enlisted, <code>false</code> if was already enlisted
*/
- private boolean enlistForPublishing(final ManagedObject adapter, final PublishingChangeKind current) {
+ private boolean enlistForPublishing(
+ final @NonNull ManagedObject adapter,
+ final @NonNull PublishingChangeKind current) {
final PublishingChangeKind previous = changeKindByEnlistedAdapter.get(adapter);
if(previous == null) {
changeKindByEnlistedAdapter.put(adapter, current);
@@ -200,92 +226,20 @@ public class ChangedObjectsService implements TransactionScopeListener {
return previous == null;
}
- /**
- * Intended to be called at the end of the transaction. Use {@link #onTransactionEnded()} once fully read.
- */
- public Set<AuditEntry> getChangedObjectProperties() {
- return changedObjectProperties != null
- ? changedObjectProperties
- : (changedObjectProperties = capturePostValuesAndDrain(enlistedObjectProperties));
- }
-
- private Set<AuditEntry> capturePostValuesAndDrain(final Map<AdapterAndProperty, PreAndPostValues> changedObjectProperties) {
-
- final Map<AdapterAndProperty, PreAndPostValues> processedObjectProperties = _Maps.newLinkedHashMap();
-
- while(!changedObjectProperties.isEmpty()) {
-
- final Set<AdapterAndProperty> keys = _Sets.newLinkedHashSet(changedObjectProperties.keySet());
- for (val adapterAndProperty : keys) {
-
- val preAndPostValues = changedObjectProperties.remove(adapterAndProperty);
-
- ManagedObject adapter = adapterAndProperty.getAdapter();
- if(EntityUtil.isDestroyed(adapter)) {
- // don't touch the object!!!
- // JDO, for example, will complain otherwise...
- preAndPostValues.setPost(IsisTransactionPlaceholder.DELETED);
- } else {
- preAndPostValues.setPost(adapterAndProperty.getPropertyValue());
- }
-
- // if we encounter the same objectProperty again, this will simply overwrite it
- processedObjectProperties.put(adapterAndProperty, preAndPostValues);
- }
- }
-
- return processedObjectProperties.entrySet().stream()
- .filter(PreAndPostValues::shouldAudit)
- .map(entry->AuditEntry.of(entry.getKey(), entry.getValue()))
- .collect(_Sets.toUnmodifiable());
-
- }
-
- protected boolean shouldIgnore(final ManagedObject adapter) {
- final ObjectSpecification adapterSpec = adapter.getSpecification();
- final Class<?> adapterClass = adapterSpec.getCorrespondingClass();
- return HasUniqueId.class.isAssignableFrom(adapterClass);
- }
-
-
- public Map<ManagedObject, PublishingChangeKind> getChangeKindByEnlistedAdapter() {
- return changeKindByEnlistedAdapter;
- }
-
- public int numberObjectsDirtied() {
- return changeKindByEnlistedAdapter.size();
- }
-
- public int numberObjectPropertiesModified() {
- if(changedObjectProperties == null) {
- // normally done during auditing, but in case none of the objects in this xactn are audited...
- getChangedObjectProperties();
- }
- return changedObjectProperties.size();
- }
-
- /**
- * Intended to be called at the end of a transaction.
- *
- * TODO: we ought to use Spring's @TransactionScope rather than roll-our-own.
- */
- @Override
- public void onTransactionEnded() {
- enlistedObjectProperties.clear();
- changeKindByEnlistedAdapter.clear();
- changedObjectProperties = null;
- }
-
-
- static String asString(Object object) {
- return object != null? object.toString(): null;
- }
-
- private void enlist(
+ private void enlistForAuditing(
final ManagedObject adapter,
- final Stream<ObjectAssociation> properties,
final Function<AdapterAndProperty, PreAndPostValues> pre) {
- properties
+
+ if(changedObjectPropertiesRef.isMemoized()) {
+ throw _Exceptions.illegalState("Cannot enlist additional changes for auditing, "
+ + "since changedObjectPropertiesRef was already prepared (memoized) for auditing.");
+ }
+
+ System.err.println("ENLIST " + adapter);
+
+ adapter.getSpecification()
+ .streamAssociations(Contributed.EXCLUDED)
+ .filter(ObjectAssociation.Predicates.PROPERTIES)
.filter(property->!property.isNotPersisted())
.map(property->AdapterAndProperty.of(adapter, property))
.filter(aap->!enlistedObjectProperties.containsKey(aap)) // already enlisted, so ignore
@@ -293,6 +247,38 @@ public class ChangedObjectsService implements TransactionScopeListener {
enlistedObjectProperties.put(aap, pre.apply(aap));
});
}
+
+ /**
+ * For any enlisted Object Properties collects those, that are meant for auditing.
+ * then clears enlisted objects.
+ */
+ private Set<AuditEntry> capturePostValuesAndDrain() {
+
+ System.err.println("capturePostValuesAndDrain");
+
+ val postValues = enlistedObjectProperties.entrySet().stream()
+ .peek(this::updatePostOn)
+ .filter(PreAndPostValues::shouldAudit)
+ .map(entry->AuditEntry.of(entry.getKey(), entry.getValue()))
+ .collect(_Sets.toUnmodifiable());
+
+ enlistedObjectProperties.clear();
+
+ return postValues;
+ }
+ private final void updatePostOn(Map.Entry<AdapterAndProperty, PreAndPostValues> enlistedEntry) {
+ val adapterAndProperty = enlistedEntry.getKey();
+ val preAndPostValues = enlistedEntry.getValue();
+ val adapter = adapterAndProperty.getAdapter();
+ if(EntityUtil.isDestroyed(adapter)) {
+ // don't touch the object!!!
+ // JDO, for example, will complain otherwise...
+ preAndPostValues.setPost(IsisTransactionPlaceholder.DELETED);
+ } else {
+ preAndPostValues.setPost(adapterAndProperty.getPropertyValue());
+ }
+ }
+
}
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/TransactionScopeListener.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/transaction/HasEnlistedForAuditing.java
similarity index 56%
copy from api/applib/src/main/java/org/apache/isis/applib/services/TransactionScopeListener.java
copy to core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/transaction/HasEnlistedForAuditing.java
index 028bf40..8c37069 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/TransactionScopeListener.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/transaction/HasEnlistedForAuditing.java
@@ -16,27 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.isis.core.runtime.persistence.transaction;
-package org.apache.isis.applib.services;
+import java.util.Set;
-import org.apache.isis.applib.annotation.IsisInteractionScope;
+//TODO[ISIS-2441] intermediate for refactoring keep?
+public interface HasEnlistedForAuditing {
+
+ Set<AuditEntry> getChangedObjectProperties();
-/**
- * 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)
- */
-// tag::refguide[]
-public interface TransactionScopeListener {
-
- default void onTransactionStarted() {
- // default: do nothing
- }
-
- void onTransactionEnded();
}
-// end::refguide[]
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/TransactionScopeListener.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/transaction/HasEnlistedForMetrics.java
similarity index 56%
copy from api/applib/src/main/java/org/apache/isis/applib/services/TransactionScopeListener.java
copy to core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/transaction/HasEnlistedForMetrics.java
index 028bf40..3305866 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/TransactionScopeListener.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/transaction/HasEnlistedForMetrics.java
@@ -16,27 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.isis.core.runtime.persistence.transaction;
-package org.apache.isis.applib.services;
+//TODO[ISIS-2441] intermediate for refactoring keep?
+public interface HasEnlistedForMetrics {
-import org.apache.isis.applib.annotation.IsisInteractionScope;
+ int numberObjectsDirtied();
-/**
- * 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)
- */
-// tag::refguide[]
-public interface TransactionScopeListener {
-
- default void onTransactionStarted() {
- // default: do nothing
- }
-
- void onTransactionEnded();
}
-// end::refguide[]
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/TransactionScopeListener.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/transaction/HasEnlistedForPublishing.java
similarity index 56%
copy from api/applib/src/main/java/org/apache/isis/applib/services/TransactionScopeListener.java
copy to core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/transaction/HasEnlistedForPublishing.java
index 028bf40..90267e6 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/TransactionScopeListener.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/transaction/HasEnlistedForPublishing.java
@@ -16,27 +16,18 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.isis.core.runtime.persistence.transaction;
-package org.apache.isis.applib.services;
+import java.util.Map;
-import org.apache.isis.applib.annotation.IsisInteractionScope;
+import org.apache.isis.applib.annotation.PublishingChangeKind;
+import org.apache.isis.core.metamodel.spec.ManagedObject;
+
+//TODO[ISIS-2441] intermediate for refactoring keep?
+public interface HasEnlistedForPublishing {
+
+ Map<ManagedObject, PublishingChangeKind> getChangeKindByEnlistedAdapter();
+
+ int numberObjectPropertiesModified();
-/**
- * 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)
- */
-// tag::refguide[]
-public interface TransactionScopeListener {
-
- default void onTransactionStarted() {
- // default: do nothing
- }
-
- void onTransactionEnded();
}
-// end::refguide[]
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/publish/PublisherDispatchServiceDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/publish/PublisherDispatchServiceDefault.java
index 7a052f1..45bd189 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/publish/PublisherDispatchServiceDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/publish/PublisherDispatchServiceDefault.java
@@ -19,7 +19,6 @@
package org.apache.isis.core.runtimeservices.publish;
-import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -48,11 +47,10 @@ import org.apache.isis.commons.internal.collections._Maps;
import org.apache.isis.core.metamodel.facets.object.publishedobject.PublishedObjectFacet;
import org.apache.isis.core.metamodel.services.publishing.PublisherDispatchService;
import org.apache.isis.core.metamodel.spec.ManagedObject;
-import org.apache.isis.core.runtime.persistence.transaction.ChangedObjectsService;
+import org.apache.isis.core.runtime.persistence.transaction.HasEnlistedForPublishing;
import lombok.RequiredArgsConstructor;
import lombok.val;
-import lombok.extern.log4j.Log4j2;
/**
* Wrapper around {@link PublisherService}. Is a no-op if there is no injected service.
@@ -63,14 +61,14 @@ import lombok.extern.log4j.Log4j2;
@Primary
@Qualifier("Default")
@IsisInteractionScope
-@Log4j2
@RequiredArgsConstructor
+//@Log4j2
public class PublisherDispatchServiceDefault implements PublisherDispatchService {
@Inject final List<PublisherService> publisherServices;
@Inject final ClockService clockService;
@Inject final UserService userService;
- @Inject final Provider<ChangedObjectsService> changedObjectsProvider;
+ @Inject final Provider<HasEnlistedForPublishing> changedObjectsProvider;
@Inject final Provider<InteractionContext> interactionContextProvider;
@Inject final Provider<MetricsService> metricsServiceProvider;
@@ -113,7 +111,7 @@ public class PublisherDispatchServiceDefault implements PublisherDispatchService
final int numberObjectPropertiesModified,
final Map<ManagedObject, PublishingChangeKind> changeKindByPublishedAdapter) {
- final Interaction interaction = interactionContextProvider.get().getInteraction();
+ val interaction = interactionContextProvider.get().getInteraction();
val uniqueId = interaction.getUniqueId();
if(uniqueId == null) {
@@ -122,8 +120,8 @@ public class PublisherDispatchServiceDefault implements PublisherDispatchService
}
final int nextEventSequence = interaction.next(Interaction.Sequence.INTERACTION.id());
- final String userName = userService.getUser().getName();
- final Timestamp timestamp = clockService.nowAsJavaSqlTimestamp();
+ val userName = userService.getUser().getName();
+ val timestamp = clockService.nowAsJavaSqlTimestamp();
return new PublishedObjectsDefault(
uniqueId, nextEventSequence,
diff --git a/persistence/jdo/datanucleus-5/src/main/java/org/apache/isis/persistence/jdo/datanucleus5/metrics/MetricsServiceForJdo.java b/persistence/jdo/datanucleus-5/src/main/java/org/apache/isis/persistence/jdo/datanucleus5/metrics/MetricsServiceForJdo.java
index 061c4a2..07ee345 100644
--- a/persistence/jdo/datanucleus-5/src/main/java/org/apache/isis/persistence/jdo/datanucleus5/metrics/MetricsServiceForJdo.java
+++ b/persistence/jdo/datanucleus-5/src/main/java/org/apache/isis/persistence/jdo/datanucleus5/metrics/MetricsServiceForJdo.java
@@ -35,7 +35,7 @@ import org.apache.isis.applib.annotation.IsisInteractionScope;
import org.apache.isis.applib.annotation.OrderPrecedence;
import org.apache.isis.applib.services.TransactionScopeListener;
import org.apache.isis.applib.services.metrics.MetricsService;
-import org.apache.isis.core.runtime.persistence.transaction.ChangedObjectsService;
+import org.apache.isis.core.runtime.persistence.transaction.HasEnlistedForMetrics;
@Service
@Named("isisJdoDn5.MetricsServiceForJdo")
@@ -47,7 +47,7 @@ import org.apache.isis.core.runtime.persistence.transaction.ChangedObjectsServic
public class MetricsServiceForJdo
implements MetricsService, InstanceLifecycleListener, LoadLifecycleListener, TransactionScopeListener {
- @Inject private javax.inject.Provider<ChangedObjectsService> changedObjectsProvider;
+ @Inject private javax.inject.Provider<HasEnlistedForMetrics> changedObjectsProvider;
private LongAdder numberLoaded = new LongAdder();
@@ -71,7 +71,7 @@ implements MetricsService, InstanceLifecycleListener, LoadLifecycleListener, Tra
* a transaction-scoped service; since that isn't yet supported by the framework, we have to manually reset).
*/
@Override
- public void onTransactionEnded() {
+ public void onTransactionEnding() {
numberLoaded.reset();
}
diff --git a/persistence/jdo/datanucleus-5/src/main/java/org/apache/isis/persistence/jdo/datanucleus5/persistence/IsisTransactionJdo.java b/persistence/jdo/datanucleus-5/src/main/java/org/apache/isis/persistence/jdo/datanucleus5/persistence/IsisTransactionJdo.java
index 9b77289..2dbd415 100644
--- a/persistence/jdo/datanucleus-5/src/main/java/org/apache/isis/persistence/jdo/datanucleus5/persistence/IsisTransactionJdo.java
+++ b/persistence/jdo/datanucleus-5/src/main/java/org/apache/isis/persistence/jdo/datanucleus5/persistence/IsisTransactionJdo.java
@@ -304,8 +304,8 @@ public class IsisTransactionJdo implements Transaction {
}
/**
+ * Called by both {@link #commit()} and {@link #flush()}:
* <p>
- * Called by both {@link #commit()} and by {@link #flush()}:
* <table>
* <tr>
* <th>called from</th>
@@ -330,7 +330,7 @@ public class IsisTransactionJdo implements Transaction {
// it's possible that in executing these commands that more will be created.
// so we keep flushing until no more are available (ISIS-533)
//
- // this is a do...while rather than a while... just for backward compatibilty
+ // this is a do...while rather than a while... just for backward compatibility
// with previous algorithm that always went through the execute phase at least once.
//
do {
@@ -376,17 +376,17 @@ public class IsisTransactionJdo implements Transaction {
try {
+ doFlush();
+
auditerDispatchService.audit();
publisherDispatchService.publishObjects();
-
- doFlush();
} catch (final RuntimeException ex) {
setAbortCause(new IsisTransactionManagerException(ex));
throw ex;
} finally {
for (TransactionScopeListener listener : transactionScopeListeners) {
- listener.onTransactionEnded();
+ listener.onTransactionEnding();
}
}
}
@@ -404,6 +404,7 @@ public class IsisTransactionJdo implements Transaction {
}
setState(State.COMMITTED);
+
}
// -- abortCause, markAsAborted
diff --git a/regressiontests/stable/src/test/java/org/apache/isis/testdomain/commons/InteractionBoundaryProbe.java b/regressiontests/stable/src/test/java/org/apache/isis/testdomain/commons/InteractionBoundaryProbe.java
index 360019c..4e981a0 100644
--- a/regressiontests/stable/src/test/java/org/apache/isis/testdomain/commons/InteractionBoundaryProbe.java
+++ b/regressiontests/stable/src/test/java/org/apache/isis/testdomain/commons/InteractionBoundaryProbe.java
@@ -59,8 +59,8 @@ public class InteractionBoundaryProbe implements TransactionScopeListener {
/** TRANSACTION END BOUNDARY */
@Override
- public void onTransactionEnded() {
- kvStoreForTesting.incrementCounter(InteractionBoundaryProbe.class, "txEnded");
+ public void onTransactionEnding() {
+ kvStoreForTesting.incrementCounter(InteractionBoundaryProbe.class, "txEnding");
}
// -- ACCESS TO COUNTERS
@@ -78,7 +78,7 @@ public class InteractionBoundaryProbe implements TransactionScopeListener {
}
public static long totalTransactionsEnded(KVStoreForTesting kvStoreForTesting) {
- return kvStoreForTesting.getCounter(InteractionBoundaryProbe.class, "txEnded");
+ return kvStoreForTesting.getCounter(InteractionBoundaryProbe.class, "txEnding");
}
// -- ASSERTIONS (INTERACTIONAL)
diff --git a/regressiontests/stable/src/test/java/org/apache/isis/testdomain/entitychangemetrics/ChangedObjectsTest.java b/regressiontests/stable/src/test/java/org/apache/isis/testdomain/entitychangemetrics/ChangedObjectsTest.java
index e9b94ed..871cd42 100644
--- a/regressiontests/stable/src/test/java/org/apache/isis/testdomain/entitychangemetrics/ChangedObjectsTest.java
+++ b/regressiontests/stable/src/test/java/org/apache/isis/testdomain/entitychangemetrics/ChangedObjectsTest.java
@@ -52,7 +52,8 @@ import lombok.val;
InteractionBoundaryProbe.class
},
properties = {
- "logging.level.org.apache.isis.testdomain.util.rest.KVStoreForTesting=DEBUG"
+ "logging.level.org.apache.isis.testdomain.util.rest.KVStoreForTesting=DEBUG",
+ "logging.level.org.apache.isis.persistence.jdo.datanucleus5.persistence.IsisTransactionJdo=DEBUG"
})
@TestPropertySource({
IsisPresets.SilenceWicket
@@ -69,6 +70,8 @@ class ChangedObjectsTest extends InteractionTestAbstract {
@BeforeEach
void setUp() {
+
+ System.err.println("===BEFORE SETUP");
// cleanup
fixtureScripts.runPersona(JdoTestDomainPersona.PurgeAll);
@@ -79,6 +82,8 @@ class ChangedObjectsTest extends InteractionTestAbstract {
// each test runs in its own interaction context (check)
val testRunNr = kvStoreForTesting.incrementCounter(ChangedObjectsTest.class, "test-run");
assertEquals(testRunNr, InteractionBoundaryProbe.totalInteractionsStarted(kvStoreForTesting));
+
+ System.err.println("===AFTER SETUP");
}
@Test
@@ -88,10 +93,14 @@ class ChangedObjectsTest extends InteractionTestAbstract {
val book = getBookSample();
val inventoryManager = factoryService.create(JdoInventoryManager.class);
+ System.err.println("=1==BEFORE TX");
+
// spawns its own transactional boundary (check)
val product = assertTransactional(
()->wrapper.wrap(inventoryManager).updateProductPrice(book, 12.));
+ System.err.println("=1==AFTER TX");
+
assertEquals(12., product.getPrice(), 1E-3);
// previous transaction has committed, so ChangedObjectsService should have cleared its data
@@ -105,10 +114,14 @@ class ChangedObjectsTest extends InteractionTestAbstract {
// given
val book = getBookSample();
+ System.err.println("=2==BEFORE TX");
+
// spawns its own transactional boundary (check)
val product = (JdoProduct) assertTransactional(
()->invokeAction(JdoInventoryManager.class, "updateProductPrice", _Lists.of(book, 12.)));
+ System.err.println("=2==AFTER TX");
+
assertEquals(12., product.getPrice(), 1E-3);
// previous transaction has committed, so ChangedObjectsService should have cleared its data
@@ -118,10 +131,16 @@ class ChangedObjectsTest extends InteractionTestAbstract {
// -- HELPER
private JdoBook getBookSample() {
+
+ System.err.println("===BEFORE BOOK");
+
// spawns its own transactional boundary (check)
val books = assertTransactional(()->repositoryService.allInstances(JdoBook.class));
assertEquals(1, books.size());
val book = books.listIterator().next();
+
+ System.err.println("===AFTER BOOK");
+
return book;
}