Classifier
About
The <classifier>
element in Maven is an optional part of artifact coordinates. It is used to distinguish artifacts that are built from the same project but serve different purposes.
The classifier adds an extra label to the artifact name and allows us to attach and retrieve alternate artifacts, such as source code, documentation, or test versions, without changing the main artifact details.
Maven projects may need to generate or consume more than one artifact from the same codebase. Using a classifier helps:
Identify different types of outputs (e.g., main JAR, test JAR, source JAR)
Separate OS-specific or environment-specific builds
Attach custom builds in CI/CD pipelines
Coordinate Format
An artifact with a classifier has this format:
<groupId>:<artifactId>:<version>:<classifier>
Example:
com.example:utility-lib:1.0.0:sources
This refers to the sources JAR of version 1.0.0
of utility-lib
.
1. classifier - sources
What It Means
The sources
classifier is used to publish or consume a JAR file that contains the source code of a Maven project. This is typically used to:
Make the source code available to developers using the library.
Enable IDE features like "Go to definition", "View source", and debugging inside dependencies.
Improve traceability and code visibility during integration or support.
When to Use
We use the sources
classifier when:
We are publishing a library and want to include the readable
.java
source files for other developers.We are consuming a dependency and want to download and attach its source code (commonly done by IDEs).
We want to debug into external library code.
How It Works
-> Without Classifier
Maven typically builds and installs:
my-lib-1.0.0.jar → Compiled .class files
-> With sources
Classifier
An additional artifact is created:
my-lib-1.0.0-sources.jar → Contains .java source files
Both are deployed to the Maven repository, and the sources JAR can be retrieved using the classifier.
Publishing Sources with Maven
Step 1: Use maven-source-plugin
maven-source-plugin
This plugin creates a separate JAR that contains all .java
source files.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
<phase>verify</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
This will generate a my-lib-1.0.0-sources.jar
in the target/
directory and attach it to the build.
Step 2: Install or Deploy
To install to local repository:
mvn clean install
To deploy to remote repository:
mvn clean deploy
Both the main JAR and the sources JAR will be uploaded.
Consuming Source JAR in Another Project
To explicitly add the source JAR via classifier:
<dependency>
<groupId>com.example</groupId>
<artifactId>my-lib</artifactId>
<version>1.0.0</version>
<classifier>sources</classifier>
</dependency>
This will only bring in the my-lib-1.0.0-sources.jar
and not the compiled classes.
Note: In real-world use, developers rarely add the
sources
JAR manually. IDEs like IntelliJ and Eclipse auto-fetch them if available.
2. classifier - classes
What It Means
The classes
classifier is used to generate and attach a JAR containing only the compiled .class
files, excluding other resources, metadata, or bundled dependencies. It differs from the default JAR in that it:
Does not include
META-INF/
,resources/
, or other files fromsrc/main/resources
Is typically used when we need a pure bytecode-only output
When to Use
We might use classifier=classes
when:
We need just the compiled classes to embed or bundle elsewhere.
We are creating multiple variants of our artifact for a framework or platform.
We are building a custom artifact (e.g., a stripped-down version without resources or META-INF).
We are developing a multi-module project where some modules only need raw
.class
files from others (e.g., code generators, transformation tools).
How It Works
Standard Build Output
By default, Maven creates:
my-lib-1.0.0.jar → Includes compiled .class files + resources + META-INF
With classifier=classes
It creates:
my-lib-1.0.0-classes.jar → Only compiled .class files from /target/classes
How to Generate a classes
JAR
classes
JARStep 1: Use maven-jar-plugin
to attach a classes
JAR
maven-jar-plugin
to attach a classes
JAR<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-classes-jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>classes</classifier>
<includes>
<include>**/*.class</include>
</includes>
<excludes>
<exclude>META-INF/**</exclude>
</excludes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Step 2: Run the build
mvn clean package
The target/
directory will contain:
my-lib-1.0.0.jar
(default)my-lib-1.0.0-classes.jar
(only.class
files)
Consuming the classes
JAR
classes
JARIf another module or project wants to depend only on the .class
content, it can declare:
<dependency>
<groupId>com.example</groupId>
<artifactId>my-lib</artifactId>
<version>1.0.0</version>
<classifier>classes</classifier>
</dependency>
This brings in only the stripped-down compiled code.
3. classifier - api
What It Means
The api
classifier is used to attach a JAR containing API specification files—most commonly OpenAPI (Swagger) YAML or JSON files. It allows developers to:
Distribute machine-readable API contracts independently of the main code.
Enable clients or consumers to generate client SDKs.
Share API definition artifacts in CI/CD pipelines.
Version API contracts separately from the implementation logic.
When to Use
Use classifier=api
when:
We want to publish an OpenAPI spec (
openapi.yaml
,openapi.json
) as a standalone artifact.We are working in a contract-first or API-first architecture.
We have multiple teams where one team owns the API and another consumes it.
We want to let consumers generate clients using tools like Swagger Codegen or OpenAPI Generator.
How It Works
Standard Build Output
By default, Maven creates:
my-service-1.0.0.jar → Application classes and resources
With classifier=api
We generate an additional artifact:
my-service-1.0.0-api.jar → Contains only OpenAPI spec files (e.g., openapi.yaml)
This allows publishing and versioning the API specification alongside the service, but independently usable.
How to Generate an api
JAR
api
JARWe manually or automatically place OpenAPI spec files (like openapi.yaml
) under a known directory, and attach them using the maven-jar-plugin
.
Step 1: Place API Spec in a Directory
Place our OpenAPI file at:
src/main/api/openapi.yaml
Step 2: Configure maven-jar-plugin
to attach it
maven-jar-plugin
to attach it<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-api-jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>api</classifier>
<includes>
<include>**/*.yaml</include>
<include>**/*.yml</include>
<include>**/*.json</include>
</includes>
<basedir>${project.basedir}/src/main/api</basedir>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
This tells Maven to package the API files from src/main/api
into a JAR with the api
classifier.
Step 3: Run the Build
mvn clean package
Output:
target/my-service-1.0.0.jar
→ default application JARtarget/my-service-1.0.0-api.jar
→ contains onlyopenapi.yaml
or similar
Consuming the API Spec in Another Project
Other teams or modules can now depend on the published API artifact:
<dependency>
<groupId>com.mycompany.services</groupId>
<artifactId>my-service</artifactId>
<version>1.0.0</version>
<classifier>api</classifier>
</dependency>
This can be used by:
Code generation tools to build client stubs
API documentation sites
Linter/contract validator plugins in CI
4. classifier - javadoc
What It Means
The javadoc
classifier is used to attach a separate JAR that contains Javadoc-generated HTML documentation for a project’s public API. This classifier allows developers to:
Publish human-readable API documentation as a separate artifact.
Let consuming developers explore classes and methods directly in IDEs.
Maintain documentation versioned alongside the codebase.
When to Use
Use the javadoc
classifier when:
We want to distribute HTML documentation for a library.
We are building a reusable SDK or module used by other teams.
We want documentation to be browsable inside IDEs or on artifact repository websites.
We want to expose a stable API to external clients while hiding implementation details.
How It Works
Without Classifier
Standard Maven build produces:
my-lib-1.0.0.jar → compiled code + resources
With classifier=javadoc
We generate an additional artifact:
my-lib-1.0.0-javadoc.jar → contains `index.html` and related Javadoc files
This artifact can be attached and deployed along with the main JAR.
How to Generate a Javadoc JAR
Step 1: Use the maven-javadoc-plugin
maven-javadoc-plugin
Add the following plugin to our pom.xml
:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadoc</id>
<goals>
<goal>jar</goal>
</goals>
<phase>verify</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
This tells Maven to generate Javadoc and attach it as a JAR with classifier javadoc
.
Step 2: Run the Build
mvn clean verify
Output in the target/
directory:
my-lib-1.0.0.jar
→ compiled application/librarymy-lib-1.0.0-javadoc.jar
→ generated API docs
Consuming the Javadoc JAR
To explicitly include the Javadoc artifact:
<dependency>
<groupId>com.example</groupId>
<artifactId>my-lib</artifactId>
<version>1.0.0</version>
<classifier>javadoc</classifier>
</dependency>
Note: In practice, developers rarely add this manually. Tools like IntelliJ IDEA and Eclipse auto-download the Javadoc if available in the repository.
5. classifier - tests
What It Means
The tests
classifier is used to package and attach a JAR that contains the compiled test classes (usually from src/test/java
). This allows us to:
Share common test utilities and base classes between modules.
Create dedicated test libraries reused across projects.
Enable integration tests or functional tests to depend on unit test components of another module.
This JAR is not built by default in Maven and requires manual configuration.
When to Use
Use classifier=tests
when:
We have reusable test utilities, base test classes, or mocks needed in other modules.
We are creating a shared testing framework for an internal team.
We want to isolate test logic from production logic but still distribute it.
We are testing libraries that require simulation or shared mock data.
How It Works
Normal Maven Build
Produces:
my-lib-1.0.0.jar → compiled main classes only
With classifier=tests
We generate:
my-lib-1.0.0-tests.jar → compiled test classes from `src/test/java`
This allows other projects to include test code separately from production code.
How to Generate a Test JAR
Step 1: Use maven-jar-plugin
maven-jar-plugin
Add the following plugin configuration to pom.xml
:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-tests</id>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
This will create a JAR from the src/test/java
directory and attach it with the tests
classifier.
Step 2: Run the Build
mvn clean package
We’ll now see in the target/
directory:
my-lib-1.0.0.jar
→ main compiled codemy-lib-1.0.0-tests.jar
→ compiled test classes only
Consuming the Test JAR in Another Module
Another module that wants to reuse the test classes can add a dependency like:
<dependency>
<groupId>com.example</groupId>
<artifactId>my-lib</artifactId>
<version>1.0.0</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
The
scope
should be set totest
to avoid this code leaking into production classpath.Maven will resolve and include the test-only JAR during test compilation of the consuming module.
6. classifier - platform-specific
What It Means
The platform-specific classifier is used to publish artifacts targeted for a specific operating system or hardware architecture. It allows us to:
Deliver native binaries (
.so
,.dll
,.dylib
) tailored to a platform.Provide different configurations or compiled results per platform.
Maintain consistent artifact coordinates across platforms while delivering different contents.
This classifier is often used in:
JNI (Java Native Interface) bindings
Cross-platform CLI tools
Embedded systems
Libraries that integrate with native SDKs or drivers
When to Use
Use platform-specific classifiers when:
We build and package different binaries per platform (e.g., Linux vs. Windows vs. macOS).
We Java code wraps native libraries using JNI or JNA.
Our app requires platform-specific launchers or shell scripts.
We distribute executable wrappers like
.exe
,.sh
,.bat
.
How It Works
Let’s say our project image-processor
builds a shared native library using C/C++ and JNI. We compile this native library separately for:
Linux (x86_64)
macOS (ARM64)
Windows (x64)
We package each output as a separate artifact with a unique classifier:
image-processor-1.0.0-linux-x86_64.jar
image-processor-1.0.0-mac-arm64.jar
image-processor-1.0.0-windows-x64.jar
All these have the same groupId, artifactId, and version, but differ in classifier.
How to Build and Attach Platform-Specific Artifacts
Step 1: Build native libraries for each platform
We typically do this using external build tools like:
CMake
Gradle with JNI support
Docker (for cross-compilation)
Let’s assume each native binary is named:
libimageproc.so
for Linuxlibimageproc.dylib
for macOSimageproc.dll
for Windows
Step 2: Place the binary in a custom directory, like:
src/main/native/linux-x86_64/
src/main/native/mac-arm64/
src/main/native/windows-x64/
Step 3: Configure maven-jar-plugin
for each classifier
maven-jar-plugin
for each classifierWe can use Maven profiles to create different platform-specific JARs:
<profiles>
<profile>
<id>linux-x86_64</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-linux</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>linux-x86_64</classifier>
<basedir>${project.basedir}/src/main/native/linux-x86_64</basedir>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Repeat for other platforms (mac-arm64, windows-x64) using separate profiles.
Step 4: Build each classifier version
mvn clean package -Plinux-x86_64
mvn clean package -Pmac-arm64
mvn clean package -Pwindows-x64
Each command generates a different artifact with a platform-specific classifier.
Consuming Platform-Specific Artifact
In another project, depending on the runtime platform, use the appropriate dependency:
<dependency>
<groupId>com.example</groupId>
<artifactId>image-processor</artifactId>
<version>1.0.0</version>
<classifier>linux-x86_64</classifier>
</dependency>
To make this dynamic, we can write platform-detection logic or let our CI/CD or packaging tool resolve the correct artifact based on OS.
Last updated
Was this helpful?