Throw a PortInUseException when Netty start fails with a BindException

Closes gh-8737
This commit is contained in:
Andy Wilkinson
2017-07-21 22:03:44 +01:00
parent ded7cea761
commit 9b6b663cc7
2 changed files with 26 additions and 2 deletions

View File

@@ -17,6 +17,8 @@
package org.springframework.boot.web.embedded.netty;
import java.net.BindException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -24,6 +26,7 @@ import reactor.ipc.netty.http.HttpResources;
import reactor.ipc.netty.http.server.HttpServer;
import reactor.ipc.netty.tcp.BlockingNettyContext;
import org.springframework.boot.web.server.PortInUseException;
import org.springframework.boot.web.server.WebServer;
import org.springframework.boot.web.server.WebServerException;
import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
@@ -35,6 +38,7 @@ import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
*
* @author Brian Clozel
* @author Madhura Bhave
* @author Andy Wilkinson
* @since 2.0.0
*/
public class NettyWebServer implements WebServer {
@@ -61,7 +65,11 @@ public class NettyWebServer implements WebServer {
}
catch (Exception ex) {
if (findBindException(ex) != null) {
// throw new PortInUseException();
SocketAddress address = this.reactorServer.options().getAddress();
if (address instanceof InetSocketAddress) {
throw new PortInUseException(
((InetSocketAddress) address).getPort());
}
}
throw new WebServerException("Unable to start Netty", ex);
}
@@ -100,7 +108,8 @@ public class NettyWebServer implements WebServer {
if (this.nettyContext != null) {
this.nettyContext.shutdown();
// temporary fix for gh-9146
this.nettyContext.getContext().onClose().doOnSuccess(aVoid -> HttpResources.reset()).block();
this.nettyContext.getContext().onClose()
.doOnSuccess(aVoid -> HttpResources.reset()).block();
this.nettyContext = null;
}
}

View File

@@ -25,6 +25,7 @@ import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import org.springframework.boot.testsupport.rule.OutputCapture;
import org.springframework.boot.web.server.PortInUseException;
import org.springframework.boot.web.server.WebServer;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
@@ -37,6 +38,7 @@ import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.equalTo;
/**
* Base for testing classes that extends {@link AbstractReactiveWebServerFactory}.
@@ -102,6 +104,19 @@ public abstract class AbstractReactiveWebServerFactoryTests {
assertThat(this.webServer.getPort()).isEqualTo(specificPort);
}
@Test
public void portInUseExceptionIsThrownWhenPortIsAlreadyInUse() throws Exception {
AbstractReactiveWebServerFactory factory = getFactory();
factory.setPort(0);
this.webServer = factory.getWebServer(new EchoHandler());
this.webServer.start();
factory.setPort(this.webServer.getPort());
this.thrown.expect(PortInUseException.class);
this.thrown.expectMessage(
equalTo("Port " + this.webServer.getPort() + " is already in use"));
factory.getWebServer(new EchoHandler()).start();
}
protected WebClient getWebClient() {
return WebClient.create("http://localhost:" + this.webServer.getPort());
}