Skip to content

Use Gradle or Maven

B. K. Oxley (binkley) edited this page Apr 3, 2024 · 11 revisions
Maven Gradle

Use Gradle or Maven

The choice between Gradle and Maven depends on your team, your broader ecosystem, and your project needs. In summary:

  • Gradle — your build script is written in Groovy or Kotlin; dynamic, imperative, and mutable; requires debugging your build on occasion, but less verbose than Maven's XML. Use of "parent" (umbrella) projects is possible but challenging. You can locally extend your build script either inline with build code, with project plugins, or with plugins from a separate project (perhaps shared across project for your team). If interested in custom plugins, read more here

  • Maven — your build scripts is written in XML; declarative and immutable; verbose but specific; it either works or not. Use of "parent" (umbrella) projects is simple with built-in support. You can locally extend your build with plugins from a separate project (perhaps shared across project for your team). If interested in custom plugins, read more here

For Modern Java/JVM projects, use Gradle or Maven unless your language provides you a native build tool (Clojure, Scala). The article doesn't cover alternative build tools: industry data shows Gradle or Maven are the build tools for most folks. Unless you find yourself in a complex monorepo culture (Google, etc.), or there are mandates from above, you need to select one of Gradle or Maven. However, for projects not using Gradle or Maven, you will still find improvements for your build herein (though details will differ).

For new projects, you may find Spring Initializr, mn from Micronaut, or JHipster, among many other project excellent starters, more to your liking: they provide you with starter Gradle or Maven scripts specific for those frameworks. That's great! This article should still help you improve your build beyond "getting started". You should pick and choose build features as makes sense to you and your circumstances.

This article offers no preference between Gradle or Maven. You need to decide with your team and circumstances. After picking your build tool, you might rename run-with-gradle.sh or run-with-maven.sh to just run.sh or similar.

Projects using Ant should migrate. It is true that Ant is well-maintained (the latest version dates from 2021). However, you will spend much effort in providing modern build tooling, and effort in migrating from Ant is repaid in smaller work for integrating modern tools. Data point: consider the number of Stackoverflow posts providing Gradle or Maven answers to those for Ant. Consider Ant builds to be no longer well-supported, and a form of Tech Debt.

Throughout, when covering both Gradle and Maven, Gradle will be discussed first, then Maven. This is no expressing a preference! It is neutral alphabetical ordering.

NB — Gradle Enterprise provides additional features for Maven as well such as build caching and build scans.

Cleaning up

Once you pick between Gradle or Maven, it is a good time to clean up. If you have cloned the project, some renames/deletions to consider:

You are ready to make great software.

Keeping Gradle or Maven up to date

Gradle

To update Gradle:

$ $EDITOR gradle.properties  # Update gradleWrapperVersion property
$ ./gradlew wrapper  # Update scripts and supporting files
$ ./gradlew wrapper  # Confirm, and download files if needed

Maven

To update Maven:

$ $EDITOR pom.xml  # Update maven.version property
$ ./mvnw wrapper:wrapper  # Update scripts and supporting files
$ ./mvnw wrapper:wra  # Confirm, and download files if needed

Note that Maven wrapper is developing, and will be bundled with an upcoming Maven release. For now it is a separate plugin in your pom.xml.

Tips

  • Take advantage of your shell's tab completion:
  • The sample Gradle and Maven build scripts often specify specific versions of the tooling, separate from the plugin versions. This is intentional. You should be able to update the latest tool version even when the plugin has not yet caught up.
  • Gradle itself does not provide support for "profiles", a key Maven feature. This is different from profiling build performance! Maven profiles can be used in many ways. The most common are to enabling/disabling build features on the command line, tailoring the build to a particular deployment environment, or using different credentials for other systems. If this feature is important for your team, you can code if/else blocks directly in build.gradle, or use a plugin such as Kordamp Profiles Gradle plugin. (Kordamp has a suite of interesting Gradle plugins beyond this one; read more on that page)
  • Gradle uses advanced terminal control, so you cannot always see what is happening. To view Gradle steps plainly when debugging your build, use:
    $ ./gradlew <your tasks> | cat
    or save the output to a file:
    $ ./gradlew <your tasks> | tee -o some-file
  • If your source code is in Kotlin, so should be your build. Gradle provides a Kotlin DSL for build scripts as a first-class counterpart to the traditional Groovy DSL.
  • Maven colorizes output, but does not use terminal control to overwrite output.
  • See Setup your CI for another approach to getting plain text console output
  • The Maven Notifier may be to your liking.
  • If you like Maven, but XML isn't your thing, you might explore the Polyglot for Maven extension which provides the POM in multiple languages/formats (eg, Ruby, YAML, many others).
  • If you have a multi-module Maven build, you might consider Takari Smart Builder to speed it up.
  • Maven best practice is to specify the version for each plugin, even default plugins that come with your version of Maven. This enforces reproducible builds. See also the Maven Enforcer Plugin to exactly specify the version of Maven for your build.
Clone this wiki locally