How to Shrink Spring Boot JARs by Extracting Dependencies and Config Files with Maven

This guide tackles the problem of oversized Spring Boot JARs by showing how to separate library JARs and configuration files from the main artifact, presenting three Maven‑based solutions—spring‑boot‑maven‑plugin, maven‑jar‑plugin, and maven‑assembly‑plugin—complete with configuration snippets, build commands, and deployment tips.

Architect
Architect
Architect
How to Shrink Spring Boot JARs by Extracting Dependencies and Config Files with Maven

When publishing a Spring Boot application in production, the default packaging process creates a single executable JAR that contains all compiled classes, all dependency JARs, and configuration files. Even a tiny code change forces a full rebuild and upload of a large file, slowing down the development cycle.

The proposed solution is to decouple the third‑party libraries (the lib folder) and configuration resources (the config folder) from the core application JAR, so that only the lightweight core needs to be redeployed.

Method 1 – Using spring-boot-maven-plugin

Step 1: Exclude configuration files from the main JAR and place them in config

<resources>
  <resource>
    <directory>src/main/resources</directory>
    <filtering>true</filtering>
    <includes>
      <include>**/*.properties</include>
      <include>**/*.yml</include>
      <include>**/*.xml</include>
      <include>mapper/*.xml</include>
    </includes>
    <targetPath>${project.build.directory}/config</targetPath>
  </resource>
</resources>

Step 2: Build an executable JAR while excluding dependency JARs

<plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
  <configuration>
    <jvmArguments>-Dfile.encoding=UTF-8</jvmArguments>
    <layout>ZIP</layout>
    <includes>
      <include>no-exists-jar</include> <!-- placeholder to skip all deps -->
    </includes>
  </configuration>
  <executions>
    <execution>
      <goals>
        <goal>repackage</goal>
      </goals>
    </execution>
  </executions>
</plugin>

Step 3: Copy runtime dependencies to lib

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-dependency-plugin</artifactId>
  <executions>
    <execution>
      <id>copy-dependencies</id>
      <phase>package</phase>
      <goals>
        <goal>copy-dependencies</goal>
      </goals>
      <configuration>
        <outputDirectory>${project.build.directory}/lib</outputDirectory>
        <includeScope>runtime</includeScope>
        <excludeTransitive>false</excludeTransitive>
      </configuration>
    </execution>
  </executions>
</plugin>

After packaging, the directory layout looks like:

Spring Boot packaging directory structure
Spring Boot packaging directory structure

Run the application with the external libraries loaded:

java -jar -Dloader.path=./lib -jar xxx.jar
Spring Boot automatically reads configuration files from the config directory, so you do not need to specify -Dspring.config.location explicitly.

Method 2 – Using maven-jar-plugin (and maven-resources-plugin )

Step 1: Package configuration files into config

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-resources-plugin</artifactId>
  <configuration>
    <encoding>UTF-8</encoding>
  </configuration>
  <executions>
    <execution>
      <id>copy-config</id>
      <phase>package</phase>
      <goals>
        <goal>copy-resources</goal>
      </goals>
      <configuration>
        <outputDirectory>${project.build.directory}/twin-web/config</outputDirectory>
        <resources>
          <resource>
            <directory>src/main/resources</directory>
          </resource>
        </resources>
      </configuration>
    </execution>
  </executions>
</plugin>

Step 2: Build an executable JAR without the dependencies

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  <configuration>
    <outputDirectory>${project.build.directory}/twin-web/</outputDirectory>
    <archive>
      <addMavenDescriptor>false</addMavenDescriptor>
      <manifest>
        <addClasspath>true</addClasspath>
        <classpathPrefix>./libs/</classpathPrefix>
        <mainClass>com.keqing.twinweb.TwinWebApplication</mainClass>
      </manifest>
      <manifestEntries>
        <Class-Path>./config/</Class-Path>
      </manifestEntries>
    </archive>
    <excludes>
      <exclude>*.yml</exclude>
      <exclude>mapper/**</exclude>
      <exclude>*.xml</exclude>
    </excludes>
  </configuration>
</plugin>

Step 3: Copy runtime libraries to libs

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-dependency-plugin</artifactId>
  <executions>
    <execution>
      <id>copy-dependencies</id>
      <phase>package</phase>
      <goals>
        <goal>copy-dependencies</goal>
      </goals>
      <configuration>
        <outputDirectory>${project.build.directory}/twin-web/libs</outputDirectory>
        <includeScope>runtime</includeScope>
      </configuration>
    </execution>
  </executions>
</plugin>

Resulting package structure (illustrated in the image below) shows separate config, lib, and the core JAR.

Package layout after using maven‑jar‑plugin
Package layout after using maven‑jar‑plugin

Start the application with:

java -jar xxx.jar

Method 3 – Using maven-assembly-plugin

Step 1: Declare the assembly plugin

<plugin>
  <artifactId>maven-assembly-plugin</artifactId>
  <configuration>
    <appendAssemblyId>false</appendAssemblyId>
    <descriptors>
      <descriptor>assembly.xml</descriptor>
    </descriptors>
  </configuration>
  <executions>
    <execution>
      <id>make-assembly</id>
      <phase>package</phase>
      <goals>
        <goal>single</goal>
      </goals>
    </execution>
  </executions>
</plugin>

Step 2: Create assembly.xml to define what goes where

<assembly>
  <id>make-assembly</id>
  <formats>
    <format>tar.gz</format>
    <format>zip</format>
  </formats>
  <includeBaseDirectory>true</includeBaseDirectory>
  <fileSets>
    <fileSet>
      <directory>${basedir}/bin</directory>
      <outputDirectory>/</outputDirectory>
      <fileMode>0755</fileMode>
      <includes>
        <include>**.sh</include>
        <include>**.bat</include>
      </includes>
    </fileSet>
    <fileSet>
      <directory>${basedir}/src/main/resources</directory>
      <outputDirectory>config</outputDirectory>
      <fileMode>0644</fileMode>
      <includes>
        <include>*.properties</include>
        <include>*.yml</include>
        <include>*.xml</include>
        <include>mapper/*.xml</include>
      </includes>
    </fileSet>
    <fileSet>
      <directory>${project.build.directory}</directory>
      <outputDirectory>/</outputDirectory>
      <includes>
        <include>*.jar</include>
      </includes>
    </fileSet>
  </fileSets>
  <dependencySets>
    <dependencySet>
      <useProjectArtifact>true</useProjectArtifact>
      <outputDirectory>lib</outputDirectory>
      <scope>runtime</scope>
      <unpack>false</unpack>
    </dependencySet>
  </dependencySets>
</assembly>

After running mvn package, the generated .zip or .tar.gz contains the core JAR, the config directory, and a lib folder with all runtime dependencies. The application can be started with the same loader path command:

java -jar -Dloader.path=./lib -jar xxx.jar
Assembly plugin packaged archive
Assembly plugin packaged archive

All three approaches achieve the same goal: a lean executable JAR that loads external libraries and configuration at runtime, dramatically reducing upload size and speeding up deployment cycles.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaMicroservicesDevOpsdependency managementmavenSpring Bootpackaging
Architect
Written by

Architect

Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.