Skip to content

Commit 4df28eb

Browse files
authored
Issue #11039 duplicate durable listeners on maven restart (#11042)
1 parent 90244c3 commit 4df28eb

File tree

5 files changed

+126
-28
lines changed

5 files changed

+126
-28
lines changed

jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyEmbedder.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.eclipse.jetty.server.Server;
2727
import org.eclipse.jetty.server.ShutdownMonitor;
2828
import org.eclipse.jetty.server.handler.ContextHandler;
29+
import org.eclipse.jetty.servlet.ServletHandler;
2930
import org.eclipse.jetty.util.component.AbstractLifeCycle;
3031
import org.eclipse.jetty.util.resource.Resource;
3132

@@ -227,6 +228,12 @@ protected void redeployWebApp() throws Exception
227228
{
228229
if (!webApp.isStopped())
229230
webApp.stop();
231+
232+
//clear the ServletHandler, which may have
233+
//remembered "durable" Servlets, Filters, Listeners
234+
//from the context xml file, but as we will re-apply
235+
//the context xml, we should not retain them
236+
webApp.setServletHandler(new ServletHandler());
230237

231238
//regenerate config properties
232239
applyWebAppProperties();
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//
2+
// ========================================================================
3+
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
4+
//
5+
// This program and the accompanying materials are made available under the
6+
// terms of the Eclipse Public License v. 2.0 which is available at
7+
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
8+
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
9+
//
10+
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
11+
// ========================================================================
12+
//
13+
14+
package org.eclipse.jetty.maven.plugin;
15+
16+
import java.util.EventListener;
17+
18+
public class SomeListener implements EventListener
19+
{
20+
21+
}

jetty-maven-plugin/src/test/java/org/eclipse/jetty/maven/plugin/TestJettyEmbedder.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.eclipse.jetty.server.Server;
2222
import org.eclipse.jetty.server.handler.ContextHandler;
2323
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
24+
import org.eclipse.jetty.servlet.ListenerHolder;
2425
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
2526
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
2627
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
@@ -29,9 +30,12 @@
2930
import org.junit.jupiter.api.Test;
3031
import org.junit.jupiter.api.extension.ExtendWith;
3132

33+
import static org.hamcrest.MatcherAssert.assertThat;
34+
import static org.hamcrest.Matchers.is;
3235
import static org.junit.jupiter.api.Assertions.assertEquals;
3336
import static org.junit.jupiter.api.Assertions.assertNotNull;
3437
import static org.junit.jupiter.api.Assertions.assertTrue;
38+
import static org.junit.jupiter.api.Assertions.fail;
3539

3640
@ExtendWith(WorkDirExtension.class)
3741
public class TestJettyEmbedder
@@ -117,6 +121,37 @@ public void testJettyEmbedder()
117121
assertNotNull(contexts);
118122
assertTrue(contexts.contains(otherHandler));
119123
assertTrue(contexts.contains(webApp));
124+
125+
//stop the webapp and check durable listener retained
126+
jetty.getWebApp().stop();
127+
boolean someListener = false;
128+
for (ListenerHolder h : webApp.getServletHandler().getListeners())
129+
{
130+
if (h.getHeldClass() != null && "org.eclipse.jetty.maven.plugin.SomeListener".equalsIgnoreCase(h.getHeldClass().getName()))
131+
{
132+
if (someListener)
133+
fail("Duplicate listeners");
134+
else
135+
someListener = true;
136+
}
137+
}
138+
139+
140+
//restart the webapp
141+
jetty.redeployWebApp();
142+
someListener = false;
143+
144+
//ensure still only 1 listener
145+
for (ListenerHolder h : webApp.getServletHandler().getListeners())
146+
{
147+
if (h.getHeldClass() != null && "org.eclipse.jetty.maven.plugin.SomeListener".equalsIgnoreCase(h.getHeldClass().getName()))
148+
{
149+
if (someListener)
150+
fail("Duplicate listeners");
151+
else
152+
someListener = true;
153+
}
154+
}
120155
}
121156
finally
122157
{

jetty-maven-plugin/src/test/resources/embedder-context.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,16 @@
33

44
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
55
<Set name="contextPath">/embedder</Set>
6+
7+
<Get name="servletHandler">
8+
<Call name="addListener">
9+
<Arg>
10+
<New class="org.eclipse.jetty.servlet.ListenerHolder">
11+
<Set name="listener">
12+
<New class="org.eclipse.jetty.maven.plugin.SomeListener"/>
13+
</Set>
14+
</New>
15+
</Arg>
16+
</Call>
17+
</Get>
618
</Configure>

jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletHandlerTest.java

Lines changed: 51 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ public class ServletHandlerTest
6464
FilterHolder fh5 = new FilterHolder(Source.JAVAX_API);
6565
FilterMapping fm5 = new FilterMapping();
6666

67+
FilterHolder fh6 = new FilterHolder(Source.EMBEDDED);
68+
FilterMapping fm6 = new FilterMapping();
69+
70+
FilterHolder fh7 = new FilterHolder(Source.EMBEDDED);
71+
FilterMapping fm7 = new FilterMapping();
72+
6773
ServletHolder sh1 = new ServletHolder(new Source(Source.Origin.DESCRIPTOR, "foo.xml"));
6874
ServletMapping sm1 = new ServletMapping();
6975

@@ -73,6 +79,12 @@ public class ServletHandlerTest
7379
ServletHolder sh3 = new ServletHolder(new Source(Source.Origin.DESCRIPTOR, "foo.xml"));
7480
ServletMapping sm3 = new ServletMapping();
7581

82+
ServletHolder sh4 = new ServletHolder(Source.EMBEDDED);
83+
ServletMapping sm4 = new ServletMapping();
84+
85+
ServletHolder sh5 = new ServletHolder(Source.EMBEDDED);
86+
ServletMapping sm5 = new ServletMapping();
87+
7688
@BeforeEach
7789
public void initMappings()
7890
{
@@ -842,50 +854,61 @@ public void testDurable() throws Exception
842854
ServletContextHandler context = new ServletContextHandler();
843855
server.setHandler(context);
844856
ServletHandler handler = new ServletHandler();
857+
handler.setEnsureDefaultServlet(false);
845858
context.setHandler(handler);
846859
ListenerHolder lh1 = new ListenerHolder(HSListener.class);
847860
ListenerHolder lh2 = new ListenerHolder(SCListener.class);
848861

849-
fh1.setFilter(new SomeFilter());
850-
fm1.setPathSpec("/sm1");
851-
fm1.setFilterHolder(fh1);
852-
fh2.setFilter(new SomeFilter(){});
853-
fm2.setPathSpec("/sm2");
854-
fm2.setFilterHolder(fh2);
855-
sh1.setServlet(new SomeServlet());
856-
sm1.setPathSpec("/sm1");
857-
sm1.setServletName(sh1.getName());
858-
sh2.setServlet(new SomeServlet());
859-
sm2.setPathSpec("/sm2");
860-
sm2.setServletName(sh2.getName());
862+
fh6.setFilter(new SomeFilter());
863+
fm6.setPathSpec("/sm4");
864+
fm6.setFilterHolder(fh6);
865+
fh7.setFilter(new SomeFilter(){});
866+
fm7.setPathSpec("/sm5");
867+
fm7.setFilterHolder(fh7);
868+
sh4.setServlet(new SomeServlet());
869+
sm4.setPathSpec("/sm4");
870+
sm4.setServletName(sh4.getName());
871+
sh5.setServlet(new SomeServlet());
872+
sm5.setPathSpec("/sm5");
873+
sm5.setServletName(sh5.getName());
861874

862875
handler.setListeners(new ListenerHolder[] {lh1});
863-
handler.setFilters(new FilterHolder[] {fh1});
864-
handler.setFilterMappings(new FilterMapping[] {fm1});
865-
handler.setServlets(new ServletHolder[] {sh1});
866-
handler.setServletMappings(new ServletMapping[] {sm1});
876+
handler.setFilters(new FilterHolder[] {fh6});
877+
handler.setFilterMappings(new FilterMapping[] {fm6});
878+
handler.setServlets(new ServletHolder[] {sh4});
879+
handler.setServletMappings(new ServletMapping[] {sm4});
867880

868881
server.start();
869882

883+
//emulate some listeners, servlets and filters added after the ServletHandler has started,
884+
//these cannot be durable
870885
handler.setListeners(new ListenerHolder[] {lh1, lh2});
871-
handler.setFilters(new FilterHolder[] {fh1, fh2});
872-
handler.setFilterMappings(new FilterMapping[] {fm1, fm2});
873-
handler.setServlets(new ServletHolder[] {sh1, sh2});
874-
handler.setServletMappings(new ServletMapping[] {sm1, sm2});
886+
handler.setFilters(new FilterHolder[] {fh6, fh7});
887+
handler.setFilterMappings(new FilterMapping[] {fm6, fm7});
888+
handler.setServlets(new ServletHolder[] {sh4, sh5});
889+
handler.setServletMappings(new ServletMapping[] {sm4, sm5});
875890

876891
assertThat(Arrays.asList(handler.getListeners()), contains(lh1, lh2));
877-
assertThat(Arrays.asList(handler.getFilters()), contains(fh1, fh2));
878-
assertThat(Arrays.asList(handler.getFilterMappings()), contains(fm1, fm2));
879-
assertThat(Arrays.asList(handler.getServlets()), contains(sh1, sh2));
880-
assertThat(Arrays.asList(handler.getServletMappings()), contains(sm1, sm2));
892+
assertThat(Arrays.asList(handler.getFilters()), contains(fh6, fh7));
893+
assertThat(Arrays.asList(handler.getFilterMappings()), contains(fm6, fm7));
894+
assertThat(Arrays.asList(handler.getServlets()), contains(sh4, sh5));
895+
assertThat(Arrays.asList(handler.getServletMappings()), contains(sm4, sm5));
881896

882897
server.stop();
883898

884899
assertThat(Arrays.asList(handler.getListeners()), contains(lh1));
885-
assertThat(Arrays.asList(handler.getFilters()), contains(fh1));
886-
assertThat(Arrays.asList(handler.getFilterMappings()), contains(fm1));
887-
assertThat(Arrays.asList(handler.getServlets()), contains(sh1));
888-
assertThat(Arrays.asList(handler.getServletMappings()), contains(sm1));
900+
assertThat(Arrays.asList(handler.getFilters()), contains(fh6));
901+
assertThat(Arrays.asList(handler.getFilterMappings()), contains(fm6));
902+
assertThat(Arrays.asList(handler.getServlets()), contains(sh4));
903+
assertThat(Arrays.asList(handler.getServletMappings()), contains(sm4));
904+
905+
server.start();
906+
907+
assertThat(handler.getListeners().length, is(1));
908+
assertThat(handler.getFilters().length, is(1));
909+
assertThat(handler.getFilterMappings().length, is(1));
910+
assertThat(handler.getServlets().length, is(1));
911+
assertThat(handler.getServletMappings().length, is(1));
889912
}
890913

891914
public static class HSListener implements HttpSessionListener

0 commit comments

Comments
 (0)