Bhaskar Karambelkar's Blog

Maven best practices: Use dependency management for multi module projects.

 

Tags: maven java


Do you struggle to maintain a common configuration for dependencies (version #, type etc.), between various modules of your multi-module maven 2.x project ? There is a very easy way to control all your dependency related configurations from the parent ‘pom’ project.

Instead of specifying the same kind of configuration for dependencies over and over, in various modules, just specify them once inside the <dependencyManagement> node of the parent pom.xml.

What ever configurations are done in the ‘dependencyManagement’ section of the parent pom.xml, are automatically inherited by the child projects. Typical configurations include a version number of the dependency artifact, a list of transitive dependencies to exclude, when including this dependency, the default scope of the dependency, etc. Infact when properly configured, any sub project needs to specify only the group-id and artifact-id of a required dependency, everything else is inherited from the parent pom.xml.

Just think about it for a second, a clear simple way to have the same version of log4j jars in all your sub modules, A clear way to have junit.jar scope set to ‘test’ in all sub projects. And when you need to change the version of a dependency, you just need to do it in one place, and bam. every child project now referes to the newer version of your dependency.

Here’s a code sniplet of ‘dependencyManagement’ block in one of my parent pom.xml

<project....>
  ......
  <packaging>pom</packaging>
  ............
  <dependencymanagement>
     <dependencies>
         <dependency>
               <groupid>commons-logging</groupid>
               <artifactid>commons-logging</artifactid>
               <version>${commons.logging.version}</version>
               <exclusions>
                   <exclusion>
                       <groupid>log4j</groupid>
                       <artifactid>log4j</artifactid>
                   </exclusion>
                   <exclusion>
                       <groupid>logkit</groupid>
                       <artifactid>logkit</artifactid>
                   </exclusion>
                   <exclusion>
                       <groupid>avalon-framework</groupid>
                       <artifactid>avalon-framework</artifactid>
                   </exclusion>
                   <exclusion>
                       <groupid>javax.servlet</groupid>
                       <artifactid>servlet-api</artifactid>
                   </exclusion>
               </exclusions>
           </dependency>
          ..........
       </dependencies>
  </dependencymanagement>
  <properties>
     <commons.logging.version>1.1</commons.logging.version>
  </properties>
</project....>

As you can see, I have 2 things here, I have specified a default version that all subsequent children projects will inherit, and I have also specified a bunch of transitive dependencies that I want to exclude from this dependency.

Now all a child project needs to do is

<project>
···<packaging>jar</packaging>
···<dependencies>
···      <dependency>
               <groupid>commons-logging</groupid>
               <artifactid>commons-logging</artifactid>
······</dependency>
···.....
···</dependencies>
</project>

Everything else is inherited from the parent, and when commons-logging is out with a new version, that I need to use I need to change the version # in just one place.

WARNING Beware that any dependency specified in ‘dependencyManagement’ section is not an actual dependency on either the parent project nor the child project, unless it is explicitly specified as one, in the regular ‘dependencies’ block. So in short dependencyManagement is a place to configure all possible dependencies that your sub-projects may have, but not a place to actually state a dependency. e.g. for the above configuration, a child project will not have a dependency on commons-logging unless it includes it in its pom.xml.

Another thing to keep in mind, is that many IDEs that have the ability to work with maven projects (Eclipse, Netbeans etc), might not give you this functionality of managing dependencies from ‘dependencyManagement’ block , so you may have to do this part by hand. In my case, where I use Netbean 6.0 IDE, the IDE picks up correct dependency attributes from the parent pom, only if the files already have the stuff setup before opening the project. If I add a dependency inside the pom.xml of an open parent project, and then refer to it in a open child project, the maven plugin gets confused, and refuses to recognize the child project as a valid maven project. The only solution in that case is to restart the IDE :(.

Hope you have found this little piece of information helpful.