]> source.dussan.org Git - vaadin-framework.git/commitdiff
Test case and fix for #3605 - Concurrent modification exceptions in EventRouter
authorArtur Signell <artur.signell@itmill.com>
Wed, 25 Nov 2009 16:13:15 +0000 (16:13 +0000)
committerArtur Signell <artur.signell@itmill.com>
Wed, 25 Nov 2009 16:13:15 +0000 (16:13 +0000)
svn changeset:10031/svn branch:6.2

src/com/vaadin/event/EventRouter.java
tests/src/com/vaadin/tests/server/TestEventRouter.java [new file with mode: 0644]

index ca98c5e799fb2cae5972902aa476df00a6a67aaf..76673d65f0d5436ac013a2fe5a3be2329c720723 100644 (file)
@@ -138,13 +138,17 @@ public class EventRouter implements MethodEventSource {
     public void fireEvent(EventObject event) {
         // It is not necessary to send any events if there are no listeners
         if (listenerList != null) {
+
+            // Make a copy of the listener list to allow listeners to be added
+            // inside listener methods. Fixes #3605.
+
             // Send the event to all listeners. The listeners themselves
             // will filter out unwanted events.
-
-            final Iterator i = listenerList.iterator();
-            while (i.hasNext()) {
-                ((ListenerMethod) i.next()).receiveEvent(event);
+            final Object[] listeners = listenerList.toArray();
+            for (int i = 0; i < listeners.length; i++) {
+                ((ListenerMethod) listeners[i]).receiveEvent(event);
             }
+
         }
     }
 }
diff --git a/tests/src/com/vaadin/tests/server/TestEventRouter.java b/tests/src/com/vaadin/tests/server/TestEventRouter.java
new file mode 100644 (file)
index 0000000..dc388a6
--- /dev/null
@@ -0,0 +1,37 @@
+package com.vaadin.tests.server;
+
+import junit.framework.TestCase;
+
+import com.vaadin.data.Property.ValueChangeEvent;
+import com.vaadin.data.Property.ValueChangeListener;
+import com.vaadin.ui.TextField;
+
+public class TestEventRouter extends TestCase {
+
+    int innerListenerCalls = 0;
+
+    public void testAddInEventListener() {
+        final TextField tf = new TextField();
+
+        final ValueChangeListener outer = new ValueChangeListener() {
+
+            public void valueChange(ValueChangeEvent event) {
+                ValueChangeListener inner = new ValueChangeListener() {
+
+                    public void valueChange(ValueChangeEvent event) {
+                        innerListenerCalls++;
+                        System.out.println("The inner listener was called");
+                    }
+                };
+
+                tf.addListener(inner);
+            }
+        };
+
+        tf.addListener(outer);
+        tf.setValue("abc"); // No inner listener calls, adds one inner
+        tf.setValue("def"); // One inner listener call, adds one inner
+        tf.setValue("ghi"); // Two inner listener calls, adds one inner
+        assert (innerListenerCalls == 3);
+    }
+}