Edited 2025-10-15: Fix the Maven pom.xml sample.
JeKa is a modern Java build tool focused on simplicity.
This post is part of the "Jeka: the simplest way to..." series and shows how to create a fat jar (shaded or not) effortlessly.
For Applications : Simple Fat Jar
A common way to package Java applications is by creating FAT jars. A fat jar bundles all classes from the dependencies, so you only need the jar (along with the Java Runtime) to run the application.
Your application may need dependencies, which you can list in the dependencies.txt file as shown in the example below:
== COMPILE ==
com.github.lalyos:jfiglet:0.0.9
com.google.guava:guava:33.4.0-jre
com.fasterxml.jackson.core:jackson-core:2.18.2
== TEST ==
org.junit.jupiter:junit-jupiter:5.8.1
To configure the fat jar generation, edit the jeka.properties file:
jeka.version=0.11.11
jeka.java.version=17
@project.pack.detectMainClass=true
@project.pack.jarType=FAT
The @project.pack.jarType
property specifies the type of JAR to generate. It can be REGULAR
, FAT
, or SHADE
.
The @project.pack.detectMainClass=true
setting instructs Jeka to detect the main
class to include in the manifest file.
To generate the jar, run the following command:
jeka project: pack
The FAT jar will be created in the jeka-output directory. To run it, just execute: java -jar [jar-name].jar
.
For Libraries : Shade Fat jar
For libraries, an established practice consists in keeping a regular Jar and providing a Fat Jar as an additional option.
In some situation, such as a version clash, dependency classes should be relocated to a specific package to avoid classpath conflicts for the consumers. We call a shade jar, a fat jar where the dependencies classes have been re-located in a specific package.
To create such a jar, configure JeKa as follows:
jeka.version=0.11.11
jeka.java.version=17
@project.moduleId=org.examples:my-lib
@project.version=1.0.0-SNAPSHOT
@project.pack.shadeJarClassifier=all
@maven.publication.extraArtifacts=all
Now, invoking jeka prpject: pack
will also create a org.examples.my-lib-all.jar file.
By opening this jar file, we can see that all dependency classes has been automatically relocated.
.
├── org
│ └── example
│ └── mylib <- Base package for my-lib classes
│ ├── MyLyb.class
│ └── _shaded <- Base package for dependency classes
│ ├── com.google...
│ ├── com.fasterxml.jackson...
│ └── com.github.lalyos.jfiglat...
└── META-INF
└── MANIFEST.MF
Additionally, adding @maven.publication.extraArtifacts=all
to jeka.properties, includes the shaded JAR in the Maven publication generated by the jeka maven: publish
command.
Maven Comparison
As demonstrated below, Maven requires significantly more typing to achieve a similar goal.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.examples</groupId>
<artifactId>my-lib</artifactId>
<version>0.1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.github.lalyos</groupId>
<artifactId>jfiglet</artifactId>
<version>0.0.9</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.2.1-jre</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.17.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<minimizeJar>true</minimizeJar>
<artifactSet>
<includes>
<include>com.google.guava:guava</include>
<include>com.github.lalyos:jfiglet</include>
<include>com.fasterxml.jackson.core:jackson-core</include>
</includes>
</artifactSet>
<relocations>
<relocation>
<pattern>com.google.common</pattern>
<shadedPattern>org.elasticsearch.common</shadedPattern>
</relocation>
<relocation>
<pattern>com.fasterxml.jackson</pattern>
<shadedPattern>org.elasticsearch.common.jackson</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/license/**</exclude>
<exclude>META-INF/*</exclude>
<exclude>META-INF/maven/**</exclude>
<exclude>LICENSE</exclude>
<exclude>NOTICE</exclude>
<exclude>/*.txt</exclude>
<exclude>build.properties</exclude>
</excludes>
</filter>
</filters>
</configuration>
</plugin>
</plugins>
</build>
</project>
Conclusion
Jeka makes building Java projects significantly easier, with minimal configuration compared to Maven or Gradle.
Explore more examples to discover how Jeka can adapt to your project’s needs!
Top comments (2)
The given example for Maven duplicates the maven-shade-plugin, uses different versions of the plugin (apart from that, hose version are ancient old ca. a decade old!), explicitly defines the binding of the plugin to the
package
phase which is simply not required nor does it make sense... Also I would ask here why is the relocation required? Using a shaded jar as a dependency is the dead of your dependency propagation...Simply no... because I as a consumer will be able to overwrite transitive dependencies if I have to ... simple use cases which happens very often are for example security issues with particular versions of dependenc(y/ies) (or something else; because I have other libs which use different versions)... if you use only the shaded jar you are simply lost or even worse you don't even realize it...
How does JeKa configuration handle the issues with duplicate files from different jar files like MANIFEST.MF, multi release JAR configuration (module-info) or code for particular JDK versions
META-INF/versions/17/...
(as an example?) , or other resources like xml files, signatures of JAR files, orMETA-INF/services
etc. ?Thank you for your feedback.
For the Maven example, I just used one I found via Google. If you have a better, more relevant, and efficient sample, I’d be happy to update the article with it.
You're correct that you cannot override re-located dependencies. The property
configures the publication of an extra shade artifact alongside the original one. The consumer can choose to use either the shaded or regular dependency, depending on their needs. I'll mitigate the part of the article you mentioned.
For details, the implementation relies on the Maven Shade Plugin.
JeKa doesn't aim to be exhaustive in rendering this functionality upfront but focuses on making it simple from the user's point of view. The API surface will grow as needs and constraints, raised by users, emerge.