Migrating a Java Maven Project to use Gradle
By: Zubair Haque
Tags: Java, Microservices, JVM, Spring Boot, Gradle

I’m working on a Java Spring Boot service and the time has come to upgrade from Apache Maven to Gradle. We’re going to replace the pom.xml file as well. I won’t need that xml file anymore and I’ll have something much more readable. Gradle is a general purpose build management and automation tool you can use to deploy your Java service. It’s an open source build system that supports ANT, Maven and lvy repositories. It supports a Groovy based DSL instead of XML making it much more easier on the eyes.

Installation

I have a macOS so I’m going to be using the Homebrew package manager to install this particular build tool:

$ brew install gradle

In the same directory run the following command to make sure the install was successful, check which version of Gradle you have installed by running the following command:

$ gradle -v

the terminal output should list out the Gradle version & Groovy version on your machine. You can also run:

$ which gradle

the terminal should now display that Gradle is in your /usr/local/bin directory which is a common place where third party software binaries are installed on your box.

Setting up your project

Once you have Gradle installed, you can now setup a new or existing project. We can initialize the project to use our new build tool by typing in the following command:

$ gradle init

The init built-in task initializes a new Gradle project in your repository. If you do an ls command now in your terminal you’ll see:

├── gradle

│ └── wrapper

│ ├── gradle-wrapper.jar

│ └── gradle-wrapper.properties

running the init command generated folder for the necessary wrapper files, which live in the gradle/ directory. You will also see the settings.gradle file, which defines the project that is being built and it’s subprojects.

rootProject.name = 'my-service'

The rootProject.name is where you can assign the name of the service to the project, the assignment occurs during run time of your build script. Now, you’re also gonna see the following files at the base directory level:

├── gradlew

├── gradlew.bat

these are the initial wrapper files that are generated when a Gradle project is instantiated, which we can leave as is for now.

build.gradle

You can build your project by prefacing all commands with gradle in front of it. When executing tasks via command line the runner is looking for the build.gradle file which is just a build execution script. This script will allow you to run tasks that will make your day to day work life much easier and streamline normal efforts such as compiling your changes locally on a branch, as well as running tests, etc., etc. To start off we’re going to want to add plugins to ur build script:

plugins {

id 'org.springframework.boot' version 'VERSION.RELEASE'

id 'io.spring.dependency-management' version 'VERSION.RELEASE'

id 'java'

}

This is where you want to add your standard plugins for your Spring Boot project such as Java, Spring Dependency Management and Spring Boot Framework. You can also add plugins like SonarQube which is a tool you can use to continuously inspect your code for security vulnerabilities, code smells, bugs and much more. After declaring your plugins we’re going to set the version of our Java project next:

version = "0.0.${System.getenv('SEM_VER')}"

Gradle allows you to declare the version as a String keep in mind that this isn’t mandatory, so if you don’t set the version it will just default to unspecified . A common practice in a microservices architecture is to share a common set of dependencies across all services. A custom configuration makes it easier to incorporate all of the dependencies, which should live in a specific location. You can use the built in apply function in Gradle to call your parent gradle file which probably lives in JFrog or Nexus:

Let’s move on to adding the necessary dependencies needed for our project, we can start by declaring a dependencies object in our build.gradle file:

dependencies {

implementation 'org.postgresql:postgresql:42.2.8.jre7'

testImplementation ' junit:junit:4.13 '

}

There are two types of dependencies being add to the dependencies object above:

implementation: these are required dependencies needed for your project to compile, above it shows us adding PostGreSQL database to our project as an example.

these are required dependencies needed for your project to compile, above it shows us adding PostGreSQL database to our project as an example. testImplementation: these dependencies are used for compiling and running tests, but not necessarily required for running the project’s runtime code. Above we are adding the JUnit dependency needed to test the various endpoint in our project.

For those that like documenting their code and use Javadoc can use the

and they could really be the same file Spring Boot Actuator’s info endpoint automatically publishes information about your build in the presence of a META-INF/build-info.properties file. A BuildInfo task is provided to generate this file. The easiest way to use the task is via the plugin’s DSL

springBoot {

buildInfo()

}

This will configure a BuildInfo task named bootBuildInfo and, if it exists, make the Java plugin’s classes task depend upon it. The task’s destination directory will be META-INF in the output directory of the main source set’s resources (typically build/resources/main ).

Configuring the SonarScanner

Assuming a local SonarQube server with out-of-the-box settings is up and running, no further configuration is required.

$ ./gradlew sonarqube

SonarQube Task Dependencies

All tasks that produce output that should be included in the SonarQube analysis need to be executed before the sonarqube task runs. Typically, these are compile tasks, test tasks, and code coverage tasks

tasks['sonarqube'].dependsOn jacocoTestReport

in the end your gradle file should look something like this: