JUnit test with Embedded tomcat server , how to specify automatic ports for both http and https connectors? JUnit test with Embedded tomcat server , how to specify automatic ports for both http and https connectors? jenkins jenkins

JUnit test with Embedded tomcat server , how to specify automatic ports for both http and https connectors?


I have two solutions for this problem:

Select SSL port manually

The ServerSocket(0) constructor automatically selects a free port. The Tomcat uses this method also.

try (ServerSocket testSocket = new ServerSocket(0)) {    int randomFreePort = testSocket.getLocalPort();     sslConnector.setPort(randomFreePort);    defaultConnector.setRedirectPort( randomFreePort);} // At this point the testSocket.close() calledtomcat.start();

I know, there is a probability, that an another process allocates the same port between the testSocket.close() and tomcat.start(), but you can detect this situation, with LifecycleState.FAILED.equals(sslConnector.getState()) test.

Use lifecycle listeners

Tomcat connectors are lifecycle aware, so you will be notified on 'before_init' and 'after_init' events. Tomcat initializes the connectors in the order as you added them to the Service.

  1. Add the ssl connector.
  2. Add an http connector. (That will be the 'default' connector. Don't call the mTomcat.getConnector() because it gets the first or creates a new connector. )
  3. When the ssl connector initialization complete, you can get the chosen port with getLocalPort() call.
  4. Before the http connector initialization, call the setRedirectPort

Full example:

    Tomcat mTomcat = new Tomcat();    Connector sslConnector = getSSLConnector();     mTomcat.getService().addConnector(sslConnector);        Connector defaultConnector = new Connector();    defaultConnector.setPort(0);    mTomcat.getService().addConnector(defaultConnector);    // Do the rest of the Tomcat setup    AtomicInteger sslPort = new AtomicInteger();    sslConnector.addLifecycleListener(event->{        if( "after_init".equals(event.getType()) )            sslPort.set(sslConnector.getLocalPort());    });    defaultConnector.addLifecycleListener(event->{        if( "before_init".equals(event.getType()) )            defaultConnector.setRedirectPort(sslPort.get());    });    mTomcat.start();


I haven't tried it but from the code it looks like

  1. You can setRedirectPort after server was started

  2. You can use Connector.getLocalPort to get actual port

So I think you could try to add something like

mTomcat.start(); // <-- your existing codedefaultConnector.setRedirectPort(SSLConnector.getLocalPort())