A simple java project with Gradle
How do you create a Java project ? . Most probably you will be using IDE like Eclipse or IntelliJ. When I started Java programming, I started with Eclipse IDE to create a Java application where I could run it from the IDE and export as runnable jar. But later I have more requirements..
- I wanted to use external libraries (sl4j, JSON etc.)
- Create the application with a version and a given name
- Build the application without any IDE
- Execute the test cases
- Publish the output jar into a repository
- … and more
So how could I fulfill all this requirements ?. Using Gradle .
IDE like IntelliJ or Eclipse already have built in plugin to create Gradle projects. My goal here is to show you how to do without an IDE. Later you can import the project into any IDE and easily change the build script based on your requirements. To do this, we need some basic understanding about Gradle. Lets have some basic info for our quick start..
What is Gradle ?
Gradle is an open-source build automation tool that is designed to be flexible enough to build almost any type of software. That's nice to read, but how do I start with this tool ?.. How can I use it ?. Before we directly jumping into the Gradle configuration for Java, lets start something very simple. Lets create a gradle task to print “Hello World” to the console.
Gradle Installation
- Install Gradle https://docs.gradle.org/current/userguide/installation.html
- Check if gradle installed properly
U:\>gradle -vWelcome to Gradle 6.7!
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
Note : If the version info is not displayed, please check if you have set the PATH properly, as mentioned in the official gradle page
Hello World with Gradle
How do we start writing code for gradle ?. Gradle provides a domain specific language, or DSL, for describing builds. This build language is available in Groovy and Kotlin.
Now lets start with our “Hello World”
- Create a new directory “gradle-demo”
- Create a file “build.gradle” in a directory
- Write the following code
//Print a message to the console
task printHello() {
println “Hello World”
}
- Open the terminal and execute gradle printHello
$ gradle -q printHello
> Configure project :
Hello World
build.gradle : The gradle command looks for a file called build.gradle in the current directory. The build script defines a project and its tasks.
Lets create some meaningful task with gradle. Create a task to copy all images from a directory.
Copy files
task copyImages(type: Copy) {
println “Copying images…”
from “${System.getProperty(‘user.dir’)}/data”
include “*.jpg”
into “${System.getProperty(‘user.dir’)}/images”
}
We copy all the files with the extension “jpg” by creating an instance of Gradle’s builtin Copy task and configuring it with the location of the input and output directory. System.getProperty(‘user.dir’) gets the current working directory.
Here is the official documentation more on gradle task .I would recommend to go through this to have a good understanding. https://docs.gradle.org/current/userguide/tutorial_using_tasks.html
Gradle plugin
As you know some idea how gradle task works, we can create task to fulfill all our requirements. But there is an easy way to achieve this by using gradle plugin concept. Plugin is set of tasks, such as compiling tasks, setting up source files etc. Applying a plugin to a project means that allows the plugin to extend the project’s capabilities.
For example, to configure a java project, we can use the plugin “java”.
plugins {
id 'java'
}
You can find a list of core plugins from gradle here : https://docs.gradle.org/current/userguide/plugin_reference.html
Gradle wrapper
The recommended way to execute any Gradle build is with the help of the Gradle Wrapper (in short just “Wrapper”). The Wrapper is a script that invokes a declared version of Gradle, downloading it beforehand if necessary. As a result, developers can get up and running with a Gradle project quickly without having to follow manual installation processes saving your company time and money.
Java project
Enough theories. Lets finally create our java project. Gradle provides a quick start by using gradle init
command. This command creates the following things for us
- Gradle wrapper
- build.gradle with the required plugins and dependencies
- Java application directory structure
- A sample class with main method which prints HelloWorld
- JUnit test classes.
Lets execute the command.
- Create a folder and open a terminal
- Execute
gradle init --type java-application
gradle init --type java-application
Configuration on demand is an incubating feature.Select build script DSL:
1: Groovy
2: Kotlin
Enter selection (default: Groovy) [1..2] 1Select test framework:
1: JUnit 4
2: TestNG
3: Spock
4: JUnit Jupiter
Enter selection (default: JUnit 4) [1..4] 1Project name (default: gradle-init):
Source package (default: gradle.init): com.example.gradle> Task :init
Get more help with your project: https://docs.gradle.org/6.7/samples/sample_building_java_applications.htmlBUILD SUCCESSFUL in 15s
2 actionable tasks: 2 executed
We get a project structure as follows
You can open the project in any of your favorite IDE. For example I have imported the project into Eclipse as a gradle project
Execute the following gradle commands to see if all works
- Open a command terminal on the project folder
- Execute gradle build
- Execute gradle run
Lets have a deeper look into the build.gradle
Application plugin
plugins {
id 'application'
}
The Application plugin facilitates creating an executable JVM application. It makes it easy to start the application locally during development, and to package the application as a TAR and/or ZIP including operating system specific start scripts.
To see the list of task being executed by the ‘application’ plugin, you can execute
gradle tasks --all
Repositories
repositories {
jcenter()
}
A repository is storage location for software packages (E.g. library jars). Gradle can resolve dependencies from one or many repositories based on Maven, Ivy or flat directory formats. By specifying jcenter as the repository, gradle knows where to look all the dependency jars. Other popular repository is mavenCentral
A detailed description of repositories can be read here :
Dependencies
dependencies {
testImplementation 'junit:junit:4.13'
implementation 'com.google.guava:guava:29.0-jre'
}
Every dependency declared for a Gradle project applies to a specific scope. For example testImplementation should be used for compiling source code whereas implementation need to be available also at runtime.
Example : To add the JSON dependency to the project,
- Google “gradle json dependency”
- Select https://mvnrepository.com/artifact/org.json/json
- Select the latest version
- Copy the gradle configuration to your build.gradle
dependencies {
compile group: 'org.json', name: 'json', version: '20200518'
}
- Add the desired code in the App.java
public JSONObject createJSONObject(String data) {
return new JSONObject(data);
}
- Execute gradle build
More details on gradle dependencies can be read here :
Ok.. now you should be familiar with the basics of gradle and how to use a plugin to build your project. Lets create a gradle task to build a runnable jar.
Runnable Jar
The runnable jar contains a MANIFEST.MF file, which defines the Main class to be executed when the jar is run. I name the task as fatJar because we are creating a jar, copying all the dependencies to the jar. The build script below, may be confusing to you, but that is the Groovy syntax. We create a manifest file with the main class name and copying all the dependencies to the jar.
task fatJar(type: Jar) { manifest {attributes 'Main-Class': 'com.example.gradle.App'}
from {
configurations.compile.collect
{ it.isDirectory() ? it : zipTree(it) }
}with jar}
- Execute gradle fatJar
gradle --info fatJar
- Run the application
java -jar app\build\libs\app.jarHello World!
{"key1":"value1","key2":"value2"}
We can also create a runnable jar with all its dependencies copied and adding the classpath to the manifest. To do that, lets create a task to copy all the dependency jars into a folder
def dependsDir = "${buildDir}/libs/dependencies/"task copyDependencies(type: Copy) {
from configurations.compile
into "${dependsDir}"
}
- Execute gradle copyDependencies
You can see that the JSON lib is copied to app\build\libs\dependencies
Now we can create a task to create the runnable jar with the classpath entries in the manifest.
task createJar(dependsOn: copyDependencies, type: Jar) { manifest {
attributes(
'Main-Class': 'com.example.gradle.App',
'Class-Path': configurations.compile.collect
{ 'dependencies/' + it.getName() }.join(' ')
)}
with jar
}
- Execute gradle createJar
- Run the application
java -jar app\build\libs\app.jarHello World!
{"key1":"value1","key2":"value2"}
Great !. I hope that this gradle introduction helps you to have a good understanding about the gradle build concept and will helps you to build applications.
Conclusion
- We discussed about what is gradle and how to create simple tasks
- Overview about gradle plugins
- How to create a Java application without IDE and build the application
- Create runnable jars with dependencies managed.
You can download the sample project from GitHub : https://github.com/jafarmlp/gradle-java