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-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org