Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maven: Multiple Parent POMs?

I have a multi-module foo project with the following POM structure:

Foo

Foo POM Structure

/pom.xml             (root/'grandparent' POM)
/parent-foo/pom.xml  (a parent with 'foo' dependencies & configurations) 
/child-1/pom.xml     
...
/child-n/pom.xml   

Foo POM Inheritance

This standard parent-child relationship has parent-foo inherit from the root, and child-n inherit from parent-foo.

root -> parent-foo -> child-n

This is all well & good, and works fine for this trivial case.

(Future) Use Case

Using parent-foo works for the foo-based legacy use case, but also test the future use case that we're migrating too: bar.

Bar

Bar POM Structure

/pom.xml             (root POM)
/parent-bar/pom.xml  (a parent with 'bar' dependencies & configurations) 
/child-1/pom.xml     
...
/child-n/pom.xml 

Bar POM Inheritance

root -> parent-bar -> child-n

Question

Can I achieve the following reactor build without having to do the workaround each time to modify the child-n POMs? Or, something like it? Or, is Maven simply the wrong tool for this use case?

[INFO] ------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] 
[INFO] root ............................................... SUCCESS
[INFO] parent-foo ......................................... SUCCESS
[INFO] child-1 ............................................ SUCCESS (foo parent)
[INFO] ...
[INFO] child-n ............................................ SUCCESS (foo parent)
[INFO] parent-bar ......................................... SUCCESS
[INFO] child-1 ............................................ SUCCESS (bar parent)
[INFO] ...
[INFO] child-n ............................................ SUCCESS (bar parent)
[INFO] ------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------

Ideally, I'd like to just have it all in one reactor build, with each child-n compiled & used with each parent-*'s inherited dependencies. I know it would leave my Maven repo in an undesired state, but at least I could plug the reactor build into my CI and get assurance that my build ran on both parent-* dependency platforms.

Current Workaround

The current workaround is to modify all the child-n POMs' parents, such that:

# 1. modify all child-n POMs
   # Old:
      root -> parent-foo -> child-n
   # New:
      root -> parent-bar -> child-n
2. Run reactor build effective with 'root -> parent-bar -> child-n' dependency tree

Edit 1:

  • Noted root POM was essentially the "grandparent" POM, per @OhadR's comment.
  • Noted that both 'foo' and 'bar' are more than just dependency inheritance providers; they also provide build configuration--if they had only provided dependencies, a Maven profile-based solution would have sufficed.
like image 217
JJ Zabkar Avatar asked Dec 02 '14 17:12

JJ Zabkar


2 Answers

short answer Maven doesn't support multiple inheritance, it indirectly supports the concept by using the "import" scope in the dependency management section

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>other.pom.group.id</groupId>
            <artifactId>other-pom-artifact-id</artifactId>
            <version>SNAPSHOT</version>
            <scope>import</scope>
            <type>pom</type>
        </dependency>   
    </dependencies>
</dependencyManagement> 

as its in the management section, the only inconvenience is you have to declare the dependencies explicitly, but... what you have achieved is:

having different poms - each managing a group of related dependencies. The projects only need to import these poms and then use the dependencies without worry about the dependency version. essentially this keeps the parent poms simple and lean.

like image 52
Junchen Liu Avatar answered Oct 06 '22 01:10

Junchen Liu


how are the dependencies between the child-n projects? only inside each parent-* or accross the parents-*?

if i where you, i would create something like this:

/pom.xml                                    (Parent POM for all projects)

/project-foo/pom.xml                        (BOM for Project Foo. only dependencyManagement for foo-* artefacts)
/project-foo/parent/pom.xml                 (Parent POM for Project Foo. dependencyManagement for external used artifacts. ev.including import of bar BOM)
/project-foo/parent/foo-child1/pom.xml      (Child Artifact fron Project Foo)
/project-foo/parent/foo-child2/pom.xml      (Child Artifact fron Project Foo)
/project-foo/parent/foo-child3/pom.xml      (Child Artifact fron Project Foo)

/project-bar/pom.xml                        (BOM for Project Bar. only dependencyManagement for bar-* artefacts. ev.including import of foo BOM)
/project-bar/parent/pom.xml                 (Parent POM for Project Bar)
/project-bar/parent/bar-child1/pom.xml      (Child Artifact fron Project Bar)
/project-bar/parent/bar-child2/pom.xml      (Child Artifact fron Project Bar)
/project-bar/parent/bar-child2/pom.xml      (Child Artifact fron Project Bar)

i think you have a countinuous integration/build job per Project (Foo / Bar). then you could point it to your /project-*/pom.xml

Link from official maven page: http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Management

i hope i have fully understand your problem...

like image 27
StefanHeimberg Avatar answered Oct 06 '22 01:10

StefanHeimberg