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.
- Add the ssl connector.
- 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. ) - When the ssl connector initialization complete, you can get the chosen port with getLocalPort() call.
- 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
You can
setRedirectPort
after server was startedYou 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())