Probleme beim Übergeben von Systemeigenschaften und -parametern beim Ausführen der Java-Klasse über Gradle

82

Ich versuche, im Rahmen eines schnellen Integrationstests eine Java-Befehlszeilen-App über Gradle auszuführen. Ich portiere meine Build-Skripte von Maven, wo dies einfach über möglich war exec-maven-plugin. Meine zwei großen Anforderungen sind:

  • In der Lage sein, Systemeigenschaften an den ausführbaren Java-Code zu übergeben
  • Befehlszeilenargumente an den ausführbaren Java-Code übergeben können

Bitte beachten Sie, dass ich nicht versuche, diese Eigenschaften im Build-Skript zu lesen, sondern sie im Java-Programm zu lesen, das das Skript erstellt und ausführt.

Ich habe zwei weitere SO-Posts gefunden, die sich mit der Ausführung von Java-Programmen über Gradle befassen: einen mit einer Antwort, die die Verwendung apply plugin: "application"in der Build-Datei und gradle runin der Befehlszeile befürwortettask execute(type:JavaExec)gradle execute , und einen mit Antworten, die diesen Ansatz befürworten, sowie die Verwendung in der Build-Datei und im Befehlszeile . Ich habe beide Ansätze ausprobiert und es nicht geschafft.

Ich habe zwei Probleme:

(1) Ich kann die ausführbare Java-Datei nicht zum Lesen der Systemeigenschaften bringen

Ob ich das mache:

build.gradle :

apply plugin: 'application'
mainClassName = "com.mycompany.MyMain"

Befehlszeile :

gradle run -Dmyproperty=myvalue

Oder dieses:

build.gradle :

task execute (type:JavaExec) {
    main = "com.mycompany.MyMain"
    classpath = sourceSets.main.runtimeClasspath 
}

Befehlszeile :

gradle execute -Dmyproperty=myvalue

In beiden Fällen mypropertyschafft es nicht durch. Der Code, der ab ausgeführt wird, MyMain.main (...)liest die mypropertySystemeigenschaft als null / fehlend.

(2) Ich kann keine Befehlszeilenargumente übergeben

Dies hängt wahrscheinlich mit dem ersten Problem zusammen. In exec-maven-pluginzum Beispiel Befehlszeile args waren , sich in über eine Systemeigenschaft übergeben. Ist das bei Gradle der Fall oder gibt es eine andere Möglichkeit, Befehlszeilenargumente zu übergeben?

Wie komme ich durch diese Variablen? Auch ist es besser zu verwenden apply plugin: 'application'oder task execute (type:JavaExec)?

sparc_spread
quelle

Antworten:

123

Herausgefunden. Das Hauptproblem besteht darin, dass Gradle beim Gabeln eines neuen Java-Prozesses die Umgebungsvariablenwerte nicht automatisch an die neue Umgebung weitergibt. Diese Variablen müssen explizit über die systemPropertiesEigenschaft der Aufgabe oder des Plugins übergeben werden.

Das andere Problem bestand darin, zu verstehen, wie Befehlszeilenargumente übergeben werden. Diese sind über die argsEigenschaft auf der Aufgabe oder dem Plugin. Wie beim Maven exec-maven-pluginsollten sie über eine weitere Systemeigenschaft in der Befehlszeile übergeben werden, als durch Leerzeichen getrennte Liste, die dann split()vor dem Festlegen erstellt werden muss argsund ListObjekte akzeptiert . Ich habe die Eigenschaft benannt exec.args, die der alte Maven-Name ist.

Es scheint, dass sowohl der javaExecAnsatz als auch der Anwendungs-Plugin gültig sind. Man könnte den Ansatz des Anwendungs-Plugins bevorzugen, wenn man einige seiner anderen Funktionen nutzen möchte (automatisch eine Distribution zusammenstellen usw.)

Hier sind die Lösungen:

JavaExec-Ansatz

Befehlszeile :

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()    
}

Anwendungs-Plugin-Ansatz

Befehlszeile :

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()    
}
sparc_spread
quelle
3
Ich denke, das sollte System.getProperties () (Hauptstadt S) sein.
Orlanthi
1
Wenn Sie gradle 2.xx verwenden, können Sie auch Folgendes verwenden: -systemProperty "myvariable", "${myvariable}"
eadjei
1
Vielen Dank! Ich habe versucht, Gurkentests auszuführen, und wollte Umgebungsvariablen an die JVM übergeben. Ich habe gerade "systemProperties System.getProperties ()" in test {} anstatt in run {}
Svante
1
Bitte beachten Sie, dass die Standardaufteilung keine Argumente mit Leerzeichen zulässt, z. B. -Dexec.args="--greeting 'hello there'"- funktioniert nicht, es muss ein anderes Trennzeichen festgelegt werden.
Ivan Balashov
3
Verwenden Sie: args System.getProperty ("exec.args", "") .split (), um eine Nullzeigerausnahme zu vermeiden, wenn keine Argumente angegeben werden. Zum Beispiel werden selbst "Gradle-Aufgaben" eine Ausnahme mit dem vorgeschlagenen build.gradle
Mike Hanafey
12

Für diejenigen, die die Systemeigenschaften Ihrer Anwendung möglicherweise nicht durch Übergabe nicht verwandter Gradle-Requisiten verschmutzen möchten, empfehle ich, Ihre Argumente mit einem Namespace zu versehen.

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

java ... -Dprefix.my.prop=true wird bestehen my.prop

geg
quelle
3

Ich bin neu in Gradle, also brauchte ich das und was mit Gradle 4.6 für mich funktioniert, scheint für die Kommandozeile etwas einfacher zu sein. Anstatt 1 Arg-String zu analysieren, können Sie ein Array von Args übergeben, und ich habe einen Weg gefunden, alle Eigenschaften auch mit einer Zeile zu übergeben. Unten kombiniert:

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=
Stan Towianski
quelle
-1

Vielleicht komme ich zu spät zur Party, aber hat jemand versucht, "die Requisite vor dem Ausführen von Gradle zu setzen"? Ich habe getestet und das funktioniert anscheinend auch.

myVar=myVal gradle test

Sie können das aktive Profil beispielsweise wie folgt festlegen:

SPRING_PROFILES_ACTIVE=dev  gradle test

Diese funktionieren anscheinend auch: (getestet)

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

Seien Sie vorsichtig, myVardas nicht durch Perioden getrennt werden kann. oder nur der Teil vor der ersten Periode wird als Schlüssel genommen.

WesternGun
quelle