Merge pull request #36103 from asashour

* gh-36103:
  Polish "Change WebServer log messages to use port or ports, not port(s)"
  Change WebServer log messages to use port or ports, not port(s)

Closes gh-36103
pull/36155/head
Andy Wilkinson 1 year ago
commit eb35f8d593

@ -105,8 +105,8 @@ public class ApplicationRunner extends DefaultTask {
} }
public void normalizeTomcatPort() { public void normalizeTomcatPort() {
this.normalizations.put("(Tomcat started on port\\(s\\): )[\\d]+( \\(http\\))", "$18080$2"); this.normalizations.put("(Tomcat started on port )[\\d]+( \\(http\\))", "$18080$2");
this.normalizations.put("(Tomcat initialized with port\\(s\\): )[\\d]+( \\(http\\))", "$18080$2"); this.normalizations.put("(Tomcat initialized with port )[\\d]+( \\(http\\))", "$18080$2");
} }
public void normalizeLiveReloadPort() { public void normalizeLiveReloadPort() {

@ -9,7 +9,7 @@
2017-08-08 17:12:30.910 INFO 19866 --- [ main] s.f.SampleWebFreeMarkerApplication : Starting SampleWebFreeMarkerApplication with PID 19866 2017-08-08 17:12:30.910 INFO 19866 --- [ main] s.f.SampleWebFreeMarkerApplication : Starting SampleWebFreeMarkerApplication with PID 19866
2017-08-08 17:12:30.913 INFO 19866 --- [ main] s.f.SampleWebFreeMarkerApplication : No active profile set, falling back to default profiles: default 2017-08-08 17:12:30.913 INFO 19866 --- [ main] s.f.SampleWebFreeMarkerApplication : No active profile set, falling back to default profiles: default
2017-08-08 17:12:30.952 INFO 19866 --- [ main] ConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@76b10754: startup date [Tue Aug 08 17:12:30 BST 2017]; root of context hierarchy 2017-08-08 17:12:30.952 INFO 19866 --- [ main] ConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@76b10754: startup date [Tue Aug 08 17:12:30 BST 2017]; root of context hierarchy
2017-08-08 17:12:31.878 INFO 19866 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http) 2017-08-08 17:12:31.878 INFO 19866 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http)
2017-08-08 17:12:31.889 INFO 19866 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2017-08-08 17:12:31.889 INFO 19866 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2017-08-08 17:12:31.890 INFO 19866 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.16 2017-08-08 17:12:31.890 INFO 19866 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.16
2017-08-08 17:12:31.978 INFO 19866 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2017-08-08 17:12:31.978 INFO 19866 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
@ -27,5 +27,5 @@
2017-08-08 17:12:32.471 INFO 19866 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2017-08-08 17:12:32.471 INFO 19866 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-08-08 17:12:32.600 INFO 19866 --- [ main] o.s.w.s.v.f.FreeMarkerConfigurer : ClassTemplateLoader for Spring macros added to FreeMarker configuration 2017-08-08 17:12:32.600 INFO 19866 --- [ main] o.s.w.s.v.f.FreeMarkerConfigurer : ClassTemplateLoader for Spring macros added to FreeMarker configuration
2017-08-08 17:12:32.681 INFO 19866 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup 2017-08-08 17:12:32.681 INFO 19866 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2017-08-08 17:12:32.744 INFO 19866 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) 2017-08-08 17:12:32.744 INFO 19866 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http)
2017-08-08 17:12:32.750 INFO 19866 --- [ main] s.f.SampleWebFreeMarkerApplication : Started SampleWebFreeMarkerApplication in 2.172 seconds (JVM running for 2.479) 2017-08-08 17:12:32.750 INFO 19866 --- [ main] s.f.SampleWebFreeMarkerApplication : Started SampleWebFreeMarkerApplication in 2.172 seconds (JVM running for 2.479)

