Is it possible to determine consumer Java version in library?

I have a library which is written in Java 8 and it is consumed by some projects which are in Java 11, therefore when building the consumer projects some packages are missing like in this stack overflow thread.
One of the fixes is adding

compile  "jakarta.xml.ws:jakarta.xml.ws-api:2.3.3",
          "com.sun.activation:javax.activation:1.2.0"

in my library’s build.gradle. Is it possible to conditionally attach those dependencies only if the consumer Java version is 11?

Forgive me if this question is ridiculously stupid but I’ve been working with Gradle for only 3 weeks now.

If your consumers are Gradle builds, you can use variant aware resolution: Gradle User Manual: Version 6.8.3
Those docs have an example of different dependencies for Java 8 and Java 9+.
Maybe start reading further up in the docs to get an understanding of the whole feature.

1 Like

To be honest with the knowledge I currently have, it is nearly impossible for me to figure it out only basing on the documentation. While reading the docs I feel like it assumes some things to be trivial for the reader which are not (in my case). As you said it mentions the possibility of having two variants with the attribute org.gradle.jvm.version set differently but that’s all. There are no examples as to how to declare variants (I only mangaed to declare attributes for a configuration but when I print the outgoingVariants task it only shows the runtimeElements and apiElements variants.

Did you start to read at the link or earlier as I advised?

I did start reading earlier. I have tried something and I think I’ve managed to specify a feature variant and declare an attribute to it (TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE to 11).

Below is the producer build script

import org.gradle.api.attributes.java.TargetJvmVersion

plugins {
id ‘java-library’
id ‘maven-publish’
}

group ‘org.example’
version ‘1.0-SNAPSHOT’

java {
registerFeature(‘java11Config’) {
usingSourceSet(sourceSets.main)
}
}

configurations.named(“java11ConfigRuntimeElements”) {
attributes {
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 11)
}
}

configurations.named(“runtimeElements”) {
attributes {
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 8)
}
}

sourceCompatibility = 1.8

repositories {
mavenCentral()
}

dependencies {
java11ConfigRuntimeElements(‘com.google.code.gson:gson:2.8.6’)
runtimeElements(‘org.slf4j:slf4j-api:1.7.30’)
}

test {
useJUnitPlatform()
}

publishing {
publications {
maven(MavenPublication) {
from components.java
}
}
}

and in my outgoingVariants I can see both java11ConfigRuntimeElements and java11ConfigApiElements like this
image
yet still my consumer seems to pick those default ones - apiElements and runtimeElements despite being in Java 11. (I’m deducing that basing on its dependencies, it has org.slf4j:slf4j-api:1.7.30 in its runtimeClasspath)

Could you shed some light as to why this works different than I expect?

You don’t need to deduce, I think you should see exactly what variant is chosen if you utilize the dependencyInsight task on the consumer. :slight_smile:

image
So just as I thought. Now I’m even more confused. In the documentation part about org.gradle.jvm.version. in the compatibility and disambiguation rules it says Defaults to the JVM version used by Gradle, lower is compatible with higher, prefers highest compatible. Shouldn’t it match the variant with the highest available version? (assuming every other attribute is the same)

Should the org.gradle.jvm.version. attribute be specified in the consumer as well or is it automatically set by gradle?

Hey,

From a quick look, I believe the issue is that you set the Java 11 attribute value only on the java11ConfigRuntimeElements but not on the java11ConfigApiElements.
And your dependencyInsight looks at compileClasspath.

Could you verify what happens for the runtimeClasspath of the consumer?
Also, are those two projects in the same build or do you use publication in between?
If the later, looking at the produced metadata might help confirm the additional variants are indeed published.

Looks like this other thread has the right answer: adding a feature variant is done by adding a capability.

See that other thread for more information.