- 🔍 The Maven install phase does not automatically compile all modules unless you set it up that way.
- ⚙️ Modules with
pompackaging, no source code, or inactive profiles often get skipped duringmvn install. - 🛠️ Plugin bindings to specific build phases like
compileare important for each module to be part of the build. - 🧪 CI/CD pipelines should use
mvn clean installorverifyto make sure multi-module builds always work the same way. - 🧰 Maven’s
-Xdebug flag shows which modules were skipped and if any plugin steps did not run during the build.
If you work on a multi-module Maven project and find that mvn install does not compile all modules, you are not alone. Knowing how Maven’s build phases work with plugin settings and module setups helps fix this common issue. We will look at Maven’s build process to find out why these problems happen and how to set up your project so all modules compile reliably.
Understanding the Maven Lifecycle
In Maven, a "lifecycle" sets the order for running build goals. The default lifecycle is common for standard projects. It includes these main phases:
validate: checks that the project’s structure is correctcompile: compiles the project’s source codetest: runs tests using a suitable testing frameworkpackage: packages the compiled code (JAR/WAR)verify: runs additional checks on the results of packaginginstall: installs the file into the local Maven repositorydeploy: copies the final package to a remote repository
Each phase also includes the ones before it. For example, when you run mvn install, it also runs verify, package, test, and compile.
But, the build phases do not run everything unless you have specific plugins and setups. The Maven compiler plugin usually connects only to the compile and test-compile phases. You need to set it up otherwise. This means running mvn install alone may not compile all sources unless every module has the right plugin connections.
🔗 Reference: Maven Build Lifecycle
Maven Modules Overview
A multi-module Maven project has one parent POM. This parent POM contains a list of submodules. Each submodule has its own POM file. This way, things are better organized, different parts can be worked on at the same time, and common settings can be used again.
Here’s a simple version:
<modules>
<module>core</module>
<module>api</module>
<module>web</module>
</modules>
The parent POM file often has settings for managing dependencies, repositories, plugin versions, and general properties. Submodules can change or use these settings if needed.
How each module acts depends a lot on its packaging type. Most modules use jar or war. But some, like utility or aggregator modules, might use pom. A module with packaging=pom usually does not have Java code. So, it does not get compiled, even when you run mvn install.
You must understand how each module type is set up and what it does. For instance, if you think a pom-type module will compile, you might wonder why mvn install does not compile everything.
Why mvn install Might Not Compile All Modules
People often think that running mvn install means every module and every file gets compiled. But this is not always true. This happens because of different project settings and plugin setups. Let's look at why modules might be skipped during installation:
1. Wrong Packaging Type
Modules with packaging set to pom will not compile any Java code. These modules mainly hold other dependencies together.
2. No Source Files Present
If a module has no Java source files (meaning src/main/java is empty or missing), Maven may skip the compile step for that module.
3. Modules Included by Profile
Modules that are part of Maven profiles will only run if you activate those specific profiles in the build command (for example, -Pdev).
4. Plugin Not Connected to Any Phase
If a module’s POM is missing the maven-compiler-plugin or other needed plugins, Maven has no compiler logic to run for that module.
5. Optional Module Declaration
An optional module linked through dependencies in pom.xml might not run if certain things are true (like missing dependencies or excluded scopes).
When these things come together, developers sometimes run mvn install and then find that some modules were not built.
Plugin Binding: How the Problem Starts
Maven plugins do specific tasks (like compile, test, copy-resources). You must connect them to a phase using the <executions> block inside a module’s pom.xml. Without this connection, Maven does not know when to run a plugin goal.
For example, the Maven Compiler Plugin works to compile Java code. It usually connects to compile and test-compile by default:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
If this plugin is not set up (especially in projects that do not get it from the parent POM), then the compile phase does nothing for that module. And then, install cannot finish the way you want.
🔗 Reference: Maven Compiler Plugin
Using mvn install -X to Find Module Problems
The -X debug flag is very helpful for finding out why a module was skipped during a build. It shows the detailed decisions Maven makes while running.
mvn install -X
This command will show full logs. These logs include plugin connections, skipped modules, and reasons for running. Look for messages like:
Skipping execution: nothing changed
Module XYZ not built due to missing executions
No sources found to compile
These messages can help you fix module setups, missing connections, or issues with dependency order.
Common Reasons Modules Don’t Compile
Let's list the common reasons why your modules might not compile without telling you:
❌ Missing Module Declaration
If a module is not listed inside the <modules> tag of the parent POM, mvn install will not build it.
🔧 Plugin Misconfiguration
Modules need the right plugin setups, especially for build tasks like the compiler, surefire, or jar plugins.
🤐 Silent Skips Due to No Content
Maven quietly skips modules that have no source code or ignored dependencies. This is common if the packaging type means no build output.
🗂️ Profile-based Exclusion
If a module is only part of a Maven profile and that profile is not active, the module is skipped.
🏗️ Lifecycle Binding Issues
Goals like compile, test-compile, package only run if plugins connected to them are active. This needs proper <execution> tags when the default settings are not enough.
How to Make All Modules Compile
To make sure every module gets processed, compiled, and rebuilt completely, use this command:
mvn clean install
The clean command removes old build files (the target/ folder). This helps make sure no old parts are used again. This is important in multi-module setups. An old binary from one module could cause problems for another module's testing or packaging phase.
You can also use more Maven command-line options for building specific parts:
👥 --also-make
This builds a module along with all the modules it depends on. This is helpful when you work on modules further down the line.
mvn install --projects api --also-make
📦 --projects
This builds only the modules you name, and sometimes their dependencies.
Comparing Maven Lifecycle Goals
Knowing what each common Maven goal does helps you pick the right build phase for what you need:
| Goal | Description |
|---|---|
compile |
Compiles the main source code of the project |
package |
Compiles and packages code into a JAR/WAR |
install |
Installs built parts into the local .m2/repository |
deploy |
Puts the package into a remote repository |
verify |
Checks if the package is ready with more tests or checks |
Tips:
mvn compile: will not install or export anything.mvn package: makes the actual output (JAR/WAR), but does not install it.mvn install: installs parts locally. This is key for resolving dependencies in multi-module workflows.
Using all of them together:
mvn clean compile package install
This command ensures your whole project structure is rebuilt completely.
Good Ways to Handle Multi-Module Maven Builds
Here are some standard rules for keeping your build processes reliable:
- ✅ Use
<dependencyManagement>in your parent POM to manage dependencies and their versions in one place. - ✅ Keep all modules listed under
<modules>and do not use unofficial links. - ✅ Use
mvn verifyin CI to find missed plugin phases or test failures. - ✅ Write down Maven profiles and what they do clearly, so teams do not get confused.
- ✅ Set up builds that always produce the same result using the Maven Wrapper.
Keeping a well-ordered module structure, where modules depend on each other, stops many problems. These problems happen when a module compiles fine locally but then breaks in CI/CD.
Bonus Tip: IDE vs CLI – What Is Different
Integrated Development Environments (IDEs) like IntelliJ IDEA or Eclipse often build projects in ways that are not exactly like Maven’s lifecycle. They might:
- Use their own compilers that only build what changed.
- Compile only files that have been changed.
- Find dependencies in a different way than the Maven command line.
Because of this:
- Things "work" in the IDE but fail on the command line or in CI.
- Plugin connections that are not set up well do not show errors until you try to deploy.
- Some modules pass checks in the IDE but fail actual tests.
To avoid unexpected bugs, always check your builds with the command line (mvn clean install) and in CI pipelines.
Real-World Example: Fixing a Skipped Module Build
Let's say your build setup is fine, but the api module is not compiling. When you run:
mvn install -X
…you see this:
Skipping execution: plugin not bound to the lifecycle phase
✅ Solution:
Add specific plugin connections inside api/pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Now run:
mvn clean install
…and check that api and other modules are properly compiled and installed.
When You Need More Control: Custom Lifecycle Bindings
Standard lifecycle connections cover most cases. But some setups might need custom phase connections for plugins. Developers can connect plugin tasks to different phases like verify, install, or even pre-site. This allows for custom checks or code generation rules.
Example:
<execution>
<id>force-compile-on-install</id>
<phase>install</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
⚠️ Always write down custom phase connections carefully. They change how Maven usually works and can make things confusing for others who work on the project later.
Keep Your Builds Clean and Complete
Working well with Maven in a multi-module setup means you understand how the Maven lifecycle works. It also means you know what plugin connections do and how to handle module setups.
By using mvn clean install, checking plugin setups, and knowing about profile and packaging settings, you can make sure every module compiles and installs the way it should.
📘 Organizations like Sonatype say that over 60% of Java teams now use multi-module builds with Maven. Knowing this skill helps a lot in big Java projects.
More Information
- Apache Maven Lifecycle Documentation
- Maven Compiler Plugin Documentation
- Maven Wrapper — helpful for consistent builds in teams
Citations
- Apache Maven Project. (n.d.). Introduction to the Build Lifecycle. https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
- Apache Maven Compiler Plugin. (n.d.). Introduction. https://maven.apache.org/plugins/maven-compiler-plugin/
- DeBellis, A., & Selvin, D. (2021). Java DevOps Best Practices. O’Reilly Media.
- Sonatype. (2020). The State of the Software Supply Chain Report.