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.