Difference Between <optional>true</optional> and <scope>provided</scope>

Furkan Danışmaz
3 min readSep 7, 2018

--

Dependency management is one of the main functionality provided by maven. Whatever dependency we need, we just add them to the POM.xml. All the necessary classes and resources are automatically added to the classpath of our project thanks to maven.

While adding dependencies, we can use the optional flag, or set the scope to “provided”. In both cases, the dependencies will be in the classpath of the module where they are declared, but they will not be added transitively in other projects using the module that defines them as dependencies.

In this story, I will try to explain the difference between using the optional flag and setting the scope to provided and when to use which one of them through an example.

Dependency Graph

In this example, the Project A is our application which uses Project B. Therefore, we should add Project B inside the POM.xml of Project A

The POM.xml of Project A

<dependency>
<groupId>some.company</groupId>
<artifactId>project-b</artifactId>
</dependency>

The POM.xml of Project B

<dependency>
<groupId>some.company</groupId>
<artifactId>project-c</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>some.company</groupId>
<artifactId>project-d</artifactId>
<scope>provided</scope>
</dependency>

Project C is defined as optional and Project D is defined as provided in Project B. Therefore, they will be available during the compile time of the Project B.

But, they both will not be available in Project A’s classpath. So, if you try to use any class of Project C or D in Project A, you will get a compilation error unless you manually add them to the POM.xml of Project A.

It seems like both using “optional flag” and “provided scope” have similar effects. So what is the difference and when to use which one of them?

Using The Optional Flag

In the example above, we defined Project C as an optional dependency in Project B. By doing this, we actually mean that:

“Project B has many features but during the development of some features we have used some capabilities of Project C. However, those features are optional, that means you don’t have to use them in your project. Therefore, you don’t need Project C in your classpath unless you want to use those features of Project B that depends on Project C”

If you want to use those features of Project B that depends on Project C, then you need to add Project C in your application explicitly:

The POM.xml of Project A, in this case, should look like:

<dependency>
<groupId>some.company</groupId>
<artifactId>project-b</artifactId>
</dependency>
<dependency>
<groupId>some.company</groupId>
<artifactId>project-c</artifactId>
</dependency>

The Provided Scope

Project D is added with “provided” scope in Project B. Adding dependency with provided scope is logically different than adding a dependency with the optional flag. In this case, we are telling that the dependency will be provided by the runtime environment of our module. There is no optional feature in this case.

In the example above, if we need to use functionalities of Project D directly in Project A (if we need Project D at compile time), again we need to declare Project D dependency in the POM.xml of Project A.

The POM.xml of Project A, in this case, should look like:

<dependency>
<groupId>some.company</groupId>
<artifactId>project-b</artifactId>
</dependency>
<dependency>
<groupId>some.company</groupId>
<artifactId>project-d</artifactId>
<scope>provided</scope>
</dependency>

Note that, Project D is again added with the provided scope because we know that it will be provided by the runtime environment of Project A.

--

--