We have a modular project with about 10 artifacts:
parent
+- artifact1
+- artifact2
+- artifact3
+- ...
+- artifact10
Furthermore, some of the artifacts have dependencies among each other:
artifact1
+-> artifact2
+-> artifact3
+-> ...
+-> artifact10
artifact2
+-> artifact3
artifact4
+-> artifact3
artifact4
+-> artifact5
artifact5
+-> artifact6
Our current setup looks like this:
- parent is an artifact containing the parent POM.
- This parent POM defines all necessary dependencies (like Spring, JPA, ...) in .
- All of our artifacts are defined in , too.
- Our artifacts reference the parent artifact as - stating the obvious - parent.
- Only the parent POM defines versions. All other POMs don't.
We use a versioning scheme with three numbers:
<major version>.<minor version>.<patch level>
For example:
0.1.0-SNAPSHOT (a young artifact in development)
0.1.0 (the same artifact once it has been released)
0.1.1 (the same artifact after a hotfix)
The problem:
Once we change the version of an artifact (e.g.: 0.1.0 => 0.1.1), our parent artifact version (12.7.3) needs to be updated because it references the old artifact version (0.1.0). Since we change this reference in the parent POM (0.1.0 => 0.1.1), we need to increase the parent POM's version, too (12.7.3 => 12.7.4). Now, our artifact still references the previous parent version (12.7.3), i.e. we need to update it again... That's circular.
What is the best way to resolve such circular parent-child relationships? We could remove our own dependencies from the parent POM and define their versions in all of the other artifact's POMs but this implies that we would need to update all artifacts once a dependency changed.
EDIT
A simplified directory structure that contains our artifacts:
.
├── [api:0.14.0-SNAPSHOT]
│ ├── pom.xml
│ └── src
│ ├── main
│ │ ├── java ...
│ │ └── webapp ...
│ └── test
├── [dao:1.21.0-SNAPSHOT]
│ ├── pom.xml
│ └── src
│ ├── main ...
│ └── test ...
├── [parent:0.11.0-SNAPSHOT]
│ ├── pom.xml
│ └── src
│ ├── main ...
│ └── test ...
├── [pdf-exporter:0.2.0-SNAPSHOT]
│ ├── pom.xml
│ └── src
│ ├── main ...
│ └── test ...
├── [docx-exporter:0.3.0-SNAPSHOT]
│ ├── pom.xml
│ └── src
│ ├── main ...
│ └── test ...
├── [exporter-commons:0.9.0-SNAPSHOT]
│ ├── pom.xml
│ └── src
│ ├── main ...
│ └── test ...
└── [security:0.6.0-SNAPSHOT]
├── pom.xml
└── src
├── main ...
└── test ...
The artifact directories (in square brackets; along with the artifact version) are independent from each other, i.e. they are only in a common root directory (".") for convenience. Every artifact has its own git repository. "api" is the artifact that gets deployed on an application server. All artifacts reference "parent" like this (during development):
<parent>
<groupId>com.acme</groupId>
<artifactId>parent</artifactId>
<version>0.11.0-SNAPSHOT</version>
</parent>
<artifactId>api</artifactId>
<version>0.14.0-SNAPSHOT</version>
Scenario:
- exporter-commons gets an update: 0.9.0-SNAPSHOT => 0.9.1-SNAPSHOT.
- docx-exporter and pdf-exporter reference exporter-commons without version, i.e. no change is necessary.
- parent needs to be updated to reflect the update of exporter-commons: 0.11.0-SNAPSHOT => 0.12.0-SNAPSHOT.
Problem: api:0.14.0-SNAPSHOT references parent:0.11.0-SNAPSHOT. api:0.14.0-SNAPSHOT is then updated to reference parent:0.12.0-SNAPSHOT. api:0.14.0-SNAPSHOT becomes api:0.15.0-SNAPSHOT. But the pom.xml in parent:0.12.0-SNAPSHOT references api:0.14.0-SNAPSHOT.
=> Vicious circle.
(Note: The artifact names are made up for simplicity.)