134

There is simple Eclipse plugin to run Gradle, that just uses command line way to launch gradle.

What is gradle analog for maven compile and run mvn compile exec:java -Dexec.mainClass=example.Example

This way any project with gradle.build could be run.

UPDATE: There was similar question What is the gradle equivalent of maven's exec plugin for running Java apps? asked before, but solution suggested altering every project build.gradle

package runclass;

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

Then executing 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   
Community
  • 1
  • 1
Paul Verest
  • 60,022
  • 51
  • 208
  • 332

4 Answers4

159

There is no direct equivalent to mvn exec:java in gradle, you need to either apply the application plugin or have a JavaExec task.

application plugin

Activate the plugin:

plugins {
    id 'application'
    ...
}

Configure it as follows:

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

On the command line, write

$ gradle -PmainClass=Boo run

JavaExec task

Define a task, let's say execute:

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

To run, write gradle -PmainClass=Boo execute. You get

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

mainClass is a property passed in dynamically at command line. classpath is set to pickup the latest classes.


If you do not pass in the mainClass property, both of the approaches fail as expected.

$ 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'.
Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
First Zero
  • 21,586
  • 6
  • 46
  • 45
  • Thanks for letting know, but in this case `build.gralde` also needds to be modified, also now there is hard-coded classpath to care about. – Paul Verest Jan 26 '14 at 06:54
  • 3
    You have to modify `build.gradle`, the `classpath` is hardcoded to pick up the [tag:java] classes from your `build.gradle` [tag:java] source classpath. Even when you run `mvn exec:java` the classpath is set to pick up the java source files in the current maven directory. In the `JavaExec` task, I have done the same. Change the `classpath` for your [tag:java] source and the class path will change automatically. There is no - `mvn exec:java` equivalent in `gradle` you need to either apply the `application` plugin or have a `JavaExec` task. – First Zero Jan 26 '14 at 07:39
  • 1
    OR the other option is you write your own plugin to do this and even then you have to change the build.gradle to pick up your plugin. – First Zero Jan 26 '14 at 07:40
  • Thank you so much. This is complete answer. Now with `gradle -PmainClass=runclass.RunClass execute` I can select which class to execute. – Paul Verest Jan 26 '14 at 07:53
  • If someone knows how to do the above for android studio/gradle that'd be great, because in my case sourceSets.main does not exist. Apparently android.sourceSets.main exists, but no runtimeClasspath after that... – AgentKnopf Jan 26 '15 at 11:25
  • 3
    I just tried this and it seems that after adding `task execute(...` to build.gradle, every other task fails with the same error message telling that gradle expects mainClass to be passed along. I can't do clean or build. – Nirro Jun 19 '16 at 21:42
  • 6
    @Nirei Substitute `main = mainClass` with `main = getProperty("mainClass")` and it will no longer yell at you. – Adi Gerber Aug 10 '16 at 04:57
  • @Adidishen, that didn't work for me. However this does: `mainClassName = findProperty("mainClass") ?: ""` – Tarrasch Aug 18 '16 at 02:41
  • 2
    this still breaks `gradle build`, see my answer below. – Matt Feb 15 '17 at 20:38
  • 1
    `mainClassName = project.hasProperty("mainClass") ? getProperty("mainClass") : "NULL"` does not work for me. `getProperty("mainClass")` needs to be changed to `project.getProperty("mainClassName")`. I am using Gradle 6.5.1. – Jingguo Yao Aug 28 '20 at 11:51
  • Execution failed for task ':execute'. > Process 'command 'C:\Program Files\Java\jdk-14.0.1\bin\java.exe'' finished with non-zero exit value 1 – john k Nov 24 '20 at 19:28
  • Minor update for deprecated method in Gradle 8.0, "The JavaApplication.setMainClassName(String) method has been deprecated. This is scheduled to be removed in Gradle 8.0. Use #getMainClass().set(...) instead." -> `getMainClass().set(project.hasProperty("mainClass") ? project.getProperty("mainClass") : "NULL")` – Rubén Morales Aug 10 '22 at 00:45
146

You just need to use the Gradle Application plugin:

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

And then simply gradle run.

As Teresa points out, you can also configure mainClass as a system property and run with a command line argument.

Paweł Prażak
  • 3,091
  • 1
  • 27
  • 42
Vidya
  • 29,932
  • 7
  • 42
  • 70
  • 3
    That would require to hard code every such class into `build.graldle`. But I have project with a lot of util classes, that every has main method. – Paul Verest Jan 26 '14 at 01:57
  • And you are sure 1) the fully qualified class name is correct 2) you put the right property name in your build file--*e.g.* `System.getProperty("mainClass")`, 3) the source code is where it is supposed to be according to convention, 4) it all works when you put `RunClass` in the build file? – Vidya Jan 26 '14 at 02:15
  • It only works if `build.gradle` has `mainClassName = "runclass.RunClass"` . Parameter `-DmainClass` has no effect: `gradle run -DmainClass=runclass.RunClass2` executes the hard-coded mainclass. – Paul Verest Jan 26 '14 at 02:21
  • 3
    If you do both (build file approach and property approach), I actually don't know which takes precedence. You should either find that answer or not do both in your testing. – Vidya Jan 26 '14 at 02:25
  • 2
    @PaulVerest Here's what I did: ```ext.mainClass = project.hasProperty('mainClass') ? project.getProperty('mainClass') : 'org.gradle.sample.Main' ; apply plugin:'application' ; mainClassName = ext.mainClass``` Now when you do `gradle -PmainClass=Foo run` it should use `Foo` as the main class. – msridhar Apr 06 '16 at 22:33
  • to pass args: https://stackoverflow.com/questions/27604283/gradle-task-pass-arguments-to-java-application – Leon Feb 28 '18 at 13:02
30

Expanding on First Zero's answer, I'm guess you want something where you can also run gradle build without errors.

Both gradle build and gradle -PmainClass=foo runApp work with this:

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

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

where you set your default main class.

Matt
  • 1,194
  • 1
  • 18
  • 18
  • 3
    Imho this should be the accepted answer. Using FirstZero's or Vidya's method will cause other tasks to complain due to the main class not being specified. – yanhan May 07 '18 at 12:30
  • Matt's approach to setting the main value also works for the application plugin. I am using it with the Gradle Kotlin DSL: `plugins { application }; application { mainClassName = if (project.hasProperty("mainClass")) project.properties.get("mainClass").toString() else "Foo" }` – pvillela Jul 15 '18 at 14:58
  • @Matt This approach breaks my simple Java program that uses a `Scanner` to read `nextLine()`. Any thought on a fix for this? Keep getting "no line found" when running using runApp. – Greg Hilston Aug 10 '19 at 15:57
  • 2
    To anyone reading this in the future, I used ` standardInput = System.in` to allow my gradle execution to still pass in input – Greg Hilston Aug 10 '19 at 16:49
1

You can parameterise it and pass 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
  • 1,722
  • 1
  • 22
  • 41