Getting Started With Gradle: Our First Java Project

This blog post describes how we can compile and package a simple Java project by using Gradle.

Our Java project has only one requirement:

Our build script must create an executable jar file. In other words, we must be able to run our program by using the command:

java -jar jarfile.jar

Let's find out how we can fulfil this requirement.

Additional reading:

If you are not familiar with Gradle, you should read the following blog post before you continue reading this blog post:

Creating a Java Project

We can create a Java project by applying the Java plugin. We can do this by adding the following line to our build.gradle file:

apply plugin: 'java'

That is it. We have now created a Java project.

The Java plugin adds new conventions (e.g. the default project layout), new tasks, and new properties to our build.

Let’s move on and take a quick look at the default project layout.

The Project Layout of a Java Project

The default project layout of a Java project is following:

  • The src/main/java directory contains the source code of our project.
  • The src/main/resources directory contains the resources (such as properties files) of our project.
  • The src/test/java directory contains the test classes.
  • The src/test/resources directory contains the test resources.

All output files of our build are created under the build directory. This directory contains the following subdirectories which are relevant to this blog post (there are other subdirectories too, but we will talk about them in the future):

  • The classes directory contains the compiled .class files.
  • The libs directory contains the jar or war files created by the build.

Let's move on and add a simple main class to our project.

Adding a Main Class to Our Build

Let's create a simple main class which prints the words: "Hello World" to System.out. The source code of the HelloWorld class looks as follows:

package net.petrikainulainen.gradle;

public class HelloWorld {

    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}
The HelloWorld class was added to the src/main/java/net/petrikainulainen/gradle directory.

That is nice. However, we still have to compile and package our project. Let's move on and take a look at the tasks of a Java project.

The Tasks of a Java Project

The Java plugin adds many tasks to our build but the tasks which are relevant for this blog post are:

  • The assemble task compiles the source code of our application and packages it to a jar file. This task doesn’t run the unit tests.
  • The build task performs a full build of the project.
  • The clean task deletes the build directory.
  • The compileJava task compiles the source code of our application.

We can also get the full list of runnable tasks and their description by running the following command at the command prompt:

gradle tasks

This is a good way to get a brief overview of our project without reading the build script. If we run this command in the root directory of our example project, we see the following output:

> gradle tasks
:tasks

------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------

Build tasks
-----------
assemble - Assembles the outputs of this project.
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildNeeded - Assembles and tests this project and all projects it depends on.
classes - Assembles classes 'main'.
clean - Deletes the build directory.
jar - Assembles a jar archive containing the main classes.
testClasses - Assembles classes 'test'.

Build Setup tasks
-----------------
init - Initializes a new Gradle build. [incubating]
wrapper - Generates Gradle wrapper files. [incubating]

Documentation tasks
-------------------
javadoc - Generates Javadoc API documentation for the main source code.

Help tasks
----------
dependencies - Displays all dependencies declared in root project 'first-java-project'.
dependencyInsight - Displays the insight into a specific dependency in root project 'first-java-project'.
help - Displays a help message
projects - Displays the sub-projects of root project 'first-java-project'.
properties - Displays the properties of root project 'first-java-project'.
tasks - Displays the tasks runnable from root project 'first-java-project'.

Verification tasks
------------------
check - Runs all checks.
test - Runs the unit tests.

Rules
-----
Pattern: build<ConfigurationName>: Assembles the artifacts of a configuration.
Pattern: upload<ConfigurationName>: Assembles and uploads the artifacts belonging to a configuration.
Pattern: clean<TaskName>: Cleans the output files of a task.

To see all tasks and more detail, run with --all.

BUILD SUCCESSFUL

Total time: 2.792 secs

Let’s move on and find out how we can package our Java project.

Packaging Our Java Project

We can package our application by using two different tasks:

If the run the command gradle assemble at command prompt, we see the following output:

> gradle assemble
:compileJava
:processResources 
:classes
:jar
:assemble

BUILD SUCCESSFUL

Total time: 3.163 secs

If we run the command gradle build at command prompt, we see the following output:

> gradle build
:compileJava
:processResources 
:classes
:jar
:assemble
:compileTestJava 
:processTestResources 
:testClasses 
:test 
:check 
:build

BUILD SUCCESSFUL

Total time: 3.01 secs

The outputs of these commands demonstrate that the difference of these tasks is that:

  • The assemble task runs only the tasks which are required to package our application.
  • The build task runs the tasks which are required to package our application AND runs automated tests.

Both of these commands create the first-java-project.jar file to the build/libs directory.

The default name of the created jar file is created by using the following template: [project name].jar, and the default name of the project is the same than the name of the directory in which it is created. Because the name of our project directory is first-java-project, the name of created jar is first-java-project.jar.

We can now try to run our application by using the following command:

java -jar first-java-project.jar 

When we do this, we see the following output:

> java -jar first-java.project.jar
No main manifest attribute, in first-java-project.jar

The problem is that we haven't configured the main class of the jar file in the manifest file. Let's find out how we can fix this problem.

Configuring the Main Class of a Jar File

