You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2011/06/30 13:58:36 UTC

svn commit: r1141495 - in /tomcat/trunk: java/org/apache/catalina/startup/Tomcat.java test/org/apache/catalina/core/TestStandardWrapper.java webapps/docs/changelog.xml

Author: markt
Date: Thu Jun 30 11:58:36 2011
New Revision: 1141495

URL: http://svn.apache.org/viewvc?rev=1141495&view=rev
Log:
Improve the handling for Servlets that implement the deprecated SingleThreadModel when embedding Tomcat.

Modified:
    tomcat/trunk/java/org/apache/catalina/startup/Tomcat.java
    tomcat/trunk/test/org/apache/catalina/core/TestStandardWrapper.java
    tomcat/trunk/webapps/docs/changelog.xml

Modified: tomcat/trunk/java/org/apache/catalina/startup/Tomcat.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/Tomcat.java?rev=1141495&r1=1141494&r2=1141495&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/Tomcat.java (original)
+++ tomcat/trunk/java/org/apache/catalina/startup/Tomcat.java Thu Jun 30 11:58:36 2011
@@ -23,6 +23,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Stack;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -812,18 +813,35 @@ public class Tomcat {
     public static class ExistingStandardWrapper extends StandardWrapper {
         private Servlet existing;
         boolean init = false;
-        
+
+        @SuppressWarnings("deprecation")
         public ExistingStandardWrapper( Servlet existing ) {
             this.existing = existing;
+            if (existing instanceof javax.servlet.SingleThreadModel) {
+                singleThreadModel = true;
+                instancePool = new Stack<Servlet>();
+            }
         }
         @Override
         public synchronized Servlet loadServlet() throws ServletException {
-            if (!init) {
-                existing.init(facade);
-                init = true;
+            if (singleThreadModel) {
+                Servlet instance;
+                try {
+                    instance = existing.getClass().newInstance();
+                } catch (InstantiationException e) {
+                    throw new ServletException(e);
+                } catch (IllegalAccessException e) {
+                    throw new ServletException(e);
+                }
+                instance.init(facade);
+                return instance;
+            } else {
+                if (!init) {
+                    existing.init(facade);
+                    init = true;
+                }
+                return existing;
             }
-            return existing;
-
         }
         @Override
         public long getAvailable() {

Modified: tomcat/trunk/test/org/apache/catalina/core/TestStandardWrapper.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/core/TestStandardWrapper.java?rev=1141495&r1=1141494&r2=1141495&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/core/TestStandardWrapper.java (original)
+++ tomcat/trunk/test/org/apache/catalina/core/TestStandardWrapper.java Thu Jun 30 11:58:36 2011
@@ -21,9 +21,11 @@ import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.CountDownLatch;
 
 import javax.servlet.Servlet;
 import javax.servlet.ServletConfig;
@@ -329,6 +331,8 @@ public class TestStandardWrapper extends
     }
 
 
+    public static final int BUG51445_THREAD_COUNT = 5;
+
     public void testBug51445() throws Exception {
         Tomcat tomcat = getTomcatInstance();
 
@@ -341,29 +345,85 @@ public class TestStandardWrapper extends
         
         tomcat.start();
 
-        ByteChunk res = getUrl("http://localhost:" + getPort() + "/");
+        // Start the threads
+        Bug51445Thread[] threads = new Bug51445Thread[5];
+        for (int i = 0; i < BUG51445_THREAD_COUNT; i ++) {
+            threads[i] = new Bug51445Thread(getPort());
+            threads[i].start();
+        }
+
+        // Wait for threads to finish
+        for (int i = 0; i < BUG51445_THREAD_COUNT; i ++) {
+            threads[i].join();
+        }
+
+        Set<String> servlets = new HashSet<String>();
+        // Check the result
+        for (int i = 0; i < BUG51445_THREAD_COUNT; i ++) {
+            String[] results = threads[i].getResult().split(",");
+            assertEquals(2, results.length);
+            assertEquals("10", results[0]);
+            System.out.println(results[1]);
+            assertFalse(servlets.contains(results[1]));
+            servlets.add(results[1]);
+        }
 
-        assertEquals("10", res.toString());
     }
 
+    private static class Bug51445Thread extends Thread {
+
+        private int port;
+        private String result;
+
+        public Bug51445Thread(int port) {
+            this.port = port;
+        }
+
+        @Override
+        public void run() {
+            try {
+                ByteChunk res = getUrl("http://localhost:" + port + "/");
+                result = res.toString();
+            } catch (IOException ioe) {
+                result = ioe.getMessage();
+            }
+        }
+
+        public String getResult() {
+            return result;
+        }
+    }
 
     /**
      * SingleThreadModel servlet that sets a value in the init() method.
      */
     @SuppressWarnings("deprecation")
-    private static class Bug51445Servlet extends HttpServlet
+    public static class Bug51445Servlet extends HttpServlet
             implements javax.servlet.SingleThreadModel {
 
         private static final long serialVersionUID = 1L;
 
+        private static final CountDownLatch latch =
+            new CountDownLatch(BUG51445_THREAD_COUNT);
+
         private int data = 0;
 
         @Override
         protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                 throws ServletException, IOException {
-            
+
+            // Ensure all threads have their own instance of the servlet
+            latch.countDown();
+            try {
+                latch.await();
+            } catch (InterruptedException e) {
+                // Ignore
+            }
+
             resp.setContentType("text/plain");
             resp.getWriter().print(data);
+            resp.getWriter().print(",");
+            resp.getWriter().print(hashCode());
         }
 
         @Override

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1141495&r1=1141494&r2=1141495&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Thu Jun 30 11:58:36 2011
@@ -172,6 +172,10 @@
         the target Servlet does not call startAsync() or complete() that Tomcat
         calls complete() once the target Servlet exits. (markt)
       </fix>
+      <fix>
+        Improve the handling for Servlets that implement the deprecated
+        SingleThreadModel when embedding Tomcat. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org