diff --git a/spring-bootstrap-actuator/src/main/java/org/springframework/bootstrap/actuate/autoconfigure/ManagementServerConfiguration.java b/spring-bootstrap-actuator/src/main/java/org/springframework/bootstrap/actuate/autoconfigure/ManagementServerConfiguration.java index 9dae0abacf3..37960ca2b41 100644 --- a/spring-bootstrap-actuator/src/main/java/org/springframework/bootstrap/actuate/autoconfigure/ManagementServerConfiguration.java +++ b/spring-bootstrap-actuator/src/main/java/org/springframework/bootstrap/actuate/autoconfigure/ManagementServerConfiguration.java @@ -104,6 +104,7 @@ public class ManagementServerConfiguration implements BeanPostProcessor { AbstractEmbeddedServletContainerFactory factory = (AbstractEmbeddedServletContainerFactory) bean; factory.setPort(this.configuration.getPort()); + factory.setAddress(this.configuration.getAddress()); factory.setContextPath(this.configuration.getContextPath()); factory.setErrorPages(Collections diff --git a/spring-bootstrap-actuator/src/main/java/org/springframework/bootstrap/actuate/autoconfigure/ServerConfiguration.java b/spring-bootstrap-actuator/src/main/java/org/springframework/bootstrap/actuate/autoconfigure/ServerConfiguration.java index 85c44faa04f..aaec6c0f509 100644 --- a/spring-bootstrap-actuator/src/main/java/org/springframework/bootstrap/actuate/autoconfigure/ServerConfiguration.java +++ b/spring-bootstrap-actuator/src/main/java/org/springframework/bootstrap/actuate/autoconfigure/ServerConfiguration.java @@ -96,6 +96,7 @@ public class ServerConfiguration implements BeanPostProcessor, BeanFactoryAware AbstractEmbeddedServletContainerFactory factory = (AbstractEmbeddedServletContainerFactory) bean; factory.setPort(server.getPort()); + factory.setAddress(server.getAddress()); factory.setContextPath(server.getContextPath()); if (factory instanceof TomcatEmbeddedServletContainerFactory) { diff --git a/spring-bootstrap-actuator/src/main/java/org/springframework/bootstrap/actuate/properties/ManagementServerProperties.java b/spring-bootstrap-actuator/src/main/java/org/springframework/bootstrap/actuate/properties/ManagementServerProperties.java index 90c49a6d11d..e5ff86552d6 100644 --- a/spring-bootstrap-actuator/src/main/java/org/springframework/bootstrap/actuate/properties/ManagementServerProperties.java +++ b/spring-bootstrap-actuator/src/main/java/org/springframework/bootstrap/actuate/properties/ManagementServerProperties.java @@ -16,6 +16,8 @@ package org.springframework.bootstrap.actuate.properties; +import java.net.InetAddress; + import javax.validation.constraints.NotNull; import org.springframework.bootstrap.context.annotation.ConfigurationProperties; @@ -30,6 +32,8 @@ public class ManagementServerProperties { private int port = 8080; + private InetAddress address; + @NotNull private String contextPath = ""; @@ -51,6 +55,14 @@ public class ManagementServerProperties { this.port = port; } + public InetAddress getAddress() { + return this.address; + } + + public void setAddress(InetAddress address) { + this.address = address; + } + public String getContextPath() { return this.contextPath; } diff --git a/spring-bootstrap-actuator/src/main/java/org/springframework/bootstrap/actuate/properties/ServerProperties.java b/spring-bootstrap-actuator/src/main/java/org/springframework/bootstrap/actuate/properties/ServerProperties.java index 9aebb680699..13f5a9bc4cf 100644 --- a/spring-bootstrap-actuator/src/main/java/org/springframework/bootstrap/actuate/properties/ServerProperties.java +++ b/spring-bootstrap-actuator/src/main/java/org/springframework/bootstrap/actuate/properties/ServerProperties.java @@ -17,6 +17,7 @@ package org.springframework.bootstrap.actuate.properties; import java.io.File; +import java.net.InetAddress; import javax.validation.constraints.NotNull; @@ -32,6 +33,8 @@ public class ServerProperties { private int port = 8080; + private InetAddress address; + @NotNull private String contextPath = ""; @@ -57,6 +60,14 @@ public class ServerProperties { this.port = port; } + public InetAddress getAddress() { + return this.address; + } + + public void setAddress(InetAddress address) { + this.address = address; + } + public static class Tomcat { private String accessLogPattern; diff --git a/spring-bootstrap-samples/spring-bootstrap-actuator-sample/src/main/resources/application.properties b/spring-bootstrap-samples/spring-bootstrap-actuator-sample/src/main/resources/application.properties index c7fe96e1cf4..8691d54080d 100644 --- a/spring-bootstrap-samples/spring-bootstrap-actuator-sample/src/main/resources/application.properties +++ b/spring-bootstrap-samples/spring-bootstrap-actuator-sample/src/main/resources/application.properties @@ -1,5 +1,6 @@ logging.file: /tmp/logs/app.log management.port: 8080 +management.address: 127.0.0.1 management.allow_shutdown: true server.port: 8080 server.tomcat.basedir: target/tomcat diff --git a/spring-bootstrap-samples/spring-bootstrap-actuator-sample/src/test/java/org/springframework/bootstrap/sample/service/VarzAddressServiceBootstrapApplicationTests.java b/spring-bootstrap-samples/spring-bootstrap-actuator-sample/src/test/java/org/springframework/bootstrap/sample/service/VarzAddressServiceBootstrapApplicationTests.java new file mode 100644 index 00000000000..55241be7e33 --- /dev/null +++ b/spring-bootstrap-samples/spring-bootstrap-actuator-sample/src/test/java/org/springframework/bootstrap/sample/service/VarzAddressServiceBootstrapApplicationTests.java @@ -0,0 +1,148 @@ +package org.springframework.bootstrap.sample.service; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.bootstrap.SpringApplication; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.http.HttpRequest; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.http.client.InterceptingClientHttpRequestFactory; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.security.crypto.codec.Base64; +import org.springframework.web.client.DefaultResponseErrorHandler; +import org.springframework.web.client.RestTemplate; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * Integration tests for separate management and main service ports. + * + * @author Dave Syer + * + */ +public class VarzAddressServiceBootstrapApplicationTests { + + private static ConfigurableApplicationContext context; + + private static int port = 9000; + private static int managementPort = 9001; + + @BeforeClass + public static void start() throws Exception { + final String[] args = new String[] { "--server.port=" + port, + "--management.port=" + managementPort }; + Future future = Executors + .newSingleThreadExecutor().submit( + new Callable() { + @Override + public ConfigurableApplicationContext call() throws Exception { + return (ConfigurableApplicationContext) SpringApplication + .run(ServiceBootstrapApplication.class, args); + } + }); + context = future.get(10, TimeUnit.SECONDS); + } + + @AfterClass + public static void stop() { + if (context != null) { + context.close(); + } + } + + @Test + public void testHome() throws Exception { + @SuppressWarnings("rawtypes") + ResponseEntity entity = getRestTemplate("user", "password").getForEntity( + "http://localhost:" + port, Map.class); + assertEquals(HttpStatus.OK, entity.getStatusCode()); + @SuppressWarnings("unchecked") + Map body = entity.getBody(); + assertEquals("Hello Phil", body.get("message")); + } + + @Test + public void testVarz() throws Exception { + testHome(); // makes sure some requests have been made + @SuppressWarnings("rawtypes") + ResponseEntity entity = getRestTemplate().getForEntity( + "http://localhost:" + managementPort + "/varz", Map.class); + assertEquals(HttpStatus.OK, entity.getStatusCode()); + @SuppressWarnings("unchecked") + Map body = entity.getBody(); + assertTrue("Wrong body: " + body, body.containsKey("counter.status.200.root")); + } + + @Test + public void testHealthz() throws Exception { + ResponseEntity entity = getRestTemplate().getForEntity( + "http://localhost:" + managementPort + "/healthz", String.class); + assertEquals(HttpStatus.OK, entity.getStatusCode()); + assertEquals("ok", entity.getBody()); + } + + @Test + public void testErrorPage() throws Exception { + @SuppressWarnings("rawtypes") + ResponseEntity entity = getRestTemplate().getForEntity( + "http://localhost:" + managementPort + "/error", Map.class); + assertEquals(HttpStatus.OK, entity.getStatusCode()); + @SuppressWarnings("unchecked") + Map body = entity.getBody(); + assertEquals(999, body.get("status")); + } + + private RestTemplate getRestTemplate() { + return getRestTemplate(null, null); + } + + private RestTemplate getRestTemplate(final String username, final String password) { + + List interceptors = new ArrayList(); + + if (username != null) { + + interceptors.add(new ClientHttpRequestInterceptor() { + + @Override + public ClientHttpResponse intercept(HttpRequest request, byte[] body, + ClientHttpRequestExecution execution) throws IOException { + request.getHeaders().add( + "Authorization", + "Basic " + + new String(Base64 + .encode((username + ":" + password) + .getBytes()))); + return execution.execute(request, body); + } + }); + } + + RestTemplate restTemplate = new RestTemplate( + new InterceptingClientHttpRequestFactory( + new SimpleClientHttpRequestFactory(), interceptors)); + restTemplate.setErrorHandler(new DefaultResponseErrorHandler() { + @Override + public void handleError(ClientHttpResponse response) throws IOException { + } + }); + return restTemplate; + + } + +} diff --git a/spring-bootstrap-samples/spring-bootstrap-actuator-sample/src/test/java/org/springframework/bootstrap/sample/service/VarzContextServiceBootstrapApplicationTests.java b/spring-bootstrap-samples/spring-bootstrap-actuator-sample/src/test/java/org/springframework/bootstrap/sample/service/VarzContextServiceBootstrapApplicationTests.java index f1f390546c5..baec04765dc 100644 --- a/spring-bootstrap-samples/spring-bootstrap-actuator-sample/src/test/java/org/springframework/bootstrap/sample/service/VarzContextServiceBootstrapApplicationTests.java +++ b/spring-bootstrap-samples/spring-bootstrap-actuator-sample/src/test/java/org/springframework/bootstrap/sample/service/VarzContextServiceBootstrapApplicationTests.java @@ -1,8 +1,6 @@ package org.springframework.bootstrap.sample.service; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.Executors; @@ -14,20 +12,13 @@ import org.junit.BeforeClass; import org.junit.Test; import org.springframework.bootstrap.SpringApplication; import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.http.HttpRequest; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.http.client.ClientHttpRequestExecution; -import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.ClientHttpResponse; -import org.springframework.http.client.InterceptingClientHttpRequestFactory; -import org.springframework.http.client.SimpleClientHttpRequestFactory; -import org.springframework.security.crypto.codec.Base64; import org.springframework.web.client.DefaultResponseErrorHandler; import org.springframework.web.client.RestTemplate; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; /** * Integration tests for separate management and main service ports. @@ -45,7 +36,7 @@ public class VarzContextServiceBootstrapApplicationTests { @BeforeClass public static void start() throws Exception { final String[] args = new String[] { "--server.port=" + port, - "--management.port=" + managementPort }; + "--management.port=" + managementPort, "--management.address=127.0.0.1" }; Future future = Executors .newSingleThreadExecutor().submit( new Callable() { @@ -67,25 +58,10 @@ public class VarzContextServiceBootstrapApplicationTests { @Test public void testHome() throws Exception { - @SuppressWarnings("rawtypes") - ResponseEntity entity = getRestTemplate("user", "password").getForEntity( - "http://localhost:" + port, Map.class); - assertEquals(HttpStatus.OK, entity.getStatusCode()); - @SuppressWarnings("unchecked") - Map body = entity.getBody(); - assertEquals("Hello Phil", body.get("message")); - } - - @Test - public void testVarz() throws Exception { - testHome(); // makes sure some requests have been made @SuppressWarnings("rawtypes") ResponseEntity entity = getRestTemplate().getForEntity( - "http://localhost:" + managementPort + "/varz", Map.class); - assertEquals(HttpStatus.OK, entity.getStatusCode()); - @SuppressWarnings("unchecked") - Map body = entity.getBody(); - assertTrue("Wrong body: " + body, body.containsKey("counter.status.200.root")); + "http://localhost:" + port, Map.class); + assertEquals(HttpStatus.FORBIDDEN, entity.getStatusCode()); } @Test @@ -96,46 +72,9 @@ public class VarzContextServiceBootstrapApplicationTests { assertEquals("ok", entity.getBody()); } - @Test - public void testErrorPage() throws Exception { - @SuppressWarnings("rawtypes") - ResponseEntity entity = getRestTemplate().getForEntity( - "http://localhost:" + managementPort + "/error", Map.class); - assertEquals(HttpStatus.OK, entity.getStatusCode()); - @SuppressWarnings("unchecked") - Map body = entity.getBody(); - assertEquals(999, body.get("status")); - } - private RestTemplate getRestTemplate() { - return getRestTemplate(null, null); - } - private RestTemplate getRestTemplate(final String username, final String password) { - - List interceptors = new ArrayList(); - - if (username != null) { - - interceptors.add(new ClientHttpRequestInterceptor() { - - @Override - public ClientHttpResponse intercept(HttpRequest request, byte[] body, - ClientHttpRequestExecution execution) throws IOException { - request.getHeaders().add( - "Authorization", - "Basic " - + new String(Base64 - .encode((username + ":" + password) - .getBytes()))); - return execution.execute(request, body); - } - }); - } - - RestTemplate restTemplate = new RestTemplate( - new InterceptingClientHttpRequestFactory( - new SimpleClientHttpRequestFactory(), interceptors)); + RestTemplate restTemplate = new RestTemplate(); restTemplate.setErrorHandler(new DefaultResponseErrorHandler() { @Override public void handleError(ClientHttpResponse response) throws IOException { diff --git a/spring-bootstrap-service/src/test/java/org/springframework/bootstrap/service/properties/ServerPropertiesTests.java b/spring-bootstrap-service/src/test/java/org/springframework/bootstrap/service/properties/ServerPropertiesTests.java new file mode 100644 index 00000000000..d9240d2fa89 --- /dev/null +++ b/spring-bootstrap-service/src/test/java/org/springframework/bootstrap/service/properties/ServerPropertiesTests.java @@ -0,0 +1,54 @@ +/* + * Copyright 2012-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.bootstrap.service.properties; + +import java.net.InetAddress; +import java.util.Collections; + +import org.junit.Test; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.bootstrap.bind.RelaxedDataBinder; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +/** + * Externalized configuration for server properties + * + * @author Dave Syer + * + */ +public class ServerPropertiesTests { + + private ServerProperties properties = new ServerProperties(); + + @Test + public void testAddressBinding() throws Exception { + RelaxedDataBinder binder = new RelaxedDataBinder(this.properties, "server"); + binder.bind(new MutablePropertyValues(Collections.singletonMap("server.address", + "127.0.0.1"))); + assertFalse(binder.getBindingResult().hasErrors()); + assertEquals(InetAddress.getLocalHost(), this.properties.getAddress()); + } + + @Test + public void testPortBinding() throws Exception { + new RelaxedDataBinder(this.properties, "server").bind(new MutablePropertyValues( + Collections.singletonMap("server.port", "9000"))); + assertEquals(9000, this.properties.getPort()); + } + +} diff --git a/spring-bootstrap/src/main/java/org/springframework/bootstrap/bind/InetAddressEditor.java b/spring-bootstrap/src/main/java/org/springframework/bootstrap/bind/InetAddressEditor.java new file mode 100644 index 00000000000..9ddde83fc5a --- /dev/null +++ b/spring-bootstrap/src/main/java/org/springframework/bootstrap/bind/InetAddressEditor.java @@ -0,0 +1,43 @@ +/* + * Copyright 2012-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.bootstrap.bind; + +import java.beans.PropertyEditor; +import java.beans.PropertyEditorSupport; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * @author Dave Syer + * + */ +public class InetAddressEditor extends PropertyEditorSupport implements PropertyEditor { + + @Override + public String getAsText() { + return ((InetAddress) getValue()).getHostAddress(); + } + + @Override + public void setAsText(String text) throws IllegalArgumentException { + try { + setValue(InetAddress.getByName(text)); + } catch (UnknownHostException e) { + throw new IllegalArgumentException("Cannot locate host", e); + } + } + +} diff --git a/spring-bootstrap/src/main/java/org/springframework/bootstrap/bind/RelaxedDataBinder.java b/spring-bootstrap/src/main/java/org/springframework/bootstrap/bind/RelaxedDataBinder.java index f11e83c4248..25d6ef039d1 100644 --- a/spring-bootstrap/src/main/java/org/springframework/bootstrap/bind/RelaxedDataBinder.java +++ b/spring-bootstrap/src/main/java/org/springframework/bootstrap/bind/RelaxedDataBinder.java @@ -16,6 +16,7 @@ package org.springframework.bootstrap.bind; +import java.net.InetAddress; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -68,6 +69,9 @@ public class RelaxedDataBinder extends DataBinder { @Override protected void doBind(MutablePropertyValues propertyValues) { propertyValues = modifyProperties(propertyValues, getTarget()); + // Harmless additional property editor comes in very handy sometimes... + getPropertyEditorRegistry().registerCustomEditor(InetAddress.class, + new InetAddressEditor()); super.doBind(propertyValues); } diff --git a/spring-bootstrap/src/main/java/org/springframework/bootstrap/context/embedded/AbstractEmbeddedServletContainerFactory.java b/spring-bootstrap/src/main/java/org/springframework/bootstrap/context/embedded/AbstractEmbeddedServletContainerFactory.java index c588cb5ece9..1c07bd3358b 100644 --- a/spring-bootstrap/src/main/java/org/springframework/bootstrap/context/embedded/AbstractEmbeddedServletContainerFactory.java +++ b/spring-bootstrap/src/main/java/org/springframework/bootstrap/context/embedded/AbstractEmbeddedServletContainerFactory.java @@ -17,6 +17,7 @@ package org.springframework.bootstrap.context.embedded; import java.io.File; +import java.net.InetAddress; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashSet; @@ -56,6 +57,8 @@ public abstract class AbstractEmbeddedServletContainerFactory implements private Set errorPages = new LinkedHashSet(); + private InetAddress address; + /** * Create a new {@link AbstractEmbeddedServletContainerFactory} instance. */ @@ -132,6 +135,22 @@ public abstract class AbstractEmbeddedServletContainerFactory implements return this.port; } + /** + * If you need the server to bind to a specific network address, provide one here. + * + * @param address the address to set (defaults to null) + */ + public void setAddress(InetAddress address) { + this.address = address; + } + + /** + * @return the address the embedded container binds to + */ + public InetAddress getAddress() { + return this.address; + } + /** * Sets {@link ServletContextInitializer} that should be applied in addition to * {@link #getEmbdeddedServletContainer(ServletContextInitializer...)} parameters. diff --git a/spring-bootstrap/src/main/java/org/springframework/bootstrap/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java b/spring-bootstrap/src/main/java/org/springframework/bootstrap/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java index df6abe6dc64..f8462ea2b1d 100644 --- a/spring-bootstrap/src/main/java/org/springframework/bootstrap/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java +++ b/spring-bootstrap/src/main/java/org/springframework/bootstrap/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java @@ -17,6 +17,7 @@ package org.springframework.bootstrap.context.embedded.jetty; import java.io.File; +import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -98,7 +99,7 @@ public class JettyEmbeddedServletContainerFactory extends if (getPort() == 0) { return new EmptyEmbeddedServletContainer(); } - Server server = new Server(getPort()); + Server server = new Server(new InetSocketAddress(getAddress(), getPort())); WebAppContext context = new WebAppContext(); if (this.resourceLoader != null) { diff --git a/spring-bootstrap/src/main/java/org/springframework/bootstrap/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java b/spring-bootstrap/src/main/java/org/springframework/bootstrap/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java index 40aaf25221f..a980c1cac7b 100644 --- a/spring-bootstrap/src/main/java/org/springframework/bootstrap/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java +++ b/spring-bootstrap/src/main/java/org/springframework/bootstrap/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java @@ -36,6 +36,7 @@ import org.apache.catalina.core.StandardHost; import org.apache.catalina.core.StandardService; import org.apache.catalina.startup.Tomcat; import org.apache.catalina.startup.Tomcat.FixContextListener; +import org.apache.coyote.AbstractProtocol; import org.springframework.bootstrap.context.embedded.AbstractEmbeddedServletContainerFactory; import org.springframework.bootstrap.context.embedded.EmbeddedServletContainer; import org.springframework.bootstrap.context.embedded.EmbeddedServletContainerException; @@ -121,7 +122,7 @@ public class TomcatEmbeddedServletContainerFactory extends } else { Connector connector = new Connector( "org.apache.coyote.http11.Http11NioProtocol"); - connector.setPort(getPort()); + customizeConnector(connector); this.tomcat.getService().addConnector(connector); this.tomcat.setConnector(connector); } @@ -181,6 +182,14 @@ public class TomcatEmbeddedServletContainerFactory extends context.addServletMapping("*.jspx", "jsp"); } + private void customizeConnector(Connector connector) { + connector.setPort(getPort()); + if (connector.getProtocolHandler() instanceof AbstractProtocol + && getAddress() != null) { + ((AbstractProtocol) connector.getProtocolHandler()).setAddress(getAddress()); + } + } + /** * Configure the Tomcat {@link Context}. * @param context the Tomcat context @@ -339,8 +348,9 @@ public class TomcatEmbeddedServletContainerFactory extends } StandardService service = new StandardService(); service.setName(name); - Connector connector = new Connector("HTTP/1.1"); - connector.setPort(getPort()); + Connector connector = new Connector( + "org.apache.coyote.http11.Http11NioProtocol"); + customizeConnector(connector); service.addConnector(connector); StandardEngine engine = new StandardEngine(); engine.setName(name);