6

There are a few similar questions, but nothing like this. How do you deal with this situation (typical scenario) :

A project of 8-11 child projects, having a parent artifact/project and one main project that mostly uses/declares those others as modules.

The problem is that all projects "strictly" share only the common dependencies, like testng, logging, apache commons and stuff. But always like 3 of them use 50-60% of the same specific deps (apache-chemistry, jackrabbit, abdera, etc.), another 2-3 of them also use 50-60% of the same but different dependencies. And the main one uses a lot of the same deps.

I cannot put those "non-strictly" shared deps into parent project for others to inherit them. So only the common deps are inherited. And there is tons of duplicate dependencies. And I can only manage their versions via <dependencyManagement>.

Another option is having parent pom contain most of the dependencies, but child projects inherit even those they don't need.

I could have more than 1 parent project, but it doesn't feel right. Also inheritance from parent project could be nightmare, because you don't know what dependencies the project needs, if you don't document/comment the parent pom definition properly.

Another way is to create pom artifacts that serves only as dependency containers - they declare specific groups of dependencies, so that modules just declare those to gain transitive dependencies. But hey, would you like to deploy and commit some sort of

OneDepArtifact declaring jackrabit, abdera, chemistry

AnotherDepArtifact declaring htmlcleaner, google-api, tika

ThirdDepArtifact declaring spring, httpclient, selenium

It's a huge mess, I'm not sure if I use <dependencyManagement> correctly, it seems to be only useful for managing dependency versions.

I was thinking of adapting my app development to "maven multimodule design". But If you want to create spring services/beans, that just use various libraries, in one module, you don't implement them in different module, just because they use library that other module also uses :-)

lisak
  • 21,611
  • 40
  • 152
  • 243
  • I have exactly the same problem. I like to manage multimodule project because of the other advantages it brings, but this cross mudule dependency sharing is a nightmare, if the project gets big. – lisak Jun 14 '11 at 18:15
  • Maybe that one has to adapt the actual app development to the multimodule project design and try to create such components so that there wouldn't be any dependencies reuse ... But that doesn't seem to be right – lisak Jun 14 '11 at 18:31

3 Answers3

3

I know you said it might be a nightmare, but I strongly feel inheritance between your parent pom's is the way to go.

I describe a good multi-module project structure in this answer. It also describes using an aggregator and parent-chaining inheritance.

Some things that will help you keep things organized and sane...

  • Use good naming conventions; don't just call the parent projects parent1 and parent2. Use names which describe what kind of dependencies and other things they configure so it is intuitive for people to know which to use when.
  • Use maven's release/deploy feature so that these are versioned in your repo properly and always reference fixed version artifacts. Not using SNAPSHOTs is the first step in having deterministic, reproducable builds. Debugging problems when things are changing on the fly is very difficult.
  • Don't rely on a pom.xml file to know what dependencies your project needs. This will lead you to avoid inheritance and other things like custom profiles. You should use the maven-dependency-plugin to perform these analysis tasks. There are commands like mvn dependency:tree which shows you all the dependencies of a project and mvn dependency:analyze which shows you unused dependencies.

Hopefully, with this advice, parent POM file inheritance won't seem so complicated and nightmarish. Good luck!

Community
  • 1
  • 1
Jesse Webb
  • 43,135
  • 27
  • 106
  • 143
  • I just have a parent dir/pom (inherits from SuperPom and aggregates all 10 modules) and module dirs/pom at the same level. The modules inherit from parent and they are its modules. However I already do everything as you suggest. I believe that I just have to accept it as it is. I don't want chaining inheritance with 3 sub-parents... I'd really rather have all modules declare all those duplicate dependencies across the multimodule project – lisak Jun 14 '11 at 22:15
  • @lisak - Why would you prefer to redeclare all of the duplicate dependencies as opposed to using inheritance? Also, you should try making your parent pom DIFFERENT from the aggregator pom. In my experience, this always makes things easier. I describe this layout in the answer I linked to. – Jesse Webb Jun 15 '11 at 14:49
  • If sharing dependencies is the only aspect that makes the modules siblings, chaining inheritance is imho redundant. If there were also some plugins or build phase things to inherit, why not. But otherwise I find it more easy to work with. Also it is hard to track Unused declared runtime/test dependencies that are listed in dependency:analyze ... simply I don't care if I use it or not, maybe that's the main problem, existence of this feature doesn't bring any relief to me in this case :-) – lisak Jun 15 '11 at 16:27
3

Maven 3.1 should solve this problem by introducing "mixins". In the meantime, it seems that I can get most of the needed features by the proper use of profiles, as I described in this blog post:

http://weblogs.java.net/blog/fabriziogiudici/archive/2011/07/19/maven-pom-composition-means-profiles

Please let me know whether you find it useful.

Fabrizio Giudici
  • 532
  • 3
  • 15
  • the link is broken, page not found – Eddy Hernandez Jun 14 '22 at 16:18
  • Unfortunately the whole site of java.net blogs went off several years ago... But it can be found at archive.org. https://web.archive.org/web/20130301032410/http://weblogs.java.net/blog/fabriziogiudici/archive/2011/07/19/maven-pom-composition-means-profiles – Fabrizio Giudici Oct 30 '22 at 21:23
-1

If its mainly about version (number) control - why not specify only the dependency version as property in the parent project and use it in the child projects, like

Parent

<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>foo.bar</groupId>
    <artifactId>maven-parent</artifactId>
    <version>0.0.1</version>
    <packaging>pom</packaging>

    <properties>
        <log4j.version>1.2.16</log4j.version>
    </properties>

</project>

Child

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

    <parent>
        <artifactId>maven-parent</artifactId>
        <groupId>foo.bar</groupId>
        <version>0.0.1</version>
    </parent>

    <groupId>foo.bar</groupId>
    <artifactId>maven-child</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>
    </dependencies>

</project>

This is a simple solution that let you specify specific project dependencies with consistent version numbers.

FrVaBe
  • 47,963
  • 16
  • 124
  • 157
  • It is not about version control at all, this is only thing that is good for...I don't have problems with version hell, unlike others... I mentioned it in the question, that this is only thing that I have under control ... I combine properties with dependencyManagement, based on what is inherited and what's not – lisak Jun 14 '11 at 19:59
  • The problem is the quantity and duplication of dependencies in all those poms, even if you have versions under control, it is simply very hard to maintain in a big project – lisak Jun 14 '11 at 20:03