Catch application exception in tomcat starter thread and rethrow

Fixes gh-1088
pull/1118/head
Dave Syer 11 years ago
parent 6c4d9d7190
commit d842446186

@ -16,12 +16,12 @@
package org.springframework.boot.context.embedded.tomcat; package org.springframework.boot.context.embedded.tomcat;
import javax.servlet.ServletException;
import org.apache.catalina.Lifecycle; import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent; import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener; import org.apache.catalina.LifecycleListener;
import org.apache.catalina.core.StandardContext; import org.apache.catalina.core.StandardContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.context.embedded.ServletContextInitializer; import org.springframework.boot.context.embedded.ServletContextInitializer;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -29,10 +29,15 @@ import org.springframework.util.Assert;
* Tomcat {@link LifecycleListener} that calls {@link ServletContextInitializer}s. * Tomcat {@link LifecycleListener} that calls {@link ServletContextInitializer}s.
* *
* @author Phillip Webb * @author Phillip Webb
* @author Dave Syer
*/ */
public class ServletContextInitializerLifecycleListener implements LifecycleListener { public class ServletContextInitializerLifecycleListener implements LifecycleListener {
private static Log logger = LogFactory
.getLog(ServletContextInitializerLifecycleListener.class);
private final ServletContextInitializer[] initializers; private final ServletContextInitializer[] initializers;
private Exception startUpException;
/** /**
* Create a new {@link ServletContextInitializerLifecycleListener} instance with the * Create a new {@link ServletContextInitializerLifecycleListener} instance with the
@ -44,6 +49,10 @@ public class ServletContextInitializerLifecycleListener implements LifecycleList
this.initializers = initializers; this.initializers = initializers;
} }
public Exception getStartUpException() {
return this.startUpException;
}
@Override @Override
public void lifecycleEvent(LifecycleEvent event) { public void lifecycleEvent(LifecycleEvent event) {
if (Lifecycle.CONFIGURE_START_EVENT.equals(event.getType())) { if (Lifecycle.CONFIGURE_START_EVENT.equals(event.getType())) {
@ -53,8 +62,13 @@ public class ServletContextInitializerLifecycleListener implements LifecycleList
try { try {
initializer.onStartup(standardContext.getServletContext()); initializer.onStartup(standardContext.getServletContext());
} }
catch (ServletException ex) { catch (Exception ex) {
throw new IllegalStateException(ex); this.startUpException = ex;
// Prevent Tomcat from logging and re-throwing when we know we can
// deal with it in the main thread, but log for information here.
logger.error("Error starting Tomcat context: "
+ ex.getClass().getName());
break;
} }
} }
} }

@ -28,6 +28,8 @@ import org.springframework.util.ClassUtils;
*/ */
class TomcatEmbeddedContext extends StandardContext { class TomcatEmbeddedContext extends StandardContext {
private ServletContextInitializerLifecycleListener starter;
@Override @Override
public void loadOnStartup(Container[] children) { public void loadOnStartup(Container[] children) {
} }
@ -49,4 +51,12 @@ class TomcatEmbeddedContext extends StandardContext {
} }
} }
public void setStarter(ServletContextInitializerLifecycleListener starter) {
this.starter = starter;
}
public ServletContextInitializerLifecycleListener getStarter() {
return this.starter;
}
} }

@ -77,6 +77,16 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer
engine.setName(engine.getName() + "-" + instanceId); engine.setName(engine.getName() + "-" + instanceId);
} }
this.tomcat.start(); this.tomcat.start();
Container[] children = this.tomcat.getHost().findChildren();
for (Container container : children) {
if (container instanceof TomcatEmbeddedContext) {
Exception exception = ((TomcatEmbeddedContext) container)
.getStarter().getStartUpException();
if (exception != null) {
throw exception;
}
}
}
try { try {
// Allow the server to start so the ServletContext is available, but stop // Allow the server to start so the ServletContext is available, but stop
// the connector to prevent requests from being handled before the Spring // the connector to prevent requests from being handled before the Spring

@ -242,8 +242,13 @@ public class TomcatEmbeddedServletContainerFactory extends
*/ */
protected void configureContext(Context context, protected void configureContext(Context context,
ServletContextInitializer[] initializers) { ServletContextInitializer[] initializers) {
context.addLifecycleListener(new ServletContextInitializerLifecycleListener( ServletContextInitializerLifecycleListener starter = new ServletContextInitializerLifecycleListener(
initializers)); initializers);
if (context instanceof TomcatEmbeddedContext) {
// Should be true
((TomcatEmbeddedContext) context).setStarter(starter);
}
context.addLifecycleListener(starter);
for (LifecycleListener lifecycleListener : this.contextLifecycleListeners) { for (LifecycleListener lifecycleListener : this.contextLifecycleListeners) {
context.addLifecycleListener(lifecycleListener); context.addLifecycleListener(lifecycleListener);
} }

Loading…
Cancel
Save