Проблемы с передачей свойств и параметров системы при запуске Java-класса через Gradle

Я пытаюсь запустить приложение Java с командной строкой через Gradle как часть теста быстрой интеграции. Я переношу свои скрипты сборки из Maven, где это легко было сделать с помощью exec-maven-plugin. Мои два больших требования:

  • Возможность передавать свойства системы исполняемому Java-коду
  • Возможность передавать аргументы командной строки исполняемому Java-коду

Обратите внимание, что я не пытаюсь прочитать эти свойства в сборке script, я пытаюсь прочитать их в программе Java, которую создает и выполняет script.

Я нашел два других сообщения SO, которые адресуют выполнение Java-программы через Gradle: один с ответом, который защищает использование apply plugin: "application" в файле сборки и gradle run на командной строки и другой с ответами, защищающими этот подход, а также используя task execute(type:JavaExec) в файле сборки и gradle execute в командной строке. Я пробовал оба подхода и не добился успеха.

У меня две проблемы:

(1) Я не могу заставить исполняемый файл Java читать свойства системы

Выполняю ли я это:

build.gradle

apply plugin: 'application'
mainClassName = "com.mycompany.MyMain"

Командная строка:

gradle run -Dmyproperty=myvalue

Или это:

build.gradle

task execute (type:JavaExec) {
    main = "com.mycompany.MyMain"
    classpath = sourceSets.main.runtimeClasspath 
}

Командная строка:

gradle execute -Dmyproperty=myvalue

В любом случае myproperty не проходит. Код, начинающийся с MyMain.main (...), считывает системное свойство myproperty как null/missing.

(2) Я не могу передать аргументы командной строки

Это, вероятно, связано с первой проблемой. В exec-maven-plugin, например, аргументы командной строки сами были переданы через системное свойство. Это случай с Gradle, или есть другой способ передать аргументы командной строки?

Как мне получить эти переменные? Кроме того, лучше использовать apply plugin: 'application' или task execute (type:JavaExec)?

Ответ 1

Выяснил это. Основная проблема заключается в том, что, когда Gradle открывает новый процесс Java, он автоматически не переносит значения переменной среды в новую среду. Нужно явно передать эти переменные с помощью свойства systemProperties задачи или плагина.

Другой проблемой было понимание того, как передавать аргументы командной строки; это через свойство args в задаче или плагине. Как и в случае с Maven exec-maven-plugin, они должны быть переданы в командной строке через еще одно системное свойство, как список с разделителями пробелов, который затем должен быть split() перед установкой args, который принимает объекты List. Я назвал свойство exec.args, которое является старым именем Maven.

Кажется, что действительны и методы javaExec, и плагин приложения. Можно использовать подход плагина приложения, если вы хотите использовать некоторые другие его функции (автоматически собирать дистрибутив и т.д.).

Вот решения:

Подход JavaExec

Командная строка:

gradle execute -Dmyvariable=myvalue -Dexec.args="arg1 arg2 arg3"

build.gradle

task execute (type:JavaExec) {

    main = "com.myCompany.MyMain"
    classpath = sourceSets.main.runtimeClasspath 

    /* Can pass all the properties: */
    systemProperties System.getProperties()

    /* Or just each by name: */
    systemProperty "myvariable", System.getProperty("myvariable")

    /* Need to split the space-delimited value in the exec.args */
    args System.getProperty("exec.args", "").split()    
}

Подход к плагину приложений

Командная строка:

gradle run -Dmyvariable=myvalue -Dexec.args="arg1 arg2 arg3"

build.gradle

apply plugin: 'application'
mainClassName = "com.mycompany.MyMain"
run {    
    /* Can pass all the properties: */
    systemProperties System.getProperties()

    /* Or just each by name: */
    systemProperty "myvariable", System.getProperty("myvariable")

    /* Need to split the space-delimited value in the exec.args */
    args System.getProperty("exec.args", "").split()    
}

Ответ 2

Для тех, кто не хочет загрязнять свойства вашей прикладной системы, передавая несвязанные реквизиты Gradle, я рекомендую namespacing ваши аргументы.

tasks.withType(JavaExec) {
    System.properties.each { k,v->
        if (k.startsWith("prefix.")) {
            systemProperty k - "prefix.", v
        }
    }
}

java ... -Dprefix.my.prop=true пройдет my.prop