In a multi-module project, how do you keep dependency versions consistent across modules?
answer
- versions in parent dependencyManagement
- version properties ${x.version}
- children omit version
- ${project.version}/${revision} for inter-module
- import external BOMs in parent
basics
~10 sPut a <dependencyManagement> block (and version properties) in the shared parent POM. Child modules declare dependencies without versions, so every module uses the parent's pinned version.
solid answer
~30 sCentralize versions in the reactor's parent POM using `<dependencyManagement>` plus `<properties>` for version numbers (e.g. `${jackson.version}`). Child modules inherit this and declare dependencies without a `<version>`, so a single change in the parent propagates everywhere — no drift. For inter-module references, keep `<version>${project.version}` aligned via a shared property or revision (CI-friendly versioning). If you also consume external version sets, import their BOMs inside the parent's `<dependencyManagement>`. This guarantees that, say, every module uses the same Jackson and the same internal module version, which is essential to avoid classpath conflicts when modules are assembled together.
code
xml · 11 lines<!-- parent -->
<properties><jackson.version>2.17.1</jackson.version></properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
</dependencies>
</dependencyManagement>go deeper
Children should omit versions and inherit them from the parent.
Use dependencyManagement + properties; align inter-module versions with project.version.
Adopt ${revision} CI-friendly versioning and import external BOMs centrally.
Define org-wide version-governance conventions and publish a BOM as the contract.
## The drift problem In a multi-module (reactor) build, if each module declares its own versions, modules can diverge — module A on Jackson 2.16, module B on 2.17 — causing subtle runtime classpath conflicts when they're packaged together. Centralizing fixes this. ## Step 1 — version properties in the parent ```xml <properties> <jackson.version>2.17.1</jackson.version> <junit.version>5.10.2</junit.version> </properties> ``` ## Step 2 — dependencyManagement in the parent ```xml <dependencyManagement> <dependencies> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson.version}</version> </dependency> </dependencies> </dependencyManagement> ``` ## Step 3 — children declare version-free ```xml <dependencies> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> </dependencies> ``` The child inherits the managed version. Change `${jackson.version}` once and all modules move together. ## Inter-module versions For dependencies between your own modules, use `<version>${project.version}</version>` or the **CI-friendly `${revision}`** property so all modules share one version stamp: ```xml <version>${revision}</version> <properties> <revision>1.4.0-SNAPSHOT</revision> </properties> ``` Then `mvn -Drevision=1.4.0 deploy` versions the whole reactor at once. ## Pulling in external version sets Need Spring/Jackson curated sets too? Import their BOMs in the parent's `<dependencyManagement>` (scope=import, type=pom). All children inherit those managed versions automatically. ## Optionally publish your own BOM If downstream teams consume your modules, also publish a BOM so they pin your modules without adopting your parent. The parent governs your internal build; the BOM exports the version contract.
- How do you keep inter-module dependency versions in sync?Use ${project.version} or the CI-friendly ${revision} property so every module shares one version stamp.
- Where do you put external BOM imports for a reactor?In the parent POM's <dependencyManagement> with scope=import; children inherit the managed versions.
saying these in an interview costs you the question
- Repeating versions in every child module (causes drift).
- Hardcoding inter-module versions instead of ${project.version}/${revision}.
- Putting versions in <dependencies> of the parent (forces them onto all children) when you only meant to manage them.