Update to Unmodified Object in PreUpdate not Triggering PostUpdate

Jadon G Hansell <[email protected]> Wed, 5 Nov 2025 13:36:03 -0800
Newsgroups gmane.comp.java.cayenne.user
Message-ID <[email protected]>
--Apple-Mail=_25FA590F-A713-4977-BAE4-39615683B3F7
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
	charset=utf-8

Hello,

I=E2=80=99m running into an issue that I don=E2=80=99t think is intended =
behavior, but I=E2=80=99m not sure.

I=E2=80=99ll use the test entities for an example. Let=E2=80=99s say I =
register a PreUpdate callback on Artist that updates the description of =
all their paintings to read =E2=80=9CPainted by artistName=E2=80=9D, and =
I also register a PostUpdate callback on Painting. If the painting had =
no changes before the commit, then the description is updated correctly =
but the PostUpdate callback on the painting is never called. Is it =
intended that PostUpdate callbacks are only triggered on objects that =
had changes before committing?

Here is a patch for a breaking test in 4.2 with that situation. The =
painting=E2=80=99s description is updated correctly, but `isPostUpdated` =
is still false at the end:

```
Subject: [PATCH] cay-missing-post-update
---
Index: =
cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/Painting.ja=
va
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
diff --git =
a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/Painting.=
java =
b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/Painting.=
java
--- =
a/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/Painting.=
java	(revision c282ada74f696d181a569f15681f948ac2456914)
+++ =
b/cayenne-server/src/test/java/org/apache/cayenne/testdo/testmap/Painting.=
java	(date 1762365288222)
@@ -27,11 +27,13 @@
    protected boolean postAdded;
    protected boolean preRemoved;
    protected boolean preUpdated;
+    protected boolean postUpdated;

    public void resetCallbackFlags() {
        postAdded =3D false;
        preRemoved =3D false;
        preUpdated =3D false;
+        postUpdated =3D false;
    }

    public void postAddCallback() {
@@ -46,6 +48,10 @@
        preUpdated =3D true;
    }

+    public void postUpdateCallback() {
+        postUpdated =3D true;
+    }
+
    public boolean isPostAdded() {
        return postAdded;
    }
@@ -58,6 +64,10 @@
        return preUpdated;
    }

+    public boolean isPostUpdated() {
+        return postUpdated;
+    }
+
    public boolean isValidateForSaveCalled() {
        return validateForSaveCalled;
    }
Index: =
cayenne-server/src/test/java/org/apache/cayenne/access/DataDomainCallbacks=
IT.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
diff --git =
a/cayenne-server/src/test/java/org/apache/cayenne/access/DataDomainCallbac=
ksIT.java =
b/cayenne-server/src/test/java/org/apache/cayenne/access/DataDomainCallbac=
ksIT.java
--- =
a/cayenne-server/src/test/java/org/apache/cayenne/access/DataDomainCallbac=
ksIT.java	(revision c282ada74f696d181a569f15681f948ac2456914)
+++ =
b/cayenne-server/src/test/java/org/apache/cayenne/access/DataDomainCallbac=
ksIT.java	(date 1762365550630)
@@ -336,6 +336,37 @@
        assertSame(a1, listener2.getPublicCalledbackEntity());
    }

+    static class ArtistAttributionListener {
+        public void updatePaintingAttributions(Artist artist) {
+            String attribution =3D "Painted by " + =
artist.getArtistName();
+            for (Painting painting : artist.getPaintingArray()) {
+                painting.setPaintingDescription(attribution);
+            }
+        }
+    }
+
+    @Test
+    public void testPostUpdate_ChangedInPreUpdate() {
+        LifecycleCallbackRegistry registry =3D =
resolver.getCallbackRegistry();
+
+        Artist a1 =3D context.newObject(Artist.class);
+        a1.setArtistName("XX");
+
+        Painting p1 =3D context.newObject(Painting.class);
+        p1.setToArtist(a1);
+        p1.setPaintingTitle("Painting 1");
+
+        context.commitChanges();
+        assertFalse(p1.isPostUpdated());
+
+        registry.addListener(LifecycleEvent.PRE_UPDATE, Artist.class, =
new ArtistAttributionListener(), "updatePaintingAttributions");
+        registry.addCallback(LifecycleEvent.POST_UPDATE, =
Painting.class, "postUpdateCallback");
+        a1.setArtistName("ZZ");
+        context.commitChanges();
+        assertEquals(p1.getPaintingDescription(), "Painted by " + =
a1.getArtistName());
+        assertTrue(p1.isPostUpdated());
+    }
+
    @Test
    public void testPostRemove() {
```

Thank you,
Jadon Hansell=

--Apple-Mail=_25FA590F-A713-4977-BAE4-39615683B3F7--