16
16
17
17
package org .springframework .boot .context .embedded .tomcat ;
18
18
19
+ import java .util .HashMap ;
20
+ import java .util .Map ;
19
21
import java .util .concurrent .atomic .AtomicInteger ;
20
22
21
23
import org .apache .catalina .Container ;
22
24
import org .apache .catalina .Engine ;
23
25
import org .apache .catalina .LifecycleException ;
24
26
import org .apache .catalina .LifecycleState ;
27
+ import org .apache .catalina .Server ;
28
+ import org .apache .catalina .Service ;
25
29
import org .apache .catalina .connector .Connector ;
26
30
import org .apache .catalina .startup .Tomcat ;
27
31
import org .apache .commons .logging .Log ;
@@ -47,6 +51,8 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer
47
51
48
52
private final Tomcat tomcat ;
49
53
54
+ private final Map <Service , Connector []> serviceConnectors = new HashMap <Service , Connector []>();
55
+
50
56
private final boolean autoStart ;
51
57
52
58
/**
@@ -71,12 +77,25 @@ public TomcatEmbeddedServletContainer(Tomcat tomcat, boolean autoStart) {
71
77
72
78
private synchronized void initialize () throws EmbeddedServletContainerException {
73
79
try {
80
+ Server server = this .tomcat .getServer ();
74
81
int instanceId = containerCounter .incrementAndGet ();
75
82
if (instanceId > 0 ) {
76
83
Engine engine = this .tomcat .getEngine ();
77
84
engine .setName (engine .getName () + "-" + instanceId );
78
85
}
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
79
97
this .tomcat .start ();
98
+
80
99
Container [] children = this .tomcat .getHost ().findChildren ();
81
100
for (Container container : children ) {
82
101
if (container instanceof TomcatEmbeddedContext ) {
@@ -87,16 +106,7 @@ private synchronized void initialize() throws EmbeddedServletContainerException
87
106
}
88
107
}
89
108
}
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
+
100
110
// Unlike Jetty, all Tomcat threads are daemon threads. We create a
101
111
// blocking non-daemon to stop immediate shutdown
102
112
Thread awaitThread = new Thread ("container-" + (containerCounter .get ())) {
@@ -120,6 +130,20 @@ public void run() {
120
130
121
131
@ Override
122
132
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
+ }
123
147
Connector connector = this .tomcat .getConnector ();
124
148
if (connector != null && this .autoStart ) {
125
149
try {
@@ -139,6 +163,19 @@ public void start() throws EmbeddedServletContainerException {
139
163
}
140
164
}
141
165
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
+
142
179
private void logPorts () {
143
180
StringBuilder ports = new StringBuilder ();
144
181
for (Connector additionalConnector : this .tomcat .getService ().findConnectors ()) {
0 commit comments