Gradle project properties provide an easy way to customise builds which may need to run differently in certain situations. In this article you’ll learn the most effective ways to use and set properties, along with some common scenarios you might come across in your Gradle project.

UPDATED in July 2021 to reflect recent versions of Gradle.

Why do we need project properties in a Gradle build?

A Gradle project property is a property that can be accessed in your project’s build.gradle and gets passed in from an external source when your build is executed.

Just like you might externalise configuration properties for an application so it can execute differently in different scenarios, the same applies to your Gradle build.

Let’s look at some reasons you might use project properties.

Avoid storing credentials or other sensitive information in version control

The following build.gradle configures the Gradle maven-publish plugin to publish a jar file built by the java plugin:

plugins {
    id 'java'
    id 'maven-publish'
}

publishing {
    publications {
        maven(MavenPublication) {
            from components.java
        }
    }
    repositories {
        maven {
            url 'https://maven.tomgregory.com/repository/snapshots'
            credentials {
                username 'tom'
                password 'buttons123'
            }
        }
    }
}

group 'org.example'
version '1.0-SNAPSHOT'

The above code will publish a jar file to a Maven repository when ./gradlew publish is run.

But, you can see the username and password for the Maven repository are hard-coded. Assuming we’re committing our code into version control, then this represents bad practice since anyone who checks out our code would immediately have access to the credentials.

Much better would be to pass the credentials in externally, using Gradle project properties. The build.gradle just needs to be modified slightly:

            ...
            credentials {
                username mavenUsername
                password mavenPassword
            }
            ...

Now when we call the publish task we can pass the properties in using the Gradle -P flag, like this:

./gradlew publish -PmavenUsername=tom -PmavenPassword=buttons123

The build may need to be run differently depending on the situation

Sometimes rather than hard-coding parts of our build, we need to be more flexible and run it differently in different situations. For example, in the previous section the Maven repository URL was hard coded, like this:

        maven {
            url 'https://maven.tomgregory.com/repository/snapshots'
            credentials {
                username mavenUsername
                password mavenPassword
            }
        }

There may be a requirement to sometimes push to a different repository, in which case we’d also want to externalise this property using a project property.

Some other scenarios like this include:

  • deployment - if your Gradle build is responsible for deploying then you may need to pass in extra information such as the environment and region to which to deploy
  • test memory allocation - the Gradle test task allows you to configure it’s maxHeapSize property. By using a project property, you can externalise this configuration and easily tweak the memory allocation for different environments.
  • database connection string - if your build needs to connect to a database to run tests, you could use a project property to provide the option to connect to a different database.

What ways are there to configure project properties?

Gradle provides several ways to pass properties into a build, some of which have higher priority than others. Or in other words, the same property key can be passed into the build in multiple ways, but the one with highest priority wins.

Here’s a quick overview of how that hierarchy works:

We’ll run through the ways to configure project properties from highest to lowest priority.

1) On the command line when calling Gradle using -P

When you run a Gradle command you can pass as many -PpropertyName=propertyValue flags as you like. For example:

./gradlew <task-name> -PmyPropName1=myPropValue1 -PmyPropName2=myPropValue2

2) As Java system properties using -D

You can pass Java system properties using the following syntax:

./gradlew <task-name> -Dorg.gradle.project.myPropName1=myPropValue1 -Dorg.gradle.project.myPropName2=myPropValue2

3) As environment variables

You can pass project properties as environment variables using the following syntax:

ORG_GRADLE_PROJECT_myPropName1=myPropValue1 ORG_GRADLE_PROJECT_myPropName2=myPropValue2 ./gradlew publish

4) In a gradle.properties file (Gradle user home directory)

A gradle.properties file is a list of key values pairs, each of which represents a property name and value. For example:

myPropName1=myPropValue1
myPropName2=myPropValue2

This gradle.properties is located in the GRADLE_USER_HOME directory, which is usually ~/.gradle/gradle.properties

5) In a gradle.properties file (project root directory)

Similar to above, a gradle.properties file can also be placed in the project root directory, i.e. my-awesome-project/gradle.properties.

For a full understanding of project properties, as well as other techniques for effectively organising your project like multi-project builds, I highly recommend signing up to the Gradle Hero course.

How can we access project properties in builds?

Once a property has been passed into our Gradle build, there are three ways to access it:

1) Directly as a variable

You can treat a project property as a variable, and just reference it by its name.

For example, if we passed in a project property with ./gradlew <task-name> -PmyPropName1=myPropValue1 then it could be accessed in build.gradle like this:

println myPropName1

If the property is not found, then a MissingPropertyException is thrown.

Also note, that with this method IDEs may have a problem understanding and show a syntax error. Here’s the output from IntelliJ IDEA:

Cannot infer argument type error

2) Using the property method

Gradle provides the following method to access a property:

Object property(String var1) throws MissingPropertyException

For example, if we called ./gradlew <task-name> -PmyPropName1=myPropValue1 then the property could be accessed like this:

println property('myPropName1')

Like before, if the property is not found, then a MissingPropertyException is thrown.

3) Using the findProperty method

When we need to access a property but don’t want an exception to be thrown if it’s not provided, use the findProperty method:

Object findProperty(String var1)

If we called ./gradlew <task-name> -PmyPropName1=myPropValue1 then the property could be accessed like this:

println findProperty('myPropName1')

This time, if the property is not found null is returned. This can be very useful if we want to return a default value, which we can do using Groovy’s Elvis operator:

println findProperty('myPropName1') ?: 'defaultValue'

Checking if a property exists with hasProperty

Lastly, we can check for the presence of the property using the hasProperty method:

boolean hasProperty(String var1)

This could be used where we have some build logic that’s only enabled if a specific property is set, for example:

if (hasProperty('myPropName1')) {
    println 'Doing some conditional build logic'
}

Summary

Here’s a summary of the 3 ways to access a property value:

Throws MissingPropertyException? IDE understands?
As a variable Yes No
property method Yes Yes
findProperty method No Yes

Resources

Documentation

See this Gradle Build Environment documentation which covers project properties, as well as Gradle and system properties.

Video

Check out the accompanying video from the Tom Gregory Tech YouTube channel.