This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch test/document-datamapping-events
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 623be84e7126607de7f0b92e4a579f9f58803e52
Author: Walter Duque de Estrada <[email protected]>
AuthorDate: Fri Aug 14 10:44:29 2026 -0500

    Fix DomainEventListener IntelliJ warnings
    
    - entityEvents field made final (never reassigned)
    - Removed ZERO_PARAMS constant (zero references anywhere in the repo)
    - Parameterized raw ConnectionSourcesProvider/Class usages
    - supportsEventType now null-safe: Spring 7's
      SmartApplicationListener.supportsEventType declares its parameter
      @Nullable, and this override would NPE via Class.isAssignableFrom(null)
    - invokeEvent's ea.refresh() call is now guarded by the same ea != null
      check already used earlier in the method, closing a latent NPE path
    - Removed the two switch branches in onPersistenceEvent (SaveOrUpdate,
      Validation) that were duplicates of the default branch
    - Reordered each before/after method pair so the 2-arg overload holds
      the real logic and is canonical; the 3-arg overload (whose event
      parameter has been unused since the dead 1-arg-hook branch was
      removed) is now @Deprecated, forwards to the 2-arg overload, and is
      scheduled for removal in 9.0. onPersistenceEvent now calls the 2-arg
      overloads directly instead of the newly-deprecated 3-arg ones.
    
    Added tests for the deprecated overloads' delegation and the null
    eventType case. Full suite, jacoco, and codeStyle all clean.
---
 .../datastore/gorm/events/DomainEventListener.java | 123 ++++++++++++---------
 .../gorm/events/DomainEventListenerSpec.groovy     |  36 ++++++
 2 files changed, 108 insertions(+), 51 deletions(-)

diff --git 
a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/events/DomainEventListener.java
 
b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/events/DomainEventListener.java
index fca82d846f..75899037c9 100644
--- 
a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/events/DomainEventListener.java
+++ 
b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/events/DomainEventListener.java
@@ -58,10 +58,8 @@ import 
org.grails.datastore.mapping.model.config.GormProperties;
 public class DomainEventListener extends AbstractPersistenceEventListener
        implements MappingContext.Listener {
 
-    private Map<PersistentEntity, Map<String, Method>> entityEvents = new 
ConcurrentHashMap<>();
+    private final Map<PersistentEntity, Map<String, Method>> entityEvents = 
new ConcurrentHashMap<>();
 
-    @SuppressWarnings("rawtypes")
-    public static final Class[] ZERO_PARAMS = {};
     public static final String EVENT_BEFORE_INSERT = "beforeInsert";
     private static final String EVENT_BEFORE_UPDATE = "beforeUpdate";
     private static final String EVENT_BEFORE_DELETE = "beforeDelete";
@@ -84,15 +82,15 @@ public class DomainEventListener extends 
AbstractPersistenceEventListener
         }
 
         datastore.getMappingContext().addMappingContextListener(this);
-        if (datastore instanceof ConnectionSourcesProvider) {
-            autowireEntities = ((ConnectionSourcesProvider) 
datastore).getConnectionSources().getDefaultConnectionSource().getSettings().isAutowire();
+        if (datastore instanceof ConnectionSourcesProvider<?, ?>) {
+            autowireEntities = ((ConnectionSourcesProvider<?, ?>) 
datastore).getConnectionSources().getDefaultConnectionSource().getSettings().isAutowire();
         }
         else {
             autowireEntities = false;
         }
     }
 
