What is the `classifier` configuration in the Spring Boot build plugins, and when would you set one?
answer
- classifier = suffix on same coordinates
- default: fat jar replaces plain (.original backup)
- set 'exec' -> plain stays main, fat attached
- needed when module is app AND library
- Gradle 2.5+ plain jar gets '-plain' classifier
basics
~20 sBy default the executable jar replaces the plain jar under the same coordinates. Setting a classifier (e.g. exec) gives the executable jar a suffixed name so both the plain library jar and the executable jar are kept and can be published side by side.
solid answer
~40 sA Maven/Gradle `classifier` is a suffix on an artifact's coordinates (e.g. `app-1.0-exec.jar`) that lets multiple artifacts share the same groupId/artifactId/version. By default Spring Boot's `repackage`/`bootJar` makes the executable jar the *main* artifact — it overwrites the plain jar (Maven saves the plain one as `.original`). If you set `<classifier>exec</classifier>` in Maven, the executable jar is attached under that classifier and the *plain* jar remains the main artifact. This matters when a module is both a runnable app and a library other modules depend on: consumers get the lean plain jar via normal coordinates, while the executable jar is published separately as `...-exec.jar`. In Gradle you achieve the split via the `bootJar` task's `archiveClassifier` (and re-enabling the plain `jar`). Without it, publishing the fat jar as a dependency drags every nested dependency into consumers.
code
java · 14 lines// Maven: keep the plain jar as the MAIN artifact, attach the executable one.
//
// <plugin>
// <groupId>org.springframework.boot</groupId>
// <artifactId>spring-boot-maven-plugin</artifactId>
// <configuration>
// <classifier>exec</classifier>
// </configuration>
// </plugin>
//
// Produces:
// target/app-1.0.jar -> plain library jar (main artifact; consumers resolve this)
// target/app-1.0-exec.jar -> executable fat jar (run with java -jar)
public class ClassifierNotes { }go deeper
May not know classifier exists; fine to just know default replaces the plain jar.
Understands classifier suffixes and the .original backup.
Must explain the app-and-library conflict and configure classifier to keep the plain jar as main artifact.
Owns publication strategy so shared modules never leak fat jars into consumers' classpaths.
**What a classifier is.** In Maven/Gradle coordinates `groupId:artifactId:version[:classifier]`, the *classifier* is an optional suffix that distinguishes multiple artifacts built from the same project — e.g. `-sources`, `-javadoc`, or a custom `-exec`. Files are named `artifactId-version-classifier.jar`. **Default Spring Boot behavior (no classifier).** The `repackage` goal replaces the project's main jar with the executable (fat) jar under the *same* name, and stores the pre-repackage plain jar as `target/<name>.jar.original`. So the artifact your build installs/deploys to a repository is the fat, self-contained one. For a pure application this is exactly what you want. **The problem it causes.** If the same module is *also* used as a compile dependency by another module, publishing the fat jar is bad: the consumer would pull in a jar with all of your app's dependencies nested inside `BOOT-INF/lib`, which is not resolvable as normal transitive dependencies and bloats/pollutes their classpath. You want the consumer to get the *plain* library jar. **Setting a classifier (Maven).** Configuring the plugin with `<classifier>exec</classifier>` changes the split: - The executable jar is *attached* as a secondary artifact named `app-1.0-exec.jar` (classifier `exec`). - The plain jar keeps the *main* coordinates `app-1.0.jar` and is the artifact consumers resolve by default. Now both are published: libraries depend on the main plain jar; your deployment pipeline grabs the `exec` classified jar to run. **Gradle equivalent.** In Gradle the split is expressed via task classifiers. Since Spring Boot 2.5, applying the plugin keeps the standard `jar` task enabled but gives its output the `plain` classifier by convention, so you get both `app-plain.jar` (from `jar`) and `app.jar` (from `bootJar`). You can customize with `bootJar { archiveClassifier = 'boot' }` or `jar { archiveClassifier = '' }`. To publish the plain jar as the library artifact and the boot jar separately, you configure the publication accordingly. **When to set a classifier.** - The module is both runnable and a shared library. (Set one.) - You want to publish a plain jar for tooling/IDE indexing while still deploying an executable jar. (Set one.) - Pure leaf application, nothing depends on it → default is fine, no classifier needed. **Gotchas.** - Forgetting the classifier and then depending on the module drags the fat jar into other builds — a common real-world pollution bug. - The `.original` file is Maven-only default behavior; it's not a published artifact by itself. - In Gradle 2.5+ people are surprised to see two jars (`-plain` + boot); that's the plain-classifier convention, not a bug. To suppress the plain jar entirely, disable the `jar` task.
- You set no classifier and another module depends on this app. What goes wrong?The consumer resolves the fat executable jar as its dependency, pulling in every nested library under BOOT-INF/lib. Those aren't normal transitive deps, so the classpath is bloated/polluted and compilation against them can fail. Use a classifier so the plain jar stays the main artifact.
- In Gradle 2.5+ you see both `app.jar` and `app-plain.jar` — why?The plugin keeps the standard `jar` task enabled but gives its plain output the `plain` classifier by convention, while `bootJar` produces the executable `app.jar`. To emit only the boot jar, disable the `jar` task.
saying these in an interview costs you the question
- Thinking a classifier changes the jar's contents rather than its coordinates/name
- Believing the fat jar is a good compile dependency for other modules
- Assuming the .original file is what gets published to the repository