You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Java version/vendor(use: java -version)
does not matter
OS type/version
does not matter
Description
Commit c59de80 introduced durable Servlets, Filters and Listeners.
In Jetty 9.4.x branch only Listeners with Source.EMBEDDED were "copied forward" on webapp restart whereas starting with Jetty 10.x doStart() of ServletHandler registers all Listeners with Source.(ANNOTATION|DESCRIPTOR) as "durable" and always retains them on webapp restarts.
The addListener Method of ServletHandler does not perform any checks and concatenates the existing "durable" list of Listeners with the passed new Listener that was found by the scan of changed files which triggered the restart of the webapp. So each restart creates n+1 instances of any Listener registered with Source.(ANNOTATION|DESCRIPTOR) and results in multiple event callbacks.
How to reproduce?
Use jetty-maven-plugin with scan enabled
Add any (Http|Servlet)*Listener using @weblistener annotation
Add no-arg Constructor with syso print to log
trigger scan and restart of Jetty and watch syso prints duplicating
Resolution
Ensure uniqueness of all Listeners by overriding hashCode and equals based on the (held) class name?
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ListenerHolder.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ListenerHolder.java
index ff7a96a2f7..8c9384627d 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ListenerHolder.java+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ListenerHolder.java@@ -128,6 +128,22 @@ public class ListenerHolder extends BaseHolder<EventListener>
}
}
+ @Override+ public boolean equals(Object that)+ {+ if (this == that)+ return true;+ if (!(that instanceof ListenerHolder))+ return false;+ return hashCode() == ((ListenerHolder)that).hashCode();+ }++ @Override+ public int hashCode()+ {+ return getClassName().hashCode(); // holder class+ }+
@Override
public String toString()
{
Validate if the Listener to be added is present within the "durable" list of Listeners.
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java
index c77bf64cb3..66101c4b7a 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java@@ -797,8 +797,16 @@ public class ServletHandler extends ScopedHandler
*/
public void addListener(ListenerHolder listener)
{
- if (listener != null)- setListeners(ArrayUtil.addToArray(getListeners(), listener, ListenerHolder.class));+ if (listener == null)+ {+ return;+ }++ try (AutoLock ignored = lock())+ {+ if (!containsListenerHolder(listener))+ setListeners(ArrayUtil.addToArray(getListeners(), listener, ListenerHolder.class));+ }
}
public ListenerHolder[] getListeners()
@@ -1433,6 +1441,14 @@ public class ServletHandler extends ScopedHandler
}
}
+ protected boolean containsListenerHolder(ListenerHolder holder)+ {+ try (AutoLock ignored = lock())+ {+ return _listeners.contains(holder);+ }+ }+
protected boolean containsServletHolder(ServletHolder holder)
{
try (AutoLock ignored = lock())
BR
The text was updated successfully, but these errors were encountered:
Jetty version(s)
10.x, 11.x, 12.x
Jetty Environment
ee8, ee9, ee10
Java version/vendor
(use: java -version)
does not matter
OS type/version
does not matter
Description
Commit c59de80 introduced durable Servlets, Filters and Listeners.
In Jetty 9.4.x branch only Listeners with Source.EMBEDDED were "copied forward" on webapp restart whereas starting with Jetty 10.x doStart() of ServletHandler registers all Listeners with Source.(ANNOTATION|DESCRIPTOR) as "durable" and always retains them on webapp restarts.
The addListener Method of ServletHandler does not perform any checks and concatenates the existing "durable" list of Listeners with the passed new Listener that was found by the scan of changed files which triggered the restart of the webapp. So each restart creates n+1 instances of any Listener registered with Source.(ANNOTATION|DESCRIPTOR) and results in multiple event callbacks.
How to reproduce?
Resolution
Ensure uniqueness of all Listeners by overriding hashCode and equals based on the (held) class name?
Validate if the Listener to be added is present within the "durable" list of Listeners.
BR
The text was updated successfully, but these errors were encountered: