Gradle is one of several Java development tools featured in Stackify’s Comprehensive Java Developer’s Guide, but it’s not the only build automation tool to consider. Maven is an older and commonly used alternative, but which build system is best for your project? With other tools, such as Spring, allowing developers to choose between the two systems, coupled with an increasing number of integrations for both, the decision is largely up to you.
The size of your project, your need for customization, and a few other variables can help you choose. Let’s take a look.
Gradle is a build automation system that is fully open source and uses the concepts you see on Apache Maven and Apache Ant. It uses domain-specific language based on the programming language Groovy, differentiating it from Apache Maven, which uses XML for its project configuration. It also determines the order of tasks run by using a directed acyclic graph.
Several developers created Gradle and first released in 2007, and in 2013, it was adopted by Google as the build system for Android projects. It was designed to support multi-project builds that are expected to be quite huge. It also allows for incrementally adding to your build, because it knows which parts of your project are updated. Tasks that are dependent on updated parts are no longer re-executed. For now, the latest stable release is version 3.4, which was launched in February 2017. It supports development and subsequent deployment using Java, Scala, and Groovy, with other project workflows and languages being introduced in the future.
Maven is used for project build automation using Java. It helps you map out how a particular software is built, as well as its different dependencies. It uses an XML file to describe the project that you are building, the dependencies of the software with regards to third-party modules and parts, the build order, as well as the needed plugins. There are pre-defined targets for tasks such as packaging and compiling.
Maven will download libraries and plugins from the different repositories and then puts them all in a cache on your local machine. While predominantly used for Java projects, you can use it for Scala, Ruby, and C#, as well as a host of other languages.
There are some fundamental differences in the way that the two systems approach builds. Gradle is based on a graph of task dependencies – in which tasks are the things that do the work – while Maven is based on a fixed and linear model of phases. With Maven, goals are attached to project phases, and goals serve a similar function to Gradle’s tasks, being the “things that do the work.”
Performance-wise, both allow for multi-module builds to run in parallel. However, Gradle allows for incremental builds because it checks which tasks are updated or not. If it is, then the task is not executed, giving you a much shorter build time. Other distinguishing performance features you can find on Gradle include:
When it comes to managing dependencies, both Gradle and Maven can handle dynamic and transitive dependencies, to use third-party dependency caches, and to read POM metadata format. You can also declare library versions via central versioning definition and enforce central versioning. Both download transitive dependencies from their artifact repositories. Maven has Maven Central while Gradle has JCenter, and you can define your own private company repository as well. If there are several dependencies required, Maven can download these simultaneously.
Gradle, however, wins when it comes to API and implementation dependencies, as well as inherently allowing concurrent safe caches. It also keeps repository metadata along with cached dependencies, ensuring that two or more projects using the same cache will not overwrite each other, and it has a checksum-based cache and can synchronize cache with the repository. Furthermore, Gradle is compatible with IVY Metadata, allowing you to define custom rules to specify a version for a dynamic dependency, and resolving version conflicts. These are not available on Maven.
Other dependency management features that you can find only on Gradle are:
Gradle also gives you an easier time when working with composite builds, and it enables you to work with ad-hoc and permanent composite builds, as well as combine different builds and importing a composite build into Eclipse of IntelliJ IDEA.
As far as execution models are concerned, both have task groups and descriptions. Both enable you to build only the specified project and its dependencies. Gradle, however, has a fully configurable DAG, while with Maven, a goal can be attached only to one other goal. Multiple goals take on the form of an ordered list. Gradle also allows task exclusions, transitive exclusions, and task dependency inference. Gradle also has advanced features for task ordering and finalizers, among others.
Administering build infrastructure is another strong point for Gradle as it uses wrappers that accept auto provisioning, while with Maven, you need to have an extension to support self-provisioning builds. Gradle also enables you to configure version-based build environments without having to set these up manually. It also allows custom distributions.
In a comparison of Ant, Gradle, and Maven, Naresh Joshi compares the code required to create a build script that compiles, performs static analysis, runs unit tests, and creates JAR files at Programming Mitra.
Here’s the code required to achieve this with Maven:
<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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.programming.mitra</groupId> <artifactId>java-build-tools</artifactId> <packaging>jar</packaging> <version>1.0</version> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> </plugin> </plugins> </build> </project>
To run the Maven goal that creates the JAR file, you would execute the following:
mvn package
Note that using this code, you’re setting the parameters but not specifying the tasks that must be carried out. You can add plugins (such as Maven CheckStyle, FindBugs and PMD) to execute the static analysis as a single target together with unit tests, but you’ll want to specify the path to the customs check style configuration to ensure that it fails on error, using code such as:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-checkstyle-plugin</artifactId> <version>2.12.1</version> <executions> <execution> <configuration> <configLocation>config/checkstyle/checkstyle.xml</configLocation> <consoleOutput>true</consoleOutput> <failsOnError>true</failsOnError> </configuration> <goals> <goal>check</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>findbugs-maven-plugin</artifactId> <version>2.5.4</version> <executions> <execution> <goals> <goal>check</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-pmd-plugin</artifactId> <version>3.1</version> <executions> <execution> <goals> <goal>check</goal> </goals> </execution> </executions> </plugin>
To run the goal to achieve this, execute the following:
mvn verify
It requires quite a bit of XML code to achieve some basic and common tasks, and for this reason, projects in Maven with a large number of tasks and dependencies can result in pom.xml files that consist of hundreds to thousands of lines of code.
To compare, here’s an example of build.gradle code that achieves a similar outcome:
apply plugin:'java' apply plugin:'checkstyle' apply plugin:'findbugs' apply plugin:'pmd' version ='1.0' repositories { mavenCentral() } dependencies { testCompile group:'junit', name:'junit', version:'4.11' }
This code is shorter and also introduces some useful tasks that aren’t covered with the Maven code above. Execute the following for a list of tasks that Gradle can run with the current configuration:
gradle tasks --all
Overall, both tools have their respective strengths and weaknesses.
In the end, what you choose will depend primarily on what you need. Gradle is more powerful. However, there are times that you really do not need most of the features and functionalities it offers. Maven might be best for small projects, while Gradle is best for bigger projects. If you’ve been working with Maven and find that your project has outgrown it, it is possible to migrate from Maven to Gradle.
For further reading and more information, including helpful tutorials, visit the following resources:
Stackify's APM tools are used by thousands of .NET, Java, PHP, Node.js, Python, & Ruby developers all over the world.
Explore Retrace's product features to learn more.
If you would like to be a guest contributor to the Stackify blog please reach out to [email protected]