Author: markt
Date: Tue Jan 9 21:50:44 2018
New Revision: 1820705
URL: http://svn.apache.org/viewvc?rev=1820705&view=rev
Log:
Prevent NullPointerException and other errors if the stock ticker example is
running when the examples web application is stopped.
Added:
tomcat/trunk/webapps/examples/WEB-INF/classes/async/AsyncStockContextListener.java
(with props)
Modified:
tomcat/trunk/webapps/docs/changelog.xml
tomcat/trunk/webapps/examples/WEB-INF/classes/async/AsyncStockServlet.java
tomcat/trunk/webapps/examples/WEB-INF/classes/async/Stockticker.java
tomcat/trunk/webapps/examples/WEB-INF/web.xml
Modified: tomcat/trunk/webapps/docs/changelog.xml
URL:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1820705&r1=1820704&r2=1820705&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Tue Jan 9 21:50:44 2018
@@ -183,6 +183,11 @@
application. (markt)
</fix>
<fix>
+ <bug>61886</bug>: Prevent <code>NullPointerException</code> and other
+ errors if the stock ticker example is running when the examples web
+ application is stopped. (markt)
+ </fix>
+ <fix>
<bug>61910</bug>: Clarify the meaning of the <code>allowLinking</code>
option in the documentation web application. (markt)
</fix>
Added:
tomcat/trunk/webapps/examples/WEB-INF/classes/async/AsyncStockContextListener.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/classes/async/AsyncStockContextListener.java?rev=1820705&view=auto
==============================================================================
---
tomcat/trunk/webapps/examples/WEB-INF/classes/async/AsyncStockContextListener.java
(added)
+++
tomcat/trunk/webapps/examples/WEB-INF/classes/async/AsyncStockContextListener.java
Tue Jan 9 21:50:44 2018
@@ -0,0 +1,44 @@
+/*
+ * 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 async;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+/*
+ * Ensures the Stockticker is shut down cleanly when the context stops. This
+ * also covers the case when the server shuts down.
+ */
+public class AsyncStockContextListener implements ServletContextListener {
+
+ public static final String STOCK_TICKER_KEY = "StockTicker";
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce) {
+ Stockticker stockticker = new Stockticker();
+ ServletContext sc = sce.getServletContext();
+ sc.setAttribute(STOCK_TICKER_KEY, stockticker);
+ }
+
+ @Override
+ public void contextDestroyed(ServletContextEvent sce) {
+ ServletContext sc = sce.getServletContext();
+ Stockticker stockticker = (Stockticker)
sc.getAttribute(STOCK_TICKER_KEY);
+ stockticker.shutdown();
+ }
+}
Propchange:
tomcat/trunk/webapps/examples/WEB-INF/classes/async/AsyncStockContextListener.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
tomcat/trunk/webapps/examples/WEB-INF/classes/async/AsyncStockServlet.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/classes/async/AsyncStockServlet.java?rev=1820705&r1=1820704&r2=1820705&view=diff
==============================================================================
--- tomcat/trunk/webapps/examples/WEB-INF/classes/async/AsyncStockServlet.java
(original)
+++ tomcat/trunk/webapps/examples/WEB-INF/classes/async/AsyncStockServlet.java
Tue Jan 9 21:50:44 2018
@@ -25,6 +25,7 @@ import java.util.concurrent.atomic.Atomi
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
+import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
@@ -45,7 +46,6 @@ public class AsyncStockServlet extends H
private static final ConcurrentLinkedQueue<AsyncContext> clients =
new ConcurrentLinkedQueue<>();
private static final AtomicInteger clientcount = new AtomicInteger(0);
- private static final Stockticker ticker = new Stockticker();
public AsyncStockServlet() {
log.info("AsyncStockServlet created");
@@ -63,6 +63,8 @@ public class AsyncStockServlet extends H
resp.setContentType("text/plain");
clients.add(actx);
if (clientcount.incrementAndGet()==1) {
+ Stockticker ticker = (Stockticker)
req.getServletContext().getAttribute(
+ AsyncStockContextListener.STOCK_TICKER_KEY);
ticker.addTickListener(this);
}
} else {
@@ -104,8 +106,27 @@ public class AsyncStockServlet extends H
@Override
+ public void shutdown() {
+ // The web application is shutting down. Complete any AsyncContexts
+ // associated with an active client.
+ Iterator<AsyncContext> it = clients.iterator();
+ while (it.hasNext()) {
+ AsyncContext actx = it.next();
+ try {
+ actx.complete();
+ } catch (Exception e) {
+ // Ignore. The async error handling will deal with this.
+ }
+ }
+ }
+
+
+ @Override
public void onComplete(AsyncEvent event) throws IOException {
if (clients.remove(event.getAsyncContext()) &&
clientcount.decrementAndGet()==0) {
+ ServletContext sc =
event.getAsyncContext().getRequest().getServletContext();
+ Stockticker ticker = (Stockticker) sc.getAttribute(
+ AsyncStockContextListener.STOCK_TICKER_KEY);
ticker.removeTickListener(this);
}
}
Modified: tomcat/trunk/webapps/examples/WEB-INF/classes/async/Stockticker.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/classes/async/Stockticker.java?rev=1820705&r1=1820704&r2=1820705&view=diff
==============================================================================
--- tomcat/trunk/webapps/examples/WEB-INF/classes/async/Stockticker.java
(original)
+++ tomcat/trunk/webapps/examples/WEB-INF/classes/async/Stockticker.java Tue
Jan 9 21:50:44 2018
@@ -37,6 +37,12 @@ public class Stockticker implements Runn
}
public synchronized void stop() {
+ // On context stop this can be called multiple times.
+ // NO-OP is the ticker thread is not set
+ // (i.e. stop() has already completed)
+ if (ticker == null) {
+ return;
+ }
run = false;
try {
ticker.join();
@@ -47,6 +53,17 @@ public class Stockticker implements Runn
ticker = null;
}
+ public void shutdown() {
+ // Notify each listener of the shutdown. This enables them to
+ // trigger any necessary clean-up.
+ for (TickListener l : listeners) {
+ l.shutdown();
+ }
+ // Wait for the thread to stop. This prevents warnings in the logs
+ // that the thread is still active when the context stops.
+ stop();
+ }
+
public void addTickListener(TickListener listener) {
if (listeners.add(listener)) {
if (counter.incrementAndGet()==1) start();
@@ -98,6 +115,7 @@ public class Stockticker implements Runn
public static interface TickListener {
public void tick(Stock stock);
+ public void shutdown();
}
public static final class Stock implements Cloneable {
Modified: tomcat/trunk/webapps/examples/WEB-INF/web.xml
URL:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/web.xml?rev=1820705&r1=1820704&r2=1820705&view=diff
==============================================================================
--- tomcat/trunk/webapps/examples/WEB-INF/web.xml (original)
+++ tomcat/trunk/webapps/examples/WEB-INF/web.xml Tue Jan 9 21:50:44 2018
@@ -95,6 +95,11 @@
<listener-class>listeners.SessionListener</listener-class>
</listener>
+ <!-- Define listeners required by examples -->
+ <listener>
+ <listener-class>async.AsyncStockContextListener</listener-class>
+ </listener>
+
<!-- Define servlets that are included in the example application -->
<servlet>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]