Question

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

Was it helpful?

Solution

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.

OTHER TIPS

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!

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top