skip to content

When would you choose maven-shade-plugin over the spring-boot-maven-plugin or maven-assembly-plugin for packaging?

level: principalimportance: should knowfreq 35%

answer

  1. shade = flatten + relocate + transformers
  2. spring-boot = nested BOOT-INF/lib + custom loader
  3. assembly = arbitrary archives, no relocation
  4. shade for libs/plugins/big-data
  5. don't shade a Boot app

basics

~20 s

Use 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 s

All 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
xml
<!-- 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

for a junior

Knows shade makes a fat JAR; may not distinguish the alternatives.

for a middle

Can name the three plugins and their basic output formats.

for a senior

Chooses correctly per use case and explains the nested-vs-flattened layout difference.

for a principal

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

context