Gradle para executar a classe Java (sem modificar build.gradle)

119

Existe um plugin Eclipse simples para executar o Gradle, que usa apenas a linha de comando para iniciar o gradle.

O que é gradle analog para maven compilar e executar mvn compile exec:java -Dexec.mainClass=example.Example

Desta forma, qualquer projeto com gradle.buildpode ser executado.

ATUALIZAÇÃO: houve uma pergunta semelhante: Qual é o equivalente do Gradle do plug-in exec do maven para executar aplicativos Java? perguntado antes, mas a solução sugeriu alterar todos os projetosbuild.gradle

package runclass;

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

Em seguida, executando 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
fonte
Provável duplicata de stackoverflow.com/questions/16350757/…
Teresa Carrigan
Use o comando: gradle run
a_subscriber

Respostas:

138

Não há equivalente direto mvn exec:javano gradle, você precisa aplicar o applicationplugin ou ter uma JavaExectarefa.

application plugar

Ative o plugin:

plugins {
    id 'application'
    ...
}

Configure-o da seguinte maneira:

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

Na linha de comando, escreva

$ gradle -PmainClass=Boo run

JavaExec tarefa

Defina uma tarefa, digamos execute:

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

Para correr, escreva gradle -PmainClass=Boo execute. Você consegue

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

mainClassé uma propriedade passada dinamicamente na linha de comando. classpathestá definido para pegar as últimas classes.


Se você não passar na mainClasspropriedade, ambas as abordagens falharão conforme o esperado.

$ 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'.
Primeiro Zero
fonte
1
Você tem que modificar build.gradle, o classpathestá codificado para pegar as classes java de seu classpath de origem build.gradle java . Mesmo quando você executa mvn exec:javao classpath é configurado para coletar os arquivos de origem java no diretório maven atual. Na JavaExectarefa, fiz o mesmo. Altere o classpathpara sua fonte java e o caminho da classe mudará automaticamente. Não há mvn exec:javaequivalente em gradlevocê precisar aplicar o applicationplugin ou ter uma JavaExectarefa.
Primeiro Zero
1
OU a outra opção é você escrever seu próprio plugin para fazer isso e, mesmo assim, você tem que alterar o build.gradle para pegar seu plugin.
Primeiro Zero
3
Acabei de tentar isso e parece que depois de adicionar o task execute(...build.gradle, todas as outras tarefas falham com a mesma mensagem de erro, informando que o gradle espera que mainClass seja transmitido. Não consigo limpar ou construir.
Nirro
4
@Nirei Substitua main = mainClasspor main = getProperty("mainClass")e ele não gritará mais com você.
Adi Gerber de
2
isso ainda quebra gradle build, veja minha resposta abaixo.
Matt
140

Você só precisa usar o plug - in do aplicativo Gradle :

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

E então simplesmente gradle run.

Como Teresa aponta, você também pode configurar mainClassNamecomo uma propriedade do sistema e executar com um argumento de linha de comando.

Vidya
fonte
2
Isso exigiria hard code em cada uma dessas classes build.graldle. Mas eu tenho um projeto com várias classes util, cada uma com o método principal.
Paul Verest
E você tem certeza de 1) o nome de classe totalmente qualificado está correto 2) você colocou o nome de propriedade correto em seu arquivo de compilação - por exemplo System.getProperty("mainClass") , 3) o código-fonte está onde deveria estar de acordo com a convenção, 4) tudo funciona quando você coloca RunClassno arquivo de compilação?
Vidya
Só funciona se build.gradletiver mainClassName = "runclass.RunClass". O parâmetro -DmainClassnão tem efeito: gradle run -DmainClass=runclass.RunClass2executa a classe principal embutida em código.
Paul Verest
3
Se você fizer ambos (abordagem de construção de arquivo e abordagem de propriedade), na verdade não sei qual tem precedência. Você deve encontrar essa resposta ou não fazer as duas coisas em seu teste.
Vidya
2
@PaulVerest Aqui está o que eu fiz: ext.mainClass = project.hasProperty('mainClass') ? project.getProperty('mainClass') : 'org.gradle.sample.Main' ; apply plugin:'application' ; mainClassName = ext.mainClass Agora, quando você fizer gradle -PmainClass=Foo runisso, deve usar Foocomo classe principal.
msridhar
26

Expandindo a resposta do First Zero, acho que você quer algo onde também possa executar gradle buildsem erros.

Ambos gradle builde gradle -PmainClass=foo runApptrabalhar com isso:

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

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

onde você define sua classe principal padrão.

Matt
fonte
2
Imho esta deve ser a resposta aceita. Usar o método do FirstZero ou do Vidya fará com que outras tarefas reclamam devido à classe principal não ter sido especificada.
yanhan
A abordagem de Matt para definir o valor principal também funciona para o plug-in do aplicativo. Estou usando com o Gradle Kotlin DSL: plugins { application }; application { mainClassName = if (project.hasProperty("mainClass")) project.properties.get("mainClass").toString() else "Foo" }
pvillela
@Matt Esta abordagem quebra meu programa Java simples que usa um Scannerpara ler nextLine(). Alguma ideia de uma solução para isso? Continue obtendo "nenhuma linha encontrada" ao executar o runApp.
Greg Hilston
2
Para qualquer pessoa que ler isso no futuro, usei `standardInput = System.in` para permitir que minha execução do gradle ainda passasse na entrada
Greg Hilston
0

Você pode parametrizá-lo e passar o 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
fonte