What is the purpose of Mavens dependency declarations classifier property?

Learn what is the purpose of mavens dependency declarations classifier property? with practical examples, diagrams, and best practices. Covers java, maven, dependency-management development techniq...

Understanding Maven's Dependency Classifier Property

Hero image for What is the purpose of Mavens dependency declarations classifier property?

Explore the purpose and practical applications of the 'classifier' property in Maven dependency declarations, enhancing build flexibility and artifact management.

Maven's dependency management is a cornerstone of Java project development, simplifying the inclusion of external libraries. While most dependencies are straightforward, some scenarios require more granular control over which specific variant of an artifact is included. This is where the classifier property comes into play. It allows developers to distinguish between different types of artifacts generated from the same project coordinates (groupId, artifactId, version).

What is a Classifier?

In Maven, a dependency is uniquely identified by its groupId, artifactId, and version. However, a single project might produce multiple artifacts with the same core coordinates but different content. For example, a project might generate a standard JAR file containing compiled classes, a source JAR containing the source code, a Javadoc JAR containing API documentation, or even platform-specific native libraries. The classifier property serves as an additional discriminator to select these specific variants.

flowchart TD
    A[Maven Project Build] --> B{Standard JAR}
    A --> C{Source JAR}
    A --> D{Javadoc JAR}
    A --> E{Test JAR}

    B -- groupId:artifactId:version --> F[Default Dependency]
    C -- groupId:artifactId:version:sources --> G[Source Dependency]
    D -- groupId:artifactId:version:javadoc --> H[Javadoc Dependency]
    E -- groupId:artifactId:version:tests --> I[Test Dependency]

    subgraph Artifacts with Classifiers
        G
        H
        I
    end

How Maven Classifiers Distinguish Artifacts

Without the classifier, Maven would default to the primary artifact (usually the main JAR). The classifier provides a mechanism to explicitly request a non-primary artifact. It's an optional element in the dependency declaration, used only when the default artifact is not sufficient or the project produces multiple distinct artifacts.

Common Use Cases for Classifiers

The classifier property is particularly useful in several common scenarios:

1. Source and Javadoc JARs

Many IDEs (like IntelliJ IDEA or Eclipse) can automatically attach source code and Javadoc to third-party libraries, enabling easier debugging and API exploration. These are typically published as separate JARs with classifiers sources and javadoc respectively.

<dependency>
    <groupId>org.example</groupId>
    <artifactId>my-library</artifactId>
    <version>1.0.0</version>
    <classifier>sources</classifier>
</dependency>

<dependency>
    <groupId>org.example</groupId>
    <artifactId>my-library</artifactId>
    <version>1.0.0</version>
    <classifier>javadoc</classifier>
</dependency>

Declaring dependencies for source and Javadoc JARs

2. Test JARs

Sometimes, a project might want to share utility classes or test data specifically for testing purposes. These can be packaged into a 'test-jar' artifact, which is then consumed by other modules for their tests.

<!-- In the producing project's POM -->
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>3.3.0</version>
            <executions>
                <execution>
                    <goals>
                        <goal>test-jar</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

<!-- In a consuming project's POM -->
<dependency>
    <groupId>org.example</groupId>
    <artifactId>my-library</artifactId>
    <version>1.0.0</version>
    <type>test-jar</type>
    <scope>test</scope>
</dependency>

Producing and consuming a test-jar artifact

3. Platform-Specific or Variant Builds

For projects that need to provide different binaries for various operating systems, architectures, or specific configurations, classifiers are invaluable. For instance, native libraries might have windows-x64, linux-arm, or macos classifiers.

<dependency>
    <groupId>com.example</groupId>
    <artifactId>native-lib</artifactId>
    <version>2.1.0</version>
    <classifier>windows-x64</classifier>
</dependency>

<dependency>
    <groupId>com.example</groupId>
    <artifactId>native-lib</artifactId>
    <version>2.1.0</version>
    <classifier>linux-arm</classifier>
</dependency>

Requesting platform-specific native library variants

4. Fat JARs / Shaded JARs

When a project needs to produce a 'fat JAR' (a single executable JAR containing all its dependencies) alongside its regular JAR, the fat JAR can be given a classifier like shaded or all.

<!-- In the producing project's POM (using maven-shade-plugin) -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.4.1</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
                <finalName>${project.artifactId}-${project.version}-shaded</finalName>
                <classifier>shaded</classifier>
            </configuration>
        </execution>
    </executions>
</plugin>

<!-- In a consuming project's POM -->
<dependency>
    <groupId>org.example</groupId>
    <artifactId>my-app</artifactId>
    <version>1.0.0</version>
    <classifier>shaded</classifier>
</dependency>

Producing and consuming a shaded JAR with a classifier

Best Practices and Considerations

When working with classifiers, keep the following in mind:

1. Consistency is Key

Ensure that the classifiers used in your dependency declarations precisely match the classifiers defined in the producing project's pom.xml or generated by its build plugins. A mismatch will result in Maven being unable to find the artifact.

2. Understand Default Behavior

If no classifier is specified, Maven will always attempt to resolve the primary artifact (the one without a classifier). This is usually the main JAR file containing compiled classes.

3. Avoid Ambiguity

While Maven allows arbitrary classifier names, it's best to stick to widely recognized conventions (sources, javadoc, tests, shaded, bin, client, etc.) to improve readability and maintainability.

4. Impact on Transitive Dependencies

The classifier property only affects the direct dependency you declare. It does not automatically propagate to transitive dependencies. If a transitive dependency also has classified artifacts you need, you must declare it explicitly with its own classifier.