The Java application has one job: it runs a single runnable jar. Nothing compiles on the server, so your build tool does the real work — packaging your code and every library it uses into one fat jar you upload. The two tools for that are Maven and Gradle. This guide helps you pick one and gives a minimal, complete config for each that produces a app.jar ready to run on Falix.
| At a glance | |
|---|---|
| You need | A Falix server running the Java application; Maven or Gradle on your own computer |
| Plan | Any |
| Time | Twenty minutes |
| Good to already know | Java on Falix (the fat-jar model, the JAR FILE variable) |
Which one?
Both produce exactly the same thing — a runnable fat jar — so there's no wrong answer. Pick by fit:
| Maven | Gradle | |
|---|---|---|
| Config file | pom.xml (XML) |
build.gradle (Groovy) or build.gradle.kts (Kotlin) |
| Style | Convention-heavy, verbose, predictable | Concise, scriptable, flexible |
| Learning curve | Gentle; easy to read and copy | Steeper, but less boilerplate once learned |
| Fat-jar plugin | Shade | Shadow |
| Best when | You want the simplest, most-documented path, or your project/tutorial already uses it | You want faster incremental builds, a terser config, or the project already uses it |
Rule of thumb: if you're starting from scratch and just want it to work, Maven has the shortest path and the most copy-paste examples. If you value a compact build script and quicker rebuilds — or your tutorial/framework leans that way — Gradle is a fine choice. If a project already has one, keep it; converting buys you nothing.
The shared goal
Whichever you use, the output must be a jar that:
- is named
app.jar(to match the JAR FILE variable's default), and - declares a
Main-Classin its manifest, and - has every dependency bundled inside it (that's what makes it "fat").
Test it locally first — java -jar app.jar should start your program on your own machine. If it runs there, it runs on Falix.
Maven: a minimal fat-jar pom.xml
The Shade plugin bundles dependencies and writes the Main-Class into the manifest. This complete pom.xml produces target/app.jar:
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.release>21</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- your libraries go here -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.11.0</version>
</dependency>
</dependencies>
<build>
<finalName>app</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.6.0</version>
<executions>
<execution>
<phase>package</phase>
<goals><goal>shade</goal></goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>app.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Build with mvn package. <finalName>app</finalName> makes the output target/app.jar, and the ManifestResourceTransformer sets Main-Class to your class (app.Main — change it to yours). Maven also leaves a target/original-app.jar next to it — that's the thin pre-shade jar; upload the plain app.jar, not that one.
Gradle: a minimal fat-jar build.gradle
Gradle's fat-jar plugin is Shadow. With the application plugin providing the main class, the Shadow plugin writes it into the manifest for you. This complete build.gradle produces build/libs/app.jar:
plugins {
id 'application'
id 'com.gradleup.shadow' version '8.3.5'
}
group = 'com.example'
version = '1.0.0'
repositories {
mavenCentral()
}
dependencies {
// your libraries go here
implementation 'com.google.code.gson:gson:2.11.0'
}
java {
toolchain { languageVersion = JavaLanguageVersion.of(21) }
}
application {
mainClass = 'app.Main'
}
tasks.named('shadowJar') {
archiveFileName = 'app.jar'
}
Build with gradle shadowJar. archiveFileName = 'app.jar' names the output build/libs/app.jar, and mainClass feeds the manifest. Change app.Main to your class.
🎯 Good to know: Set the compiler/toolchain version (
maven.compiler.releaseor Gradle'slanguageVersion) to a Java version no newer than the runtime you'll pick in Settings. A jar built for Java 21 won't run on a Java 17 runtime — that mismatch is the most common Java startup failure. See Java on Falix.
Getting the jar onto Falix
Same two paths as any Java project:
- Upload it — drag
app.jarinto the File Manager, or copy it up over SFTP, then Start. - Build on deploy — connect your repo on the Git page and add a post-deploy command (
mvn packageorgradle shadowJar) plus one to move the jar into place. See Build steps.
Troubleshooting
no main manifest attribute, in app.jar— the manifest has noMain-Class. You built a plain jar; make sure the Shade transformer / GradlemainClassis set and you're uploading the shaded jar.NoClassDefFoundError/ClassNotFoundException— a dependency isn't inside the jar. The fat-jar step didn't run or you uploaded the thin jar (original-app.jaron Maven). Rebuild and upload the bundled one.UnsupportedClassVersionError— the Settings runtime is older than the JDK you compiled with. Bump the Java version in Settings, or lower your build's target.- Builds locally, won't build on deploy — the build tool must be available in the deploy step. When in doubt, the upload path always works.
The build tools themselves go far deeper — the official references are maven.apache.org and gradle.org.