Issue #11039 duplicate durable listeners on maven restart (#11042)

This commit is contained in:
Jan Bartel 2023-12-13 05:24:21 +01:00 committed by GitHub
parent 90244c35d0
commit 4df28ebac8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 126 additions and 28 deletions

View File

@ -26,6 +26,7 @@ import org.eclipse.jetty.server.RequestLog;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ShutdownMonitor;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.resource.Resource;
@ -227,6 +228,12 @@ public class JettyEmbedder extends AbstractLifeCycle
{
if (!webApp.isStopped())
webApp.stop();
//clear the ServletHandler, which may have
//remembered "durable" Servlets, Filters, Listeners
//from the context xml file, but as we will re-apply
//the context xml, we should not retain them
webApp.setServletHandler(new ServletHandler());
//regenerate config properties
applyWebAppProperties();

View File

@ -0,0 +1,21 @@
//
// ========================================================================
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//
package org.eclipse.jetty.maven.plugin;
import java.util.EventListener;
public class SomeListener implements EventListener
{
}

View File

@ -21,6 +21,7 @@ import java.util.Map;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.servlet.ListenerHolder;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
@ -29,9 +30,12 @@ import org.eclipse.jetty.util.resource.Resource;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
@ExtendWith(WorkDirExtension.class)
public class TestJettyEmbedder
@ -117,6 +121,37 @@ public class TestJettyEmbedder
assertNotNull(contexts);
assertTrue(contexts.contains(otherHandler));
assertTrue(contexts.contains(webApp));
//stop the webapp and check durable listener retained
jetty.getWebApp().stop();
boolean someListener = false;
for (ListenerHolder h : webApp.getServletHandler().getListeners())
{
if (h.getHeldClass() != null && "org.eclipse.jetty.maven.plugin.SomeListener".equalsIgnoreCase(h.getHeldClass().getName()))
{
if (someListener)
fail("Duplicate listeners");
else
someListener = true;
}
}
//restart the webapp
jetty.redeployWebApp();
someListener = false;
//ensure still only 1 listener
for (ListenerHolder h : webApp.getServletHandler().getListeners())
{
if (h.getHeldClass() != null && "org.eclipse.jetty.maven.plugin.SomeListener".equalsIgnoreCase(h.getHeldClass().getName()))
{
if (someListener)
fail("Duplicate listeners");
else
someListener = true;
}
}
}
finally
{

View File

@ -3,4 +3,16 @@
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/embedder</Set>
<Get name="servletHandler">
<Call name="addListener">
<Arg>
<New class="org.eclipse.jetty.servlet.ListenerHolder">
<Set name="listener">
<New class="org.eclipse.jetty.maven.plugin.SomeListener"/>
</Set>
</New>
</Arg>
</Call>
</Get>
</Configure>

View File

@ -64,6 +64,12 @@ public class ServletHandlerTest
FilterHolder fh5 = new FilterHolder(Source.JAVAX_API);
FilterMapping fm5 = new FilterMapping();
FilterHolder fh6 = new FilterHolder(Source.EMBEDDED);
FilterMapping fm6 = new FilterMapping();
FilterHolder fh7 = new FilterHolder(Source.EMBEDDED);
FilterMapping fm7 = new FilterMapping();
ServletHolder sh1 = new ServletHolder(new Source(Source.Origin.DESCRIPTOR, "foo.xml"));
ServletMapping sm1 = new ServletMapping();
@ -73,6 +79,12 @@ public class ServletHandlerTest
ServletHolder sh3 = new ServletHolder(new Source(Source.Origin.DESCRIPTOR, "foo.xml"));
ServletMapping sm3 = new ServletMapping();
ServletHolder sh4 = new ServletHolder(Source.EMBEDDED);
ServletMapping sm4 = new ServletMapping();
ServletHolder sh5 = new ServletHolder(Source.EMBEDDED);
ServletMapping sm5 = new ServletMapping();
@BeforeEach
public void initMappings()
{
@ -842,50 +854,61 @@ public class ServletHandlerTest
ServletContextHandler context = new ServletContextHandler();
server.setHandler(context);
ServletHandler handler = new ServletHandler();
handler.setEnsureDefaultServlet(false);
context.setHandler(handler);
ListenerHolder lh1 = new ListenerHolder(HSListener.class);
ListenerHolder lh2 = new ListenerHolder(SCListener.class);
fh1.setFilter(new SomeFilter());
fm1.setPathSpec("/sm1");
fm1.setFilterHolder(fh1);
fh2.setFilter(new SomeFilter(){});
fm2.setPathSpec("/sm2");
fm2.setFilterHolder(fh2);
sh1.setServlet(new SomeServlet());
sm1.setPathSpec("/sm1");
sm1.setServletName(sh1.getName());
sh2.setServlet(new SomeServlet());
sm2.setPathSpec("/sm2");
sm2.setServletName(sh2.getName());
fh6.setFilter(new SomeFilter());
fm6.setPathSpec("/sm4");
fm6.setFilterHolder(fh6);
fh7.setFilter(new SomeFilter(){});
fm7.setPathSpec("/sm5");
fm7.setFilterHolder(fh7);
sh4.setServlet(new SomeServlet());
sm4.setPathSpec("/sm4");
sm4.setServletName(sh4.getName());
sh5.setServlet(new SomeServlet());
sm5.setPathSpec("/sm5");
sm5.setServletName(sh5.getName());
handler.setListeners(new ListenerHolder[] {lh1});
handler.setFilters(new FilterHolder[] {fh1});
handler.setFilterMappings(new FilterMapping[] {fm1});
handler.setServlets(new ServletHolder[] {sh1});
handler.setServletMappings(new ServletMapping[] {sm1});
handler.setFilters(new FilterHolder[] {fh6});
handler.setFilterMappings(new FilterMapping[] {fm6});
handler.setServlets(new ServletHolder[] {sh4});
handler.setServletMappings(new ServletMapping[] {sm4});
server.start();
//emulate some listeners, servlets and filters added after the ServletHandler has started,
//these cannot be durable
handler.setListeners(new ListenerHolder[] {lh1, lh2});
handler.setFilters(new FilterHolder[] {fh1, fh2});
handler.setFilterMappings(new FilterMapping[] {fm1, fm2});
handler.setServlets(new ServletHolder[] {sh1, sh2});
handler.setServletMappings(new ServletMapping[] {sm1, sm2});
handler.setFilters(new FilterHolder[] {fh6, fh7});
handler.setFilterMappings(new FilterMapping[] {fm6, fm7});
handler.setServlets(new ServletHolder[] {sh4, sh5});
handler.setServletMappings(new ServletMapping[] {sm4, sm5});
assertThat(Arrays.asList(handler.getListeners()), contains(lh1, lh2));
assertThat(Arrays.asList(handler.getFilters()), contains(fh1, fh2));
assertThat(Arrays.asList(handler.getFilterMappings()), contains(fm1, fm2));
assertThat(Arrays.asList(handler.getServlets()), contains(sh1, sh2));
assertThat(Arrays.asList(handler.getServletMappings()), contains(sm1, sm2));
assertThat(Arrays.asList(handler.getFilters()), contains(fh6, fh7));
assertThat(Arrays.asList(handler.getFilterMappings()), contains(fm6, fm7));
assertThat(Arrays.asList(handler.getServlets()), contains(sh4, sh5));
assertThat(Arrays.asList(handler.getServletMappings()), contains(sm4, sm5));
server.stop();
assertThat(Arrays.asList(handler.getListeners()), contains(lh1));
assertThat(Arrays.asList(handler.getFilters()), contains(fh1));
assertThat(Arrays.asList(handler.getFilterMappings()), contains(fm1));
assertThat(Arrays.asList(handler.getServlets()), contains(sh1));
assertThat(Arrays.asList(handler.getServletMappings()), contains(sm1));
assertThat(Arrays.asList(handler.getFilters()), contains(fh6));
assertThat(Arrays.asList(handler.getFilterMappings()), contains(fm6));
assertThat(Arrays.asList(handler.getServlets()), contains(sh4));
assertThat(Arrays.asList(handler.getServletMappings()), contains(sm4));
server.start();
assertThat(handler.getListeners().length, is(1));
assertThat(handler.getFilters().length, is(1));
assertThat(handler.getFilterMappings().length, is(1));
assertThat(handler.getServlets().length, is(1));
assertThat(handler.getServletMappings().length, is(1));
}
public static class HSListener implements HttpSessionListener