I am using Kotlin to write a Gradle plugin for personal use. I would like to use some features only found in recent versions of the Java standard library, such as javax.xml.parsers.SAXParserFactory.newDefaultNSInstance()
, which was added in Java 13.
I have configured Gradle for Kotlin plugin creation, and set it to use a Java 17 JDK for both Java and Kotlin:
plugins {
`java-gradle-plugin`
kotlin("jvm") version "1.7.0"
kotlin("plugin.serialization") version "1.7.0"
}
repositories(RepositoryHandler::mavenCentral)
java.toolchain.languageVersion.set(JavaLanguageVersion.of(17))
kotlin.jvmToolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
Unfortunately, this leaves me with two SAXParserFactory
implementations in my compilation classpath:
/home/liblit/.gradle/caches/7.4.2/generated-gradle-jars/gradle-api-7.4.2.jar!/javax/xml/parsers/SAXParserFactory.class
/usr/lib/jvm/java-17!/java.xml/javax/xml/parsers/SAXParserFactory.class
Kotlin compilation via the compileKotlin
task seems to pick up the grade-api-7.4.2.jar
implementation first, and unfortunately that’s a rather old version. It’s too old to include the newDefaultNSInstance()
method I wish to use, so compileKotlin
fails. I could work around this specific example by using other SAXParserFactory
methods, but there’s a bigger general issue here.
How can a Kotlin-based Gradle plugin use newer classes than the ones that are bundled into the Gradle API jar? Is it possible to reorder dependencies such that my plugin uses the JDK-provided implementations instead? Or is it a terrible idea to build a plugin using a newer JDK than that used by Gradle’s APIs? If the latter, then what specific JDK is Gradle 7.4.2 built against, so that I can build my plugin using the same toolchain version?
I tried creating an analogous situation with a Java-based plugin, but in that case compileJava
succeeds! I am not sure why. I think that the same two SAXParserFactory
implementations are present in my compilation classpath. Perhaps the classpath is just ordered differently when compiling Java instead of Kotlin? Perhaps the order is non-deterministic and compileJava
is getting lucky but compileKotlin
is not?