diff --git a/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/NettyWebServer.java b/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/NettyWebServer.java index 7ef15b5753..052527155c 100644 --- a/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/NettyWebServer.java +++ b/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/NettyWebServer.java @@ -16,9 +16,12 @@ package org.springframework.boot.web.embedded.netty; +import java.net.BindException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReference; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import reactor.core.Loopback; import reactor.ipc.netty.NettyContext; import reactor.ipc.netty.http.server.HttpServer; @@ -33,10 +36,13 @@ import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter; * directly. * * @author Brian Clozel + * @author Madhura Bhave * @since 2.0.0 */ public class NettyWebServer implements WebServer, Loopback { + private static final Log logger = LogFactory.getLog(NettyWebServer.class); + private static CountDownLatch latch = new CountDownLatch(1); private final ReactorHttpHandlerAdapter handlerAdapter; @@ -64,12 +70,32 @@ public class NettyWebServer implements WebServer, Loopback { @Override public void start() throws WebServerException { if (this.nettyContext.get() == null) { - this.nettyContext - .set(this.reactorServer.newHandler(this.handlerAdapter).block()); + try { + this.nettyContext + .set(this.reactorServer.newHandler(this.handlerAdapter).block()); + } + catch (Exception ex) { + if (findBindException(ex) != null) { +// throw new PortInUseException(); + } + throw new WebServerException("Unable to start Netty", ex); + } + NettyWebServer.logger.info("Netty started on port(s): " + getPort()); startDaemonAwaitThread(); } } + private BindException findBindException(Exception ex) { + Throwable candidate = ex; + while (candidate != null) { + if (candidate instanceof BindException) { + return (BindException) candidate; + } + candidate = candidate.getCause(); + } + return null; + } + private void startDaemonAwaitThread() { Thread awaitThread = new Thread("server") { diff --git a/spring-boot/src/test/java/org/springframework/boot/web/reactive/server/AbstractReactiveWebServerFactoryTests.java b/spring-boot/src/test/java/org/springframework/boot/web/reactive/server/AbstractReactiveWebServerFactoryTests.java index ff2dac7672..d1f3dc19c1 100644 --- a/spring-boot/src/test/java/org/springframework/boot/web/reactive/server/AbstractReactiveWebServerFactoryTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/web/reactive/server/AbstractReactiveWebServerFactoryTests.java @@ -88,6 +88,7 @@ public abstract class AbstractReactiveWebServerFactoryTests { public void startStopServer() { this.webServer = getFactory().getWebServer(new EchoHandler()); this.webServer.start(); + assertThat(this.output.toString()).contains("started on port"); Mono result = getWebClient().post().uri("/test") .contentType(MediaType.TEXT_PLAIN) .exchange(BodyInserters.fromObject("Hello World"))