Gradle zum Ausführen der Java-Klasse (ohne build.gradle zu ändern)

119

Es gibt ein einfaches Eclipse-Plugin zum Ausführen von Gradle, das nur die Befehlszeilenmethode zum Starten von Gradle verwendet.

Was ist Gradle Analog für Maven kompilieren und ausführen mvn compile exec:java -Dexec.mainClass=example.Example

Auf diese Weise kann jedes Projekt mit ausgeführt gradle.buildwerden.

UPDATE: Es gab eine ähnliche Frage. Was ist das Gradle-Äquivalent des Exec-Plugins von maven zum Ausführen von Java-Apps? vorher gefragt, aber die Lösung schlug vor, jedes Projekt zu ändernbuild.gradle

package runclass;

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

Dann ausführen 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
quelle
Wahrscheinliches Duplikat von stackoverflow.com/questions/16350757/…
Teresa Carrigan
Verwenden Sie den Befehl: gradle run
a_subscriber

Antworten:

138

Es gibt kein direktes Äquivalent zu mvn exec:javain gradle. Sie müssen entweder das applicationPlugin anwenden oder eine JavaExecAufgabe haben.

application Plugin

Aktivieren Sie das Plugin:

plugins {
    id 'application'
    ...
}

Konfigurieren Sie es wie folgt:

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

Schreiben Sie in die Befehlszeile

$ gradle -PmainClass=Boo run

JavaExec Aufgabe

Definieren Sie eine Aufgabe, sagen wir execute:

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

Zum Laufen schreiben gradle -PmainClass=Boo execute. Du erhältst

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

mainClassist eine Eigenschaft, die dynamisch über die Befehlszeile übergeben wird. classpathist so eingestellt, dass die neuesten Klassen abgeholt werden.


Wenn Sie die mainClassEigenschaft nicht übergeben, schlagen beide Ansätze wie erwartet fehl.

$ 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'.
Erste Null
quelle
1
Sie müssen Änderungen vornehmen build.gradle, die fest classpathcodiert sind, um die Java- Klassen aus Ihrem build.gradle Java- Quellklassenpfad abzurufen. Selbst wenn Sie mvn exec:javaden Klassenpfad ausführen , werden die Java-Quelldateien im aktuellen Maven-Verzeichnis abgerufen. In der JavaExecAufgabe habe ich das gleiche getan. Ändern Sie die classpathfür Ihre Java- Quelle und der Klassenpfad ändert sich automatisch. Es gibt kein mvn exec:javaÄquivalent gradledazu, dass Sie entweder das applicationPlugin anwenden oder eine JavaExecAufgabe haben müssen.
Erste Null
1
ODER die andere Option ist, dass Sie Ihr eigenes Plugin schreiben, um dies zu tun, und selbst dann müssen Sie das build.gradle ändern, um Ihr Plugin aufzunehmen.
Erste Null
3
Ich habe es gerade versucht und es scheint, dass nach dem Hinzufügen task execute(...zu build.gradle jede andere Aufgabe mit derselben Fehlermeldung fehlschlägt, die besagt, dass gradle erwartet, dass mainClass weitergegeben wird. Ich kann nicht putzen oder bauen.
Nirro
4
@Nirei Ersetzen Sie main = mainClassmit main = getProperty("mainClass")und es wird Sie nicht mehr anschreien.
Adi Gerber
2
das bricht immer noch gradle build, siehe meine Antwort unten.
Matt
140

Sie müssen nur das Gradle Application Plugin verwenden :

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

Und dann einfach gradle run.

Wie Teresa betont, können Sie auch mainClassNameals Systemeigenschaft konfigurieren und mit einem Befehlszeilenargument ausführen.

Vidya
quelle
2
Das würde erfordern, jede solche Klasse hart zu codieren build.graldle. Aber ich habe ein Projekt mit vielen Util-Klassen, von denen jede eine Hauptmethode hat.
Paul Verest
Und Sie sind sicher, 1) der vollständig qualifizierte Klassenname ist korrekt 2) Sie haben den richtigen Eigenschaftsnamen in Ihre Build-Datei eingefügt - z. B. System.getProperty("mainClass") 3) der Quellcode befindet sich dort, wo er gemäß Konvention sein soll, 4) alles funktioniert Wann legst du RunClassdie Build-Datei ein?
Vidya
Es funktioniert nur wenn build.gradlehat mainClassName = "runclass.RunClass". Parameter -DmainClasshat keine Auswirkung: gradle run -DmainClass=runclass.RunClass2Führt die fest codierte Hauptklasse aus.
Paul Verest
3
Wenn Sie beides tun (Build-File-Ansatz und Property-Ansatz), weiß ich eigentlich nicht, welcher Vorrang hat. Sie sollten diese Antwort entweder finden oder nicht beides in Ihren Tests tun.
Vidya
2
@PaulVerest Folgendes habe ich getan: ext.mainClass = project.hasProperty('mainClass') ? project.getProperty('mainClass') : 'org.gradle.sample.Main' ; apply plugin:'application' ; mainClassName = ext.mainClass Wenn Sie dies tun gradle -PmainClass=Foo run, sollte es Fooals Hauptklasse verwendet werden.
Msridhar
25

Wenn Sie die Antwort von First Zero erweitern, möchten Sie wahrscheinlich etwas, das Sie auch gradle buildfehlerfrei ausführen können.

Beide gradle buildundgradle -PmainClass=foo runApp arbeiten:

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

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

Hier legen Sie Ihre Standardhauptklasse fest.

Matt
quelle
2
Imho sollte dies die akzeptierte Antwort sein. Die Verwendung der Methode von FirstZero oder Vidya führt dazu, dass sich andere Aufgaben beschweren, da die Hauptklasse nicht angegeben ist.
Yanhan
Matts Ansatz zum Festlegen des Hauptwerts funktioniert auch für das Anwendungs-Plugin. Ich benutze es mit dem Gradle Kotlin DSL: plugins { application }; application { mainClassName = if (project.hasProperty("mainClass")) project.properties.get("mainClass").toString() else "Foo" }
Pvillela
@Matt Dieser Ansatz bricht mein einfaches Java-Programm, das Scannerzum Lesen ein verwendet nextLine(). Irgendwelche Gedanken zu einer Lösung dafür? Wenn Sie mit runApp ausgeführt werden, wird weiterhin "Keine Zeile gefunden" angezeigt.
Greg Hilston
2
Für alle, die dies in Zukunft lesen, habe ich "standardInput = System.in" verwendet, damit meine Gradle-Ausführung weiterhin Eingaben enthält
Greg Hilston,
0

Sie können es parametrisieren und gradle clean build -Pprokey = goodbye übergeben

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
quelle