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:
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.
Stop reading Gradle articles like these
This article helps you fix a specific problem, but it doesn't teach you the Gradle fundamentals you need to actually help your team succeed.
Instead, follow a step-by-step process that makes getting started with Gradle easy.