Проблемы с передачей свойств и параметров системы при запуске 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