1616
1717package org .springframework .boot .web .reactive .context ;
1818
19+ import java .util .function .Supplier ;
20+
21+ import reactor .core .publisher .Mono ;
22+
1923import org .springframework .beans .BeansException ;
2024import org .springframework .beans .factory .support .DefaultListableBeanFactory ;
2125import org .springframework .boot .web .context .ConfigurableWebServerApplicationContext ;
2226import org .springframework .boot .web .reactive .server .ReactiveWebServerFactory ;
2327import org .springframework .boot .web .server .WebServer ;
2428import org .springframework .context .ApplicationContextException ;
2529import org .springframework .http .server .reactive .HttpHandler ;
30+ import org .springframework .http .server .reactive .ServerHttpRequest ;
31+ import org .springframework .http .server .reactive .ServerHttpResponse ;
2632import org .springframework .util .StringUtils ;
2733
2834/**
@@ -38,6 +44,8 @@ public class ReactiveWebServerApplicationContext
3844
3945 private volatile WebServer webServer ;
4046
47+ private volatile DeferredHttpHandler httpHandler ;
48+
4149 private String serverNamespace ;
4250
4351 /**
@@ -78,6 +86,17 @@ protected void onRefresh() {
7886 }
7987 }
8088
89+ private void createWebServer () {
90+ WebServer localServer = this .webServer ;
91+ if (localServer == null ) {
92+ DeferredHttpHandler localHandler = new DeferredHttpHandler (
93+ this ::getHttpHandler );
94+ this .webServer = getWebServerFactory ().getWebServer (localHandler );
95+ this .httpHandler = localHandler ;
96+ }
97+ initPropertySources ();
98+ }
99+
81100 @ Override
82101 protected void finishRefresh () {
83102 super .finishRefresh ();
@@ -93,14 +112,6 @@ protected void onClose() {
93112 stopAndReleaseReactiveWebServer ();
94113 }
95114
96- private void createWebServer () {
97- WebServer localServer = this .webServer ;
98- if (localServer == null ) {
99- this .webServer = getWebServerFactory ().getWebServer (getHttpHandler ());
100- }
101- initPropertySources ();
102- }
103-
104115 /**
105116 * Returns the {@link WebServer} that was created by the context or {@code null} if
106117 * the server has not yet been created.
@@ -157,7 +168,12 @@ protected HttpHandler getHttpHandler() {
157168
158169 private WebServer startReactiveWebServer () {
159170 WebServer localServer = this .webServer ;
171+ DeferredHttpHandler localHandler = this .httpHandler ;
160172 if (localServer != null ) {
173+ if (localHandler != null ) {
174+ localHandler .initialize ();
175+ this .httpHandler = null ;
176+ }
161177 localServer .start ();
162178 }
163179 return localServer ;
@@ -186,4 +202,40 @@ public void setServerNamespace(String serverNamespace) {
186202 this .serverNamespace = serverNamespace ;
187203 }
188204
205+ /**
206+ * {@link HttpHandler} that defers to a supplied handler which is initialized only
207+ * when the server starts.
208+ */
209+ static class DeferredHttpHandler implements HttpHandler {
210+
211+ private Supplier <HttpHandler > factory ;
212+
213+ private HttpHandler handler ;
214+
215+ DeferredHttpHandler (Supplier <HttpHandler > factory ) {
216+ this .factory = factory ;
217+ this .handler = this ::handleUninitialized ;
218+ }
219+
220+ public void initialize () {
221+ this .handler = this .factory .get ();
222+ }
223+
224+ private Mono <Void > handleUninitialized (ServerHttpRequest request ,
225+ ServerHttpResponse response ) {
226+ throw new IllegalStateException (
227+ "The HttpHandler has not yet been initialized" );
228+ }
229+
230+ @ Override
231+ public Mono <Void > handle (ServerHttpRequest request , ServerHttpResponse response ) {
232+ return this .handler .handle (request , response );
233+ }
234+
235+ public HttpHandler getHandler () {
236+ return this .handler ;
237+ }
238+
239+ }
240+
189241}
0 commit comments