Spring Boot
MVC
Multi-Module
Executable Jar
Java Development

Spring Boot MVC Multi-Module Executeable jar

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

A Spring Boot MVC application can be split into multiple Maven modules without giving up the convenience of a single executable JAR. The usual pattern is to keep shared code in library modules and place the actual Spring Boot application entry point in one top-level web module that depends on those libraries.

The important rule is this: only the module that starts the application should be packaged as the executable Boot JAR. The other modules should behave like normal Java libraries.

A Typical Multi-Module Layout

A clean structure might look like this:

text
1parent-project/
2    pom.xml
3    common/
4        pom.xml
5    service/
6        pom.xml
7    web/
8        pom.xml

Responsibilities are usually divided like this:

  • 'common contains shared models or utility code'
  • 'service contains business logic'
  • 'web contains controllers, templates, and the main application class'

The web module depends on service, and service may depend on common.

Parent pom.xml

The parent project should use pom packaging and list the modules. It can also centralize dependency versions and plugin management.

xml
1<project>
2  <modelVersion>4.0.0</modelVersion>
3  <groupId>com.example</groupId>
4  <artifactId>parent-project</artifactId>
5  <version>1.0.0</version>
6  <packaging>pom</packaging>
7
8  <modules>
9    <module>common</module>
10    <module>service</module>
11    <module>web</module>
12  </modules>
13
14  <properties>
15    <java.version>17</java.version>
16    <spring-boot.version>3.3.0</spring-boot.version>
17  </properties>

This parent does not produce a runnable artifact. It only coordinates the build.

Library Modules Stay as Plain JARs

The common and service modules should usually have standard jar packaging and should not apply the Spring Boot repackage goal.

Example service/pom.xml:

xml
1<project>
2  <parent>
3    <groupId>com.example</groupId>
4    <artifactId>parent-project</artifactId>
5    <version>1.0.0</version>
6  </parent>
7
8  <artifactId>service</artifactId>
9
10  <dependencies>
11    <dependency>
12      <groupId>com.example</groupId>
13      <artifactId>common</artifactId>
14      <version>${project.version}</version>
15    </dependency>
16    <dependency>
17      <groupId>org.springframework</groupId>
18      <artifactId>spring-context</artifactId>
19    </dependency>
20  </dependencies>
21</project>

These modules are just dependencies. They are not standalone applications.

Put the Boot Application in the Web Module

The executable JAR should be built from the module that contains the Spring Boot entry point:

java
1package com.example.web;
2
3import org.springframework.boot.SpringApplication;
4import org.springframework.boot.autoconfigure.SpringBootApplication;
5
6@SpringBootApplication(scanBasePackages = "com.example")
7public class WebApplication {
8    public static void main(String[] args) {
9        SpringApplication.run(WebApplication.class, args);
10    }
11}

Its pom.xml should depend on the other modules and apply the Boot plugin:

xml
1<project>
2  <parent>
3    <groupId>com.example</groupId>
4    <artifactId>parent-project</artifactId>
5    <version>1.0.0</version>
6  </parent>
7
8  <artifactId>web</artifactId>
9
10  <dependencies>
11    <dependency>
12      <groupId>com.example</groupId>
13      <artifactId>service</artifactId>
14      <version>${project.version}</version>
15    </dependency>
16    <dependency>
17      <groupId>org.springframework.boot</groupId>
18      <artifactId>spring-boot-starter-web</artifactId>
19    </dependency>
20    <dependency>
21      <groupId>org.springframework.boot</groupId>
22      <artifactId>spring-boot-starter-thymeleaf</artifactId>
23    </dependency>
24  </dependencies>
25
26  <build>
27    <plugins>
28      <plugin>
29        <groupId>org.springframework.boot</groupId>
30        <artifactId>spring-boot-maven-plugin</artifactId>
31      </plugin>
32    </plugins>
33  </build>
34</project>

When you run mvn package from the parent, the web module produces the runnable JAR that contains classes and dependencies from all referenced modules.

Where MVC Resources Should Live

For a traditional MVC app, keep templates and static assets in the executable web module, because that is the module Spring Boot packages as the application artifact.

Typical locations are:

  • 'web/src/main/resources/templates'
  • 'web/src/main/resources/static'

Shared Java code can live in sibling modules, but the web-facing resources should usually stay close to the Boot entry point so classpath resolution remains predictable inside the final executable JAR.

During development, it is also common to run only the application module:

bash
mvn -pl web spring-boot:run

That command still builds dependent modules as needed, while making it explicit which module owns the application lifecycle.

Controller and Service Wiring Across Modules

As long as the packages are under a common root such as com.example, component scanning works normally across modules.

Controller in web:

java
1@Controller
2public class HomeController {
3    private final GreetingService greetingService;
4
5    public HomeController(GreetingService greetingService) {
6        this.greetingService = greetingService;
7    }
8}

Service in service:

java
1@Service
2public class GreetingService {
3    public String message() {
4        return "Hello from service module";
5    }
6}

The module boundary is a build concern. At runtime, Spring still sees classes on one application classpath.

Common Pitfalls

The most common mistake is applying the Spring Boot repackage plugin in every module. That produces multiple bootable artifacts and complicates the build for no benefit.

Another issue is placing the @SpringBootApplication class in a package that does not cover the service or common modules. If component scanning does not reach those packages, beans will not be discovered.

Dependency direction also matters. The web module can depend on service modules, but shared libraries should not depend back on the web layer.

Finally, remember that the parent module should use pom packaging. If the parent is accidentally configured as a normal jar, the build layout becomes confusing very quickly.

Summary

  • Use a parent Maven project to coordinate multiple Spring Boot MVC modules.
  • Keep shared modules as plain library JARs.
  • Put @SpringBootApplication and the Boot Maven plugin in one application module, usually the web module.
  • Let that one module build the executable JAR and depend on the others.
  • Make sure component scanning covers classes defined in sibling modules.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.