Loading...

December 13, 2016

Gradle Goodness: Passing Environment Variable Via Delegate Run Action In IntelliJ IDEA

IntelliJ IDEA 2016.3 introduced the option to delegate the run action to Gradle. This means when we have a run Configuration for our Java or Groovy classes we can use the Run action and IDEA will use Gradle to run the application. Actually IntelliJ IDEA creates a new task of type JavaExec dynamically for our specific run configuration with the main property set to the class we want to run.

In the Edit Configuration dialog window we can set the command line argument and Java system properties. These are passed on to the dynamically created JavaExec task and are accessible from within the class that runs. The environment variables that can be set in the Edit Configuration dialog windows are not passed to the JavaExec task configuration. But we can do it ourselves in the build script file of our project. We look for the dynamically created task and use the environment method to add a environment variable that can be access in the Java or Groovy class that is executed.

We start our example with a simple Groovy class that can be executed using JavaExec. We simply print out the given input arguments, all Java system properties that start with sampleApp and finally all environment variables that start with SAMPLE_APP:

// File: src/main/groovy/mrhaki/gradle/SampleApp.groovy
package mrhaki.gradle

class SampleApp {

    static void main(final String[] args) {
        final app = new SampleApp()
        app.printArgs(args)
        app.printSystemProperties()
        app.printEnv()
    }

    void printArgs(final String[] args) {
        printSection 'Command line arguments', args
    }

    void printSystemProperties() {
        printSection 'System properties', System.properties.findAll(findNameStartsWith('sampleApp'))
    }

    void printEnv() {
        printSection 'environment', System.getenv().findAll(findNameStartsWith('SAMPLE_APP'))
    }
    
    private void printSection(final String title, final values) {
        println "--- $title ---"
        println values
    }

    private Closure findNameStartsWith(final String search) {
        { name, value -> name.startsWith(search) }
    }
    
}

We create a new Run/Debug Configuration for our SampleApp class:

When we click on OK to save the configuration we are ready to use the Run 'SampleApp' action. When we look at the output we get the following result:

10:54:29: Executing external task 'run SampleApp'...
:compileJava UP-TO-DATE
:compileGroovy 
:processResources UP-TO-DATE
:classes 
:run SampleApp
--- Command line arguments ---
[Execute via IDEA delegate to Gradle]
--- System properties ---
[sampleApp:Gradle Galore]
--- environment ---
[:]

BUILD SUCCESSFUL

Total time: 3.539 secs
10:54:33: External task execution finished 'run SampleApp'.

Notice the Gradle tasks that are invoked and the dynamically created run SampleApp task. We see our Java system property is passed on, together with the program arguments. The environment variable is not passed on. We must add some extra configuration to the dynamically created task run Sample in our build.gradle file:

// File: build.gradle
...
setEnvVarRunConfiguration 'SampleApp', 'SAMPLE_APP', 'Gradle environment variable'

/**
 * Add environment variable to JavaExec task
 * configuration created by IntelliJ IDEA
 * from a Run/Debug configuration.
 * 
 * @param configuration Name of IntelliJ IDEA Run/Debug configuration
 * @param envName Name of environment variable
 * @param envValue Value for environment variable
 */
def setEnvVarRunConfiguration(
        final String configuration, 
        final String envName, 
        final String envValue) {

    // Find task by type JavaExec and matching 
    // task name for configuration name.
    final javaExecRunConfiguration = { task -> 
        task instanceof JavaExec && task.name == "run $configuration"
    }
    
    tasks.matching(javaExecRunConfiguration).all {
        // Add environment variable to JavaExec 
        // task configuration.
        environment envName, envValue
    }
}
...

Now we re-run our application and we get the following output:

11:29:19: Executing external task 'run SampleApp'...
:compileJava UP-TO-DATE
:compileGroovy UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:run SampleApp
--- Command line arguments ---
[Execute via IDEA delegate to Gradle]
--- System properties ---
[sampleApp:Gradle Galore]
--- environment ---
[SAMPLE_APP:Gradle environment variable]

BUILD SUCCESSFUL

Total time: 0.599 secs
11:29:19: External task execution finished 'run SampleApp'.

Written with IntelliJ IDEA 2016.3 and Gradle 3.2.1.