Determining System Properties With Gradle Tasks

| Comments

I had a need for a gradle task to determine at runtime a system property that would be passed to another task. Googling for an answer to what I thought was an easy problem came up empty and it took me a few hours to figure out the appropriate incantation to get it to do what I wanted so I thought I’d memorialize this for someone (possbily future me, who’s googling for this after I’ve forgotten this solution).

This is a contrived example, but it demonstrates what I needed.

If I have the following Java file that is getting configuration injected via System.getProperty():

package com.naleid;

public class Example {
  public static void main(String[] args) throws Exception {
    System.out.println("Hello from " + System.getProperty("external.ip",  "localhost"));

If my external IP is, it should print out Hello from when I execute gradle run.

If that system property is known at the time that I execute my gradle task, I want to be able to call the run task with ./gradlew -Dexternal.ip= run.

example run when passing in system property:

% gradle -Dexternal.ip= run
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:setupRun SKIPPED
Hello from


Total time: 0.642 secs

If that system property isn’t known when I execute gradle run, I want gradle to figure it out for me and pass it in to the run task as a system property.

% gradle run
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
Hello from


Total time: 0.739 secs

Here is the buiild.gradle file that gives us the desired behavior.

apply plugin: 'java'
apply plugin: 'application'

repositories {

dependencies { }

mainClassName = "com.naleid.Example"

task setupRun(type:Exec) {
  onlyIf { !System.getProperty('external.ip') }

  workingDir './'
  commandLine 'curl', '-s', ''
  standardOutput = new ByteArrayOutputStream()

  // must define it before using it
  ext {
    externalIp = null

  // after the curl command has run and exited, we have the IP in populated standard out
  doLast {
    externalIp = standardOutput.toString().trim()

run {
  dependsOn setupRun

  // must be inside a doFirst, without it, this gets evaluated before the value is populated by the task
  doFirst {
    systemProperties['external.ip'] = setupRun.externalIp ?: System.getProperty('external.ip')

This build.gradle file uses curl -s to determine the current IP. It changes the run task (provided by the application plugin) so that it dependsOn setupRun. This causes setupRun to be executed before the run task.

The setupRun task is an Exec task and we define an ext dynamic property in it (initialized to null). After the curl command completes, we take the standard ouput and set the dynamic externalIp property equal to it’s output. We also check to see if the property has already been defined (via -Dexternal.ip given to gradle). If it is, we don’t run the task.

The run task has a doFirst block where we are able to get access to the systemProperties that will be passed to the java “main” class. Here we can set up our external.ip system property and set it either to the setupRun.externalIp dynamic variable attached to the task, or fall through to the system property given to gradle by the user.

A working example of this is out in a github repo. Just clone the repo locally and execute ./gradlew run to see your current IP injected by the gradle task.