IT TIP

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

itqueen 2020. 10. 16. 19:21
반응형

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


빠른 통합 테스트의 일부로 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)습니까?


그것을 알아 냈습니다. 주요 문제는 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()    
}

For those who might not want to pollute your application's system properties by passing unrelated Gradle props, I recommend namespacing your arguments.

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

java ... -Dprefix.my.prop=true will pass my.prop


I'm new to gradle so I needed this and what is working for me with gradle 4.6 seems a little easier for the command line. Instead of parsing 1 arg string you can pass an array of args, and I found a way to pass in all property with one line as well. Combined below:

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=

Maybe I am late for the party, but has anyone tried with "set the prop before executing gradle"? I have tested and this works too, apparently.

myVar=myVal gradle test

For example, you can set the active profile like:

SPRING_PROFILES_ACTIVE=dev  gradle test

These also work, apparently:(tested)

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

Be wary that myVar cannot be period-separated; or else only the part before the first period will be taken as key.

참고URL : https://stackoverflow.com/questions/23689054/problems-passing-system-properties-and-parameters-when-running-java-class-via-gr

반응형