Quantcast
Channel: Gradle Forums - Latest posts
Viewing all articles
Browse latest Browse all 20661

Feature variants for java library

$
0
0

Hi! I’ve had the same problem, this seems like a very common scenario but it’s completely missing in the documentation. In my case, I have a library that can be used directly, but also offers support for Spring (e.g. Spring Boot auto-configuration) as an optional feature. The Spring support obviously depends on the main library and uses classes from it.

Sometimes the easiest solution would be to declare those extra dependencies “compileOnly” (i.e. optional), just forget about features, and go ahead and put all the code in the main source set. This is easier to configure in Gradle, but has the drawback that the client also has to declare those optional dependencies in order to use those extra classes. If there is more than one or two of those optional dependencies, it is not very feasible.

Option 1 you mentioned (put all features into “main” source set) solves this problem; the client can just declare with a single requireCapability that it is interested in the feature, so all those “optional” dependencies come in. A drawback is that it puts all the code into one JAR, so possibly wasting space if those extra features are not required. I guess another drawback would be that other clients of the library would still see the feature-specific classes that depend on external dependencies of the feature, but would get NoClassDefFoundErrors when they try to use it.

Option 2 (using different source sets) puts each feature code into its own source set. If the features also depend on code from “main”, one way I got this to work is to declare a dependency for the feature’s <feature>Api configuration on project(path), i.e. the project itself but without any required capabilities.

In my case the build.gradle.kts looked like this (Groovy should be very similar)

sourceSets.create("spring")

java {
    registerFeature("spring") {
        usingSourceSet(sourceSets["spring"])
    }
}

dependencies {
    // dependencies for the main/common part
    api( ... )
    implementation( ... )

    "springApi"(project(path))
    
    "springApi"("org.springframework:spring-context")

    // you can use this to inherit all the implementation stuff into springImplementation
    "springImplementation"(configurations["implementation"])
}

Viewing all articles
Browse latest Browse all 20661

Trending Articles