### Eclipse Workspace Patch 1.0
#P tomcat-8.0.x
diff --git java/org/apache/catalina/core/StandardContext.java java/org/apache/catalina/core/StandardContext.java
index 91f5699..6fb38d7 100644
--- java/org/apache/catalina/core/StandardContext.java
+++ java/org/apache/catalina/core/StandardContext.java
@@ -810,6 +810,8 @@
private String containerSciFilter;
+ private Boolean failDeploymentIfServletLoadedOnStartupFails;
+
protected static final ThreadBindingListener DEFAULT_NAMING_LISTENER = (new ThreadBindingListener() {
@Override
public void bind() {}
@@ -2618,8 +2620,32 @@
this.renewThreadsWhenStoppingContext);
}
- // -------------------------------------------------------- Context Methods
+ public Boolean isFailDeploymentIfServletLoadedOnStartupFails() {
+ return failDeploymentIfServletLoadedOnStartupFails;
+ }
+ public void setFailDeploymentIfServletLoadedOnStartupFails(
+ Boolean failDeploymentIfServletLoadedOnStartupFails) {
+ Boolean oldFailDeploymentIfServletLoadedOnStartupFails = this.failDeploymentIfServletLoadedOnStartupFails;
+ this.failDeploymentIfServletLoadedOnStartupFails = failDeploymentIfServletLoadedOnStartupFails;
+ support.firePropertyChange("failDeploymentIfServletLoadedOnStartupFails",
+ oldFailDeploymentIfServletLoadedOnStartupFails,
+ failDeploymentIfServletLoadedOnStartupFails);
+ }
+
+ protected boolean getComputedIsFailDeploymentIfServletLoadedOnStartupFails() {
+ if(failDeploymentIfServletLoadedOnStartupFails != null) {
+ return failDeploymentIfServletLoadedOnStartupFails.booleanValue();
+ }
+ //else look at Host config
+ if(getParent() instanceof StandardHost) {
+ return ((StandardHost)getParent()).isFailDeploymentIfServletLoadedOnStartupFails();
+ }
+ //else
+ return false;
+ }
+
+ // -------------------------------------------------------- Context Methods
/**
* Add a new Listener class name to the set of Listeners
@@ -4888,7 +4914,7 @@
* @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> map = new TreeMap<>();
@@ -4916,10 +4942,14 @@
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(getComputedIsFailDeploymentIfServletLoadedOnStartupFails()) {
+ return false;
+ }
}
}
}
+ return true;
}
@@ -5192,7 +5222,10 @@
// Load and initialize all "load on startup" servlets
if (ok) {
- loadOnStartup(findChildren());
+ if (!loadOnStartup(findChildren())){
+ log.error("Error loadOnStartup");
+ ok = false;
+ }
}
// Start ContainerBackgroundProcessor thread
diff --git java/org/apache/catalina/core/StandardHost.java java/org/apache/catalina/core/StandardHost.java
index 5b6b746..5ef14c2 100644
--- java/org/apache/catalina/core/StandardHost.java
+++ java/org/apache/catalina/core/StandardHost.java
@@ -182,6 +182,8 @@
private boolean undeployOldVersions = false;
+ private boolean failDeploymentIfServletLoadedOnStartupFails = false;
+
// ------------------------------------------------------------- Properties
@@ -648,6 +650,21 @@
}
+ public boolean isFailDeploymentIfServletLoadedOnStartupFails() {
+ return failDeploymentIfServletLoadedOnStartupFails;
+ }
+
+
+ public void setFailDeploymentIfServletLoadedOnStartupFails(
+ boolean failDeploymentIfServletLoadedOnStartupFails) {
+ boolean oldFailDeploymentIfServletLoadedOnStartupFails = this.failDeploymentIfServletLoadedOnStartupFails;
+ this.failDeploymentIfServletLoadedOnStartupFails = failDeploymentIfServletLoadedOnStartupFails;
+ support.firePropertyChange("failDeploymentIfServletLoadedOnStartupFails",
+ oldFailDeploymentIfServletLoadedOnStartupFails,
+ failDeploymentIfServletLoadedOnStartupFails);
+ }
+
+
// --------------------------------------------------------- Public Methods
diff --git test/org/apache/catalina/core/TestStandardContext.java test/org/apache/catalina/core/TestStandardContext.java
index 683258e..e2569b7 100644
--- test/org/apache/catalina/core/TestStandardContext.java
+++ test/org/apache/catalina/core/TestStandardContext.java
@@ -43,6 +43,7 @@
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,63 @@
}
@Test
+ public void testFlagFailDeploymentIfServletLoadedOnStartupFails()
+ 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
+ .getComputedIsFailDeploymentIfServletLoadedOnStartupFails());
+
+ StandardHost host = (StandardHost) tomcat.getHost();
+ host.setFailDeploymentIfServletLoadedOnStartupFails(true);
+ assertTrue(context
+ .getComputedIsFailDeploymentIfServletLoadedOnStartupFails());
+ context.setFailDeploymentIfServletLoadedOnStartupFails(Boolean.FALSE);
+ assertFalse(
+ "flag on Context should override Host config",
+ context.getComputedIsFailDeploymentIfServletLoadedOnStartupFails());
+
+ // 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());
+ //context.setFailDeploymentIfServletLoadedOnStartupFails(Boolean.FALSE);
+ 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();
diff --git webapps/docs/changelog.xml webapps/docs/changelog.xml
index 55cf452..7b3c0d4 100644
--- webapps/docs/changelog.xml
+++ webapps/docs/changelog.xml
@@ -146,6 +146,11 @@
problem is encountered calling a getter or setter on a component
attribute from debug to warning. (markt)
+
+ New failDeploymentIfServletLoadedOnStartupFails
attribute
+ on Context and Host configuration to force the context startup to fail
+ if a load-on-startup servlet fails its startup. (slaurent)
+
diff --git webapps/docs/config/context.xml webapps/docs/config/context.xml
index e8067a5..1f1f08f 100644
--- webapps/docs/config/context.xml
+++ webapps/docs/config/context.xml
@@ -334,6 +334,14 @@
sufficient.
+
+ Set to true
to have the context fail its startup if any
+ servlet that has load-on-startup >=0 fails its own startup.
+ If not specified, the attribute of the same name in the parent Host
+ configuration is used if specified. Otherwise the default value of
+ false
is used.
+
+
Set to true
to fire any configured
ServletRequestListeners when Tomcat forwards a request. This is
diff --git webapps/docs/config/host.xml webapps/docs/config/host.xml
index 5154f87..fb6f238 100644
--- webapps/docs/config/host.xml
+++ webapps/docs/config/host.xml
@@ -175,6 +175,15 @@
Deployment for more information.
+
+ Set to true
to have each child contexts fail its startup
+ if any of its servlet that has load-on-startup >=0 fails its own
+ startup.
+ Each child context may override this attribute.
+ If not specified, the default value of false
is
+ used.
+
+
Usually the network name of this virtual host, as registered in your
Domain Name Service server. Regardless of the case used to