You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@causeway.apache.org by ah...@apache.org on 2023/07/04 12:29:52 UTC
[causeway] 01/01: CAUSEWAY-3514: properly detect whether we are 'INSERTING'
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch 3514-JDO.callback.fixes
in repository https://gitbox.apache.org/repos/asf/causeway.git
commit aeab6d3046b673ec28a244d016b7d2a387deb7b6
Author: Andi Huber <ah...@apache.org>
AuthorDate: Tue Jul 4 14:29:45 2023 +0200
CAUSEWAY-3514: properly detect whether we are 'INSERTING'
---
.../changetracking/JdoLifecycleListener.adoc | 66 ++++++++++++++++++++++
.../changetracking/JdoLifecycleListener.java | 47 +++++++++++----
.../entities/DnStateManagerForCauseway.java | 9 ++-
3 files changed, 110 insertions(+), 12 deletions(-)
diff --git a/persistence/jdo/datanucleus/src/main/java/org/apache/causeway/persistence/jdo/datanucleus/changetracking/JdoLifecycleListener.adoc b/persistence/jdo/datanucleus/src/main/java/org/apache/causeway/persistence/jdo/datanucleus/changetracking/JdoLifecycleListener.adoc
new file mode 100644
index 0000000000..0585c238f8
--- /dev/null
+++ b/persistence/jdo/datanucleus/src/main/java/org/apache/causeway/persistence/jdo/datanucleus/changetracking/JdoLifecycleListener.adoc
@@ -0,0 +1,66 @@
+= Object Lifecycle
+
+:Notice: 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 ag [...]
+
+== DN Integration in v1
+
+[source]
+.def: transient check
+----
+isTransient := !pojo.dnIsPersistent()
+ && !pojo.dnIsDeleted()
+----
+
+[source]
+.on postLoad()
+----
+if entity is new to PersistenceSession
+then
+ add OID to PersistenceSession
+ emit LOADED
+else
+ no-op
+----
+
+[source]
+.on preStore()
+----
+if entity is transient
+then
+ emit PERSISTING
+else
+ no-op
+----
+
+[source]
+.on postStore()
+----
+if entity is transient
+then
+ enlist entity as CREATED
+ emit PERSISTED
+else
+ emit UPDATED
+----
+
+[source]
+.on preDirty()
+----
+if entity is transient
+then
+ no-op
+else
+ if entity was already enlisted before
+ then
+ no-op
+ else
+ enlist entity as UPDATING
+ emit UPDATING
+----
+
+[source]
+.on preDelete()
+----
+enlist entity as DELETING
+emit DELETING
+----
\ No newline at end of file
diff --git a/persistence/jdo/datanucleus/src/main/java/org/apache/causeway/persistence/jdo/datanucleus/changetracking/JdoLifecycleListener.java b/persistence/jdo/datanucleus/src/main/java/org/apache/causeway/persistence/jdo/datanucleus/changetracking/JdoLifecycleListener.java
index a0d9fa4f49..7700ec7702 100644
--- a/persistence/jdo/datanucleus/src/main/java/org/apache/causeway/persistence/jdo/datanucleus/changetracking/JdoLifecycleListener.java
+++ b/persistence/jdo/datanucleus/src/main/java/org/apache/causeway/persistence/jdo/datanucleus/changetracking/JdoLifecycleListener.java
@@ -87,48 +87,66 @@ DetachLifecycleListener, DirtyLifecycleListener, LoadLifecycleListener, StoreLif
@Override
public void postLoad(final InstanceLifecycleEvent event) {
log.debug("postLoad {}", ()->_Utils.debug(event));
+
+ System.err.printf("postLoad %s%n", "BEGIN {loaded}");
+
final Persistable pojo = _Utils.persistableFor(event);
val entity = adaptEntity(pojo);
+ //TODO only emit if new to session (based on OID)
objectLifecyclePublisher.onPostLoad(entity);
+
+ System.err.printf("postLoad %s%n", "END");
}
@Override
public void preStore(final InstanceLifecycleEvent event) {
log.debug("preStore {}", ()->_Utils.debug(event));
+ System.err.printf("preStore %s%n", "BEGIN {persisting, updating}");
+
final Persistable pojo = _Utils.persistableFor(event);
+ val isInserting = isInserting(pojo); // check before adapting
+ val entity = adaptEntity(pojo);
/* Called either when an entity is initially persisted,
* or when an entity is updated; fires the appropriate
* lifecycle callback. So filter for those events when initially persisting. */
- if(pojo.dnGetStateManager().isNew(pojo)) {
+ if(isInserting) {
// well but then we need an OID, so we distinguish between either we have one or not
- val entity = adaptEntity(pojo);
objectLifecyclePublisher.onPrePersist(
entity.asEitherWithOrWithoutMemoizedBookmark());
+ } else {
+ // not here, using preDirty for that instead
+ //objectLifecyclePublisher.onPreUpdate(entity, /*propertyChangeRecordSupplier*/ null);
}
+
+ System.err.printf("preStore %s%n", "END");
}
@Override
public void postStore(final InstanceLifecycleEvent event) {
log.debug("postStore {}", ()->_Utils.debug(event));
+ System.err.printf("postStore %s%n", "BEGIN {persisted, updated}");
+
final Persistable pojo = _Utils.persistableFor(event);
+ val isInserting = isInserting(pojo); // check before adapting
+
val entity = adaptEntity(pojo);
/* Called either when an entity is initially persisted, or when an entity is updated;
* fires the appropriate lifecycle callback.*/
- if(pojo.dnGetStateManager().isNew(pojo)) {
+ if(isInserting) {
objectLifecyclePublisher.onPostPersist(entity);
-
} else {
// the callback and transaction.enlist are done in the preStore callback
// (can't be done here, as the enlist requires to capture the 'before' values)
objectLifecyclePublisher.onPostUpdate(entity);
}
- }
+ System.err.printf("postStore %s%n", "END");
+ }
@Override
public void preDirty(final InstanceLifecycleEvent event) {
@@ -137,6 +155,8 @@ DetachLifecycleListener, DirtyLifecycleListener, LoadLifecycleListener, StoreLif
final Persistable pojo = _Utils.persistableFor(event);
final Runnable doPreDirty = ()->doPreDirty(pojo);
+ System.err.printf("preDirty %s%n", "BEGIN {updating}");
+
// [CAUSEWAY-3126] pre-dirty nested loop prevention,
// assuming we can cast the DN StateManager to the custom one as provided by the framework
DnStateManagerForCauseway.extractFrom(pojo).ifPresentOrElse(
@@ -144,6 +164,8 @@ DetachLifecycleListener, DirtyLifecycleListener, LoadLifecycleListener, StoreLif
stateManager.acquirePreDirtyPropagationLock(pojo.dnGetObjectId())
.ifPresent(lock->lock.releaseAfter(doPreDirty)),
doPreDirty);
+
+ System.err.printf("preDirty %s%n", "END");
}
/**
@@ -163,10 +185,7 @@ DetachLifecycleListener, DirtyLifecycleListener, LoadLifecycleListener, StoreLif
@Override
public void postDirty(final InstanceLifecycleEvent event) {
- log.debug("postDirty {}", ()->_Utils.debug(event));
- final Persistable pojo = _Utils.persistableFor(event);
- val entity = adaptEntity(pojo);
- objectLifecyclePublisher.onPostUpdate(entity);
+ // not used (historically also not in v1)
}
@Override
@@ -174,9 +193,7 @@ DetachLifecycleListener, DirtyLifecycleListener, LoadLifecycleListener, StoreLif
log.debug("preDelete {}", ()->_Utils.debug(event));
final Persistable pojo = _Utils.persistableFor(event);
-
_Assert.assertNotNull(pojo.dnGetObjectId());
- //val entity = adaptEntity(pojo, EntityAdaptingMode.NOT_YET_BOOKMARKABLE);
val entity = adaptEntity(pojo);
objectLifecyclePublisher.onPreRemove(entity);
@@ -220,4 +237,12 @@ DetachLifecycleListener, DirtyLifecycleListener, LoadLifecycleListener, StoreLif
final @NonNull Persistable pojo) {
return _Utils.adaptEntity(metaModelContext, pojo);
}
+
+ private boolean isInserting(
+ final @NonNull Persistable pojo) {
+ return DnStateManagerForCauseway.extractFrom(pojo)
+ .map(DnStateManagerForCauseway::isInsertingOrInsertingCallbacks)
+ .orElse(false);
+ }
+
}
\ No newline at end of file
diff --git a/persistence/jdo/datanucleus/src/main/java/org/apache/causeway/persistence/jdo/datanucleus/entities/DnStateManagerForCauseway.java b/persistence/jdo/datanucleus/src/main/java/org/apache/causeway/persistence/jdo/datanucleus/entities/DnStateManagerForCauseway.java
index fd6fe0670f..83037ceab4 100644
--- a/persistence/jdo/datanucleus/src/main/java/org/apache/causeway/persistence/jdo/datanucleus/entities/DnStateManagerForCauseway.java
+++ b/persistence/jdo/datanucleus/src/main/java/org/apache/causeway/persistence/jdo/datanucleus/entities/DnStateManagerForCauseway.java
@@ -135,6 +135,13 @@ extends ReferentialStateManagerImpl {
.ifPresent(oid->DnOidStoreAndRecoverHelper.forEntity(entityPojo).storeOid(oid));
}
+ // -- PREDICATES
+
+ public boolean isInsertingOrInsertingCallbacks() {
+ return super.isInserting()
+ || (flags & FLAG_INSERTING_CALLBACKS) != 0;
+ }
+
// -- HELPER
private Optional<MetaModelContext> extractMetaModelContextFrom(final ExecutionContext ec) {
@@ -208,7 +215,7 @@ extends ReferentialStateManagerImpl {
}
if (id instanceof SingleFieldId) {
id = DataNucleusHelperJDO
- .getSingleFieldIdentityForDataNucleusIdentity((SingleFieldId)id, myPC.getClass());
+ .getSingleFieldIdentityForDataNucleusIdentity((SingleFieldId<?, ?>)id, myPC.getClass());
}
val oidIfAny = entityFacet.identifierForDnPrimaryKey(id);
return oidIfAny;