Author: slaurent
Date: Sun May 18 21:16:42 2014
New Revision: 1595690

URL: http://svn.apache.org/r1595690
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=56461
New option to make context startup fail if a load-on-startup servlet fails

Modified:
    tomcat/trunk/java/org/apache/catalina/core/StandardContext.java
    tomcat/trunk/java/org/apache/catalina/core/StandardHost.java
    tomcat/trunk/test/org/apache/catalina/core/TestStandardContext.java
    tomcat/trunk/webapps/docs/changelog.xml
    tomcat/trunk/webapps/docs/config/context.xml
    tomcat/trunk/webapps/docs/config/host.xml

Modified: tomcat/trunk/java/org/apache/catalina/core/StandardContext.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardContext.java?rev=1595690&r1=1595689&r2=1595690&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardContext.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardContext.java Sun May 18 
21:16:42 2014
@@ -810,6 +810,8 @@ public class StandardContext extends Con
 
     private String containerSciFilter;
 
+    private Boolean failCtxIfServletStartFails;
+
     protected static final ThreadBindingListener DEFAULT_NAMING_LISTENER = 
(new ThreadBindingListener() {
         @Override
         public void bind() {}
@@ -2627,8 +2629,32 @@ public class StandardContext extends Con
                 this.renewThreadsWhenStoppingContext);
     }
 
-    // -------------------------------------------------------- Context Methods
+    public Boolean getFailCtxIfServletStartFails() {
+        return failCtxIfServletStartFails;
+    }
+
+    public void setFailCtxIfServletStartFails(
+            Boolean failCtxIfServletStartFails) {
+        Boolean oldFailCtxIfServletStartFails = 
this.failCtxIfServletStartFails;
+        this.failCtxIfServletStartFails = failCtxIfServletStartFails;
+        support.firePropertyChange("failCtxIfServletStartFails",
+                oldFailCtxIfServletStartFails,
+                failCtxIfServletStartFails);
+    }
+
+    protected boolean getComputedFailCtxIfServletStartFails() {
+        if(failCtxIfServletStartFails != null) {
+            return failCtxIfServletStartFails.booleanValue();
+        }
+        //else look at Host config
+        if(getParent() instanceof StandardHost) {
+            return ((StandardHost)getParent()).isFailCtxIfServletStartFails();
+        }
+        //else
+        return false;
+    }
 
+    // -------------------------------------------------------- Context Methods
 
     /**
      * Add a new Listener class name to the set of Listeners
@@ -4897,7 +4923,7 @@ public class StandardContext extends Con
      * @param children Array of wrappers for all currently defined
      *  servlets (including those not declared load on startup)
      */
-    public void loadOnStartup(Container children[]) {
+    public boolean loadOnStartup(Container children[]) {
 
         // Collect "load on startup" servlets that need to be initialized
         TreeMap<Integer, ArrayList<Wrapper>> map = new TreeMap<>();
@@ -4925,10 +4951,14 @@ public class StandardContext extends Con
                                       getName()), 
StandardWrapper.getRootCause(e));
                     // NOTE: load errors (including a servlet that throws
                     // UnavailableException from tht init() method) are NOT
-                    // fatal to application startup
+                    // fatal to application startup, excepted if 
failDeploymentIfServletLoadedOnStartupFails is specified
+                    if(getComputedFailCtxIfServletStartFails()) {
+                        return false;
+                    }
                 }
             }
         }
+        return true;
 
     }
 
@@ -5201,7 +5231,10 @@ public class StandardContext extends Con
 
             // Load and initialize all "load on startup" servlets
             if (ok) {
-                loadOnStartup(findChildren());
+                if (!loadOnStartup(findChildren())){
+                    log.error("Error loadOnStartup");
+                    ok = false;
+                }
             }
 
             // Start ContainerBackgroundProcessor thread

Modified: tomcat/trunk/java/org/apache/catalina/core/StandardHost.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardHost.java?rev=1595690&r1=1595689&r2=1595690&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardHost.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardHost.java Sun May 18 
21:16:42 2014
@@ -182,6 +182,8 @@ public class StandardHost extends Contai
 
     private boolean undeployOldVersions = false;
 
+    private boolean failCtxIfServletStartFails = false;
+
 
     // ------------------------------------------------------------- Properties
 
@@ -648,6 +650,21 @@ public class StandardHost extends Contai
     }
 
 
+    public boolean isFailCtxIfServletStartFails() {
+        return failCtxIfServletStartFails;
+    }
+
+
+    public void setFailCtxIfServletStartFails(
+            boolean failCtxIfServletStartFails) {
+        boolean oldFailCtxIfServletStartFails = 
this.failCtxIfServletStartFails;
+        this.failCtxIfServletStartFails = failCtxIfServletStartFails;
+        support.firePropertyChange("failCtxIfServletStartFails",
+                oldFailCtxIfServletStartFails,
+                failCtxIfServletStartFails);
+    }
+
+
     // --------------------------------------------------------- Public Methods
 
 

