Gradle per eseguire la classe Java (senza modificare build.gradle)


119

Esiste un semplice plug-in Eclipse per eseguire Gradle, che utilizza solo il modo della riga di comando per avviare Gradle.

Cos'è l'analogo gradle per compilare ed eseguire Maven mvn compile exec:java -Dexec.mainClass=example.Example

In questo modo qualsiasi progetto con gradle.buildpotrebbe essere eseguito.

AGGIORNAMENTO: C'era una domanda simile Qual è l'equivalente gradle del plug-in exec di Maven per l'esecuzione di app Java? chiesto prima, ma la soluzione suggeriva di modificare ogni progettobuild.gradle

package runclass;

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

Quindi esecuzione 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   


Usa il comando: gradle run
a_subscriber

Risposte:


138

Non esiste un equivalente diretto a mvn exec:javain gradle, è necessario applicare il applicationplug-in o avere JavaExecun'attività.

application collegare

Attiva il plugin:

plugins {
    id 'application'
    ...
}

Configuralo come segue:

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

Sulla riga di comando, scrivi

$ gradle -PmainClass=Boo run

JavaExec compito

Definisci un'attività, diciamo execute:

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

Per correre scrivi gradle -PmainClass=Boo execute. Ottieni

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

mainClassè una proprietà passata dinamicamente dalla riga di comando. classpathè impostato per riprendere le lezioni più recenti.


Se non si passa nella mainClassproprietà, entrambi gli approcci falliscono come previsto.

$ 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'.

1
Devi modificare build.gradle, classpathè hardcoded per prendere le classi java dal tuo classpath build.gradle java source. Anche quando esegui mvn exec:javail classpath è impostato per raccogliere i file di origine java nella directory maven corrente. Nel JavaExeccompito, ho fatto lo stesso. Cambia il classpathper la tua sorgente java e il percorso della classe cambierà automaticamente. Non è necessario applicare il plug-in o eseguire un'attività mvn exec:javaequivalente . gradleapplicationJavaExec
Primo zero

1
O l'altra opzione è che scrivi il tuo plug-in per farlo e anche allora devi cambiare build.gradle per prendere il tuo plug-in.
Primo zero

3
L'ho appena provato e sembra che dopo l'aggiunta task execute(...a build.gradle, ogni altra attività fallisca con lo stesso messaggio di errore che dice che gradle si aspetta che mainClass venga passato. Non posso pulire o costruire.
Nirro

4
@Nirei Sostituisci main = mainClasscon main = getProperty("mainClass")e non ti sgriderà più.
Adi Gerber

2
questo si rompe ancora gradle build, vedi la mia risposta di seguito.
Matt

140

Hai solo bisogno di utilizzare il plug-in dell'applicazione Gradle :

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

E poi semplicemente gradle run.

Come sottolinea Teresa, puoi anche configurare mainClassNamecome proprietà di sistema ed eseguire con un argomento della riga di comando.


2
Ciò richiederebbe di codificare in modo rigido ogni classe di questo tipo build.graldle. Ma ho un progetto con molte classi di utilità, ognuna con un metodo principale.
Paul Verest

E sei sicuro che 1) il nome della classe completo sia corretto 2) metti il ​​nome della proprietà corretto nel tuo file di build - ad esempio System.getProperty("mainClass") , 3) il codice sorgente è dove dovrebbe essere secondo la convenzione, 4) funziona tutto quando metti RunClassnel file build?
Vidya

Funziona solo se lo build.gradleha mainClassName = "runclass.RunClass". Il parametro -DmainClassnon ha effetto: gradle run -DmainClass=runclass.RunClass2esegue la classe principale hardcoded.
Paul Verest

3
Se si esegue entrambe le operazioni (approccio basato su file e approccio alla proprietà), in realtà non so quale abbia la precedenza. Dovresti trovare quella risposta o non fare entrambe le cose nel tuo test.
Vidya

2
@PaulVerest Ecco cosa ho fatto: ext.mainClass = project.hasProperty('mainClass') ? project.getProperty('mainClass') : 'org.gradle.sample.Main' ; apply plugin:'application' ; mainClassName = ext.mainClass ora, quando lo fai gradle -PmainClass=Foo run, dovresti usarlo Foocome classe principale.
msridhar

26

Espandendo la risposta di First Zero, immagino che tu voglia qualcosa in cui puoi anche eseguire gradle buildsenza errori.

Entrambi gradle builde gradle -PmainClass=foo runApplavora con questo:

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

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

dove imposti la tua classe principale predefinita.


2
Imho questa dovrebbe essere la risposta accettata. L'uso del metodo di FirstZero o di Vidya provocherà il reclamo di altre attività a causa della mancata specificazione della classe principale.
yanhan

L'approccio di Matt all'impostazione del valore principale funziona anche per il plug-in dell'applicazione. Lo sto usando con il Gradle Kotlin DSL: plugins { application }; application { mainClassName = if (project.hasProperty("mainClass")) project.properties.get("mainClass").toString() else "Foo" }
pvillela

@Matt Questo approccio rompe il mio semplice programma Java che utilizza a Scannerper leggere nextLine(). Qualche pensiero su una soluzione per questo? Continua a ricevere "nessuna linea trovata" durante l'esecuzione utilizzando runApp.
Greg Hilston

2
Per chiunque legga questo in futuro, ho usato `standardInput = System.in` per consentire alla mia esecuzione gradle di passare ancora in input
Greg Hilston

0

Puoi parametrizzarlo e passare 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;
    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.