Can maven parent project include a module at same directory level

13,488

Solution 1

To answer the question in the title of this post:

Yes, Maven can include parent and module at same directory level. I feel I first have to explain that a parent can have children and modules. Children and modules are not the same thing:

  • Child relationship is defined through parent in the child POM. If your parent is in the repo, that's that. If your parent is on the file system, you have to play with parent.relativePath for it to be found in the same folder
  • Module is defined through modules in the parent POM. Module typically contains a folder name, and the POM file is implied (e.g. <module>mod</module> is equivalent to <module>mod/pom.xml</module>). Hence a module in the same folder would be <module>pom1.xml</module> or something. (I called the module's POM file pom1.xml in this example, assuming that pom.xml is already taken by the parent — see what a mess we're getting ourselves in)

Let me quickly given an example where children and modules are distinctly different: you may have POMs to build the application of each of your teams. Each of your team may have webapps and backend apps. You may have parent POMs for webapps and backend apps. So some backend app would be a child of the POM for backend apps, while being a module of the team that is working on it.


A thing that strikes me is that you're talking about packaging. A parent POM (packaging pom) is typically just a blob of metadata and nothing else. If you want it to be something else you can still attach plugin executions to lifecycle phases. You can even run packaging plugins and attach the results to the artifact.


I didn't understand why hive cannot be a child (own folder, own POM in that folder), nicely one level down from the parent, how Maven had meant it to be. But it sounded to me like you could have some project, in whatever other directory, be dependent on the jar artifact in hive, and turn it into whatever assembly you want. So hive would be a dependency of the assembly project (let's say hive-assembly). That is getting to my next point...


The fact that Maven does in fact let you have parent and child in the same folder is not at all a good argument for doing so. It's only a matter of time for some part of Maven or one of its plugins is going to work against you. Maven is "convention over configuration", live by that!

Solution 2

This issue could be solved by using maven's Project Aggregation instead of Project Inheritance.

Solution 3

Please refer the simple examples given in maven site: http://maven.apache.org/guides/introduction/introduction-to-the-pom.html#Project_Inheritance_vs_Project_Aggregation

Which clearly explains when do you want to have parent-child relationship or package-modules relationship or parent-modules relationship(combination of both).

Example with Spring Boot projects:

I use all my sprint boot projects with spring boot starter project as parent, so here i am having parent -child relationship.

For packaging, i have separate pom file in the root directory( or relative path) that defines all the modules in it. But there is no reference of my parent project in my modules. so here i am using it as a package-module relationship.

But recently changed my configuration to use parent-modules relationship, created a parent pom file and referred spring boot starter projects as my parent with in it. finally used my parent references in all of my child modules. So this way i am using it as combination of both models.

Share:
13,488
WestCoastProjects
Author by

WestCoastProjects

R/python/javascript recently and before that Scala/Spark. Machine learning and data pipelines apps.

Updated on June 30, 2022

Comments

  • WestCoastProjects
    WestCoastProjects almost 2 years

    I am working in an established codebase with an existing standalone pom.xml.

    Th intention is to incorporate a child project called "hive" in a subdirectory off of the parent one. Note: the hive/pom.xml does already exist and it works fine by itself.

    So in the parent's pom.xml I added:

       <modules>
          <module>hive</module>
       </modules>
    

    The problem is I basically lose ability to create the deployable jar from the parent project.

     stephenb@gondolin:/shared/git2/etl$ mvn package assembly:single
    [INFO] Scanning for projects...
    [INFO] ------------------------------------------------------------------------
    [ERROR] FATAL ERROR
    [INFO] ------------------------------------------------------------------------
    [INFO] Error building POM (may not be this project's POM).
    
    
    Project ID: com.myco.etl:etl
    POM Location: /shared/git2/etl/pom.xml
    Validation Messages:
    
        [0]  Packaging 'jar' is invalid. Aggregator projects require 'pom' as packaging.
    
    
    Reason: Failed to validate POM for project com.myco.etl:etl at /shared/git2/etl/pom.xml
    
    
    [INFO] ------------------------------------------------------------------------
    [INFO] Trace
    org.apache.maven.reactor.MavenExecutionException: Failed to validate POM for project com.myco.etl:etl at /shared/git2/etl/pom.xml
        at org.apache.maven.DefaultMaven.getProjects(DefaultMaven.java:404)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:272)
        at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:138)
        at org.apache.maven.cli.MavenCli.main(MavenCli.java:362)
        at org.apache.maven.cli.compat.CompatibleMain.main(CompatibleMain.java:60)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    

    It seems that maven wants me to create a parent pom that basically does nothing except define the dependency modules.

    Well I can create a new pom.xml. But what I cannot do is to push the existing project files into a new subdirectory.

    Is there a way to work around this? E.g. defining a submodule that lives at the same level (not subdir)? Or some other way to work with the existing dir structure?

    thanks

    Follow-up: Based on input that a module can simply be a file in local dir, I created another pom that calls the original one. The original one was renamed to pommod.xml and the new one shown below is called pom.xml.

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.myco.etl</groupId>
        <artifactId>etl</artifactId>
        <name> ETL Helpers</name>
        <version>1.0.0-SNAPSHOT</version>
        <packaging>pom</packaging>
            <modules>
      <module>appminer</module>
      <module>pommod.xml</module>
       </modules>
    

    I ran "mvn compile package" But still get same error:

    Project ID: com.myco:app_miner
    POM Location: /shared/git2/etl/mycopom.xml
    Validation Messages:
    
    [0]  Packaging 'jar' is invalid. Aggregator projects require 'pom' as packaging.
    
    
    Reason: Failed to validate POM for project com.myco:app_miner at /shared/git2/etl/myco/pom.xml
    
  • WestCoastProjects
    WestCoastProjects almost 11 years
    I used your tip about having a module just be a pomXX.xml file. Still have issues and have updated the original post.
  • Sander Verhagen
    Sander Verhagen almost 11 years
    Perhaps share just a little bit more POM detail of the projects involved. Which one are you building, how does it fail?
  • WestCoastProjects
    WestCoastProjects almost 11 years
    It seems necessary to have two different pom's; one for pom target as the parent and the other for the jar file. It then works - though v inconvenient.
  • Sander Verhagen
    Sander Verhagen almost 11 years
    What are you missing if you declare the parent as pom? What does not work? I was thinking that through lifecycle binding of plugins you should be able to achieve what you want. (executions.execution.phase etc.)