(geronimo-mail) 01/02: GERONIMO-6893 - MessageCountListeners are never notified - Folder queues MessageCountEvents to the MessageChangedListener list

[email protected] Sat, 18 Jul 2026 18:22:26 +0000
Newsgroups gmane.comp.java.geronimo.cvs
Message-ID <[email protected]>
This is an automated email from the ASF dual-hosted git repository.

rzo1 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/geronimo-mail.git

commit 6e73cc97e599bbb0c7fe15c742cee5d44829e551
Author: Richard Zowalla <[email protected]>
AuthorDate: Sat Jul 18 20:22:10 2026 +0200

    GERONIMO-6893 - MessageCountListeners are never notified - Folder queues MessageCountEvents to the MessageChangedListener list
---
 .../src/main/java/jakarta/mail/Folder.java         |   4 +-
 .../jakarta/mail/FolderMessageCountEventTest.java  | 113 +++++++++++++++++++++
 geronimo-mail_2.1_tck/src/tck/geronimo.jtx         |   5 -
 3 files changed, 115 insertions(+), 7 deletions(-)

diff --git a/geronimo-mail_2.1_spec/src/main/java/jakarta/mail/Folder.java b/geronimo-mail_2.1_spec/src/main/java/jakarta/mail/Folder.java
index 82323f8..5e82e13 100644
--- a/geronimo-mail_2.1_spec/src/main/java/jakarta/mail/Folder.java
+++ b/geronimo-mail_2.1_spec/src/main/java/jakarta/mail/Folder.java
@@ -678,11 +678,11 @@ public abstract class Folder implements AutoCloseable {
     }
 
     protected void notifyMessageAddedListeners(final Message[] messages) {
-        queueEvent(new MessageCountEvent(this, MessageCountEvent.ADDED, false, messages), messageChangedListeners);
+        queueEvent(new MessageCountEvent(this, MessageCountEvent.ADDED, false, messages), messageCountListeners);
     }
 
     protected void notifyMessageRemovedListeners(final boolean removed, final Message[] messages) {
-        queueEvent(new MessageCountEvent(this, MessageCountEvent.REMOVED, removed, messages), messageChangedListeners);
+        queueEvent(new MessageCountEvent(this, MessageCountEvent.REMOVED, removed, messages), messageCountListeners);
     }
 
     public void addMessageChangedListener(final MessageChangedListener listener) {
diff --git a/geronimo-mail_2.1_spec/src/test/java/jakarta/mail/FolderMessageCountEventTest.java b/geronimo-mail_2.1_spec/src/test/java/jakarta/mail/FolderMessageCountEventTest.java
new file mode 100644
index 0000000..4a811b3
--- /dev/null
+++ b/geronimo-mail_2.1_spec/src/test/java/jakarta/mail/FolderMessageCountEventTest.java
@@ -0,0 +1,113 @@
+/**
+ *  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 jakarta.mail;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+import jakarta.mail.event.MessageCountEvent;
+import jakarta.mail.event.MessageCountListener;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Regression test: MessageCountEvents used to be queued to the
+ * MessageChangedListener list, so registered MessageCountListeners never
+ * received any notification at all.
+ */
+public class FolderMessageCountEventTest {
+
+    static class NotifyingFolder extends SimpleFolder {
+        NotifyingFolder(final Store store) {
+            super(store);
+        }
+
+        void fireAdded(final Message[] messages) {
+            notifyMessageAddedListeners(messages);
+        }
+
+        void fireRemoved(final Message[] messages) {
+            notifyMessageRemovedListeners(true, messages);
+        }
+    }
+
+    @Test
+    public void testMessageCountListenerReceivesEvents() throws Exception {
+        final Session session = Session.getInstance(new java.util.Properties());
+        final Store store = session.getStore(new Provider(Provider.Type.STORE, "test", NullStore.class.getName(), "test", "1.0"));
+        final NotifyingFolder folder = new NotifyingFolder(store);
+
+        final CountDownLatch latch = new CountDownLatch(2);
+        final AtomicInteger added = new AtomicInteger();
+        final AtomicInteger removed = new AtomicInteger();
+        final AtomicReference<MessageCountEvent> lastEvent = new AtomicReference<>();
+
+        folder.addMessageCountListener(new MessageCountListener() {
+            @Override
+            public void messagesAdded(final MessageCountEvent event) {
+                added.incrementAndGet();
+                lastEvent.set(event);
+                latch.countDown();
+            }
+
+            @Override
+            public void messagesRemoved(final MessageCountEvent event) {
+                removed.incrementAndGet();
+                latch.countDown();
+            }
+        });
+        // a changed-listener must NOT see count events
+        final AtomicInteger changed = new AtomicInteger();
+        folder.addMessageChangedListener(event -> changed.incrementAndGet());
+
+        folder.fireAdded(new Message[0]);
+        folder.fireRemoved(new Message[0]);
+
+        assertTrue(latch.await(30, TimeUnit.SECONDS), "MessageCountListener was never notified");
+        assertEquals(1, added.get());
+        assertEquals(1, removed.get());
+        assertEquals(MessageCountEvent.ADDED, lastEvent.get().getType());
+        assertEquals(0, changed.get());
+    }
+
+    public static class NullStore extends Store {
+        public NullStore(final Session session, final URLName name) {
+            super(session, name);
+        }
+
+        @Override
+        public Folder getDefaultFolder() {
+            return null;
+        }
+
+        @Override
+        public Folder getFolder(final String name) {
+            return null;
+        }
+
+        @Override
+        public Folder getFolder(final URLName name) {
+            return null;
+        }
+    }
+
+}
diff --git a/geronimo-mail_2.1_tck/src/tck/geronimo.jtx b/geronimo-mail_2.1_tck/src/tck/geronimo.jtx
index 472e33c..0b9b927 100644
--- a/geronimo-mail_2.1_tck/src/tck/geronimo.jtx
+++ b/geronimo-mail_2.1_tck/src/tck/geronimo.jtx
@@ -36,11 +36,6 @@ SignatureTest.html
 # expects them to survive close(false)).
 javasoft/sqe/tests/jakarta/mail/Folder/testlist.html#appendMessages_Test
 
-# MessageCountListener events are queued to the wrong listener list in
-# jakarta.mail.Folder (notifyMessageAdded/RemovedListeners use
-# messageChangedListeners), so count listeners never fire.
-javasoft/sqe/tests/jakarta/mail/event/FolderEvent/testlist.html#addMsgCntList_Test
-
 # Remaining baseline failures (284 passed / 31 failed after the
 # IMAPFolder.renameTo fix removed a ~90-test cascade). Distinct defects:
 # folder create/delete (topdog), permanent flags, list/listSubscribed,