Modified: tomcat/trunk/test/org/apache/catalina/core/TestStandardContext.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/core/TestStandardContext.java?rev=1595690&r1=1595689&r2=1595690&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/core/TestStandardContext.java 
(original)
+++ tomcat/trunk/test/org/apache/catalina/core/TestStandardContext.java Sun May 
18 21:16:42 2014
@@ -43,6 +43,7 @@ import javax.servlet.http.HttpServletReq
 import javax.servlet.http.HttpServletResponse;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -878,6 +879,58 @@ public class TestStandardContext extends
     }
 
     @Test
+    public void testFlagFailCtxIfServletStartFails() throws Exception {
+        Tomcat tomcat = getTomcatInstance();
+        File docBase = new File(System.getProperty("java.io.tmpdir"));
+        StandardContext context = (StandardContext) tomcat.addContext("",
+                docBase.getAbsolutePath());
+
+        // first we test the flag itself, which can be set on the Host and
+        // Context
+        assertFalse(context.getComputedFailCtxIfServletStartFails());
+
+        StandardHost host = (StandardHost) tomcat.getHost();
+        host.setFailCtxIfServletStartFails(true);
+        assertTrue(context.getComputedFailCtxIfServletStartFails());
+        context.setFailCtxIfServletStartFails(Boolean.FALSE);
+        assertFalse("flag on Context should override Host config",
+                context.getComputedFailCtxIfServletStartFails());
+
+        // second, we test the actual effect of the flag on the startup
+        Wrapper servlet = Tomcat.addServlet(context, "myservlet",
+                new FailingStartupServlet());
+        servlet.setLoadOnStartup(1);
+
+        tomcat.start();
+        assertTrue("flag false should not fail deployment", context.getState()
+                .isAvailable());
+
+        tomcat.stop();
+        assertFalse(context.getState().isAvailable());
+
+        host.removeChild(context);
+        context = (StandardContext) tomcat.addContext("",
+                docBase.getAbsolutePath());
+        servlet = Tomcat.addServlet(context, "myservlet",
+                new FailingStartupServlet());
+        servlet.setLoadOnStartup(1);
+        tomcat.start();
+        assertFalse("flag true should fail deployment", context.getState()
+                .isAvailable());
+    }
+
+    private class FailingStartupServlet extends HttpServlet {
+
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public void init() throws ServletException {
+            throw new ServletException("failing on purpose");
+        }
+
+    }
+
+    @Test
     public void testBug56085() throws Exception {
         // Set up a container
         Tomcat tomcat = getTomcatInstance();

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1595690&r1=1595689&r2=1595690&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Sun May 18 21:16:42 2014
@@ -52,6 +52,11 @@
         optionally interrupt stuck threads to attempt to unblock them.
         (slaurent)
       </add>
+      <add>
+        <bug>56461</bug>: New <code>failCtxIfServletStartFails</code> attribute
+        on Context and Host configuration to force the context startup to fail
+        if a load-on-startup servlet fails its startup. (slaurent)
+      </add>
     </changelog>
   </subsection>
 </section>

Modified: tomcat/trunk/webapps/docs/config/context.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/context.xml?rev=1595690&r1=1595689&r2=1595690&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/context.xml (original)
+++ tomcat/trunk/webapps/docs/config/context.xml Sun May 18 21:16:42 2014
@@ -334,6 +334,14 @@
         sufficient.</p>
       </attribute>
 
+      <attribute name="failCtxIfServletStartFails" required="false">
+        <p>Set to <code>true</code> to have the context fail its startup if any
+        servlet that has load-on-startup &gt;=0 fails its own startup.</p>
+        <p>If not specified, the attribute of the same name in the parent Host
+        configuration is used if specified. Otherwise the default value of
+        <code>false</code> is used.</p>
+      </attribute>
+
       <attribute name="fireRequestListenersOnForwards" required="false">
         <p>Set to <code>true</code> to fire any configured
         ServletRequestListeners  when Tomcat forwards a request. This is

Modified: tomcat/trunk/webapps/docs/config/host.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/host.xml?rev=1595690&r1=1595689&r2=1595690&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/host.xml (original)
+++ tomcat/trunk/webapps/docs/config/host.xml Sun May 18 21:16:42 2014
@@ -175,6 +175,15 @@
         Deployment</a> for more information.</p>
       </attribute>
 
+      <attribute name="failCtxIfServletStartFails" required="false">
+        <p>Set to <code>true</code> to have each child contexts fail its 
startup
+        if any of its servlet that has load-on-startup &gt;=0 fails its own
+        startup.</p>
+        <p>Each child context may override this attribute.</p>
+        <p>If not specified, the default value of <code>false</code> is
+        used.</p>
+      </attribute>
+
       <attribute name="name" required="true">
         <p>Usually the network name of this virtual host, as registered in your
         <em>Domain Name Service</em> server. Regardless of the case used to



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

Reply via email to