Spring Boot
Gradle
Multi Module
Project Build
Troubleshooting

Spring Boot multi module project with Gradle doesn't build

Interview Questions practice on Codemia

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

Browse interview questions

Introduction

Spring Boot multi-module Gradle builds commonly fail because plugin application, dependency scope, or project wiring is inconsistent across modules. Typical symptoms include missing main class detection, unresolved inter-module classes, duplicate boot jars, or tests failing due to incorrect task configuration. The fix is usually architectural rather than a single dependency tweak: keep one executable app module, treat shared modules as plain Java libraries, and centralize version management. This article provides a reliable baseline layout and a debugging sequence to resolve most multi-module build failures.

A stable setup typically has:

  • Root build for shared config.
  • app module as the only Spring Boot executable.
  • core, data, or api modules as plain libraries.

settings.gradle:

groovy
rootProject.name = 'demo-platform'
include 'app', 'core', 'data'

Root build.gradle:

groovy
1plugins {
2    id 'java'
3    id 'io.spring.dependency-management' version '1.1.6' apply false
4    id 'org.springframework.boot' version '3.3.2' apply false
5}
6
7subprojects {
8    apply plugin: 'java'
9    group = 'com.example'
10    version = '1.0.0'
11
12    repositories {
13        mavenCentral()
14    }
15}

Apply Boot Plugin Only Where Needed

Only the runnable module should apply org.springframework.boot.

app/build.gradle:

groovy
1plugins {
2    id 'org.springframework.boot'
3    id 'io.spring.dependency-management'
4}
5
6dependencies {
7    implementation project(':core')
8    implementation project(':data')
9    implementation 'org.springframework.boot:spring-boot-starter-web'
10    testImplementation 'org.springframework.boot:spring-boot-starter-test'
11}

Library modules should not produce boot jars:

core/build.gradle:

groovy
1plugins {
2    id 'java-library'
3}
4
5dependencies {
6    api 'org.slf4j:slf4j-api:2.0.13'
7}

Applying Boot to all modules often causes conflicting packaging tasks.

Dependency and Task Diagnostics

Use Gradle diagnostics before making random edits.

bash
./gradlew projects
./gradlew :app:dependencies --configuration runtimeClasspath
./gradlew :app:bootJar --info

If classes are unresolved, verify module dependency direction. app should depend on core, not the reverse (unless intentionally layered). Circular dependencies between modules can compile partially and fail at runtime or test phase.

If main class detection fails, set it explicitly:

groovy
springBoot {
    mainClass = 'com.example.app.Application'
}

Common Build Failures and Fixes

  • Could not find method implementation() in submodule: plugin mismatch (java not applied).
  • Duplicate classes/resources: overlapping generated sources or improper shading.
  • Tests failing due to missing context classes: module dependency scope wrong (testImplementation vs implementation).
  • Boot jar created for non-app module: disable boot tasks there.
groovy
// In non-app module if boot plugin accidentally applied
bootJar { enabled = false }
jar { enabled = true }

Also verify Gradle and plugin versions are compatible with your Java runtime.

Practical Verification Workflow

A reliable way to avoid regressions is to validate the solution in three passes: baseline, controlled change, and repeatability check. First, capture a baseline outcome before you apply fixes. This could be a failing command, a wrong output sample, a stack trace, or a screenshot of current behavior. Second, apply one focused change and rerun exactly the same checks so you can attribute improvements to a specific edit. Third, rerun the checks multiple times or with slightly different inputs to ensure the fix is not accidental or data-specific.

A lightweight template you can adapt for most projects looks like this:

bash
1# 1) reproduce current behavior
2./run_example.sh > before.txt
3
4# 2) apply your change
5# edit config/code based on this article
6
7# 3) verify behavior after change
8./run_example.sh > after.txt
9diff -u before.txt after.txt

If your environment involves tests, add at least one focused regression test that would fail before the fix and pass after it. This turns a one-time troubleshooting success into a durable maintenance improvement, which is especially important when teams rotate ownership or upgrade dependencies later.

Common Pitfalls

  • Applying org.springframework.boot to every module instead of only the executable app module.
  • Mixing incompatible Gradle, Java, and Spring Boot versions.
  • Declaring inter-module dependencies in the wrong direction and creating cycles.
  • Ignoring settings.gradle includes, so modules exist on disk but not in build graph.
  • Debugging by trial-and-error without using projects, dependencies, and task-specific logs.

Summary

Most Spring Boot multi-module Gradle build failures come from structure and plugin scope, not isolated dependency lines. Keep one boot-enabled app module, keep shared modules as libraries, and verify wiring with Gradle diagnostics. With clear module boundaries and consistent version management, builds become predictable and easier to evolve.


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.