Author: kkolinko
Date: Mon Jul 14 23:57:35 2014
New Revision: 1610562
URL: http://svn.apache.org/r1610562
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=56717
Fix duplicate registration of MapperListener during repeated starts of embedded
Tomcat.
Properly unregister it when Tomcat stops.
Added:
tomcat/trunk/test/org/apache/catalina/mapper/TestMapperListener.java
(with props)
Modified:
tomcat/trunk/java/org/apache/catalina/mapper/MapperListener.java
tomcat/trunk/webapps/docs/changelog.xml
Modified: tomcat/trunk/java/org/apache/catalina/mapper/MapperListener.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/mapper/MapperListener.java?rev=1610562&r1=1610561&r2=1610562&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/mapper/MapperListener.java (original)
+++ tomcat/trunk/java/org/apache/catalina/mapper/MapperListener.java Mon Jul 14
23:57:35 2014
@@ -116,6 +116,9 @@ public class MapperListener extends Life
@Override
public void stopInternal() throws LifecycleException {
setState(LifecycleState.STOPPING);
+
+ Engine engine = (Engine) service.getContainer();
+ removeListeners(engine);
}
Added: tomcat/trunk/test/org/apache/catalina/mapper/TestMapperListener.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/mapper/TestMapperListener.java?rev=1610562&view=auto
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/mapper/TestMapperListener.java (added)
+++ tomcat/trunk/test/org/apache/catalina/mapper/TestMapperListener.java Mon
Jul 14 23:57:35 2014
@@ -0,0 +1,128 @@
+/*
+ * 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 org.apache.catalina.mapper;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.catalina.Container;
+import org.apache.catalina.ContainerListener;
+import org.apache.catalina.Context;
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.LifecycleListener;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.catalina.startup.TomcatBaseTest;
+import org.apache.tomcat.util.buf.ByteChunk;
+import org.apache.tomcat.websocket.server.WsContextListener;
+
+public class TestMapperListener extends TomcatBaseTest {
+
+ @Test
+ public void testTomcatRestartListenerCount_Bug56717() throws IOException,
+ LifecycleException {
+ // The test runs Tomcat twice, tests that it has started successfully,
+ // and compares the counts of listeners registered on containers
+ // after the first and the second starts.
+ // Sample request is from TestTomcat#testSingleWebapp()
+
+ Tomcat tomcat = getTomcatInstance();
+
+ File appDir = new File(getBuildDirectory(), "webapps/examples");
+ // app dir is relative to server home
+ Context ctxt = tomcat.addWebapp(null, "/examples",
+ appDir.getAbsolutePath());
+ ctxt.addApplicationListener(WsContextListener.class.getName());
+ tomcat.start();
+
+ ByteChunk res;
+ String text;
+ res = getUrl("http://localhost:" + getPort()
+ + "/examples/servlets/servlet/HelloWorldExample");
+ text = res.toString();
+ Assert.assertTrue(text, text.contains("<h1>Hello World!</h1>"));
+
+ List<ListenersInfo> listenersFirst = new ArrayList<>();
+ populateListenersInfo(listenersFirst, tomcat.getEngine());
+
+ tomcat.stop();
+ tomcat.start();
+
+ res = getUrl("http://localhost:" + getPort()
+ + "/examples/servlets/servlet/HelloWorldExample");
+ text = res.toString();
+ Assert.assertTrue(text, text.contains("<h1>Hello World!</h1>"));
+
+ List<ListenersInfo> listenersSecond = new ArrayList<>();
+ populateListenersInfo(listenersSecond, tomcat.getEngine());
+
+ Assert.assertEquals(listenersFirst.size(), listenersSecond.size());
+ for (int i = 0, len = listenersFirst.size(); i < len; i++) {
+ ListenersInfo a = listenersFirst.get(i);
+ ListenersInfo b = listenersSecond.get(i);
+ boolean equal = a.container.getClass() == b.container.getClass()
+ && a.containerListeners.length ==
b.containerListeners.length
+ && a.lifecycleListeners.length ==
b.lifecycleListeners.length;
+ if (!equal) {
+ Assert.fail("The lists of listeners differ:\n" + a + "\n" + b);
+ }
+ }
+ }
+
+ private static class ListenersInfo {
+ public final Container container;
+ public final ContainerListener[] containerListeners;
+ public final LifecycleListener[] lifecycleListeners;
+
+ public ListenersInfo(Container container,
+ ContainerListener[] containerListeners,
+ LifecycleListener[] lifecycleListeners) {
+ this.container = container;
+ this.containerListeners = containerListeners;
+ this.lifecycleListeners = lifecycleListeners;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append("[container: \"").append(container)
+ .append("\"\n containerListeners.length: ")
+ .append(containerListeners.length)
+ .append(", lifecycleListeners.length: ")
+ .append(lifecycleListeners.length)
+ .append("\n containerListeners: ")
+ .append(Arrays.asList(containerListeners))
+ .append("\n lifecycleListeners: ")
+ .append(Arrays.asList(lifecycleListeners)).append("\n]");
+ return buf.toString();
+ }
+ }
+
+ private static void populateListenersInfo(List<ListenersInfo> list,
+ Container container) {
+ list.add(new ListenersInfo(container, container
+ .findContainerListeners(),
container.findLifecycleListeners()));
+ for (Container child : container.findChildren()) {
+ populateListenersInfo(list, child);
+ }
+ }
+}
Propchange: tomcat/trunk/test/org/apache/catalina/mapper/TestMapperListener.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: tomcat/trunk/webapps/docs/changelog.xml
URL:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1610562&r1=1610561&r2=1610562&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Mon Jul 14 23:57:35 2014
@@ -59,6 +59,11 @@
<bug>56712</bug>: Fix session idle time calculations in
<code>PersistenceManager</code>. (kkolinko)
</fix>
+ <fix>
+ <bug>56717</bug>: Fix duplicate registration of
+ <code>MapperListener</code> during repeated starts of embedded Tomcat.
+ (kkolinko)
+ </fix>
</changelog>
</subsection>
<subsection name="Coyote">
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]