Dependency: an artifact, on which your Maven project depends.
Transitive dependency: a dependency of one of your projects' dependencies.
A fundamental feature of Maven that allows developers to specify the exact version of which artifact their projects depend on.
Dependency mediation: what should be done when multiple versions of the same dependency are encountered?
Dependency exclusion: we can specifically exclude dependencies to avoid redundancies.
Optional dependencies: excluded by default for downstream projects to avoid
To write the following code:
import java.io.IOException;
import org.apache.http.client.fluent.Request;
public class HelloWorld {
public static void main(String[] args) throws IOException {
String content = Request.Get("http://example.com")
.execute()
.returnContent()
.asString();
System.out.println(content);
}
}
We must import the following dependency:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>fluent-hc</artifactId>
<version>4.5.12</version>
</dependency>
Note that the org.apache.httpcomponents:fluent-hc:4.5.12
library depends on:
org.apache.httpcomponents:httpclient:4.5.12
, which also depends on:
commons-codec:commons-codec:1.11
org.apache.httpcomponents:httpcore:4.4.13
commons-logging:commons-logging:1.2
commons-logging:commons-logging:1.2
This allows us to do:
import java.io.IOException;
import org.apache.http.client.fluent.Request;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class HelloWorld {
public static void main(String[] args) throws IOException {
String content = Request.Get("http://example.com")
.execute()
.returnContent()
.asString();
System.out.println(content);
Log log = LogFactory.getLog("My log");
log.info("Log this, please.");
}
}
Dependency scopes can help to limit the transitivity of the dependencies. They also modify the classpath for different build tasks. Maven has six default dependency scopes.
And it's important to understand that each scope — except for import — has an impact on transitive dependencies.
Apache HttpClient
, Guava
, Apache Commons IO
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>fluent-hc</artifactId>
<version>4.5.12</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.1.1-jre</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
MySQL JDBCs
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
<scope>runtime</scope>
</dependency>
Junit 5
and Truth
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.truth</groupId>
<artifactId>truth</artifactId>
<version>1.1.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baeldung</groupId>
<artifactId>custom-dependency</artifactId>
<version>1.3.2</version>
<scope>system</scope>
<systemPath>${project.basedir}/libs/custom-dependency-1.3.2.jar</systemPath>
</dependency>
This scope was added in Maven 2.0.9 and it's only available for the dependency type pom.
<dependency>
<groupId>com.baeldung</groupId>
<artifactId>custom-project</artifactId>
<version>1.3.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
Let us add junit 5's dependencies in our pom.xml
:
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.6.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.6.1</version>
<scope>test</scope>
</dependency>
For this, we will also need to adjust the version of the surefire plugin.
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
</plugins>
We can now create a unit test.
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class MyTest {
@Test
void addition() {
Assertions.assertEquals(2, 2);
}
}
We can compile and run our test file by executing:
$ mvn clean test
What if we try to use a class in junit's package in our main
method?
import org.junit.jupiter.api.Assertions;
public class HelloWorld {
public static void main(String[] args) {
Assertions.assertEquals(2, 2);
}
}
$ mvn clean compile
The build will fail, as we declared our dependencies using:
<scope>test<scope>
If we remove this line or change its value to compile, we will be able to "see" it at compile time.
Dependencies are managed by the Maven Dependency Plugin.
Important "goals":
dependency:tree
: shows the dependency tree.dependency:go-offline
: downloads all dependencies so we can compile the project offline.dependency:purge-local-repository
: deletes and re-resolves artifacts from the local repository.dependency:sources
: downloads dependencies' source files.