1616
1717package org .springframework .boot .context .embedded .tomcat ;
1818
19+ import java .util .HashMap ;
20+ import java .util .Map ;
1921import java .util .concurrent .atomic .AtomicInteger ;
2022
2123import org .apache .catalina .Container ;
2224import org .apache .catalina .Engine ;
2325import org .apache .catalina .LifecycleException ;
2426import org .apache .catalina .LifecycleState ;
27+ import org .apache .catalina .Server ;
28+ import org .apache .catalina .Service ;
2529import org .apache .catalina .connector .Connector ;
2630import org .apache .catalina .startup .Tomcat ;
2731import org .apache .commons .logging .Log ;
@@ -47,6 +51,8 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer
4751
4852 private final Tomcat tomcat ;
4953
54+ private final Map <Service , Connector []> serviceConnectors = new HashMap <Service , Connector []>();
55+
5056 private final boolean autoStart ;
5157
5258 /**
@@ -71,12 +77,25 @@ public TomcatEmbeddedServletContainer(Tomcat tomcat, boolean autoStart) {
7177
7278 private synchronized void initialize () throws EmbeddedServletContainerException {
7379 try {
80+ Server server = this .tomcat .getServer ();
7481 int instanceId = containerCounter .incrementAndGet ();
7582 if (instanceId > 0 ) {
7683 Engine engine = this .tomcat .getEngine ();
7784 engine .setName (engine .getName () + "-" + instanceId );
7885 }
86+
87+ // Remove service connectors to that protocol binding doesn't happen yet
88+ for (Service service : server .findServices ()) {
89+ Connector [] connectors = service .findConnectors ().clone ();
90+ this .serviceConnectors .put (service , connectors );
91+ for (Connector connector : connectors ) {
92+ service .removeConnector (connector );
93+ }
94+ }
95+
96+ // Start the server to trigger initialization listeners
7997 this .tomcat .start ();
98+
8099 Container [] children = this .tomcat .getHost ().findChildren ();
81100 for (Container container : children ) {
82101 if (container instanceof TomcatEmbeddedContext ) {
@@ -87,16 +106,7 @@ private synchronized void initialize() throws EmbeddedServletContainerException
87106 }
88107 }
89108 }
90- try {
91- // Allow the server to start so the ServletContext is available, but stop
92- // the connector to prevent requests from being handled before the Spring
93- // context is ready:
94- Connector connector = this .tomcat .getConnector ();
95- connector .getProtocolHandler ().stop ();
96- }
97- catch (Exception ex ) {
98- this .logger .error ("Cannot pause connector: " , ex );
99- }
109+
100110 // Unlike Jetty, all Tomcat threads are daemon threads. We create a
101111 // blocking non-daemon to stop immediate shutdown
102112 Thread awaitThread = new Thread ("container-" + (containerCounter .get ())) {
@@ -120,6 +130,20 @@ public void run() {
120130
121131 @ Override
122132 public void start () throws EmbeddedServletContainerException {
133+ // Add the previously removed connectors (also starting them)
134+ Service [] services = this .tomcat .getServer ().findServices ();
135+ for (Service service : services ) {
136+ Connector [] connectors = this .serviceConnectors .get (service );
137+ if (connectors != null ) {
138+ for (Connector connector : connectors ) {
139+ service .addConnector (connector );
140+ if (!this .autoStart ) {
141+ unbind (connector );
142+ }
143+ }
144+ this .serviceConnectors .remove (service );
145+ }
146+ }
123147 Connector connector = this .tomcat .getConnector ();
124148 if (connector != null && this .autoStart ) {
125149 try {
@@ -139,6 +163,19 @@ public void start() throws EmbeddedServletContainerException {
139163 }
140164 }
141165
166+ private void unbind (Connector connector ) {
167+ try {
168+ connector .getProtocolHandler ().stop ();
169+ }
170+ catch (Exception ex ) {
171+ this .logger .error ("Cannot pause connector: " , ex );
172+ }
173+ }
174+
175+ Map <Service , Connector []> getServiceConnectors () {
176+ return this .serviceConnectors ;
177+ }
178+
142179 private void logPorts () {
143180 StringBuilder ports = new StringBuilder ();
144181 for (Connector additionalConnector : this .tomcat .getService ().findConnectors ()) {
0 commit comments