How to use Maven for Dependency Management
In this example we are going to see how you can use maven in order to manage your project dependencies.
Maven is a build automation tool used mainly for java projects from apache.
We are going to see some maven capabilities for managing dependencies in our projects.
For this example we use the following technologies:
- MAC OSX
- Eclipse Mars.1
- Maven3
- JDK 1.8.0_65 64bits
1. Introduction
The maven dependency management mechanism is one of the best features that maven have. You can easily manage all the project dependencies with maven in a easy way, even when you are in a multi-module project with several dependencies, maven can do the task of managing dependencies in a easy way for you.
You can inherit dependencies from a parent project, you can define you own dependencies in a project. You can define dependencies scopes. You can import dependencies, this is specially usefull in large projects once you can only inherit from one pom at most.
Let´s see in details some of the maven capabilities in order to manage dependencies.
2. Transitive dependencies
When you define a dependency in your project, in most cases, that dependency needs its own dependencies too. Since Maven 2 this is made automatically by maven and is know as Transitive dependencies
. There is no limit to the number of levels that dependencies can be gathered from.
This only can be a problem if a cyclic dependency is found, that is, a dependency A depends on an artifact B that depends on an artifact C which depends on artifact A.
This mechanism faces some problems, or potential problems, and you can see how it solve them below
Multiple version of the same artifact
: This capacity is know asdependency meditation
. Since maven 2 thedependency meditation
is resolved using the nearest definition. Maven will use the closest version that is defined in your dependency tree, until maven 2.0.9 if two versions of the same artifact were in the same depth of dependency tree level, maven will no ensure wich one will choose, after maven 2.0.9, the first one (in dependency declaration order) will be choosen.Dependency management
: This allow you to define artifacts version in order to resolve transitive dependencies when no version is defined. You can see more details in the following bullets.Dependency scope
: Allow you to specify the way maven have to manage the dependency, or when that dependency has to be used. You can see more details in the following bullets.Excluded dependencies
: You can exclude an artifact that is added by the transitive dependencies mechanism if you do not need it, or you are using a different version.Optional dependencies
: You can mark a dependency as an optional one, you can see it as a ‘excluded by default’ dependency and only will be added if you add it explicitely
3. Dependency management
If you are in a multi-module project, you can specify in a parent project all the artifact version and it will be inherited by the child projects. In this way you can have all the version in a centralized point, which make easier to mantain the dependencies in your entire project.
If two projects (poms
) use the same dependency, you can easily put it in a dependencyManagement
tag inside a parent project, extend the two poms
with the parent pom
and make the two child poms
easier.
Let´s see an example
parent_pom:
<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.java.code.geeks</groupId> <artifactId>java-code-geeks-parent</artifactId> <version>1.0.1</version> <packaging>pom</packaging> <dependencyManagement> <dependencies> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies> </dependencyManagement> </project>
pom_a:
<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> <artifactId>java-code-geeks-a</artifactId> <version>1.0.1</version> <packaging>pom</packaging> <parent> <groupId>com.java.code.geeks</groupId> <version>1.0.1</version> <artifactId>aca-parent</artifactId> </parent> <dependencies> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </dependency> </dependencies> </project>
pom_b:
<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> <artifactId>java-code-geeks-b</artifactId> <version>1.0.1</version> <packaging>pom</packaging> <parent> <groupId>com.java.code.geeks</groupId> <version>1.0.1</version> <artifactId>aca-parent</artifactId> </parent> <dependencies> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </dependency> </dependencies> </project>
As you can see, the parent pom
defines some artifacts in a dependencyManagement
tag, the pom
1 and 2 inherit from the parent pom
and only have to reference the dependency, the version to use will be determined by the transitive dependencies mechanism.
4. Dependency scope
The dependency scope is useful when you want to define in which environment or build phase you want to use an artifact. There are 6 scopes available:
compile
: This is the default scope if any is indicated. The dependencies are available in all classpaths of a project. All of those dependencies are propagated to the dependent projects.provided
: Use this when you expect that the JDK or the application server carries with him the dependency. Is only avaiable on compile and test classpath and is not transitive.runtime
: Use this scope in order to indicate that the dependency is not required for compile time, but is neccesary for execution. Will be available in test and runtime classpath but not on compile classpath.test
: Use this scope to indicate that a dependency is needed in test phase, it will be available on test compilation and execution classpaths only.system
: Use this to use a local jar on your filesystem. This will no be searched into any repository.import
: Use this inside adependencyManagement
tag. Indicates that thepom
have to be replaced with the dependencies that are defined inside thatpom
.
5. Excluded dependency
Sometime you will have a dependency that depends on another dependencies. Is quite normal that those dependant dependencies get in conflict with another declared or inherited dependency. You can easily exclude a dependency in order to avoid those conficts.
Let´s see an example
exclude_pom:
<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> <artifactId>java-code-geeks-b</artifactId> <version>1.0.1</version> <packaging>pom</packaging> <parent> <groupId>com.java.code.geeks</groupId> <version>1.0.1</version> <artifactId>aca-parent</artifactId> </parent> <dependencies> <dependency> <groupId>com.atomikos</groupId> <artifactId>transactions-hibernate3</artifactId> <scope>test</scope> <exclusions> <exclusion> <artifactId>hibernate</artifactId> <groupId>org.hibernate</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </dependency> </dependencies> </project>
6. Conclusions
Maven has a very high capacity managing dependencies inside projects as you have seen in this example. All those mechanisms will bring you some powerfull ways in order to manage your projects and its dependencies.