When would you choose maven-shade-plugin over the spring-boot-maven-plugin or maven-assembly-plugin for packaging?
answer
- shade = flatten + relocate + transformers
- spring-boot = nested BOOT-INF/lib + custom loader
- assembly = arbitrary archives, no relocation
- shade for libs/plugins/big-data
- don't shade a Boot app
basics
~20 sUse shade when you need a flattened uber-JAR with package relocation and smart resource merging — typically for libraries, Maven plugins, or big-data jobs. Use spring-boot-maven-plugin for Spring Boot apps, and assembly only for simple bundles or non-JAR archives.
solid answer
~40 sAll three produce 'all-in-one' artifacts but differ structurally. **maven-shade-plugin** flattens every dependency's classes into one JAR and uniquely supports **relocation** (renaming packages to dodge version conflicts) and **resource transformers** (merging `META-INF/services`, `reference.conf`, manifests). That makes it the right tool for **published libraries, Maven plugins, and Spark/Hadoop/Flink jobs** that must bundle deps without polluting the host classpath. **spring-boot-maven-plugin** builds a *nested-JAR* executable (deps stay as whole JARs under `BOOT-INF/lib`, loaded by Boot's custom classloader) and adds layered images/buildpacks — use it for Spring Boot apps. **maven-assembly-plugin** can produce arbitrary archive layouts (tar.gz, zip, dir) and a `jar-with-dependencies`, but can't relocate or merge SPI files intelligently. Rule: shade for flattened/relocatable JARs and libraries; spring-boot for Boot services; assembly for distributions or non-JAR bundles.
code
xml · 12 lines<!-- Library that bundles + hides Guava: shade with relocation -->
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<configuration>
<relocations>
<relocation>
<pattern>com.google.common</pattern>
<shadedPattern>mylib.shaded.guava</shadedPattern>
</relocation>
</relocations>
</configuration>
</plugin>go deeper
Knows shade makes a fat JAR; may not distinguish the alternatives.
Can name the three plugins and their basic output formats.
Chooses correctly per use case and explains the nested-vs-flattened layout difference.
Sets packaging conventions across archetypes, governs shaded-library publishing, and optimizes container layering choices.
## Three tools, three layouts They all answer 'bundle my app with its dependencies' but produce different artifacts: ### maven-shade-plugin — flattened uber-JAR - **Unpacks** all deps and merges classes into one flat JAR. - Unique strengths: **relocation** (rename packages to avoid consumer version clashes) and **resource transformers** (merge `META-INF/services`, manifests, `reference.conf`). - Best for: **published libraries / Maven plugins** (relocate Guava/protobuf so they don't leak), **big-data jobs** (Spark/Flink clusters that already ship conflicting libs), CLIs. ### spring-boot-maven-plugin — nested executable JAR - Keeps each dependency as a **whole JAR** under `BOOT-INF/lib/` and your classes under `BOOT-INF/classes/`; a custom **Spring Boot loader** reads nested JARs. - Adds: `Main-Class` launcher, **layered JARs** for efficient Docker caching, **buildpacks** (`build-image`), `repackage` goal. - Best for: **Spring Boot applications**. Don't shade a Boot app — flattening breaks Boot's loader assumptions and duplicate-resource handling. ### maven-assembly-plugin — arbitrary archives - Driven by **assembly descriptors**; can output `tar.gz`, `zip`, a directory tree, or `jar-with-dependencies`. - Cannot relocate packages or smart-merge SPI files (last-wins on `META-INF/services`). - Best for: **distributions** (app + scripts + config + docs in a tarball), or simple fat JARs where you don't need relocation. ## Decision guide | Need | Choose | |------|--------| | Published library/plugin that bundles deps without leaking versions | **shade** (with relocation) | | Spark/Flink/Hadoop job JAR | **shade** | | Spring Boot microservice | **spring-boot-maven-plugin** | | Distribution tarball/zip with non-JAR files | **assembly** | | Quick fat JAR, no relocation, no SPI merging | assembly or shade | ## Governance notes (principal lens) - **Libraries should generally NOT publish shaded artifacts** as their *only* form — it hides versions from consumers' dependency management and breaks BOM-driven upgrades. If you must, publish a separate classifier (e.g. `:shaded`). - Standardize the packaging plugin per project archetype in a **parent POM** so teams don't mix approaches. - For containers, prefer **layered Spring Boot images** or jib over a monolithic shaded JAR for better layer caching.
- Why is shading a Spring Boot application discouraged?Boot's executable JAR relies on a nested-JAR layout and custom classloader; flattening with shade breaks that structure and can mishandle duplicate auto-config resources.
- How can a library bundle deps without forcing them on every consumer?Publish a shaded artifact under a separate classifier (e.g. artifact:shaded) so consumers opt in, while the default artifact keeps a clean POM.
Shade blends all ingredients into one batter; Spring Boot packs labeled containers in a lunchbox with its own opener; assembly ships a whole gift basket of separate items.
saying these in an interview costs you the question
- Saying shade and spring-boot produce the same JAR layout
- Recommending shade for a standard Spring Boot service
- Claiming assembly can relocate packages or merge SPI files like shade