skip to content

What does <optional>true</optional> do on a dependency, and how does it differ from an exclusion?

level: seniorimportance: should knowfreq 55%

answer

  1. producer-side: don't leak to consumers
  2. still used in library's own build
  3. consumer must opt in / redeclare
  4. pluggable backends (Jackson OR Gson)
  5. exclusion = consumer-side, optional = producer-side

basics

~10 s

<optional>true</optional> marks a dependency you use internally but that should NOT propagate to projects that depend on you. It still applies to your own build; it just stops Maven passing it transitively to consumers.

solid answer

~40 s

`<optional>true</optional>` is set by a **library author** on one of their dependencies. For the library's own build, the dependency is used normally. But it is **not propagated transitively** to downstream consumers of the library — Maven treats it as 'optional, declare it yourself if you need that feature'. It's the producer-side way to signal optional features: e.g. a JSON library that can use both Jackson and Gson marks both optional so consumers only pull whichever they actually use. The key contrast with `<exclusions>`: optional is declared by the **producer** and affects **all** downstream consumers globally; an exclusion is declared by the **consumer** and prunes a branch only for that consumer. Both stop transitive propagation, but from opposite ends. If a consumer relies on an optional dependency's feature, they must declare it explicitly themselves.

code

xml · 9 lines
xml
<!-- in the LIBRARY's pom.xml -->
<dependency>
  <groupId>com.google.code.gson</groupId>
  <artifactId>gson</artifactId>
  <version>2.11.0</version>
  <optional>true</optional>
</dependency>
<!-- Consumers of this library do NOT get gson transitively;
     they declare gson themselves only if they use that path. -->

go deeper

for a junior

Know optional means consumers won't automatically inherit that dependency.

for a middle

Explain it's used in the library's own build but not propagated transitively.

for a senior

Design pluggable libraries with optional backends and know it's the producer-side counterpart to consumer exclusions.

for a principal

Define API/packaging conventions: prefer optional for opt-in features, document required declarations for consumers to avoid runtime surprises.

## What it is `<optional>true</optional>` is a flag on a dependency inside a **library's** POM. It means: 'I (the library) use this when building/running my own optional code paths, but I do **not** want to force it onto anyone who depends on me.' ```xml <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.17.0</version> <optional>true</optional> </dependency> ``` ## Effect on the graph - **In the library's own build**: the dependency is present and used as normal (compile/runtime per its scope). - **For a consumer of the library**: Maven does **not** add this dependency transitively. If the consumer wants the optional feature, they must declare it themselves. ## Why authors use it Libraries often support several pluggable backends or features: - A logging facade that can bridge to Log4j2 OR Logback. - A serializer that supports Jackson OR Gson. - A driver that can talk to several databases. Making each backend `optional` keeps consumers slim: nobody is forced to drag in Gson just because Jackson support also exists. The consumer opts in by declaring the one they need. ## optional vs exclusion — the two ends of the wire | Aspect | `<optional>true</optional>` | `<exclusions>` | |---|---|---| | Declared by | the **producer** (library author) | the **consumer** | | Scope of effect | every downstream consumer | only this one consumer's branch | | Intent | 'this is opt-in, decide for yourself' | 'I specifically don't want this here' | | Result | not propagated transitively | pruned from the resolved graph | They are complementary: optional is proactive (set once, helps everyone), exclusion is reactive (fix a graph you didn't author). ## Related: optional dependencies vs profiles `<optional>` does not conditionally include things in your OWN build — it always applies to you. To conditionally activate dependencies in your own build, use `<profiles>`; `<optional>` is purely about not leaking to consumers. ## Verify In a consuming project, `mvn dependency:tree` will simply not show the optional artifact unless the consumer declared it directly.

  • If a consumer depends on your library and needs the optional Gson code path, what must they do?
    Declare the Gson dependency explicitly in their own POM, since optional dependencies are not propagated transitively.
  • Who controls optional vs who controls exclusions?
    Optional is set by the producer/library author and affects all consumers; exclusions are set by the consumer and affect only that consumer's graph.

Like a recipe noting 'garnish optional': the chef who wrote it uses parsley, but anyone copying the recipe isn't forced to buy parsley — they add it only if they want that touch.

saying these in an interview costs you the question

  • Saying <optional> makes the dependency optional in the library's own build — it is fully used there; it only stops transitive propagation.
  • Confusing <optional> with <exclusions>: they act from opposite ends (producer vs consumer).
  • Thinking optional dependencies are downloaded for consumers automatically — they are not.

context