Commit f7b7b1c8 authored by Phillip Webb's avatar Phillip Webb

Polish embedded tomcat classes

Extract some methods to aid readability.
parent aed243fb
...@@ -37,6 +37,7 @@ public class ServletContextInitializerLifecycleListener implements LifecycleList ...@@ -37,6 +37,7 @@ public class ServletContextInitializerLifecycleListener implements LifecycleList
.getLog(ServletContextInitializerLifecycleListener.class); .getLog(ServletContextInitializerLifecycleListener.class);
private final ServletContextInitializer[] initializers; private final ServletContextInitializer[] initializers;
private Exception startUpException; private Exception startUpException;
/** /**
......
...@@ -24,7 +24,6 @@ import org.apache.catalina.Container; ...@@ -24,7 +24,6 @@ import org.apache.catalina.Container;
import org.apache.catalina.Engine; import org.apache.catalina.Engine;
import org.apache.catalina.LifecycleException; import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleState; import org.apache.catalina.LifecycleState;
import org.apache.catalina.Server;
import org.apache.catalina.Service; import org.apache.catalina.Service;
import org.apache.catalina.connector.Connector; import org.apache.catalina.connector.Connector;
import org.apache.catalina.startup.Tomcat; import org.apache.catalina.startup.Tomcat;
...@@ -77,38 +76,64 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer ...@@ -77,38 +76,64 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer
private synchronized void initialize() throws EmbeddedServletContainerException { private synchronized void initialize() throws EmbeddedServletContainerException {
try { try {
Server server = this.tomcat.getServer(); addInstanceIdToEngineName();
// Remove service connectors to that protocol binding doesn't happen yet
removeServiceConnectors();
// Start the server to trigger initialization listeners
this.tomcat.start();
// We can re-throw failure exception directly in the main thread
rethrowDeferredStartupExceptions();
// Unlike Jetty, all Tomcat threads are daemon threads. We create a
// blocking non-daemon to stop immediate shutdown
startDaemonAwaitThread();
if (LifecycleState.FAILED.equals(this.tomcat.getConnector().getState())) {
this.tomcat.stop();
throw new IllegalStateException("Tomcat connector in failed state");
}
}
catch (Exception ex) {
throw new EmbeddedServletContainerException(
"Unable to start embedded Tomcat", ex);
}
}
private void addInstanceIdToEngineName() {
int instanceId = containerCounter.incrementAndGet(); int instanceId = containerCounter.incrementAndGet();
if (instanceId > 0) { if (instanceId > 0) {
Engine engine = this.tomcat.getEngine(); Engine engine = this.tomcat.getEngine();
engine.setName(engine.getName() + "-" + instanceId); engine.setName(engine.getName() + "-" + instanceId);
} }
}
// Remove service connectors to that protocol binding doesn't happen yet private void removeServiceConnectors() {
for (Service service : server.findServices()) { for (Service service : this.tomcat.getServer().findServices()) {
Connector[] connectors = service.findConnectors().clone(); Connector[] connectors = service.findConnectors().clone();
this.serviceConnectors.put(service, connectors); this.serviceConnectors.put(service, connectors);
for (Connector connector : connectors) { for (Connector connector : connectors) {
service.removeConnector(connector); service.removeConnector(connector);
} }
} }
}
// Start the server to trigger initialization listeners private void rethrowDeferredStartupExceptions() throws Exception {
this.tomcat.start();
Container[] children = this.tomcat.getHost().findChildren(); Container[] children = this.tomcat.getHost().findChildren();
for (Container container : children) { for (Container container : children) {
if (container instanceof TomcatEmbeddedContext) { if (container instanceof TomcatEmbeddedContext) {
Exception exception = ((TomcatEmbeddedContext) container) Exception exception = ((TomcatEmbeddedContext) container).getStarter()
.getStarter().getStartUpException(); .getStartUpException();
if (exception != null) { if (exception != null) {
throw exception; throw exception;
} }
} }
} }
}
// Unlike Jetty, all Tomcat threads are daemon threads. We create a private void startDaemonAwaitThread() {
// blocking non-daemon to stop immediate shutdown
Thread awaitThread = new Thread("container-" + (containerCounter.get())) { Thread awaitThread = new Thread("container-" + (containerCounter.get())) {
@Override @Override
public void run() { public void run() {
...@@ -117,20 +142,18 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer ...@@ -117,20 +142,18 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer
}; };
awaitThread.setDaemon(false); awaitThread.setDaemon(false);
awaitThread.start(); awaitThread.start();
if (LifecycleState.FAILED.equals(this.tomcat.getConnector().getState())) {
this.tomcat.stop();
throw new IllegalStateException("Tomcat connector in failed state");
}
}
catch (Exception ex) {
throw new EmbeddedServletContainerException(
"Unable to start embedded Tomcat", ex);
}
} }
@Override @Override
public void start() throws EmbeddedServletContainerException { public void start() throws EmbeddedServletContainerException {
// Add the previously removed connectors (also starting them) addPreviouslyRemovedConnectors();
Connector connector = this.tomcat.getConnector();
if (connector != null && this.autoStart) {
startConnector(connector);
}
}
private void addPreviouslyRemovedConnectors() {
Service[] services = this.tomcat.getServer().findServices(); Service[] services = this.tomcat.getServer().findServices();
for (Service service : services) { for (Service service : services) {
Connector[] connectors = this.serviceConnectors.get(service); Connector[] connectors = this.serviceConnectors.get(service);
...@@ -138,21 +161,30 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer ...@@ -138,21 +161,30 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer
for (Connector connector : connectors) { for (Connector connector : connectors) {
service.addConnector(connector); service.addConnector(connector);
if (!this.autoStart) { if (!this.autoStart) {
unbind(connector); stopProtocolHandler(connector);
} }
} }
this.serviceConnectors.remove(service); this.serviceConnectors.remove(service);
} }
} }
Connector connector = this.tomcat.getConnector(); }
if (connector != null && this.autoStart) {
private void stopProtocolHandler(Connector connector) {
try {
connector.getProtocolHandler().stop();
}
catch (Exception ex) {
this.logger.error("Cannot pause connector: ", ex);
}
}
private void startConnector(Connector connector) {
try { try {
for (Container child : this.tomcat.getHost().findChildren()) { for (Container child : this.tomcat.getHost().findChildren()) {
if (child instanceof TomcatEmbeddedContext) { if (child instanceof TomcatEmbeddedContext) {
((TomcatEmbeddedContext) child).deferredLoadOnStartup(); ((TomcatEmbeddedContext) child).deferredLoadOnStartup();
} }
} }
connector.getProtocolHandler().start();
logPorts(); logPorts();
} }
catch (Exception ex) { catch (Exception ex) {
...@@ -161,16 +193,6 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer ...@@ -161,16 +193,6 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer
"Unable to start embedded Tomcat connectors", ex); "Unable to start embedded Tomcat connectors", ex);
} }
} }
}
private void unbind(Connector connector) {
try {
connector.getProtocolHandler().stop();
}
catch (Exception ex) {
this.logger.error("Cannot pause connector: ", ex);
}
}
Map<Service, Connector[]> getServiceConnectors() { Map<Service, Connector[]> getServiceConnectors() {
return this.serviceConnectors; return this.serviceConnectors;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment