12

I have a gradle build script which currently works by simply executing a Java class through it's main method. What I want to know is, how can I call a static method in the same class but not have to go through the main method. The current gradle code is as follows:

import org.apache.tools.ant.taskdefs.condition.Os
apply plugin: 'java'

defaultTasks 'runSimple'

project.ext.set("artifactId", "test-java")

File rootDir = project.getProjectDir()
File targetDir = file("${rootDir}/target")
FileCollection javaClasspath = files("${targetDir}/tools.jar")

task(runSimple, dependsOn: 'classes', type: JavaExec) {
    main = 'com.test.model.JavaTest'
    classpath = javaClasspath
    args 'arg1'
    args 'arg2'
}

And my Java class as follows:

package com.test.model;

public class JavaTest {

    public static void main(String[] args) throws Exception {
        System.out.println("In main");
        anotherMethod(args[0], args[1]);
    }

    public static void anotherMethod(String arg1, String arg2) {
        System.out.println("In anotherMethod");
        System.out.println(arg1 + " " + arg2);
    }
}

This gives me the output:

:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:runSimple
In main
In anotherMethod
arg1 arg2

BUILD SUCCESSFUL

Total time: 2.344 secs

My question is simply how can I skip the main method, and call the method "anotherMethod" directly from the gradle script? The output would then simply be:

In anotherMethod
arg1 arg2

Thanks

danielbeddoe
  • 149
  • 1
  • 1
  • 5
  • Do you want it to run in the context (i.e. the classloader) of the Gradle build, or as a separate process? The `JavaExec` task works just like calling the `java` command from a shell. It will always execute the `main` method. – ajoberstar Jul 11 '13 at 23:05
  • I would ideally like it to run as a separate process. Is there any way to achieve this in Gradle? Furthemore, this Java method will be called upon many times during the execution of the Gradle script. Therefore I would like it to not spin up a new JVM every time it makes a call to the same Java method, and run within the same JVM. Does that make sense? – danielbeddoe Jul 15 '13 at 09:30
  • Hmm... If you want it to be a separate process that you can call repeatedly using the same process, it seems more like a daemon or service. Gradle's `JavaExec` merely supports the equivalent of calling the `java` command from the shell. That is, it will run the main method of the class you specify **once**. Gradle can run any Groovy code you want, so I'm sure that it is possible to do this, but I don't see any straightforward way. – ajoberstar Jul 16 '13 at 01:28
  • Why don't you make a Bootstrap class with a main method that calls your static method that needs to execute several times? This way you only have one JVM running your code. – mtrovo Jul 19 '13 at 19:41

4 Answers4

3

you have to add the jar or class to the classpath. here is an example with a jar file who contains the class. Inside the file build.gradle add the dependencies. My jar file is in the lib folder the path is lib/MQMonitor.jar.

import mypackage.MyClass
buildscript {
   repositories {
      flatDir name: 'localRepository', dirs: 'lib'
   }
    dependencies {
        classpath name: 'MQMonitor'
    }
}

task myTaskCallJava << {
   MyClass.foo()
}
Mike
  • 8,055
  • 1
  • 30
  • 44
1

I have been working on this too. You know I like the function of eclipse and intellij with the run with Junit options, and I want to do this using command line and gradle.

If you could accept putting your test method in the directory of 'test' directory of gradle. I actually have a fair solution.

package com.udacity.gradle;
import org.junit.Test;

    public class TestClass {
        @Test
        public void anotherMethod() {
            System.out.println("This is it, I want this!!!");
        }
        @Test
        public void notMyWantedMethod1() {

            System.out.println("not my wanted");
        }

        public void notMyWantedMethod2() {
            System.out.println("not my wanted");
        }

    }

This my test class which is in src/test/java/com/udacity/gradle/TestClass.java

Then the under below is the file of my build.gradle

apply plugin: "java"
repositories {
    mavenCentral()
}
dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
}


test {
    testLogging.showStandardStreams = true
    filter {
        //include specific method in any of the tests
        includeTestsMatching "*.TestClass.anotherMethod"
    }
}

Simple idea you know this is a test class so I use the test task of gradle. And to specify which method to use, I added a Test filter which could specify down to method.

Then you could just run

gradle test

Then you could find in console that you have what you want in there. However, remember to add

testLogging.showStandardStreams = true

if you don't do this, gradle would swallow your console output. But even if you don't add this line. You could read a test log in the directory of

...../build/test-results/test/TEST-com.udacity.gradle.TestClass.xml

There are well organized test reports output in it.

<?xml version="1.0" encoding="UTF-8"?>
<testsuite name="com.udacity.gradle.TestClass" tests="1" skipped="0" failures="0" errors="0" timestamp="2018-03-31T19:26:44" hostname="hexin-PC" time="0.022">
  <properties/>
  <testcase name="anotherMethod" classname="com.udacity.gradle.TestClass" time="0.022"/>
  <system-out><![CDATA[This is it, I want this!!!
]]></system-out>
  <system-err><![CDATA[]]></system-err>
</testsuite>
X.HE
  • 11
  • 1
1

Assuming the class is on the buildscript classpath (it should be, since you're calling main from the same class)

task runSimple {
  doLast {
    com.test.model.JavaTest.anotherMethod("foo", "bar")
  }
}

Tested on Gradle 4.6

Abhijit Sarkar
  • 21,927
  • 20
  • 110
  • 219
-2

If you want to execute a static method you will need to add the class to the Gradle build script's classpath.

To add the code to the build scripts classpath if your code is in a repository:

buildscript {
    repositories {
        maven { url "${yourRepositoryURL}" }
    }
    dependencies {
        classpath 'com.yourgroup:yourpackagename:version'
    }
}

To add the code to the build scripts classpath if you code is built locally (I didn't test this one):

buildscript {
    dependencies {
        classpath files("path/to/where/the/class/files/are")
    }
}

Then you should be able to call that method just like any other:

task runSimple(dependsOn: 'classes') {
    doFirst() {
        com.test.model.JavaTest.anotherMethod('arg1', 'arg2')
    }
}
Adam R.
  • 71
  • 7
  • 1
    yeah.. this doesn't work at all.. and I still can't figure out an elegant way to do this.. I don't want to have to create a class for a single line of Java – Thomas Beauvais Jul 29 '15 at 11:56