@ -62,7 +62,7 @@ public class NettyRSocketServer implements RSocketServer {
@Override @Override
public void start() throws RSocketServerException { public void start() throws RSocketServerException {
this.channel = block(this.starter, this.lifecycleTimeout); this.channel = block(this.starter, this.lifecycleTimeout);
logger.info("Netty RSocket started on port(s): " + address().getPort()); logger.info("Netty RSocket started on port " + address().getPort());
startDaemonAwaitThread(this.channel); startDaemonAwaitThread(this.channel);
} }

@ -168,8 +168,7 @@ public class JettyWebServer implements WebServer {
} }
} }
this.started = true; this.started = true;
logger.info("Jetty started on port(s) " + getActualPortsDescription() + " with context path '" logger.info(getStartedLogMessage());
+ getContextPath() + "'");
} }
catch (WebServerException ex) { catch (WebServerException ex) {
stopSilently(); stopSilently();
@ -182,15 +181,25 @@ public class JettyWebServer implements WebServer {
} }
} }
String getStartedLogMessage() {
return "Jetty started on " + getActualPortsDescription() + " with context path '" + getContextPath() + "'";
}
private String getActualPortsDescription() { private String getActualPortsDescription() {
StringBuilder ports = new StringBuilder(); StringBuilder description = new StringBuilder("port");
for (Connector connector : this.server.getConnectors()) { Connector[] connectors = this.server.getConnectors();
if (ports.length() != 0) { if (connectors.length != 1) {
ports.append(", "); description.append("s");
}
description.append(" ");
for (int i = 0; i < connectors.length; i++) {
if (i != 0) {
description.append(", ");
} }
ports.append(getLocalPort(connector)).append(getProtocols(connector)); Connector connector = connectors[i];
description.append(getLocalPort(connector)).append(getProtocols(connector));
} }
return ports.toString(); return description.toString();
} }
private String getProtocols(Connector connector) { private String getProtocols(Connector connector) {

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2022 the original author or authors. * Copyright 2012-2023 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -108,7 +108,7 @@ public class NettyWebServer implements WebServer {
throw new WebServerException("Unable to start Netty", ex); throw new WebServerException("Unable to start Netty", ex);
} }
if (this.disposableServer != null) { if (this.disposableServer != null) {
logger.info("Netty started" + getStartedOnMessage(this.disposableServer)); logger.info(getStartedOnMessage(this.disposableServer));
} }
startDaemonAwaitThread(this.disposableServer); startDaemonAwaitThread(this.disposableServer);
} }
@ -118,7 +118,11 @@ public class NettyWebServer implements WebServer {
StringBuilder message = new StringBuilder(); StringBuilder message = new StringBuilder();
tryAppend(message, "port %s", server::port); tryAppend(message, "port %s", server::port);
tryAppend(message, "path %s", server::path); tryAppend(message, "path %s", server::path);
return (message.length() > 0) ? " on " + message : ""; return (message.length() > 0) ? "Netty started on " + message : "Netty started";
}
protected String getStartedLogMessage() {
return getStartedOnMessage(this.disposableServer);
} }
private void tryAppend(StringBuilder message, String format, Supplier<Object> supplier) { private void tryAppend(StringBuilder message, String format, Supplier<Object> supplier) {

@ -105,7 +105,7 @@ public class TomcatWebServer implements WebServer {
} }
private void initialize() throws WebServerException { private void initialize() throws WebServerException {
logger.info("Tomcat initialized with port(s): " + getPortsDescription(false)); logger.info("Tomcat initialized with " + getPortsDescription(false));
synchronized (this.monitor) { synchronized (this.monitor) {
try { try {
addInstanceIdToEngineName(); addInstanceIdToEngineName();
@ -218,8 +218,7 @@ public class TomcatWebServer implements WebServer {
} }
checkThatConnectorsHaveStarted(); checkThatConnectorsHaveStarted();
this.started = true; this.started = true;
logger.info("Tomcat started on port(s): " + getPortsDescription(true) + " with context path '" logger.info(getStartedLogMessage());
+ getContextPath() + "'");
} }
catch (ConnectorStartFailedException ex) { catch (ConnectorStartFailedException ex) {
stopSilently(); stopSilently();
@ -236,6 +235,10 @@ public class TomcatWebServer implements WebServer {
} }
} }
String getStartedLogMessage() {
return "Tomcat started on " + getPortsDescription(true) + " with context path '" + getContextPath() + "'";
}
private void checkThatConnectorsHaveStarted() { private void checkThatConnectorsHaveStarted() {
checkConnectorHasStarted(this.tomcat.getConnector()); checkConnectorHasStarted(this.tomcat.getConnector());
for (Connector connector : this.tomcat.getService().findConnectors()) { for (Connector connector : this.tomcat.getService().findConnectors()) {
@ -355,15 +358,22 @@ public class TomcatWebServer implements WebServer {
} }
private String getPortsDescription(boolean localPort) { private String getPortsDescription(boolean localPort) {
StringBuilder ports = new StringBuilder(); StringBuilder description = new StringBuilder();
for (Connector connector : this.tomcat.getService().findConnectors()) { Connector[] connectors = this.tomcat.getService().findConnectors();
if (ports.length() != 0) { description.append("port");
ports.append(' '); if (connectors.length != 1) {
} description.append("s");
}
description.append(" ");
for (int i = 0; i < connectors.length; i++) {
if (i != 0) {
description.append(", ");
}
Connector connector = connectors[i];
int port = localPort ? connector.getLocalPort() : connector.getPort(); int port = localPort ? connector.getLocalPort() : connector.getPort();
ports.append(port).append(" (").append(connector.getScheme()).append(')'); description.append(port).append(" (").append(connector.getScheme()).append(')');
} }
return ports.toString(); return description.toString();
} }
@Override @Override

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2022 the original author or authors. * Copyright 2012-2023 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -78,11 +78,14 @@ public class UndertowServletWebServer extends UndertowWebServer {
@Override @Override
protected String getStartLogMessage() { protected String getStartLogMessage() {
String message = super.getStartLogMessage(); if (!StringUtils.hasText(this.contextPath)) {
if (StringUtils.hasText(this.contextPath)) { return super.getStartLogMessage();
message += " with context path '" + this.contextPath + "'";
} }
return message; StringBuilder message = new StringBuilder(super.getStartLogMessage());
message.append(" with context path '");
message.append(this.contextPath);
message.append("'");
return message.toString();
} }
public DeploymentManager getDeploymentManager() { public DeploymentManager getDeploymentManager() {

@ -182,11 +182,20 @@ public class UndertowWebServer implements WebServer {
} }
private String getPortsDescription() { private String getPortsDescription() {
StringBuilder description = new StringBuilder();
List<UndertowWebServer.Port> ports = getActualPorts(); List<UndertowWebServer.Port> ports = getActualPorts();
description.append("port");
if (ports.size() != 1) {
description.append("s");
}
description.append(" ");
if (!ports.isEmpty()) { if (!ports.isEmpty()) {
return StringUtils.collectionToDelimitedString(ports, " "); description.append(StringUtils.collectionToDelimitedString(ports, ", "));
}
else {
description.append("unknown");
} }
return "unknown"; return description.toString();
} }
private List<Port> getActualPorts() { private List<Port> getActualPorts() {
@ -315,7 +324,7 @@ public class UndertowWebServer implements WebServer {
} }
protected String getStartLogMessage() { protected String getStartLogMessage() {
return "Undertow started on port(s) " + getPortsDescription(); return "Undertow started on " + getPortsDescription();
} }
/** /**

@ -31,6 +31,7 @@ import org.junit.jupiter.api.Test;
import org.mockito.InOrder; import org.mockito.InOrder;
import org.springframework.boot.testsupport.web.servlet.Servlet5ClassPathOverrides; import org.springframework.boot.testsupport.web.servlet.Servlet5ClassPathOverrides;
import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory;
import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactoryTests; import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactoryTests;
import org.springframework.boot.web.server.Shutdown; import org.springframework.boot.web.server.Shutdown;
import org.springframework.http.client.reactive.JettyResourceFactory; import org.springframework.http.client.reactive.JettyResourceFactory;
@ -161,4 +162,18 @@ class JettyReactiveWebServerFactoryTests extends AbstractReactiveWebServerFactor
assertThat(connectionLimit.getMaxConnections()).isOne(); assertThat(connectionLimit.getMaxConnections()).isOne();
} }
@Override
protected String startedLogMessage() {
return ((JettyWebServer) this.webServer).getStartedLogMessage();
}
@Override
protected void addConnector(int port, AbstractReactiveWebServerFactory factory) {
((JettyReactiveWebServerFactory) factory).addServerCustomizers((server) -> {
ServerConnector connector = new ServerConnector(server);
connector.setPort(port);
server.addConnector(connector);
});
}
} }

@ -531,6 +531,11 @@ class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryT
assertThat(connectionLimit.getMaxConnections()).isOne(); assertThat(connectionLimit.getMaxConnections()).isOne();
} }
@Override
protected String startedLogMessage() {
return ((JettyWebServer) this.webServer).getStartedLogMessage();
}
private WebAppContext findWebAppContext(JettyWebServer webServer) { private WebAppContext findWebAppContext(JettyWebServer webServer) {
return findWebAppContext(webServer.getServer().getHandler()); return findWebAppContext(webServer.getServer().getHandler());
} }

@ -23,6 +23,7 @@ import java.util.Arrays;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import org.awaitility.Awaitility; import org.awaitility.Awaitility;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.InOrder; import org.mockito.InOrder;
import reactor.core.CoreSubscriber; import reactor.core.CoreSubscriber;
@ -135,6 +136,12 @@ class NettyReactiveWebServerFactoryTests extends AbstractReactiveWebServerFactor
this.webServer.stop(); this.webServer.stop();
} }
@Override
@Test
@Disabled("Reactor Netty does not support mutiple ports")
protected void startedLogMessageWithMultiplePorts() {
}
protected Mono<String> testSslWithAlias(String alias) { protected Mono<String> testSslWithAlias(String alias) {
String keyStore = "classpath:test.jks"; String keyStore = "classpath:test.jks";
String keyPassword = "password"; String keyPassword = "password";
@ -164,6 +171,16 @@ class NettyReactiveWebServerFactoryTests extends AbstractReactiveWebServerFactor
return new NettyReactiveWebServerFactory(0); return new NettyReactiveWebServerFactory(0);
} }
@Override
protected String startedLogMessage() {
return ((NettyWebServer) this.webServer).getStartedLogMessage();
}
@Override
protected void addConnector(int port, AbstractReactiveWebServerFactory factory) {
throw new UnsupportedOperationException("Reactor Netty does not support multiple ports");
}
static class NoPortNettyReactiveWebServerFactory extends NettyReactiveWebServerFactory { static class NoPortNettyReactiveWebServerFactory extends NettyReactiveWebServerFactory {
NoPortNettyReactiveWebServerFactory(int port) { NoPortNettyReactiveWebServerFactory(int port) {

@ -275,4 +275,16 @@ class TomcatReactiveWebServerFactoryTests extends AbstractReactiveWebServerFacto
assertThat(((PortInUseException) ex).getPort()).isEqualTo(blockedPort); assertThat(((PortInUseException) ex).getPort()).isEqualTo(blockedPort);
} }
@Override
protected String startedLogMessage() {
return ((TomcatWebServer) this.webServer).getStartedLogMessage();
}
@Override
protected void addConnector(int port, AbstractReactiveWebServerFactory factory) {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setPort(port);
((TomcatReactiveWebServerFactory) factory).addAdditionalTomcatConnectors(connector);
}
} }

@ -689,4 +689,9 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory
assertThat(((ConnectorStartFailedException) ex).getPort()).isEqualTo(blockedPort); assertThat(((ConnectorStartFailedException) ex).getPort()).isEqualTo(blockedPort);
} }
@Override
protected String startedLogMessage() {
return ((TomcatWebServer) this.webServer).getStartedLogMessage();
}
} }

@ -27,6 +27,7 @@ import org.junit.jupiter.api.io.TempDir;
import org.mockito.InOrder; import org.mockito.InOrder;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory;
import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactoryTests; import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactoryTests;
import org.springframework.boot.web.server.Shutdown; import org.springframework.boot.web.server.Shutdown;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
@ -155,4 +156,15 @@ class UndertowReactiveWebServerFactoryTests extends AbstractReactiveWebServerFac
Awaitility.waitAtMost(Duration.ofSeconds(10)).until(file::exists, is(true)); Awaitility.waitAtMost(Duration.ofSeconds(10)).until(file::exists, is(true));
} }
@Override
protected String startedLogMessage() {
return ((UndertowWebServer) this.webServer).getStartLogMessage();
}
@Override
protected void addConnector(int port, AbstractReactiveWebServerFactory factory) {
((UndertowReactiveWebServerFactory) factory)
.addBuilderCustomizers((builder) -> builder.addHttpListener(port, "0.0.0.0"));
}
} }

@ -333,4 +333,9 @@ class UndertowServletWebServerFactoryTests extends AbstractServletWebServerFacto
handleExceptionCausedByBlockedPortOnPrimaryConnector(ex, blockedPort); handleExceptionCausedByBlockedPortOnPrimaryConnector(ex, blockedPort);
} }
@Override
protected String startedLogMessage() {
return ((UndertowServletWebServer) this.webServer).getStartLogMessage();
}
} }

@ -602,6 +602,25 @@ public abstract class AbstractReactiveWebServerFactoryTests {
assertThat(result.block(Duration.ofSeconds(30))).isEqualTo("Hello World"); assertThat(result.block(Duration.ofSeconds(30))).isEqualTo("Hello World");
} }
@Test
void startedLogMessageWithSinglePort() {
AbstractReactiveWebServerFactory factory = getFactory();
this.webServer = factory.getWebServer(new EchoHandler());
this.webServer.start();
assertThat(startedLogMessage()).matches("(Jetty|Netty|Tomcat|Undertow) started on port "
+ this.webServer.getPort() + "( \\(http(/1.1)?\\))?( with context path '(/)?')?");
}
@Test
protected void startedLogMessageWithMultiplePorts() {
AbstractReactiveWebServerFactory factory = getFactory();
addConnector(0, factory);
this.webServer = factory.getWebServer(new EchoHandler());
this.webServer.start();
assertThat(startedLogMessage()).matches("(Jetty|Tomcat|Undertow) started on ports " + this.webServer.getPort()
+ "( \\(http(/1.1)?\\))?, [0-9]+( \\(http(/1.1)?\\))?( with context path '(/)?')?");
}
protected WebClient prepareCompressionTest() { protected WebClient prepareCompressionTest() {
Compression compression = new Compression(); Compression compression = new Compression();
compression.setEnabled(true); compression.setEnabled(true);
@ -673,6 +692,10 @@ public abstract class AbstractReactiveWebServerFactoryTests {
} }
} }
protected abstract String startedLogMessage();
protected abstract void addConnector(int port, AbstractReactiveWebServerFactory factory);
public interface BlockedPortAction { public interface BlockedPortAction {
void run(int port); void run(int port);

@ -1336,6 +1336,35 @@ public abstract class AbstractServletWebServerFactoryTests {
} }
} }
@Test
void startedLogMessageWithSinglePort() {
AbstractServletWebServerFactory factory = getFactory();
this.webServer = factory.getWebServer();
this.webServer.start();
assertThat(startedLogMessage()).matches("(Jetty|Tomcat|Undertow) started on port " + this.webServer.getPort()
+ " \\(http(/1.1)?\\)( with context path '(/)?')?");
}
@Test
void startedLogMessageWithSinglePortAndContextPath() {
AbstractServletWebServerFactory factory = getFactory();
factory.setContextPath("/test");
this.webServer = factory.getWebServer();
this.webServer.start();
assertThat(startedLogMessage()).matches("(Jetty|Tomcat|Undertow) started on port " + this.webServer.getPort()
+ " \\(http(/1.1)?\\) with context path '/test'");
}
@Test
void startedLogMessageWithMultiplePorts() {
AbstractServletWebServerFactory factory = getFactory();
addConnector(0, factory);
this.webServer = factory.getWebServer();
this.webServer.start();
assertThat(startedLogMessage()).matches("(Jetty|Tomcat|Undertow) started on ports " + this.webServer.getPort()
+ " \\(http(/1.1)?\\), [0-9]+ \\(http(/1.1)?\\)( with context path '(/)?')?");
}
protected Future<Object> initiateGetRequest(int port, String path) { protected Future<Object> initiateGetRequest(int port, String path) {
return initiateGetRequest(HttpClients.createMinimal(), port, path); return initiateGetRequest(HttpClients.createMinimal(), port, path);
} }
@ -1584,6 +1613,8 @@ public abstract class AbstractServletWebServerFactoryTests {
} }
} }
protected abstract String startedLogMessage();
private class TestGzipInputStreamFactory implements InputStreamFactory { private class TestGzipInputStreamFactory implements InputStreamFactory {
private final AtomicBoolean requested = new AtomicBoolean(); private final AtomicBoolean requested = new AtomicBoolean();

Loading…
Cancel
Save