Gradle para ejecutar la clase Java (sin modificar build.gradle)

119

Hay un complemento simple de Eclipse para ejecutar Gradle, que solo usa la línea de comandos para iniciar gradle.

¿Qué es gradle analógico para maven compilar y ejecutar? mvn compile exec:java -Dexec.mainClass=example.Example

De esta forma se gradle.buildpodría ejecutar cualquier proyecto con .

ACTUALIZACIÓN: Hubo una pregunta similar ¿ Cuál es el equivalente gradle del complemento ejecutivo de maven para ejecutar aplicaciones Java? preguntado antes, pero la solución sugirió alterar cada proyectobuild.gradle

package runclass;

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

Luego ejecutando 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
fuente
Probable duplicado de stackoverflow.com/questions/16350757/…
Teresa Carrigan
Use el comando: gradle run
a_subscriber

Respuestas:

138

No hay un equivalente directo a mvn exec:javaen gradle, debe aplicar el applicationcomplemento o tener una JavaExectarea.

application enchufar

Activar el complemento:

plugins {
    id 'application'
    ...
}

Configúrelo de la siguiente manera:

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

En la línea de comando, escriba

$ gradle -PmainClass=Boo run

JavaExec tarea

Defina una tarea, digamos execute:

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

Para correr, escribe gradle -PmainClass=Boo execute. Usted obtiene

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

mainClasses una propiedad que se pasa dinámicamente en la línea de comandos. classpathestá configurado para recoger las últimas clases.


Si no pasa la mainClasspropiedad, ambos enfoques fallan como se esperaba.

$ 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'.
Primer cero
fuente
1
Tienes que modificarlo build.gradle, classpathestá codificado para recoger las clases java de tu ruta de clases fuente build.gradle java . Incluso cuando ejecuta, mvn exec:javala ruta de clase está configurada para recoger los archivos fuente de Java en el directorio actual de maven. En la JavaExectarea, he hecho lo mismo. Cambie el classpathde su fuente de Java y la ruta de clases cambiará automáticamente. No hay mvn exec:javaequivalente en el sentido de gradleque debe aplicar el applicationcomplemento o tener una JavaExectarea.
First Zero
1
O la otra opción es que escriba su propio complemento para hacer esto e incluso entonces tiene que cambiar el build.gradle para recoger su complemento.
First Zero
3
Intenté esto y parece que después de agregar task execute(...a build.gradle, todas las demás tareas fallan con el mismo mensaje de error que indica que gradle espera que se transmita mainClass. No puedo limpiar ni construir.
Nirro
4
@Nirei Sustituye main = mainClasscon main = getProperty("mainClass")y ya no te gritará .
Adi Gerber
2
esto todavía se rompe gradle build, vea mi respuesta a continuación.
Matt
140

Solo necesita usar el complemento de la aplicación Gradle :

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

Y luego simplemente gradle run.

Como señala Teresa, también puede configurarlo mainClassNamecomo una propiedad del sistema y ejecutarlo con un argumento de línea de comando.

Vidya
fuente
2
Eso requeriría codificar cada una de esas clases en build.graldle. Pero tengo un proyecto con muchas clases de utilidades, que cada una tiene un método principal.
Paul Verest
Y está seguro de que 1) el nombre de la clase totalmente calificado es correcto 2) puso el nombre de propiedad correcto en su archivo de compilación , por ejemplo System.getProperty("mainClass") , 3) el código fuente está donde se supone que debe estar de acuerdo con la convención, 4) todo funciona cuando pones RunClassel archivo de compilación?
Vidya
Solo funciona si build.gradletiene mainClassName = "runclass.RunClass". El parámetro -DmainClassno tiene ningún efecto: gradle run -DmainClass=runclass.RunClass2ejecuta la clase principal codificada.
Paul Verest
3
Si hace ambos (enfoque de archivo de compilación y enfoque de propiedad), en realidad no sé cuál tiene prioridad. Debe encontrar esa respuesta o no hacer ambas cosas en sus pruebas.
Vidya
2
@PaulVerest Esto es lo que hice: ext.mainClass = project.hasProperty('mainClass') ? project.getProperty('mainClass') : 'org.gradle.sample.Main' ; apply plugin:'application' ; mainClassName = ext.mainClass ahora, cuando lo hagas gradle -PmainClass=Foo run, debería usarFoo como clase principal.
msridhar
26

Ampliando la respuesta de First Zero, supongo que desea algo en el que también pueda ejecutar gradle buildsin errores.

Ambos gradle buildy gradle -PmainClass=foo runApptrabajar con esto:

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

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

donde estableces tu clase principal predeterminada.

Mate
fuente
2
En mi opinión, esta debería ser la respuesta aceptada. El uso del método de FirstZero o Vidya hará que otras tareas se quejen debido a que la clase principal no se especifica.
Yanhan
El enfoque de Matt para establecer el valor principal también funciona para el complemento de la aplicación. Lo estoy usando con Gradle Kotlin DSL: plugins { application }; application { mainClassName = if (project.hasProperty("mainClass")) project.properties.get("mainClass").toString() else "Foo" }
pvillela
@Matt Este enfoque rompe mi programa Java simple que usa un Scannerpara leer nextLine(). ¿Alguna idea de una solución para esto? Sigue obteniendo "no se encuentra ninguna línea" cuando se ejecuta con runApp.
Greg Hilston
2
Para cualquiera que lea esto en el futuro, usé `standardInput = System.in` para permitir que mi ejecución de gradle aún pase la entrada
Greg Hilston
0

Puede parametrizarlo y pasar 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
fuente