Gradle do wykonania klasy Java (bez modyfikowania build.gradle)

119

Istnieje prosta wtyczka Eclipse do uruchamiania Gradle, która po prostu używa wiersza poleceń do uruchomienia gradle.

Co to jest analog gradle dla Mavena, kompiluj i uruchamiaj mvn compile exec:java -Dexec.mainClass=example.Example

W ten sposób gradle.buildmożna uruchomić dowolny projekt .

AKTUALIZACJA: Pojawiło się podobne pytanie. Jaki jest odpowiednik w Gradle wtyczki maven do uruchamiania aplikacji Java? pytano wcześniej, ale rozwiązanie sugerowało zmianę każdego projektubuild.gradle

package runclass;

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

Następnie wykonanie 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
źródło
Prawdopodobny duplikat stackoverflow.com/questions/16350757/ ...
Teresa Carrigan
Użyj polecenia: gradle run
a_subscriber

Odpowiedzi:

138

Nie ma bezpośredniego odpowiednika mvn exec:javaw gradle, musisz albo zastosować applicationwtyczkę, albo mieć JavaExeczadanie.

application podłącz

Aktywuj wtyczkę:

plugins {
    id 'application'
    ...
}

Skonfiguruj go w następujący sposób:

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

W wierszu poleceń napisz

$ gradle -PmainClass=Boo run

JavaExec zadanie

Zdefiniuj zadanie, powiedzmy execute:

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

Aby biec, pisz gradle -PmainClass=Boo execute. Dostajesz

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

mainClassto właściwość przekazywana dynamicznie w wierszu poleceń. classpathma odebrać najnowsze zajęcia.


Jeśli nie przejdziesz mainClasswłasności, obie metody zawiodą zgodnie z oczekiwaniami.

$ 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'.
Pierwsze zero
źródło
1
Musisz zmodyfikować build.gradle, classpathjest zakodowany na stałe, aby pobrać klasy java ze ścieżki klas źródła build.gradle java . Nawet po uruchomieniu mvn exec:javaścieżka klasy jest ustawiona tak, aby pobierać pliki źródłowe Java z bieżącego katalogu maven. W JavaExeczadaniu zrobiłem to samo. Zmiana classpathdla java źródła i ścieżka klasa zmieni się automatycznie. Nie ma - mvn exec:javaodpowiednika w tym, gradleże musisz albo zastosować applicationwtyczkę, albo mieć JavaExeczadanie.
First Zero
1
LUB inną opcją jest napisanie własnej wtyczki, aby to zrobić, a nawet wtedy musisz zmienić build.gradle, aby pobrać wtyczkę.
First Zero
3
Właśnie to wypróbowałem i wygląda na to, że po dodaniu task execute(...do build.gradle każde inne zadanie kończy się niepowodzeniem z tym samym komunikatem o błędzie informującym, że gradle oczekuje przekazania metody mainClass. Nie mogę czyścić ani budować.
Nirro
4
@Nirei Zastępca main = mainClassze main = getProperty("mainClass")i to nie będzie już na ciebie krzyczeć.
Adi Gerber
2
to wciąż się psuje gradle build, zobacz moją odpowiedź poniżej.
Matt,
140

Wystarczy skorzystać z wtyczki Gradle Application :

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

A potem po prostu gradle run.

Jak wskazuje Teresa, możesz również skonfigurować mainClassNamejako właściwość systemową i uruchomić z argumentem wiersza poleceń.

Vidya
źródło
2
Wymagałoby to twardego kodu każdej takiej klasy build.graldle. Ale mam projekt z wieloma klasami użytkowymi, z których każda ma metodę główną.
Paul Verest
I jesteś pewien, że 1) w pełni kwalifikowana nazwa klasy jest poprawna 2) umieściłeś właściwą nazwę właściwości w pliku kompilacji - np. System.getProperty("mainClass") 3) kod źródłowy jest tam, gdzie powinien się znajdować, zgodnie z konwencją, 4) wszystko działa kiedy RunClasswstawiasz plik kompilacji?
Vidya,
Działa tylko wtedy, gdy build.gradlema mainClassName = "runclass.RunClass". Parametr -DmainClassnie działa: gradle run -DmainClass=runclass.RunClass2wykonuje zakodowaną na stałe klasę główną.
Paul Verest
3
Jeśli zrobisz jedno i drugie (podejście do pliku budowania i podejście do właściwości), właściwie nie wiem, które ma pierwszeństwo. Powinieneś albo znaleźć tę odpowiedź, albo nie robić obu w testach.
Vidya
2
@PaulVerest Oto, co zrobiłem: ext.mainClass = project.hasProperty('mainClass') ? project.getProperty('mainClass') : 'org.gradle.sample.Main' ; apply plugin:'application' ; mainClassName = ext.mainClass teraz, kiedy to zrobisz gradle -PmainClass=Foo run, powinieneś użyć Foojako głównej klasy.
msridhar
26

Rozwijając odpowiedź First Zero, myślę, że chcesz czegoś, na czym możesz również działać gradle buildbez błędów.

Oba gradle buildi gradle -PmainClass=foo runApppracuj z tym:

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

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

gdzie ustawiasz domyślną klasę główną.

Matt
źródło
2
Imho, powinna to być akceptowana odpowiedź. Użycie metody FirstZero lub Vidya spowoduje, że inne zadania będą narzekać z powodu braku określenia klasy głównej.
yanhan
Podejście Matta do ustawiania głównej wartości działa również w przypadku wtyczki aplikacji. Używam go z Gradle Kotlin DSL: plugins { application }; application { mainClassName = if (project.hasProperty("mainClass")) project.properties.get("mainClass").toString() else "Foo" }
pvillela
@Matt To podejście psuje mój prosty program Java, który używa Scannerdo odczytu nextLine(). Jakieś pomysły na rozwiązanie tego problemu? Podczas pracy z runApp otrzymujesz komunikat „nie znaleziono linii”.
Greg Hilston
2
Do każdego, kto czyta to w przyszłości, użyłem `standardInput = System.in`, aby umożliwić mojemu wykonaniu gradle nadal przekazywanie danych wejściowych
Greg Hilston
0

Możesz go sparametryzować i przekazać 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
źródło