0

I am trying to set up an embedded Tomcat using Spring Boot with two connectors (a HTTP and a HTTPS) and a shared executor for both of them.

I have configured the HTTPS connector on the Spring Boot application.properties and then added the HTTP connector programatically as described in the documentation.

However, I don't see any option to use the same Executor for both connectors. I would like to translate into Spring Boot's configuration this kind of setup:

<Executor name="tomcatSharedThreadPool" namePrefix="catalina-exec-" 
    maxThreads="150" minSpareThreads="4"/>

<Connector executor="tomcatSharedThreadPool"
           port="80" protocol="HTTP/1.1" 
           connectionTimeout="20000" 
           redirectPort="443" />
<Connector executor="tomcatSharedThreadPool"
           port="443" protocol="HTTP/1.1" 
           connectionTimeout="20000" />

Anyone know a way to do this ?

Thanks.

Community
  • 1
  • 1
  • Even though this question is older, there is a duplicate one with better title = easier to find... – Betlista Feb 08 '18 at 13:24
  • Possible duplicate of [Configure Spring Boot with two ports](https://stackoverflow.com/questions/36357135/configure-spring-boot-with-two-ports) – Betlista Feb 08 '18 at 13:24

2 Answers2

2

Consider this adapted snippet from my blog post: Configuring Tomcat to Listen on Multiple ports using Spring Boot

@Configuration
public class EmbeddedTomcatConfiguration {

    @Value("${server.port}")
    private String serverPort;

    @Value("${management.port:${server.port}}")
    private String managementPort;

    @Value("${server.additionalPorts:null}")
    private String additionalPorts;

    @Bean
    public EmbeddedServletContainerFactory servletContainer() {
        TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
        Connector[] additionalConnectors = this.additionalConnector();
        if (additionalConnectors != null && additionalConnectors.length > 0) {
            tomcat.addAdditionalTomcatConnectors(additionalConnectors);
        }
        return tomcat;
    }

    private Connector[] additionalConnector() {
        if (StringUtils.isBlank(this.additionalPorts)) {
            return null;
        }
        Set<String> defaultPorts = Sets.newHashSet(this.serverPort, this.managementPort);
        String[] ports = this.additionalPorts.split(",");
        List<Connector> result = new ArrayList<>();
        for (String port : ports) {
            if (!defaultPorts.contains(port)) {
                Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
                connector.setScheme("http");
                connector.setPort(Integer.valueOf(port));
                result.add(connector);
            }
        }
        return result.toArray(new Connector[] {});
    }
}

So far no executor has been set, feel free to test adding these lines after tomcat.addAdditionalTomcatConnectors(additionalConnectors);:

tomcat.addConnectorCustomizers(new TomcatConnectorCustomizer() {

                @Override
                public void customize(Connector connector) {
                    ProtocolHandler handler = connector.getProtocolHandler();
                    if (handler instanceof AbstractProtocol) {
                        AbstractProtocol<?> protocol = (AbstractProtocol<?>) handler;
                        protocol.setExecutor(<your executor bean>);
                    }
                }
            });
ootero
  • 3,235
  • 2
  • 16
  • 22
0

In order to the executor to be managed by Tomcat, you have to add your custom executor to the Tomcat service so that it is integrated into the Tomcat lifecycle.

To achieve this, use the method addConnectorCustomizersof the TomcatEmbeddedServletContainerFactory. Then, in the connector customizer, you can access the Tomcat service so that your custom executor can be added to the Tomcat lifecycle and set to each connector.

public class MultipleConnectorCustomizer implements TomcatConnectorCustomizer {
@Override
public void customize(final Connector pConnector) {
    // Create shared Tomcat executor
    Service tomcatService = pConnector.getService();
    StandardThreadExecutor executor = createExecutor();
    tomcatService.addExecutor(executor);

    // Customize default connector (HTTPS created by the TomcatEmbeddedServletContainerFactory)
    ProtocolHandler handler = pConnector.getProtocolHandler();
    if (handler instanceof AbstractProtocol) {
        AbstractProtocol<?> protocol = (AbstractProtocol<?>) handler;
        protocol.setExecutor(executor);
    }

    // Create additional redirected HTTP connector
    Connector additionalConnector = new Connector(fTomcatProperties.getProtocol().getProtocol());
    additionalConnector.setPort(fTomcatProperties.getHttpRedirectedPort().intValue());
    additionalConnector.setRedirectPort(fServerProperties.getPort().intValue());
    ProtocolHandler additionalHandler = additionalConnector.getProtocolHandler();
    if (additionalHandler instanceof AbstractProtocol) {
        AbstractProtocol<?> protocol = (AbstractProtocol<?>) additionalHandler;
        protocol.setExecutor(executor);
    }

    tomcatService.addConnector(additionalConnector);
}