-    protected DomainEventListener(ConnectionSourcesProvider 
connectionSourcesProvider, final MappingContext mappingContext) {
+    protected DomainEventListener(ConnectionSourcesProvider<?, ?> 
connectionSourcesProvider, final MappingContext mappingContext) {
         super(null);
 
         for (PersistentEntity entity : mappingContext.getPersistentEntities()) 
{
@@ -106,54 +104,41 @@ public class DomainEventListener extends 
AbstractPersistenceEventListener
     protected void onPersistenceEvent(final AbstractPersistenceEvent event) {
         switch (event.getEventType()) {
             case PreInsert:
-                if (!beforeInsert(event.getEntity(), event.getEntityAccess(), 
(PreInsertEvent) event)) {
+                if (!beforeInsert(event.getEntity(), event.getEntityAccess())) 
{
                     event.cancel();
                 }
                 break;
             case PostInsert:
-                afterInsert(event.getEntity(), event.getEntityAccess(), 
(PostInsertEvent) event);
+                afterInsert(event.getEntity(), event.getEntityAccess());
                 break;
             case PreUpdate:
-                if (!beforeUpdate(event.getEntity(), event.getEntityAccess(), 
(PreUpdateEvent) event)) {
+                if (!beforeUpdate(event.getEntity(), event.getEntityAccess())) 
{
                     event.cancel();
                 }
                 break;
             case PostUpdate:
-                afterUpdate(event.getEntity(), event.getEntityAccess(), 
(PostUpdateEvent) event);
+                afterUpdate(event.getEntity(), event.getEntityAccess());
                 break;
             case PreDelete:
-                if (!beforeDelete(event.getEntity(), event.getEntityAccess(), 
(PreDeleteEvent) event)) {
+                if (!beforeDelete(event.getEntity(), event.getEntityAccess())) 
{
                     event.cancel();
                 }
                 break;
             case PostDelete:
-                afterDelete(event.getEntity(), event.getEntityAccess(), 
(PostDeleteEvent) event);
+                afterDelete(event.getEntity(), event.getEntityAccess());
                 break;
             case PreLoad:
-                beforeLoad(event.getEntity(), event.getEntityAccess(), 
(PreLoadEvent) event);
+                beforeLoad(event.getEntity(), event.getEntityAccess());
                 break;
             case PostLoad:
-                afterLoad(event.getEntity(), event.getEntityAccess(), 
(PostLoadEvent) event);
-                break;
-            case SaveOrUpdate:
-                break;
-            case Validation:
+                afterLoad(event.getEntity(), event.getEntityAccess());
                 break;
             default:
                 break;
         }
     }
 
-    /**
-     * @deprecated Use {@link 
#beforeInsert(org.grails.datastore.mapping.model.PersistentEntity, 
org.grails.datastore.mapping.engine.EntityAccess, 
org.grails.datastore.mapping.engine.event.PreInsertEvent)} instead
-     */
-    @Deprecated
     public boolean beforeInsert(final PersistentEntity entity, final 
EntityAccess ea) {
-        return beforeInsert(entity, ea, null);
-    }
-
-    public boolean beforeInsert(final PersistentEntity entity, final 
EntityAccess ea, PreInsertEvent event) {
-
         if (entity.isVersioned()) {
             try {
                 setVersion(ea);
@@ -166,8 +151,16 @@ public class DomainEventListener extends 
AbstractPersistenceEventListener
         return invokeEvent(EVENT_BEFORE_INSERT, entity, ea);
     }
 
+    /**
+     * @deprecated the {@code event} parameter is unused; use {@link 
#beforeInsert(PersistentEntity, EntityAccess)} instead. Scheduled for removal 
in 9.0.
+     */
+    @Deprecated
+    public boolean beforeInsert(final PersistentEntity entity, final 
EntityAccess ea, @SuppressWarnings("unused") PreInsertEvent event) {
+        return beforeInsert(entity, ea);
+    }
+
     protected void setVersion(final EntityAccess ea) {
-        final Class versionType = 
ea.getPersistentEntity().getVersion().getType();
+        final Class<?> versionType = 
ea.getPersistentEntity().getVersion().getType();
         if (Number.class.isAssignableFrom(versionType)) {
             ea.setProperty(GormProperties.VERSION, 0);
         }
@@ -183,43 +176,63 @@ public class DomainEventListener extends 
AbstractPersistenceEventListener
         return invokeEvent(EVENT_BEFORE_UPDATE, entity, ea);
     }
 
-    public boolean beforeUpdate(final PersistentEntity entity, final 
EntityAccess ea, PreUpdateEvent event) {
-        return invokeEvent(EVENT_BEFORE_UPDATE, entity, ea);
+    /**
+     * @deprecated the {@code event} parameter is unused; use {@link 
#beforeUpdate(PersistentEntity, EntityAccess)} instead. Scheduled for removal 
in 9.0.
+     */
+    @Deprecated
+    public boolean beforeUpdate(final PersistentEntity entity, final 
EntityAccess ea, @SuppressWarnings("unused") PreUpdateEvent event) {
+        return beforeUpdate(entity, ea);
     }
 
     public boolean beforeDelete(final PersistentEntity entity, final 
EntityAccess ea) {
         return invokeEvent(EVENT_BEFORE_DELETE, entity, ea);
     }
 
-    public boolean beforeDelete(final PersistentEntity entity, final 
EntityAccess ea, PreDeleteEvent event) {
-        return invokeEvent(EVENT_BEFORE_DELETE, entity, ea);
+    /**
+     * @deprecated the {@code event} parameter is unused; use {@link 
#beforeDelete(PersistentEntity, EntityAccess)} instead. Scheduled for removal 
in 9.0.
+     */
+    @Deprecated
+    public boolean beforeDelete(final PersistentEntity entity, final 
EntityAccess ea, @SuppressWarnings("unused") PreDeleteEvent event) {
+        return beforeDelete(entity, ea);
     }
 
     public void beforeLoad(final PersistentEntity entity, final EntityAccess 
ea) {
-        beforeLoad(entity, ea, null);
-    }
-
-    public void beforeLoad(final PersistentEntity entity, final EntityAccess 
ea, PreLoadEvent event) {
         invokeEvent(EVENT_BEFORE_LOAD, entity, ea);
     }
 
-    public void afterDelete(final PersistentEntity entity, final EntityAccess 
ea) {
-        afterDelete(entity, ea, null);
+    /**
+     * @deprecated the {@code event} parameter is unused; use {@link 
#beforeLoad(PersistentEntity, EntityAccess)} instead. Scheduled for removal in 
9.0.
+     */
+    @Deprecated
+    public void beforeLoad(final PersistentEntity entity, final EntityAccess 
ea, @SuppressWarnings("unused") PreLoadEvent event) {
+        beforeLoad(entity, ea);
     }
 
-    public void afterDelete(final PersistentEntity entity, final EntityAccess 
ea, PostDeleteEvent event) {
+    public void afterDelete(final PersistentEntity entity, final EntityAccess 
ea) {
         invokeEvent(EVENT_AFTER_DELETE, entity, ea);
     }
 
-    public void afterInsert(final PersistentEntity entity, final EntityAccess 
ea) {
-        afterInsert(entity, ea, null);
+    /**
+     * @deprecated the {@code event} parameter is unused; use {@link 
#afterDelete(PersistentEntity, EntityAccess)} instead. Scheduled for removal in 
9.0.
+     */
+    @Deprecated
+    public void afterDelete(final PersistentEntity entity, final EntityAccess 
ea, @SuppressWarnings("unused") PostDeleteEvent event) {
+        afterDelete(entity, ea);
     }
 
-    public void afterInsert(final PersistentEntity entity, final EntityAccess 
ea, PostInsertEvent event) {
+    public void afterInsert(final PersistentEntity entity, final EntityAccess 
ea) {
         activateDirtyChecking(ea);
         invokeEvent(EVENT_AFTER_INSERT, entity, ea);
     }
 
+    /**
+     * @deprecated the {@code event} parameter is unused; use {@link 
#afterInsert(PersistentEntity, EntityAccess)} instead. Scheduled for removal in 
9.0.
+     */
+    @Deprecated
+    public void afterInsert(final PersistentEntity entity, final EntityAccess 
ea, @SuppressWarnings("unused") PostInsertEvent event) {
+        afterInsert(entity, ea);
+    }
+
     private void activateDirtyChecking(EntityAccess ea) {
         Object e = ea.getEntity();
         if (e instanceof DirtyCheckable) {
@@ -228,19 +241,19 @@ public class DomainEventListener extends 
AbstractPersistenceEventListener
     }
 
     public void afterUpdate(final PersistentEntity entity, final EntityAccess 
ea) {
-        afterUpdate(entity, ea, null);
-    }
-
-    public void afterUpdate(final PersistentEntity entity, final EntityAccess 
ea, PostUpdateEvent event) {
         activateDirtyChecking(ea); // reset dirty checking
         invokeEvent(EVENT_AFTER_UPDATE, entity, ea);
     }
 
-    public void afterLoad(final PersistentEntity entity, final EntityAccess 
ea) {
-        afterLoad(entity, ea, null);
+    /**
+     * @deprecated the {@code event} parameter is unused; use {@link 
#afterUpdate(PersistentEntity, EntityAccess)} instead. Scheduled for removal in 
9.0.
+     */
+    @Deprecated
+    public void afterUpdate(final PersistentEntity entity, final EntityAccess 
ea, @SuppressWarnings("unused") PostUpdateEvent event) {
+        afterUpdate(entity, ea);
     }
 
-    public void afterLoad(final PersistentEntity entity, final EntityAccess 
ea, PostLoadEvent event) {
+    public void afterLoad(final PersistentEntity entity, final EntityAccess 
ea) {
         activateDirtyChecking(ea);
         if (autowireEntities || (entity != null && 
entity.getMapping().getMappedForm().isAutowire())) {
             autowireBeanProperties(ea.getEntity());
@@ -248,6 +261,14 @@ public class DomainEventListener extends 
AbstractPersistenceEventListener
         invokeEvent(EVENT_AFTER_LOAD, entity, ea);
     }
 
+    /**
+     * @deprecated the {@code event} parameter is unused; use {@link 
#afterLoad(PersistentEntity, EntityAccess)} instead. Scheduled for removal in 
9.0.
+     */
+    @Deprecated
+    public void afterLoad(final PersistentEntity entity, final EntityAccess 
ea, @SuppressWarnings("unused") PostLoadEvent event) {
+        afterLoad(entity, ea);
+    }
+
     protected void autowireBeanProperties(final Object entity) {
         ConfigurableApplicationContext applicationContext = 
datastore.getApplicationContext();
         if (applicationContext != null) {
@@ -271,7 +292,7 @@ public class DomainEventListener extends 
AbstractPersistenceEventListener
      *     java.lang.Class)
      */
     public boolean supportsEventType(Class<? extends ApplicationEvent> 
eventType) {
-        return AbstractPersistenceEvent.class.isAssignableFrom(eventType);
+        return eventType != null && 
AbstractPersistenceEvent.class.isAssignableFrom(eventType);
     }
 
     private boolean invokeEvent(String eventName, PersistentEntity entity, 
EntityAccess ea) {
@@ -294,7 +315,7 @@ public class DomainEventListener extends 
AbstractPersistenceEventListener
         }
 
         boolean booleanResult = (result instanceof Boolean) ? (Boolean) result 
: true;
-        if (booleanResult && REFRESH_EVENTS.contains(eventName)) {
+        if (ea != null && booleanResult && REFRESH_EVENTS.contains(eventName)) 
{
             ea.refresh();
         }
         return booleanResult;
diff --git 
a/grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/events/DomainEventListenerSpec.groovy
 
b/grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/events/DomainEventListenerSpec.groovy
index 319f27100c..01e6f61ee8 100644
--- 
a/grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/events/DomainEventListenerSpec.groovy
+++ 
b/grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/events/DomainEventListenerSpec.groovy
@@ -123,6 +123,14 @@ class DomainEventListenerSpec extends Specification {
         !listener.supportsEventType(PayloadApplicationEvent)
     }
 
+    void "supportsEventType rejects a null event type rather than throwing, 
matching SmartApplicationListener's nullable contract"() {
+        given:
+        DomainEventListener listener = new 
DomainEventListener(plainDatastore(Stub(MappingContext) { 
getPersistentEntities() >> [] }))
+
+        expect:
+        !listener.supportsEventType(null)
+    }
+
     void "beforeInsert sets an initial numeric version to 0 when the entity is 
versioned"() {
         given:
         PersistentEntity entity = entityFor(NoHooksDomain, true, Long)
@@ -248,6 +256,34 @@ class DomainEventListenerSpec extends Specification {
         'afterLoad'     | 'afterLoad'
     }
 
+    @Unroll
+    @SuppressWarnings('deprecation')
+    void "the deprecated 3-arg #methodName(entity, ea, event) overload 
delegates to the 2-arg overload, ignoring the event argument"() {
+        given:
+        RecordingDomain domain = new RecordingDomain()
+        PersistentEntity entity = entityFor(RecordingDomain)
+        DomainEventListener listener = new 
DomainEventListener(plainDatastore(Stub(MappingContext) { 
getPersistentEntities() >> [] }))
+        listener.persistentEntityAdded(entity)
+        EntityAccess ea = Stub(EntityAccess) { getEntity() >> domain }
+
+        when:
+        listener."$methodName"(entity, ea, null)
+
+        then:
+        domain.invoked == [hookName]
+
+        where:
+        methodName     | hookName
+        'beforeInsert'  | 'beforeInsert'
+        'beforeUpdate'  | 'beforeUpdate'
+        'beforeDelete'  | 'beforeDelete'
+        'beforeLoad'    | 'beforeLoad'
+        'afterInsert'   | 'afterInsert'
+        'afterUpdate'   | 'afterUpdate'
+        'afterDelete'   | 'afterDelete'
+        'afterLoad'     | 'afterLoad'
+    }
+
     void "afterInsert activates dirty checking on entities that implement 
DirtyCheckable"() {
         given:
         DirtyCheckableDomain domain = Spy(DirtyCheckableDomain)

Reply via email to