skip to content

Assembly Plugin

The Assembly plugin's descriptors and output formats for producing zips, tarballs, and jar-with-dependencies bundles. Comes up whenever the deliverable is a distribution rather than a library.

on this pageshow

explore

questions

5

What does the maven-assembly-plugin do, and when would you reach for it instead of the default jar packaging?

level: juniorimportance: must knowfreq 55%

answer

  1. single goal -> bind to package
  2. descriptorRef vs custom assembly.xml
  3. fat jar = jar-with-dependencies
  4. formats: zip/tar.gz/dir/jar
  5. ships dependencies + extra files

basics

~20 s

The assembly plugin bundles your project output plus extra files (dependencies, scripts, docs) into a single distributable archive like a zip, tar.gz, or a fat jar. The default jar packaging only packs your own compiled classes.

solid answer

~40 s

The maven-assembly-plugin builds a custom distribution archive from your project: compiled classes, dependencies, license files, scripts, config — assembled into a single artifact such as a zip, tar.gz, dir, or an executable 'fat jar'. The default `jar` packaging only produces a jar of your own classes, with dependencies left external. You reach for assembly when you need a self-contained deliverable: a runnable jar-with-dependencies for a small tool, or a `bin`-style distribution layout (lib/, bin/, README) for an app you hand to ops. You drive it either with a built-in `descriptorRef` (`jar-with-dependencies`, `bin`, `src`, `project`) or a custom `assembly.xml` descriptor, and bind its single goal `single` to a phase (usually `package`). For runnable Spring Boot apps you'd normally use spring-boot-maven-plugin instead.

code

bash · 3 lines
bash
mvn package
# produces target/myapp-1.0-jar-with-dependencies.jar
java -jar target/myapp-1.0-jar-with-dependencies.jar

go deeper

for a junior

Know it packs your app + dependencies into one distributable like a zip or fat jar.

for a middle

Know the single goal, descriptorRefs (jar-with-dependencies, bin), and binding to package.

for a senior

Choose assembly vs shade vs spring-boot-maven-plugin appropriately and justify it.

for a principal

Standardize distribution conventions across modules; decide org-wide packaging strategy and avoid uber-jar pitfalls.

## What it is Maven's default build produces one artifact per module — for `<packaging>jar</packaging>` that is a jar containing **only your project's own compiled classes and resources**. Your dependencies are *not* inside it; at runtime they're resolved from the local repository or a classpath. That's fine for a library, but useless when you want to *ship* something a user can unzip and run. The **maven-assembly-plugin** solves this: it gathers your build output **plus arbitrary other content** (project dependencies, files, directories, scripts, license text) and packs them into one or more **distribution archives**. ## The single goal The plugin effectively has one goal you use: **`assembly:single`**. (The older `assembly:assembly` and `directory` goals are deprecated.) You typically bind `single` to the `package` phase so the archive is built during a normal `mvn package`. ## Two ways to describe the assembly 1. **Predefined `descriptorRefs`** — ready-made recipes shipped with the plugin: - `jar-with-dependencies` — a single 'fat'/'uber' jar containing your classes **and** all dependencies unpacked into it. - `bin` — a typical binary distribution: your main artifact + README/LICENSE/NOTICE at the root. - `src` — a source distribution of the project. - `project` — the whole project directory tree minus build output. 2. **Custom `descriptors`** — you point at your own `assembly.xml` file (commonly `src/main/assembly/`) and control everything: `<formats>`, `<fileSets>`, `<dependencySets>`, `<files>`, directory layout, file permissions, and whether the assembled name has a base directory. ## Output formats The `<formats>` element (or the descriptorRef's defaults) decides what is produced — you can produce several at once: - `zip`, `tar.gz`, `tar.bz2`, `tar` — archive files - `jar` / `war` — jar-style archives - `dir` — an exploded directory (no compression), handy for local inspection ## Minimal example (fat jar) ```xml <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.7.1</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest><mainClass>com.example.Main</mainClass></manifest> </archive> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals><goal>single</goal></goals> </execution> </executions> </plugin> ``` This yields `target/<artifactId>-<version>-jar-with-dependencies.jar`, runnable via `java -jar`. ## When NOT to use it For Spring Boot apps use **spring-boot-maven-plugin** (proper nested-jar layout). For uber-jars that need class relocation/shading use **maven-shade-plugin**. Assembly is best for *distribution layouts* (bin/lib/conf trees, tarballs) and simple fat jars.

  • What is the difference between jar-with-dependencies (assembly) and the shade plugin?
    Both make uber-jars, but assembly just merges files; shade can relocate (rename) packages to avoid dependency conflicts and properly merges service files (META-INF/services). For Spring Boot, use neither — use spring-boot-maven-plugin.
  • Which phase do you normally bind assembly:single to and why?
    package — so the archive is built after the project's own jar/war exists, as part of a normal build, and gets attached for install/deploy.

Default jar = just your code in a box. Assembly = a full shipping crate with your box, all the parts it needs, the manual, and the packing slip.

saying these in an interview costs you the question

  • Saying the assembly plugin replaces the default jar — it adds an extra archive alongside it.
  • Claiming jar-with-dependencies relocates/renames conflicting packages (that's shade, not assembly).
  • Using assembly to build a runnable Spring Boot jar instead of spring-boot-maven-plugin.

context

open as a page

How do you build a runnable executable fat jar with the assembly plugin, and what's needed to make `java -jar` work?

level: middleimportance: should knowfreq 50%

basics

~10 s

Use the jar-with-dependencies descriptorRef so all dependencies are merged into one jar, and set a Main-Class in the manifest via <archive><manifest><mainClass>. Then java -jar can find both your code and its dependencies.

open as a page

Walk me through writing a custom assembly.xml descriptor to produce a tar.gz distribution with a bin/lib/conf layout.

level: seniorimportance: should knowfreq 35%

basics

~20 s

Write an assembly.xml with an <id>, one or more <formats> (like tar.gz), <fileSets> to copy your scripts/config into bin/ and conf/, and a <dependencySets> to drop dependency jars into lib/. Reference it from the plugin's <descriptors> and run assembly:single.

open as a page

Compare the assembly plugin with the shade plugin and spring-boot-maven-plugin for producing distributable artifacts. When do you pick each?

level: principalimportance: should knowfreq 30%

basics

~20 s

Assembly = flexible distribution layouts (zip/tar.gz, bin/lib/conf) and simple fat jars. Shade = uber-jars that need package relocation and proper merging of service files. spring-boot-maven-plugin = runnable Spring Boot jars with nested-jar layout. Pick by what you're shipping.

open as a page

When the assembly plugin runs, what artifact does it produce relative to the main jar, and how does it get installed and deployed?

level: seniorimportance: nice to knowfreq 22%

basics

~20 s

By default the assembly is attached as a secondary artifact with a classifier (the assembly id, e.g. -dist), alongside the main jar. Because it's attached, mvn install and deploy will install/upload it to the repository too.

open as a page