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:
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)
?
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:
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()
}
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()
}
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
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=
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é.