'How to call custom Java method from Gradle
Please, what is the most convenient way how to call a Java method within Gradle build script? This method contain functionality I want to use during build; a piece of functionality too complex to be a in-script Groovy method but not enough to command full custom Gradle plugin.
My question is not about running a Java application from Gradle. That would involve forking JVM, and there is no simple way how to publish output back to Gradle and I need that output.
Initially I had my code in src/main/java but it has to be compiled early on to be callable from within Gradle build script.
Then I tried to move the build helper class to a submodule project, a one class submodule, hoping that the submodule would be builded before the main build script is called; in there I put:
buildscript {
dependencies {
classpath 'this.project:build-helper:1.0-SNAPSHOT'
}
}
But the build-helper
subproject is clearly not build first, despite having in in settings.gradle
as first and build fails as the dependency is not recognised. It seems buildscript is evaluated before submodules are built, before anything else. D'oh!
Solution 1:[1]
There's two main use cases
Source is in src/main/java
in the current project - Therefore the class does NOT exist when the buildscript classpath is defined
Options:
Use a JavaExec task to run the class in another JVM
Construct a URLClassLoader from
sourceSets.main.runtimeClasspath
and load / run the class via the classloader
eg:
task doStuff {
doLast {
URL[] urls = sourceSets.main.runtimeClasspath.files as URL[]
def classloader = new URLClassLoader(urls, null)
Class myClass = classloader.load("foo.bar.MyClass")
def myInstance = myClass.newInstance()
Method method = myClass.getMethod("doStuff")
method.invoke(myInstance)
}
}
Source is in another project. - Therefore the class will exist before the buildscript classpath is defined
In this case you can add the project to the buildscript classpath and invoke it
buildscript {
dependencies {
classpath project(':other-project')
}
}
task doStuff {
doLast {
def myClass = new MyClass()
myClass.doStuff()
}
}
Solution 2:[2]
So the easiest way is to put my build helper Java source into buildSrc
directory: <project root dir>/buildSrc/src/main/java/foo/bar/Extractor.java
and that's it, you can call new Extractor(..).extratMetadata(...)
directly from anywhere in Gradle build script, no need to import package, no need to use Java plugin, Gradle by default understands Maven like directory structure under buildScr.
Credits to: https://zeroturnaround.com/rebellabs/using-buildsrc-for-custom-logic-in-gradle-builds/
Solution 3:[3]
Groovy
- build your project files.
- run this groovy file and call object method
// This code is similar to lance-java's
def files = sourceSets.main.runtimeClasspath.files
// files[0] is C:\...\YourProject\build\classes\java\main
def classLoader = new URLClassLoader((new URL[]{files[0].toURI().toURL()}))
def myClass = Class.forName("aa.bb.c.MyClass", true, classLoader);
def myInstance = myClass.newInstance()
Method method = myClass.getMethod("sayHello")
method.invoke(myInstance)
Kotlin
- build your project files.
- run this groovy file and call class static method .
import java.net.URLClassLoader
...
task("helloworld") {
doLast {
val file: File = project.projectDir.toPath().resolve(tasks.jar.get().archiveFile.get().toString()).toFile()
val classloader: ClassLoader = URLClassLoader(arrayOf(file.toURI().toURL()))
Class.forName("mypackage.MyClass", true, classloader)
.getMethod("sayHello").invoke(null)
}
}
...
Solution 4:[4]
To run your custom Java class from Gradle build script (without JVM fork) you can include it in the buildscript classpath and then import it explicitly. Example:
buildscript {
ext {
ownRepo = "${System.properties['user.home']}/.gradle/local"
}
// Repositories for the build script.
repositories {
ivy {
url ownRepo
}
}
// Dependencies for the build script.
dependencies {
classpath "org:mytool:1.0"
}
}
import org.mytool.Checksums
task calculateChecksums() {
doLast {
new Checksums().calculate(myAppDir)
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Espinosa |
Solution 3 | |
Solution 4 | Dimitar II |