118

I'm trying to pass an argument from command line to a Java class. I followed this post: http://gradle.1045684.n5.nabble.com/Gradle-application-plugin-question-td5539555.html but the code does not work for me (perhaps it is not meant for JavaExec?). Here is what I tried:

task listTests(type:JavaExec){
    main = "util.TestGroupScanner"
    classpath = sourceSets.util.runtimeClasspath
    // this works...
    args 'demo'
    /*
    // this does not work!
    if (project.hasProperty("group")){
        args group
    }
    */
}

The output from the above hard coded args value is:

C:\ws\svn\sqe\sandbox\selenium2forbg\testgradle>g listTests
:compileUtilJava UP-TO-DATE
:processUtilResources UP-TO-DATE
:utilClasses UP-TO-DATE
:listTests
Received argument: demo

BUILD SUCCESSFUL

Total time: 13.422 secs

However, once I change the code to use the hasProperty section and pass "demo" as an argument on the command line, I get a NullPointerException:

C:\ws\svn\sqe\sandbox\selenium2forbg\testgradle>g listTests -Pgroup=demo -s

FAILURE: Build failed with an exception.

* Where:
Build file 'C:\ws\svn\sqe\sandbox\selenium2forbg\testgradle\build.gradle' line:25

* What went wrong:
A problem occurred evaluating root project 'testgradle'.
> java.lang.NullPointerException (no error message)

* Try:
Run with --info or --debug option to get more log output.

* Exception is:
org.gradle.api.GradleScriptException: A problem occurred evaluating root project
 'testgradle'.
    at org.gradle.groovy.scripts.internal.DefaultScriptRunnerFactory$ScriptRunnerImpl.run(DefaultScriptRunnerFactory.java:54)
    at org.gradle.configuration.DefaultScriptPluginFactory$ScriptPluginImpl.apply(DefaultScriptPluginFactory.java:127)
    at org.gradle.configuration.BuildScriptProcessor.evaluate(BuildScriptProcessor.java:38) 

There is a simple test project available at http://gradle.1045684.n5.nabble.com/file/n5709919/testgradle.zip that illustrates the problem.

This is using Gradle 1.0-rc-3. The NullPointer is from this line of code:

  args group 

I added the following assignment before the task definition, but it didn't change the outcome:

  group = hasProperty('group') ? group : 'nosuchgroup' 

Any pointers on how to pass command line arguments to Gradle appreciated.

aSemy
  • 5,485
  • 2
  • 25
  • 51
Lidia
  • 2,005
  • 5
  • 25
  • 32
  • TNX alot @Joshua Goldberg. sample for one argument: https://stackoverflow.com/a/58202665/2201814 – MHSaffari Oct 02 '19 at 13:36
  • Does this answer your question? [Gradle task - pass arguments to Java application](https://stackoverflow.com/questions/27604283/gradle-task-pass-arguments-to-java-application) – Joshua Goldberg Jul 05 '22 at 18:02

10 Answers10

66

project.group is a predefined property. With -P, you can only set project properties that are not predefined. Alternatively, you can set Java system properties (-D).

Peter Niederwieser
  • 121,412
  • 21
  • 324
  • 259
  • 4
    Thanks for letting me know! Changing name to testngGroup fixed the problem. Found a list of predefined properties in table 13.1 at http://gradle.org/docs/current/userguide/writing_build_scripts.html. – Lidia Jul 31 '12 at 23:50
  • 2
    Just to update the link: https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_properties_and_system_properties – Kikiwa Mar 08 '16 at 16:05
  • 1
    As of July 2018 there's a much simpler way. See [this answer](https://stackoverflow.com/a/53463332/5486) below. – Ryan Lundy Feb 18 '21 at 07:11
59

As noted in a comment, my solution is superceded by the newer built-in --args option in gradle. See this answer from @madhead or this similar question.


Building on Peter N's answer, this is an example of how to add (optional) user-specified arguments to pass to Java main for a JavaExec task (since you can't set the 'args' property manually for the reason he cites.)

Add this to the task:

