Why do the Gradle/Maven wrappers matter?

Indeed, why do these tool exist and why should I use them? After all installing Gradle or Maven is a simple task. Just download a ZIP file, configure an environment variable and voilà! Or use a package manager such as SdkMan! Well to understand these questions we must travel back in time, to a moment when Gradle was just getting started and Maven 3 was just a few months of being released.

Gradle’s inception happened sometime in late 2007. In comparison Maven was at 2.0.7 or 2.0.8 (see history of Maven release notes). Everyone knew Maven at that time but only a few heard about Gradle. By early 2009 Gradle had already gained some traction and the Maven team was ready for pushing forward with what would become Maven 3.0. Being the dominant option in the build tool space meant that finding Maven installed on a developer workstation was quite common, and somewhat common on build servers. I still remember having to ask the IT department to install a specific version of Maven in order to have a successful build. That was the challenge Gradle faced at that moment in time: even if a developer picks it up and makes a successful build, how could they ensure the CI environment will be setup as needed in a timely manner? How can they ensure other teams members (or anyone else for that matter) have the correct environment to build the project? That’s how the Gradle wrapper came to be.

The Gradle wrapper is the answer to bootstrapping Gradle on a particular system. The wrapper’s promise is this: it will execute a given version of Gradle on your build, if the version does not exist then the wrapper downloads it from a specific location, unpacks and configures it, then continues with the build. This made it much easier for developers to try out Gradle builds, as they are no longer forced to manually install Gradle first. It also helps on CI environments, as you no longer have to wait for the IT department to install Gradle on a particular server.

Let’s move on to few years later down the road. We no longer have to battle the IT department to install Gradle due to the wrapper, however the use of build farms on the cloud is now in full rage. Good news, the Gradle wrapper continues to help here. What about Maven? Well, it depends on the build provider. What if there was a Maven wrapper? If so Maven could be bootstrapped in a similar fashion as Gradle is, and that’s kind of what Brian Demers thought one day and decided to build the first iteration of the Maven wrapper. The project was later moved to takari/maven-wrapper, and it’s now (as of June 2020) in the final stages to join Maven core as part of Maven 3.7.

So there you have it, the wrapper is the means to bootstrap a build tool on a system that may not have said build tool to begin with. That is the original intention for the wrapper. But. Something else happened along the way, specifically with Gradle. The Gradle build tool moves at a frantic pace compared to Maven. Gradle releases a new version every 6 to 9 weeks, while Maven does it 4 or 5 times a year. Gradle has broken binary compatibility not only between major releases but also between minor releases. It has also broken compatibility with its own DSL. And that’s fine, it means the tool is evolving, but it also means you have to spend time upgrading the build. Unless, you use the wrapper in which case you don’t have to make any changes, as the wrapper ensures a specific version of Gradle is used to make the build.

It’s in this other category that I found some members of the Maven community do not care much about the Maven wrapper as they see Maven’s POM format as very stable compared to Gradle’s (not one, but two DSLs!) options changing more frequently. Have you tried to build a project that required Gradle 2.1 or 3.5 with say, Gradle 6.1? It’s likely not going to work. Building a Maven 3.0.1 project with Maven 3.6.3 is very likely to succeed. Anyone can claim “Of course! You’re breaching between major versions of Gradle while Maven remains the same major”. Oh yeah? Try building with Gradle 2.0 then 2.1 (the appearance of the plugins block and the Gradle Plugin Portal), or Gradle 2.6 (IIRC there was a binary incompatibility due to plugin dependencies). Gradle 4.1, 4.6, 4.7, 4.10 also added small changes to the DSL which meant you can’t build with that version unless the build files were updated. Similar things happened in Gradle 5 between minor releases.

So, at least for some releases of Gradle the wrapper has taken on another responsibility: make sure the build works with a very specific version of the tool and thus build files don’t need any updates. We don’t see that in Maven right now. Having the Maven wrapper added into core (looking at my crystal ball here, have no inside insight on this subject) could potentially help the Maven team in breaking things, change the POM syntax, add new metadata files, whatever it’s required to keep Maven moving forward, while still letting developers build with older versions.

In the end, is the Gradle/Maven wrapper worth a shot? Yes, it still is. You can use it to bootstrap a system where the build tool is not installed. That remains its primary goal. It’s secondary goal is to ensure the build works with a specific version of the tool.

UPDATE: There is one more thing that the wrappers enable: repeatable builds. It’s not just bootstrapping nor fixing the tool’s version, but also its companion plugins. The wrappers help fixing versions of core plugins. For both Gradle and Maven, make sure you fix all versions (dependencies and plugins alike). Don’t use ranges nor snapshots unless you really know what you’re doing and can deal with the consequences.

Oh, and should you want to have a wrapper for either of these two wrappers, give Gum a try.

Keep on coding!

Image by PublicDomainPictures from Pixabay

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

ˆ Back To Top