Gradle pour exécuter la classe Java (sans modifier build.gradle)

119

Il existe un simple plugin Eclipse pour exécuter Gradle, qui utilise simplement la ligne de commande pour lancer gradle.

Qu'est-ce que Gradle Analog for Maven Compile and Run mvn compile exec:java -Dexec.mainClass=example.Example

De cette façon, tout projet avec gradle.buildpeut être exécuté.

MISE À JOUR: Il y avait une question similaire Quel est l'équivalent gradle du plugin exec de maven pour exécuter des applications Java? demandé avant, mais la solution suggérée de modifier chaque projetbuild.gradle

package runclass;

public class RunClass {
    public static void main(String[] args) {
        System.out.println("app is running!");
    }
}

Puis exécution gradle run -DmainClass=runclass.RunClass

:run FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':run'.
> No main class specified   
Paul Verest
la source
Double probable de stackoverflow.com/questions/16350757/…
Teresa Carrigan
Utilisez la commande: gradle run
a_subscriber

Réponses:

138

Il n'y a pas d'équivalent direct à mvn exec:javain gradle, vous devez soit appliquer le applicationplugin, soit avoir une JavaExectâche.

application brancher

Activez le plugin:

plugins {
    id 'application'
    ...
}

Configurez-le comme suit:

application {
    mainClassName = project.hasProperty("mainClass") ? getProperty("mainClass") : "NULL"
}

Sur la ligne de commande, écrivez

$ gradle -PmainClass=Boo run

JavaExec tâche

Définissez une tâche, disons execute:

task execute(type:JavaExec) {
   main = project.hasProperty("mainClass") ? getProperty("mainClass") : "NULL"
   classpath = sourceSets.main.runtimeClasspath
}

Pour courir, écrivez gradle -PmainClass=Boo execute. Vous obtenez

$ gradle -PmainClass=Boo execute
:compileJava
:compileGroovy UP-TO-DATE
:processResources UP-TO-DATE
:classes
:execute
I am BOO!

mainClassest une propriété passée dynamiquement en ligne de commande. classpathest prêt à récupérer les dernières classes.


Si vous ne transmettez pas la mainClasspropriété, les deux approches échouent comme prévu.

$ gradle execute

FAILURE: Build failed with an exception.

* Where:
Build file 'xxxx/build.gradle' line: 4

* What went wrong:
A problem occurred evaluating root project 'Foo'.
> Could not find property 'mainClass' on task ':execute'.
Premier zéro
la source
1
Vous devez modifier build.gradle, le classpathest codé en dur pour récupérer les classes java à partir de votre build.gradle chemin de classe source java . Même lorsque vous exécutez mvn exec:javale classpath est configuré pour récupérer les fichiers source java dans le répertoire maven actuel. Dans la JavaExectâche, j'ai fait la même chose. Changez le classpathpour votre source java et le chemin de classe changera automatiquement. Il n'y a pas d' mvn exec:javaéquivalent dans la gradlenécessité d'appliquer le applicationplugin ou d'avoir une JavaExectâche.
First Zero le
1
OU l'autre option est d'écrire votre propre plugin pour ce faire et même dans ce cas, vous devez changer le build.gradle pour récupérer votre plugin.
First Zero le
3
Je viens d'essayer ceci et il semble qu'après l'ajout task execute(...à build.gradle, toutes les autres tâches échouent avec le même message d'erreur indiquant que gradle s'attend à ce que mainClass soit transmis. Je ne peux pas nettoyer ou construire.
Nirro
4
@Nirei Remplacez main = mainClasspar main = getProperty("mainClass")et il ne vous criera plus dessus.
Adi Gerber
2
cela casse encore gradle build, voir ma réponse ci-dessous.
Matt
140

Il vous suffit d'utiliser le plugin Gradle Application :

apply plugin:'application'
mainClassName = "org.gradle.sample.Main"

Et puis simplement gradle run.

Comme le souligne Teresa, vous pouvez également configurer en mainClassNametant que propriété système et exécuter avec un argument de ligne de commande.

Vidya
la source
2
Cela nécessiterait de coder en dur chaque classe dans build.graldle. Mais j'ai un projet avec beaucoup de classes util, qui ont toutes une méthode principale.
Paul Verest
Et vous êtes sûr que 1) le nom de classe pleinement qualifié est correct 2) vous avez mis le bon nom de propriété dans votre fichier de construction - par exemple System.getProperty("mainClass") , 3) le code source est là où il est censé être selon la convention, 4) tout fonctionne quand vous mettez RunClassdans le fichier de construction?
Vidya le
Il ne fonctionne que si build.gradlea mainClassName = "runclass.RunClass". Le paramètre -DmainClassn'a aucun effet: gradle run -DmainClass=runclass.RunClass2exécute la classe principale codée en dur.
Paul Verest
3
Si vous faites les deux (approche de création de fichier et approche de propriété), je ne sais pas vraiment ce qui a la priorité. Vous devriez trouver cette réponse ou ne pas faire les deux lors de vos tests.
Vidya le
2
@PaulVerest Voici ce que j'ai fait: ext.mainClass = project.hasProperty('mainClass') ? project.getProperty('mainClass') : 'org.gradle.sample.Main' ; apply plugin:'application' ; mainClassName = ext.mainClass Maintenant, quand vous le faites, vous gradle -PmainClass=Foo rundevriez l'utiliser Foocomme classe principale.
msridhar
26

En développant la réponse de First Zero, je suppose que vous voulez quelque chose où vous pouvez également exécuter gradle buildsans erreurs.

Les deux gradle buildet gradle -PmainClass=foo runApptravailler avec ceci:

task runApp(type:JavaExec) {
    classpath = sourceSets.main.runtimeClasspath

    main = project.hasProperty("mainClass") ? project.getProperty("mainClass") : "package.MyDefaultMain"
}

où vous définissez votre classe principale par défaut.

Mat
la source
2
Imho cela devrait être la réponse acceptée. L'utilisation de la méthode de FirstZero ou de Vidya provoquera la plainte d'autres tâches en raison de la non-spécification de la classe principale.
yanhan
L'approche de Matt pour définir la valeur principale fonctionne également pour le plugin d'application. Je l'utilise avec le Gradle Kotlin DSL: plugins { application }; application { mainClassName = if (project.hasProperty("mainClass")) project.properties.get("mainClass").toString() else "Foo" }
pvillela
@Matt Cette approche rompt mon programme Java simple qui utilise un Scannerpour lire nextLine(). Une réflexion sur un correctif pour cela? Continuez à obtenir "aucune ligne trouvée" lors de l'exécution en utilisant runApp.
Greg Hilston
2
À tous ceux qui liront ceci à l'avenir, j'ai utilisé `standardInput = System.in` pour permettre à mon exécution gradle de toujours passer en entrée
Greg Hilston
0

Vous pouvez le paramétrer et passer gradle clean build -Pprokey = goodbye

task choiceMyMainClass(type: JavaExec) {
     group = "Execution"
    description = "Run Option main class with JavaExecTask"
    classpath = sourceSets.main.runtimeClasspath

    if (project.hasProperty('prokey')){
        if (prokey == 'hello'){
            main = 'com.sam.home.HelloWorld'
        } 
        else if (prokey == 'goodbye'){
            main = 'com.sam.home.GoodBye'
        }
    } else {
            println 'Invalid value is enterrd';

       // println 'Invalid value is enterrd'+ project.prokey;
    }
Sameera De Silva
la source