task(runProgram, type: JavaExec) {

  [...]

  if (project.hasProperty('myargs')) {
      args(myargs.split(','))
  }

... and run at the command line like this

% ./gradlew runProgram '-Pmyargs=-x,7,--no-kidding,/Users/rogers/tests/file.txt'
Joshua Goldberg
  • 5,059
  • 2
  • 34
  • 39
  • 2
    How could I go about having separate parameters? E.g: `gradle run -Purl='localhost', -Pport='8080', -Pusername='admin' ` how would my code in build.gradle should look like? – Tomas Jan 19 '16 at 10:48
  • @Tomas I'd suggest fleshing out a top-level question for that. (I don't know that situation well enough to give a quick inline answer here myself, anyway.) – Joshua Goldberg Jan 19 '16 at 14:37
  • 1
    No worries, did it already and got sorted out [here](http://stackoverflow.com/questions/34875637/how-to-pass-multiple-parameters-in-command-line-when-running-gradle-task) – Tomas Jan 19 '16 at 14:54
  • 1
    As of July 2018 there's a much simpler way. See [this answer](https://stackoverflow.com/a/53463332/5486) below. – Ryan Lundy Feb 18 '21 at 07:11
29

My program with two arguments, args[0] and args[1]:

public static void main(String[] args) throws Exception {
    System.out.println(args);
    String host = args[0];
    System.out.println(host);
    int port = Integer.parseInt(args[1]);

my build.gradle

run {
    if ( project.hasProperty("appArgsWhatEverIWant") ) {
        args Eval.me(appArgsWhatEverIWant)
    }
}

my terminal prompt:

gradle run  -PappArgsWhatEverIWant="['localhost','8080']"
Oscar Raig Colon
  • 1,302
  • 12
  • 14
  • As of July 2018 there's a much simpler way. See [this answer](https://stackoverflow.com/a/53463332/5486) below. – Ryan Lundy Feb 18 '21 at 07:12
28

As of Gradle 4.9 Application plugin understands --args option, so passing the arguments is as simple as:

build.gradle

plugins {
    id 'application'
}

mainClassName = "my.App"

src/main/java/my/App.java

public class App {
    public static void main(String[] args) {
        System.out.println(args);
    }
}

bash

./gradlew run --args='This string will be passed into my.App#main arguments'

or in Windows, use double quotes:

gradlew run --args="This string will be passed into my.App#main arguments"
Ryan Lundy
  • 204,559
  • 37
  • 180
  • 211
madhead
  • 31,729
  • 16
  • 153
  • 201
23

You can use custom command line options in Gradle:

./gradlew printPet --pet="Puppies!"

Custom command line options were an incubating feature in Gradle 5.0 but became public in Gradle 6.0.

Java solution

Follow the instructions here:

import org.gradle.api.tasks.options.Option;

public class PrintPet extends DefaultTask {
    private String pet;

    @Option(option = "pet", description = "Name of the cute pet you would like to print out!")
    public void setPet(String pet) {
        this.pet = pet;
    }

    @Input
    public String getPet() {
        return pet;
    }

    @TaskAction
    public void print() {
        getLogger().quiet("'{}' are awesome!", pet);
    }
}

Then register it:

task printPet(type: PrintPet)

Now you can do:

./gradlew printPet --pet="Puppies!"

output:

Puppies! are awesome!

Kotlin solution

open class PrintPet : DefaultTask() {

    @Suppress("UnstableApiUsage")
    @set:Option(option = "pet", description = "The cute pet you would like to print out")
    @get:Input
    var pet: String = ""

    @TaskAction
    fun print() {    
        println("$pet are awesome!")
    }
}

then register the task with:

tasks.register<PrintPet>("printPet")
hertzsprung
  • 9,445
  • 4
  • 42
  • 77
David Rawson
  • 20,912
  • 7
  • 88
  • 124
8

If you need to check and set one argument, your build.gradle file would be like this:

....

def coverageThreshold = 0.15

if (project.hasProperty('threshold')) {
    coverageThreshold = project.property('threshold').toString().toBigDecimal()
}

//print the value of variable
println("Coverage Threshold: $coverageThreshold")
...

And the Sample command in windows:

gradlew clean test -Pthreshold=0.25

MHSaffari
  • 858
  • 1
  • 16
  • 39
4

I have written a piece of code that puts the command line arguments in the format that gradle expects.

// this method creates a command line arguments
def setCommandLineArguments(commandLineArgs) {
    // remove spaces 
    def arguments = commandLineArgs.tokenize()

            // create a string that can be used by Eval 
            def cla = "["
            // go through the list to get each argument
            arguments.each {
                    cla += "'" + "${it}" + "',"
            }

    // remove last "," add "]" and set the args 
    return cla.substring(0, cla.lastIndexOf(',')) + "]"
}

my task looks like this:

task runProgram(type: JavaExec) {
    if ( project.hasProperty("commandLineArgs") ) {
            args Eval.me( setCommandLineArguments(commandLineArgs) )
    }
}

To pass the arguments from the command line you run this:

gradle runProgram -PcommandLineArgs="arg1 arg2 arg3 arg4"    
3

There's a great example here:

https://kb.novaordis.com/index.php/Gradle_Pass_Configuration_on_Command_Line

Which details that you can pass parameters and then provide a default in an ext variable like so:

gradle -Dmy_app.color=blue

and then reference in Gradle as:

ext {
   color = System.getProperty("my_app.color", "red");
}

And then anywhere in your build script you can reference it as course anywhere you can reference it as project.ext.color

More tips here: https://kb.novaordis.com/index.php/Gradle_Variables_and_Properties

Matt Wolfe
  • 8,924
  • 8
  • 60
  • 77
0

Here is a solution for Kotlin DSL (build.gradle.kts).

I first try to get the variable as a property and if it was null try to get it from OS environment variables (can be useful in CIs like GitHub Actions).

tasks.create("MyCustomTask") {
    val songName = properties["songName"]
        ?: System.getenv("SONG_NAME")
        ?: error("""Property "songName" or environment variable "SONG_NAME" not found""")

    // OR getting the property with 'by'. Did not work for me!
    // For this approach, name of the variable should be the same as the property name
    // val songName: String? by properties

    println("The song name: $songName")
}

We can then pass a value for the property from command line:

./gradlew MyCustomTask -PsongName="Black Forest"

Or create a file named local.properties at the root of the project and set the property:

songName=Black Forest

We can also add an env variable named SONG_NAME with our desired value and then run the task:

./gradlew MyCustomTask
Mahozad
  • 18,032
  • 13
  • 118
  • 133
-5

pass a url from command line keep your url in app gradle file as follows resValue "string", "url", CommonUrl

and give a parameter in gradle.properties files as follows CommonUrl="put your url here or may be empty"

and pass a command to from command line as follows gradle assembleRelease -Pcommanurl=put your URL here