Backend Development 8 min read

How to Run Multiple Tomcat Instances in Spring Boot 3 – A Step‑by‑Step Guide

This tutorial shows how to configure Spring Boot 3 to start multiple Tomcat servers, isolate services into separate modules with shared parent configuration, and test the endpoints, providing full code snippets and screenshots for each step.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
How to Run Multiple Tomcat Instances in Spring Boot 3 – A Step‑by‑Step Guide

Environment: Spring Boot 3.2.5.

1. Introduction

By default a Spring Boot project embeds a Tomcat server, which simplifies development and deployment. Adding Actuator and configuring management.server.port moves the Actuator endpoints to a separate Tomcat instance.

<code>management:
  server:
    port: 7000</code>

After changing the Actuator port, the console shows two Tomcat instances; all Actuator endpoints run on the Tomcat listening on port 7000 (the /ac prefix was also changed).

Developers can use SpringApplicationBuilder to start multiple Tomcat instances, isolating resources while sharing the main application configuration.

2. Practical Example

The project is organized into two modules ( com.pack.m1.* and com.pack.m2.* ) that share a parent module ( com.pack.parent.* ). Each module has its own configuration file ( m1.properties , m2.properties ) analogous to the default application.yml / application.properties .

2.1 Define Modules

Module 1 configuration class:

<code>@Configuration
@ComponentScan(basePackages = {"com.pack.m1"})
@PropertySource({"classpath:m1.properties"})
@EnableAutoConfiguration
public class M1Config {
}</code>

Module 1 test controller:

<code>@RestController
@RequestMapping("/m")
public class M1Controller {
    private final ParentService parentService;
    public M1Controller(ParentService parentService) {
        this.parentService = parentService;
    }
    @GetMapping("/index")
    public Object m1() {
        return "module 01 -" + this.parentService.query();
    }
}</code>

Configuration file m1.properties :

<code># m1.properties
server.port=8075
server.servlet.context-path=/m1</code>

Module 2 mirrors Module 1 with its own package and properties:

<code>@Configuration
@ComponentScan(basePackages = {"com.pack.m2"})
@PropertySource({"classpath:m2.properties"})
@EnableAutoConfiguration
public class M2Config {
}
@RestController
@RequestMapping("/m")
public class M2Controller {
    private final ParentService parentService;
    public M2Controller(ParentService parentService) {
        this.parentService = parentService;
    }
    @GetMapping("/index")
    public Object m2() {
        return "module 02 - " + this.parentService.query();
    }
}

# m2.properties
server.port=8076
server.servlet.context-path=/m2</code>

2.2 Parent Module Definition

Shared service:

<code>@Service
public class ParentService {
    public String query() {
        return "I am parent module content";
    }
}</code>

Parent configuration class:

<code>@Configuration
@ComponentScan(basePackages = {"com.pack.parent"})
public class ParentConfig {
}</code>

Note: No Web MVC is enabled, so a controller in the parent module would not be active without additional container configuration.

2.3 Global Configuration File

The default application.yml is still applied unless spring.config.name is changed:

<code>spring:
  application:
    name: springboot-parent-child
---
logging:
  include-application-name: false
  pattern:
    dateformat: HH:mm:ss</code>

Put shared settings here if child modules need to inherit them.

2.4 Startup Class

<code>public class SpringbootParentChildApplication {
    public static void main(String[] args) {
        SpringApplicationBuilder builder = new SpringApplicationBuilder();
        // Configure parent container (non‑web)
        builder.parent(ParentConfig.class)
               // Configure first child as a web container
               .child(M1Config.class).web(WebApplicationType.SERVLET)
               // Configure sibling child container sharing the same parent
               .sibling(M2Config.class).web(WebApplicationType.SERVLET)
               .run(args);
    }
}</code>

No @SpringBootApplication annotation is added; the builder manually creates the parent and child contexts.

2.5 Test

After starting the application, the console shows two Tomcat instances on ports 8075 and 8076. Accessing the endpoints returns the expected responses from each module and the shared parent service.

Module 1 response:

Module 2 response:

Javamicroservicesbackend developmentSpring BootTomcat
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.