I’m trying to expose a separate REST API in my Spring Boot application, bound to a different port from the default server and management ports. To achieve this, I created a new TomcatServletWebServerFactory and bound the new port to the container. I also set up a new GenericWebApplicationContext and linked my REST controller to this context.
Additionally, I transferred the default parent context to the new context, so that the beans and configurations are shared between them.
However, when I attempt to launch the new child context, I encounter a PortInUseException. Despite this error, the application itself continues running, but the new port doesn’t open as expected.
Here’s an outline of my approach:
- Created a new TomcatServletWebServerFactory.
- Set a custom port for the new container.
- Created a new GenericWebApplicationContext.
- Transferred the parent context for bean access.
- Connected the REST controller to the new context.
Issue: The new context throws a PortInUseException, and the separate port fails to start, even though the main service continues functioning normally. How can I resolve this issue and get the new port working?
Any guidance or insights would be greatly appreciated. Thank you!
Tomcat Configuration Class:
@Slf4j
@Configuration
public class TopologyServerConfig {
private final ApplicationContext defaultCtx;
@Value("${server.topology.port:8099}")
private int topologyServerPort;
@Value("${spring.lifecycle.timeout-per-shutdown-phase:3000}")
private long timeOutPerShutdownPhase;
public TopologyServerConfig(ApplicationContext defaultCtx) {
this.defaultCtx = defaultCtx;
}
@Bean
public ServletWebServerFactory topologyServletContainer() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.setPort(topologyServerPort); // Set port to 8099
return factory;
}
@EventListener(ApplicationReadyEvent.class)
public void startTopologyCtxAfterDefaultCtx() {
log.info("Default context is fully started. Now starting topology context on port {}...", topologyServerPort);
// Create a new context for the topology server
GenericWebApplicationContext topologyCtx = new GenericWebApplicationContext();
topologyCtx.setParent(defaultCtx);
topologyCtx.registerBean(StreamTopologyDisplayController.class);
topologyCtx.registerBean(ServletWebServerFactory.class, this::topologyServletContainer);
topologyCtx.registerShutdownHook();
try {
ServletWebServerFactory topologyFactory = topologyServletContainer();
WebServer topologyServer = topologyFactory.getWebServer(servletContext -> {
topologyCtx.setServletContext(servletContext);
topologyCtx.refresh();
});
topologyServer.start(); // <- exception happening form this line
log.info("Topology web server started at port {}", topologyFactory.getWebServer().getPort());
} catch (Exception e) {
log.error("Failed to start topology web server on port " + topologyServerPort, e);
System.exit(1);
}
}
}
REST Controller class:
@Slf4j
@RestController
@RequestMapping("/topology")
public class StreamTopologyDisplayController {
@GetMapping
public String getStreamTopology() {
log.info("hit the getStreamTopology");
if (Constant.STREAM_TOPOLOGY_DESCRIPTION.isEmpty()) {
return "Not Found";
}
return Constant.STREAM_TOPOLOGY_DESCRIPTION;
}
}
Exception:
org.springframework.boot.web.server.PortInUseException: Port 8097 is already in use
Issue: The new context throws a PortInUseException, and the separate port fails to start, even though the main service continues functioning normally. How can I resolve this issue and get the new port working?
Any guidance or insights would be greatly appreciated. Thank you!