Gradle untuk mengeksekusi kelas Java (tanpa memodifikasi build.gradle)

119

Ada plugin Eclipse sederhana untuk menjalankan Gradle, yang hanya menggunakan cara baris perintah untuk meluncurkan gradle.

Apa analog gradle untuk kompilasi dan jalankan Maven mvn compile exec:java -Dexec.mainClass=example.Example

Dengan cara ini, proyek apa pun dengan gradle.builddapat dijalankan.

PEMBARUAN: Ada pertanyaan serupa Apa yang setara dengan gradle dari plugin exec maven untuk menjalankan aplikasi Java? ditanyakan sebelumnya, tetapi solusi menyarankan untuk mengubah setiap proyekbuild.gradle

package runclass;

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

Kemudian mengeksekusi 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
sumber
Kemungkinan duplikat stackoverflow.com/questions/16350757/…
Teresa Carrigan
Gunakan perintah: gradle run
a_subscriber

Jawaban:

138

Tidak ada padanan langsung mvn exec:javadalam gradle, Anda harus menerapkan applicationplugin atau memiliki JavaExectugas.

application plugin

Aktifkan plugin:

plugins {
    id 'application'
    ...
}

Konfigurasikan sebagai berikut:

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

Di baris perintah, tulis

$ gradle -PmainClass=Boo run

JavaExec tugas

Tentukan tugas, katakanlah execute:

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

Untuk menjalankan, tulis gradle -PmainClass=Boo execute. Anda mendapatkan

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

mainClassadalah properti yang diteruskan secara dinamis pada baris perintah. classpathdisetel untuk mengambil kelas terbaru.


Jika Anda tidak meneruskan mainClassproperti, kedua pendekatan gagal seperti yang diharapkan.

$ 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'.
Nol Pertama
sumber
1
Anda harus memodifikasi build.gradle, yang di classpath-hardcode untuk mengambil kelas java dari classpath sumber build.gradle java Anda . Bahkan saat Anda menjalankan mvn exec:javaclasspath diatur untuk mengambil file sumber java di direktori maven saat ini. Dalam JavaExectugas tersebut, saya telah melakukan hal yang sama. Ubah classpathuntuk sumber java Anda dan jalur kelas akan berubah secara otomatis. Tidak ada - hal yang mvn exec:javasetara jika gradleAnda perlu menerapkan applicationplugin atau memiliki JavaExectugas.
Nol Pertama
1
ATAU opsi lainnya adalah Anda menulis plugin Anda sendiri untuk melakukan ini dan bahkan kemudian Anda harus mengubah build.gradle untuk mengambil plugin Anda.
Nol Pertama
3
Saya baru saja mencoba ini dan tampaknya setelah menambahkan task execute(...ke build.gradle, setiap tugas lain gagal dengan pesan kesalahan yang sama yang mengatakan bahwa gradle mengharapkan mainClass diteruskan. Saya tidak bisa membersihkan atau membangun.
Nirro
4
@Nirei Pengganti main = mainClassdengan main = getProperty("mainClass")dan itu tidak akan lagi meneriaki Anda.
Adi Gerber
2
ini masih rusak gradle build, lihat jawaban saya di bawah ini.
Matt
140

Anda hanya perlu menggunakan plugin Aplikasi Gradle :

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

Dan kemudian sederhana gradle run.

Seperti yang ditunjukkan Teresa, Anda juga dapat mengonfigurasi mainClassNamesebagai properti sistem dan menjalankan dengan argumen baris perintah.

Vidya
sumber
2
Itu akan membutuhkan kode keras untuk setiap kelas seperti itu build.graldle. Tetapi saya memiliki proyek dengan banyak kelas util, yang masing-masing memiliki metode utama.
Paul Verest
Dan Anda yakin 1) nama kelas yang sepenuhnya memenuhi syarat benar 2) Anda meletakkan nama properti yang benar di file build Anda-- misalnya System.getProperty("mainClass") , 3) kode sumber adalah tempat yang seharusnya sesuai dengan konvensi, 4) semuanya berfungsi ketika Anda memasukkan RunClassfile build?
Vidya
Ini hanya berfungsi jika build.gradleada mainClassName = "runclass.RunClass". Parameter -DmainClasstidak berpengaruh: gradle run -DmainClass=runclass.RunClass2menjalankan kelas utama yang di-hardcode.
Paul Verest
3
Jika Anda melakukan keduanya (pendekatan file build dan pendekatan properti), saya sebenarnya tidak tahu mana yang diutamakan. Anda harus menemukan jawaban itu atau tidak melakukan keduanya dalam pengujian Anda.
Vidya
2
@PaulVerest Inilah yang saya lakukan: ext.mainClass = project.hasProperty('mainClass') ? project.getProperty('mainClass') : 'org.gradle.sample.Main' ; apply plugin:'application' ; mainClassName = ext.mainClass Sekarang ketika Anda melakukannya gradle -PmainClass=Foo runharus digunakan Foosebagai kelas utama.
msridhar
26

Memperluas jawaban First Zero, saya kira Anda menginginkan sesuatu di mana Anda juga dapat berjalan gradle buildtanpa kesalahan.

Baik gradle builddangradle -PmainClass=foo runApp bekerja dengan ini:

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

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

tempat Anda menyetel kelas utama default.

Matt
sumber
2
Imho ini harus menjadi jawaban yang diterima. Menggunakan metode FirstZero atau Vidya akan menyebabkan tugas lain dikeluhkan karena kelas utama tidak ditentukan.
yanhan
Pendekatan Matt untuk menyetel nilai utama juga berfungsi untuk plugin aplikasi. Saya menggunakannya dengan Gradle Kotlin DSL: plugins { application }; application { mainClassName = if (project.hasProperty("mainClass")) project.properties.get("mainClass").toString() else "Foo" }
pvillela
@Matt Pendekatan ini merusak program Java saya yang sederhana yang menggunakan a Scanneruntuk membaca nextLine(). Adakah pemikiran untuk memperbaikinya? Terus dapatkan "tidak ada baris yang ditemukan" saat menjalankan menggunakan runApp.
Greg Hilston
2
Kepada siapa pun yang membaca ini di masa mendatang, saya menggunakan `standardInput = System.in` untuk memungkinkan eksekusi gradle saya tetap meneruskan masukan
Greg Hilston
0

Anda dapat membuat parameter dan meneruskan 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
sumber