web-dev-qa-db-fra.com

Problèmes lors de la transmission des propriétés du système et des paramètres lors de l’exécution de la classe Java via Gradle

J'essaie de lancer une ligne de commande Java app via Gradle dans le cadre d'un test d'intégration rapide. Je porte mes scripts de construction depuis Maven, où cela s'est fait facilement via exec-maven-plugin. Mes deux grandes exigences sont:

  • Être capable de transmettre les propriétés du système à l'exécutable Java code
  • Pouvoir transmettre des arguments de ligne de commande à l'exécutable Java code

Veuillez noter que je n'essaie pas de lire ces propriétés dans le script de construction, j'essaie de les lire dans le programme Java que le script construit et exécute.

J'ai trouvé deux autres SO publications qui traitent Java via Gradle: dont une avec une réponse préconisant l'utilisation de apply plugin: "application" dans le fichier de construction et gradle run sur la ligne de commande , et n autre avec des réponses préconisant cette approche, tout en utilisant task execute(type:JavaExec) dans le fichier de construction et gradle execute sur la ligne de commande .J'ai essayé les deux approches et n'ai pas réussi.

J'ai deux problèmes:

(1) Je ne peux pas obtenir l'exécutable Java pour lire les propriétés du système

Que je fasse ça:

build.gradle :

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

Ligne de commande :

gradle run -Dmyproperty=myvalue

Ou ca:

build.gradle :

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

Ligne de commande :

gradle execute -Dmyproperty=myvalue

Dans les deux cas, myproperty ne réussit pas. Le code qui commence à s'exécuter à partir de MyMain.main (...) lit la propriété système myproperty comme nulle/manquante.

(2) Je ne peux pas transmettre d'arguments de ligne de commande

Ceci est probablement lié au premier problème. Dans exec-maven-plugin, Par exemple, les arguments de ligne de commande ont eux-mêmes été transmis via une propriété système. Est-ce le cas avec Gradle ou existe-t-il un autre moyen de passer des arguments en ligne de commande?

Comment puis-je obtenir ces variables? Aussi, est-il préférable d'utiliser apply plugin: 'application' Ou task execute (type:JavaExec)?

75
sparc_spread

Deviner. Le problème principal est que, lorsque Gradle lance un nouveau processus Java, il ne transmet pas automatiquement les valeurs des variables d'environnement au nouvel environnement. Il faut explicitement les transmettre via le systemProperties propriété de la tâche ou du plugin.

L'autre problème consistait à comprendre comment passer des arguments en ligne de commande; Celles-ci se font via la propriété args de la tâche ou du plugin. Comme avec le Maven exec-maven-plugin, Ils doivent être passés sur la ligne de commande via une autre propriété système, sous la forme d'une liste délimitée par des espaces devant être split() avant de définir args, qui accepte les objets List. J'ai nommé la propriété exec.args, Qui est l'ancien nom Maven.

Il semble que l’approche javaExec et le plugin d’application soient valides. On peut privilégier l’approche plug-in d’application si l’on veut utiliser certaines de ses autres fonctionnalités (assemblage automatique d’une distribution, etc.).

Voici les solutions:

Approche JavaExec

Ligne de commande:

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

Application Plugin Approach

Ligne de commande:

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

Pour ceux qui ne voudront peut-être pas polluer les propriétés système de votre application en transmettant des accessoires Gradle sans rapport, je vous recommande de mettre en espacement vos arguments.

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

Java ... -Dprefix.my.prop=true passera my.prop

12
geg

Je suis nouveau sur Gradle alors j'en avais besoin et ce qui fonctionne pour moi avec Gradle 4.6 semble un peu plus facile pour la ligne de commande. Au lieu d'analyser 1 chaîne d'arguments, vous pouvez transmettre un tableau d'arguments. J'ai également trouvé un moyen de transmettre toutes les propriétés avec une seule ligne. Combinés ci-dessous:

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

Peut-être que je suis en retard pour la fête, mais est-ce que quelqu'un a déjà essayé de "régler l'accessoire avant d'exécuter Gradle"? J'ai testé et cela fonctionne apparemment aussi.

myVar=myVal gradle test

Par exemple, vous pouvez définir le profil actif comme suit:

SPRING_PROFILES_ACTIVE=dev  gradle test

Ceux-ci fonctionnent également, apparemment: (testé)

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

Méfiez-vous que myVar ne puisse pas être séparé par des points; ou bien seule la partie avant la première période sera considérée comme clé.

0
WesternGun