The Java plugin adds a jar task to our project, and every jar object has a manifest property which is an instance of Manifest.

We can configure the main class of the created jar file by using the attributes() method of the Manifest interface. In other words, we can specify the attributes added to the manifest file by using a map which contains key-value pairs.

We can set the entry point of our application by setting the value of the Main-Class attribute. After we have made the required changes to the build.gradle file, its source code looks as follows (the relevant part is highlighted):

apply plugin: 'java'

jar {
    manifest {
        attributes 'Main-Class': 'net.petrikainulainen.gradle.HelloWorld'
    }
}
The Java SE tutorial provides more information about the manifest file.

After we have created a new jar file by running either the gradle assemble or gradle build command, we can run the jar file by using the following command:

java -jar first-java-project.jar

When we run our application, the following text is printed to the System.out:

> java -jar first-java-project.jar
Hello World!

That is all for today. Let’s find out what we learned from this blog post.

Summary

We have now created a simple Java project by using Gradle. This blog post has taught us four things:

  • We know that we can create a Java project by applying the Gradle Java plugin.
  • We learned that the default directory layout of a Java project is the same than the default directory layout of a Maven project.
  • We learned that all output files produced by our build can be found from the build directory.
  • We learned how we can customize the attributes added to the manifest file.

P.S. The example project of this blog post is available at Github.

