TomcatEmbeddedServletContainerFactory
has addAdditionalTomcatConnectors()
which allows to have both SSL and non-SSL connectors (see #2167).
This is missing for Undertow.
Comment From: wilkinsona
The concept of adding additional Connectors is Tomcat-specific. Undertow uses a builder to create its configuration. You should use an UndertowBuilderCustomizer
to add a new HTTP listener. For example:
@Bean
public UndertowEmbeddedServletContainerFactory embeddedServletContainerFactory() {
UndertowEmbeddedServletContainerFactory factory = new UndertowEmbeddedServletContainerFactory();
factory.addBuilderCustomizers(new UndertowBuilderCustomizer() {
@Override
public void customize(Builder builder) {
builder.addHttpListener(8080, "0.0.0.0");
}
});
return factory;
}
I'll add something to the documentation for others to reference
Comment From: ceefour
Wow! Thanksssss
On Thu, Jan 8, 2015, 01:05 Andy Wilkinson notifications@github.com wrote:
Closed #2191 https://github.com/spring-projects/spring-boot/issues/2191 via 735b96d https://github.com/spring-projects/spring-boot/commit/735b96dd0f5009ac01043de0dcc183a58aac8d40 .
— Reply to this email directly or view it on GitHub https://github.com/spring-projects/spring-boot/issues/2191#event-215437644 .
Comment From: masbaehr
If someone sees this in 2018 and is using SpringBoot 2.x the new code for this is:
import org.springframework.boot.web.embedded.undertow.UndertowBuilderCustomizer;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import io.undertow.Undertow.Builder;
@Bean
public UndertowServletWebServerFactory embeddedServletContainerFactory() {
UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();
factory.addBuilderCustomizers(new UndertowBuilderCustomizer() {
@Override
public void customize(Builder builder) {
builder.addHttpListener(8080, "0.0.0.0");
}
});
return factory;
}
Comment From: AlexTMjugador
I was interested in configuring both listeners for Undertow in Spring Boot 2.6 and wanted to make the builder customizer read the port and bind address from properties in application.properties
(or application.yml
). This was harder than I expected, because although the WebServerFactoryCustomizer
Javadoc warns about how early in the lifecycle this bean is initialized, the way it's worded requires quite a bit of digging and knowledge of how Spring works to make sense of and can be too abstract.
Just injecting the properties with @Value
did not work, and I had a bit of a circular dependency problem, because the @Configuration
class where I needed to put the @Bean
method highlighted above also seemingly required a servlet to be available for further configuration (it was the same class where I configured the HttpSecurity
and similar objects, and exceptions were thrown about a missing servlet context). What ended up working for me was the following:
- I made the bean-returning method
static
. The effects of this are nicely explained in the@Bean
annotation Javadoc but, in short, doing this avoids instantiating the configuration class to retrieve this bean, so the circular dependency problem goes away.
@Bean
public static WebServerFactoryCustomizer<UndertowServletWebServerFactory> alternateListenSocketCustomizer() {
return new EnvironmentAwareWebServerFactoryCustomizer();
}
- I defined the
EnvironmentAwareWebServerFactoryCustomizer
class referenced by the previous method, which implements bothWebServerFactoryCustomizer<UndertowServletWebServerFactory>
andEnvironmentAware
. I went withEnvironmentAware
due to@Value
and@Autowired
probably not working as I'd expect, according to the Javadoc of bothWebServerFactoryCustomizer
and@Bean
.
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
// Other imports...
final class EnvironmentAwareWebServerFactoryCustomizer implements WebServerFactoryCustomizer<UndertowServletWebServerFactory>, EnvironmentAware {
private Environment environment;
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
@Override
public void customize(UndertowServletWebServerFactory factory) {
factory.getBuilderCustomizers().add(
builder -> builder.addHttpListener(
environment.getRequiredProperty("server.http.port", Integer.class),
environment.getProperty("server.http.address")
)
);
}
}
I hope this saves someone else's time, or even inspires someone to make this seemingly simple task of setting up several listeners more ergonomic in more use cases. This issue comes as a top search result for the topic and is mentioned in a related StackOverflow answer, too.