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


82

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

  • Можливість передавати властивості системи виконуваному коду Java
  • Можливість передавати аргументи командного рядка виконуваному коду Java

Зверніть увагу, що я не намагаюся прочитати ці властивості у сценарії побудови, я намагаюся прочитати їх у програмі Java, яку створює та виконує сценарій.

Я знайшов дві інші публікації 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системну властивість як нульову / відсутню.

(2) Я не можу передавати аргументи командного рядка

Ймовірно, це пов’язано з першою проблемою. В exec-maven-plugin, наприклад, в командному рядку арг були самі пройшли в с допомогою системного властивості. Це випадок із Gradle, чи є інший спосіб передачі аргументів командного рядка?

Як отримати ці змінні? Крім того, чи краще використовувати apply plugin: 'application'чи task execute (type:JavaExec)?

Відповіді:


124

Розібрався. Основна проблема полягає в тому, що коли Gradle розгалужує новий процес Java, він не передає автоматично значення змінних середовища в нове середовище. Потрібно явно передавати ці змінні через systemPropertiesвластивість завдання або плагіна.

Іншим питанням було розуміння того, як передавати аргументи командного рядка; це через argsвластивість завдання або плагіна. Як і у випадку з Maven exec-maven-plugin, вони повинні передаватися в командному рядку через ще одне системне властивість, як розділений пробілом список, який потім повинен бути split()перед налаштуванням args, який приймає Listоб'єкти. Я назвав це майно exec.args, яке є старою назвою Мейвен.

Здається, 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()    
}

3
Я думаю, що це має бути System.getProperties () (велика S).
orlanthi

1
Якщо ви використовуєте gradle 2.xx, ви також можете використовувати наступне: -systemProperty "myvariable", "${myvariable}"
eadjei

1
Дякую! Я намагався запустити тести на огірок і хотів передати змінні середовища в JVM. Я просто поставив "systemProperties System.getProperties ()" в тест {} замість запуску {}
Svante

1
Зверніть увагу, що розділення за замовчуванням не дозволяє аргументи з пробілами, наприклад -Dexec.args="--greeting 'hello there'"- не буде працювати, потрібно встановити інший роздільник.
Іван Балашов

3
Використовуйте: args System.getProperty ("exec.args", "") .split (), щоб уникнути винятку нульового покажчика, якщо аргументи не вказані. Наприклад, навіть `` завдання gradle '' викличуть виняток із запропонованим build.gradle
Mike Hanafey

12

Тим, хто, можливо, не хоче забруднювати системні властивості вашої програми, передаючи не пов’язані між собою реквізити Gradle, я рекомендую розставити імена до ваших аргументів.

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

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


3

Я новачок у gradle, тому мені це було потрібно, і те, що працює для мене з gradle 4.6, здається трохи простішим для командного рядка. Замість синтаксичного аналізу 1 рядка аргументу ви можете передати масив аргументів, і я знайшов спосіб передати всі властивості за допомогою одного рядка. У поєднанні нижче:

apply plugin: 'java'
apply plugin: 'org.springframework.boot'    <- for my project

task runApp(type: JavaExec) {
  classpath = sourceSets.main.runtimeClasspath

  main = 'testit.TomcatApp'

  // arguments to pass to the application
  //  args 'myarg1 -rest'    <- came in as 1 string

  args = ["--myarg1 with spaces even", "--myarg2"]

  // and to pass in all -D system property args:
  systemProperties = System.properties
}

gradle run -Dwhatever=xxx -Dmyarg2=hey

// Java reading them:
public static void main(String[] args) {
    for ( int i = 0; i < args.length; i++ )
        {
        logger.info( "** args [" + i + "] =" + args[i] + "=" );
        }
    logger.info( "** -Dwhatever =" + System.getProperty("whatever") + "=" );
    logger.info( "** -Dmyarg2 =" + System.getProperty("myarg2") + "=" );

[main] INFO testit.TomcatApp - ** args [0] =--myarg1 with spaces even=
[main] INFO testit.TomcatApp - ** args [1] =--myarg2=
[main] INFO testit.TomcatApp - ** -Dwhatever =xxx=
[main] INFO testit.TomcatApp - ** -Dmyarg2 =hey=

-2

Можливо, я запізнююсь на вечірку, але чи хтось пробував із "встановити опору перед виконанням градле"? Я тестував, і це, мабуть, теж працює.

myVar=myVal gradle test

Наприклад, ви можете встановити активний профіль, наприклад:

SPRING_PROFILES_ACTIVE=dev  gradle test

Вони також працюють, мабуть: (перевірено)

set myVar=myVal && gradle test      # for windows
export myVar=myVal && gradle test   # for linux and mac

Будьте обережні, myVarне можна розділяти періоди; або ж лише ключовою буде взята лише частина до першого періоду.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.