Gradle을 통해 Java 클래스를 실행할 때 시스템 속성 및 매개 변수 전달 문제


82

빠른 통합 테스트의 일부로 Gradle을 통해 명령 줄 Java 앱을 실행하려고합니다. Maven에서 빌드 스크립트를 이식하고 있는데 exec-maven-plugin. 내 두 가지 큰 요구 사항은 다음과 같습니다.

  • 시스템 속성을 실행 가능한 Java 코드로 전달할 수 있음
  • 실행 가능한 Java 코드에 명령 줄 인수를 전달할 수 있음

빌드 스크립트에서 이러한 속성을 읽으려는 것이 아니라 스크립트가 빌드하고 실행하는 Java 프로그램에서 읽으려고한다는 점에 유의하십시오.

나는 다른 두 SO의 게시물을 발견 한 그 주소 자바 프로그램 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 / 누락으로 읽습니다 .

(2) 명령 줄 인수를 전달할 수 없습니다.

이것은 아마도 첫 번째 문제와 관련이 있습니다. 에서은 exec-maven-plugin, 예를 들어, 명령 줄 인수 자체가 시스템 속성을 통해 전달했다. Gradle의 경우입니까, 아니면 명령 줄 인수를 전달하는 다른 방법이 있습니까?

이 변수를 어떻게 얻습니까? 또한 apply plugin: 'application'또는 사용하는 것이 더 낫 task execute (type:JavaExec)습니까?

답변:


123

그것을 알아 냈습니다. 주요 문제는 Gradle이 새 Java 프로세스를 포크 할 때 새 환경에 환경 변수 값을 자동으로 전달하지 않는다는 것입니다. systemProperties작업 또는 플러그인 의 속성을 통해 이러한 변수를 명시 적으로 전달해야합니다 .

다른 문제는 명령 줄 인수를 전달하는 방법을 이해하는 것이 었습니다. 이는 args작업 또는 플러그인 의 속성을 통해 이루어 집니다. Maven과 마찬가지로 exec-maven-plugin, 그것들은 또 다른 시스템 속성을 통해 명령 줄에 전달되어야합니다. 공백으로 구분 된 목록 은 객체 를 받아들이는 split()setting 전에 있어야 합니다. 이전 Maven 이름 인 속성의 이름을 지정했습니다.argsListexec.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 2014-08-12

1
당신이 Gradle을 2.XX를 사용하는 경우, 당신은 또한 다음을 사용할 수 있습니다 : -systemProperty "myvariable", "${myvariable}"
eadjei

1
감사합니다! 나는 Cucumber 테스트를 실행하려고 시도했고 환경 변수를 JVM에 전달하고 싶었습니다. 난 그냥 실행에서의 {} 대신 시험 ") (systemProperties의 System.getProperties"를 넣어 {}
반테

1
기본 분할은 공백이있는 인수를 허용하지 않습니다 (예 : -Dexec.args="--greeting 'hello there'"작동하지 않음, 다른 구분 기호를 설정해야 함).
Ivan Balashov 2015 년

3
사용 : args System.getProperty ( "exec.args", "") .split () 인수가 제공되지 않은 경우 널 포인터 예외를 방지합니다. 예를 들어, 심지어 'Gradle을 작업'제안 build.gradle에 예외가 발생합니다
마이크 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 개의 arg 문자열을 구문 분석하는 대신 args 배열을 전달할 수 있으며 한 줄로 모든 속성을 전달할 수있는 방법을 찾았습니다. 아래 결합 :

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

내가 파티에 늦었을지도 모르지만, "Gradle을 실행하기 전에 소품 설정"을 시도한 사람이 있습니까? 나는 테스트했고 이것도 분명히 작동합니다.

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기간으로 구분 될 수 없다; 그렇지 않으면 첫 번째 피리어드 이전의 부분 만 키로 간주됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.