9

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.
5
  • You can look into tiles.
    – bmargulies
    Commented Dec 2, 2014 at 17:32
  • @bmarguiles 'tiles' is a pretty common word; got a link or perhaps an example? I checked maven-tiles-plugin, but it doesn't seem to fit. Also, it might be better to place this as an answer if you've got those bits of info.
    – JJ Zabkar
    Commented Dec 2, 2014 at 17:39
  • can't u create a "grandparent" pom, that will have 2 modules: parent-foo and parent-bar? what is the diff between the parent-foo and parent-bar? can u paste them here?
    – OhadR
    Commented Dec 2, 2014 at 21:10
  • 1
    @OhadR: I updated the post to reflect that the root is the grandparent. Each parent (foo, bar) has a whole build configuration to inherit (example: JKD6 for one JDK8 for another) in addition to separate dependencies. The goal is to have a common+shared root, common+shared children, and independent/intermediary parents such that they can pass their build/configurations on to the children. A grandparent is a singular static entity, and cannot achieve that solution (by itself, w/o modification).
    – JJ Zabkar
    Commented Dec 2, 2014 at 21:20
  • github.com/repaint-io/maven-tiles
    – bmargulies
    Commented Dec 3, 2014 at 3:03

2 Answers 2

15

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.

1

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...

4
  • There are only children, not "foo-children" or "bar-children". My goal with this question is to scale for n parents; while only "foo" and "bar" is trivial (n=2), I'm looking for a solution to the more general case (n>2).
    – JJ Zabkar
    Commented Jan 20, 2015 at 17:43
  • 1
    ok, i think i have now understood... i have created a git repository... i think this is better to explain.. github.com/StefanHeimberg/stackoverflow-27255471 The Problem is that a module can only use on time inside a reactor. the second problem is that properties and dependencies are inherited from parent. and you can only have one parent which is not dynamic configurable through properties because properties are not inherited by parent because the parent is not known if it where dynamic... (chicken egg problem)... Commented Jan 20, 2015 at 18:51
  • for different dependencies or properties i think the best solution would be to use profiles... but you cannot have for example child-1 more than one time inside the same build reactor. but you could create multiple jobs ind your CI. instead of two parents you have only one parent but two profiles. each enabled in the corresponding separated CI Job... but then you must have different working directories with the same source because the target folder is not "sharable" across different profile executions... Commented Jan 20, 2015 at 19:26
  • i know my english isn't the best. but i hope i understood your question and you understand what i mean Commented Jan 20, 2015 at 19:27

Not the answer you're looking for? Browse other questions tagged or ask your own question.