Java build tools: Gradle vs Maven

The Java app runs one fat jar — your build tool makes it. How to choose between Maven and Gradle, with a minimal, complete fat-jar config for each that produces a ready-to-run app.jar.

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-Class in 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.release or Gradle's languageVersion) 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.jar into 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 package or gradle shadowJar) plus one to move the jar into place. See Build steps.

Troubleshooting

  • no main manifest attribute, in app.jar — the manifest has no Main-Class. You built a plain jar; make sure the Shade transformer / Gradle mainClass is 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.jar on 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.


Next steps

Was this guide helpful?