If you want to learn how to use Gradle, you should take a look at my Gradle tutorial.
54 comments… add one
  • Akalanka Jun 22, 2014 @ 15:54

    Hi Petri,

    Nice work. Will you be writing consecutive articles on gradle? Like you do for spring data.

    • Petri Jun 22, 2014 @ 16:14

      Hi Akalanka,

      Thank your for your kind words. I really appreciate them.

      And yes, I am going to write a Gradle tutorial which covers the essential parts of Gradle. This tutorial follows the same format as my other tutorials, and the idea is that after this tutorial is over, you should be able to use Gradle in real life software projects.

  • vivek Sep 3, 2014 @ 22:32

    Nice Tute Petri . It really helps.

    • Petri Sep 4, 2014 @ 22:04

      Thanks! I am happy to hear that blog post was useful to you.

  • Svn Sep 23, 2014 @ 1:06

    Hi I have the same use case. I followed the each n every step you said. It didnt work for me. I used the class name & package name, as you did. But didnt work? Any ideas?

    • Petri Sep 23, 2014 @ 22:32

      Do you mean that you cannot run the jar file by using a command java -jar jarfile.jar? If so, what kind of an error message did you get?

      • Craig Jun 3, 2015 @ 17:41

        I am in a similar situation. I am using gradle 2.4. It builds successfully.

        when I try to run the java -jar GradleTutorial.jar
        Error: unable to access jarfile GradleTutorial

        If i navigate to the libs foldder and run java - jar GradleTutorial.jar it works. Is this how it is suppose to work? Or am I missing some configurations to make this work from the project directory?

        • Petri Jun 3, 2015 @ 18:25

          Your build seems to working as expected because the command gradle build (or gradle assemble) is supposed to create the jar file to the build/libs directory.

          If you want to run your application from the root directory of your project, you should take a look at the Gradle application plugin. I have actually written a blog post that describes how you can use it.

          Did this answer to your question?

          • Craig Jun 3, 2015 @ 18:38

            Yes it did. Thanks... Great tutorial!!

          • Petri Jun 3, 2015 @ 21:15

            You are welcome!

  • navin murrari Nov 7, 2014 @ 11:47

    Nice basic tutorial on gradle..

    • Petri Nov 9, 2014 @ 20:33

      Thank you for your kind words. I really appreciate them.

  • Douglas Borg Jan 8, 2015 @ 8:16

    Hey Petri,

    Great introduction to Gradle! I referenced it in my recent blog post: http://dougborg.org/what-makes-a-good-build-dot-gradle. Let me know what you think!

    -Doug

    • Petri Jan 9, 2015 @ 17:50

      Hi Douglas,

      I enjoyed reading your blog post, and it gave me a few ideas for new blog posts. Thank you for sharing it! I am sure that it is useful to other people as well.

  • black Jan 9, 2015 @ 9:10

    Nice tutorial, thanks

    • Petri Jan 9, 2015 @ 17:36

      You are welcome!

  • Rajat May 28, 2015 @ 0:31

    Thank you ! The gradle really lacks such a simple and straightforward tutorial !

    • Petri May 28, 2015 @ 14:25

      You are welcome! I am happy to hear that this tutorial was useful to you.

  • Ankit Jun 1, 2015 @ 15:03

    gradle is build succesfully bt as soon as i run gradle build command...it show error"Task not found in root directory"..help me on this

    • Petri Jun 1, 2015 @ 22:34

      Unfortunately it is impossible to say anything without seeing your build.gradle file. Could you add it to Pastebin and share the link with me? Also, it would be helpful to know which Gradle version you are using.

  • Anonymous Jul 26, 2015 @ 21:57

    HelloWorld.java
    ---------------------

    
    package java;
     
    public class HelloWorld {
     
        public static void main(String[] args) {
            System.out.println("Hello World!");
        }
    }
    
    

    ----------------------------

    
    build.gradle
    apply plugin: 'java'
    
    jar {
        manifest {
            attributes 'Main-Class':'src.main.java.HelloWorld'
        }
    }
    
    

    ----------------
    D:\Projects\src\build\libs>java -jar src.jar
    Error: Could not find or load main class D.Projects.src.main.java.HelloWorld

    I get error above with same setup?

    Update: I removed unnecessary information - Petri

    • Petri Jul 26, 2015 @ 22:39

      The problem is that package of your HelloWorld class is java, but the value of the Main-Class attribute is src.main.java.HelloWorld. You need to change it to java.HelloWorld.

      • Mahendra Jul 28, 2015 @ 13:47

        Thank you Petri and it has worked

        • Petri Jul 28, 2015 @ 14:52

          You are welcome!

  • NarayanaReddy Oct 14, 2015 @ 10:02

    Recently i developed project for mongoservice requirement,created project using gradle. From local environment working fine but in staging they are taking war file from junkins(junkins configured with gradle) there it is not working. problem is it is not creating .class files and not creating output directory to read files. Then i copied my local war file in staging working fine now. What i am missing with junkins to create war file with all class files and same as local war file . please help me

    • Petri Oct 14, 2015 @ 17:55

      I would love to help you, but unfortunately it is impossible to say what is wrong without seeing the build.gradle file and your Jenkins configuration.

  • Siva Oct 27, 2015 @ 12:35

    Hi Petri,
    It's simple, and easily understandable.
    Thanks for the post.

    • Petri Oct 27, 2015 @ 19:27

      Hi Siva,

      You are welcome. I am happy to hear that this blog post was useful to you.

  • neeta Nov 30, 2015 @ 18:29

    Thank you so much

    Been trying to figure out the java build works. Got it and hopefully much more.

    Thanks again. :)

    • Petri Nov 30, 2015 @ 22:13

      You are welcome! I am happy to hear that this blog post was useful to you.

  • ArunM Mar 9, 2016 @ 9:31

    Thanks Petrii. Working through the tutorials one by one.

    • Petri Mar 9, 2016 @ 16:52

      You are welcome!

  • Jarema Antosz Dec 30, 2016 @ 11:35

    You could mention gradle init --type java-library command. Very helpful for generating project structure.

  • good wisher Sep 7, 2017 @ 20:34

    Thank you! Your content is really helpful.

    • Petri Feb 16, 2018 @ 9:56

      You are welcome!

  • Lukas Feb 15, 2018 @ 16:27

    Hi man,

    I am moving from PHP to Java and I found this blog post perfect! Well explaining all the fundamentals and relations.

    • Petri Feb 16, 2018 @ 9:55

      Hi,

      Thank you for your kind words. I really appreciate them!

  • Vipul Rathod Feb 28, 2018 @ 9:14

    It was very helpful for them who are begging to learn gradle. Nice Article. :)

    • Petri Mar 12, 2018 @ 8:45

      Thank you for your kind words. I really appreciate them. Also, it was nice to hear that this blog post was useful to you.

  • Saravanan Manickam Jul 16, 2018 @ 8:35

    Very simple and easy to understand. Thanks a lot

    • Petri Jul 16, 2018 @ 10:26

      You are welcome!

  • Antani Oct 6, 2018 @ 1:20

    Great series. Thanks

    • Petri Oct 6, 2018 @ 11:02

      You are welcome. I am happy to hear that this blog post was useful to you.

  • Mikhail Apr 2, 2019 @ 16:33

    Very useful article, thank you, Petri!

    • Petri Apr 6, 2019 @ 16:27

      You are welcome!

  • Alex Apr 28, 2019 @ 16:28

    Thank you so much. Incredibly helpful.

  • hdtube Dec 3, 2019 @ 14:12

    The Gradle Wrapper is the preferred way of starting a Gradle build. It consists of a batch script for Windows and a shell script for OS X and Linux. These scripts allow you to run a Gradle build without requiring that Gradle be installed on your system. This used to be something added to your build file, but it’s been folded into Gradle, so there is no longer any need. Instead, you simply use the following command.

    • Petri Dec 3, 2019 @ 19:47

      Hi,

      I took a quick look at the Gradle User Manual and it states that:

      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.

      In other words, the Gradle Wrapper doesn't help you to create a new Gradle project. Instead, it helps you to execute an existing Gradle project without the need to manually install the required Gradle version.

  • Rishikesh Jul 7, 2020 @ 9:39

    Best gradle explanation on internet!

    • Petri Jul 10, 2020 @ 12:43

      Thank you for your kind words. I really appreciate them.

  • Ritika Sep 10, 2020 @ 11:47

    how to write gradle program to calculate area of circle and square

    • Petri Sep 11, 2020 @ 13:37

      Hi,

      This sounds a bit like home work. In any case, you can calculate the area of different shapes by using these mathematical formulas. Unfortunately I cannot help you how to write the actual program because 1) you didn't tell me which programming language you have to use AND 2) if I would help you to do your home work, you wouldn't learn anything.

Leave a Reply