From 60ab45ce2a8f5b318c5f386e96e7e2e5ffbb1e59 Mon Sep 17 00:00:00 2001 From: Robert Stupp Date: Thu, 16 Jul 2026 10:50:31 +0200 Subject: [PATCH] Make protobuf runtime selection explicit cel-core exposed cel-generated-pb transitively even though consumers may need the protobuf 3 generated classes instead. That made cel-core plus cel-generated-pb3 resolve two providers for the same generated CEL protobuf classes. Stop publishing a generated protobuf flavor from core-level artifacts, require consumers and repo modules to choose one explicitly, and cover both choices in the build-tool integration sample. The standalone jar must include relocated generated CEL protobuf classes because its public API references those relocated types and standalone consumers may use it non-transitively. Build the shadow jar from compileClasspath so compile-only generated protobuf and protobuf runtime inputs are included without pulling Jackson runtime dependencies into the standalone artifact. --- README.md | 35 ++++++++++++++++----- build-tool-integ-tests/build.gradle | 1 + build-tool-integ-tests/pom.xml | 5 +++ build.gradle.kts | 47 +++++++++++++++++++++++++---- conformance/build.gradle.kts | 1 + core/build.gradle.kts | 3 +- jackson/build.gradle.kts | 2 ++ jackson3/build.gradle.kts | 2 ++ standalone/build.gradle.kts | 30 ++++++++++-------- tools/build.gradle.kts | 2 ++ 10 files changed, 101 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index a061aded..fbe11630 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,8 @@ The CEL specification can be found [here](https://github.com/google/cel-spec). ## Getting started -The easiest way to get started is to add the CEL-Java BOM and `cel-tools` to your project. +The easiest way to get started is to add the CEL-Java BOM, `cel-tools`, and one generated protobuf +artifact to your project. Maven: @@ -47,6 +48,10 @@ Maven: + + org.projectnessie.cel + cel-generated-pb + org.projectnessie.cel cel-tools @@ -59,12 +64,22 @@ Gradle: ```groovy dependencies { implementation(enforcedPlatform("org.projectnessie.cel:cel-bom:0.6.2")) + implementation("org.projectnessie.cel:cel-generated-pb") implementation("org.projectnessie.cel:cel-tools") } ``` The `cel-bom` artifact is available for CEL-Java version 0.3.0 and newer. +Starting with CEL-Java 0.7.0, `cel-core`, `cel-tools`, and the Jackson integration artifacts no +longer choose a generated protobuf runtime transitively. Add exactly one of these artifacts: + +- `org.projectnessie.cel:cel-generated-pb` +- `org.projectnessie.cel:cel-generated-pb3` + +Do not put both generated protobuf artifacts on the same classpath; they provide the same generated +CEL protobuf classes for different protobuf runtime choices. + ## Usage ### Basic scripts @@ -102,7 +117,8 @@ public class MyClass { ### Protobuf objects -Protobuf objects and schemas are supported out of the box via `com.google.protobuf:protobuf-java`. +Protobuf objects and schemas are supported through the generated protobuf artifact selected in your +dependencies, either `cel-generated-pb` or `cel-generated-pb3`. ```protobuf syntax = "proto3"; @@ -182,6 +198,7 @@ To use Jackson 3, add `cel-jackson3` in addition to `cel-tools` or `cel-core`: ```groovy dependencies { implementation(enforcedPlatform("org.projectnessie.cel:cel-bom:0.6.2")) + implementation("org.projectnessie.cel:cel-generated-pb") implementation("org.projectnessie.cel:cel-tools") implementation("org.projectnessie.cel:cel-jackson3") } @@ -283,22 +300,24 @@ currently expose a no-standard-library construction option. | Need | Use | | --- | --- | -| Normal embedding with `ScriptHost` | `cel-tools` | +| Normal embedding with `ScriptHost` | `cel-tools` plus exactly one of `cel-generated-pb` or `cel-generated-pb3` | | Dependency isolation / relocated protobuf dependencies | `cel-standalone` | -| Jackson 3 object access | `cel-tools` or `cel-core` plus `cel-jackson3` | -| Jackson 2 object access | `cel-tools` or `cel-core` plus `cel-jackson` | +| Jackson 3 object access | `cel-tools` or `cel-core` plus `cel-jackson3` and one generated protobuf artifact | +| Jackson 2 object access | `cel-tools` or `cel-core` plus `cel-jackson` and one generated protobuf artifact | Use either `cel-tools` or `cel-standalone`, never both. ### Dependency-free artifact -The `org.projectnessie.cel:cel-standalone` artifact contains everything from CEL-Java and has no -dependencies. It comes with relocated protobuf dependencies. +The `org.projectnessie.cel:cel-standalone` artifact contains CEL-Java's core runtime and relocated +protobuf dependencies in one dependency-isolated artifact. Using `cel-standalone` is especially useful when your project requires different versions of `protobuf-java`. -If you need CEL-Java's Jackson functionality, include the Jackson dependencies in your project. +Jackson runtimes are intentionally not relocated into `cel-standalone`. If you need CEL-Java's +Jackson functionality, choose the Jackson version you want and include those Jackson dependencies in +your project. ## Implementation notes diff --git a/build-tool-integ-tests/build.gradle b/build-tool-integ-tests/build.gradle index a75f61bb..ee9c0421 100644 --- a/build-tool-integ-tests/build.gradle +++ b/build-tool-integ-tests/build.gradle @@ -28,6 +28,7 @@ repositories { dependencies { implementation(enforcedPlatform("org.projectnessie.cel:cel-bom:${System.getProperty("cel.version")}")) + implementation("org.projectnessie.cel:${System.getProperty("cel.generated.pb.artifact", "cel-generated-pb")}") implementation("org.projectnessie.cel:cel-tools") implementation("org.projectnessie.cel:cel-jackson") } diff --git a/build-tool-integ-tests/pom.xml b/build-tool-integ-tests/pom.xml index 63d459c4..f1b37596 100644 --- a/build-tool-integ-tests/pom.xml +++ b/build-tool-integ-tests/pom.xml @@ -27,6 +27,7 @@ UTF-8 8 0.6.2 + cel-generated-pb @@ -42,6 +43,10 @@ + + org.projectnessie.cel + ${cel.generated.pb.artifact} + org.projectnessie.cel cel-tools diff --git a/build.gradle.kts b/build.gradle.kts index a7c18240..df3713e0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,6 +14,7 @@ * limitations under the License. */ +import org.gradle.api.tasks.TaskProvider import org.jetbrains.gradle.ext.settings import org.jetbrains.gradle.ext.taskTriggers @@ -27,26 +28,58 @@ mapOf("versionJacoco" to libs.versions.jacoco.get(), "versionJandex" to libs.ver tasks.named("wrapper") { distributionType = Wrapper.DistributionType.ALL } -val buildToolIntegrationGradle = - tasks.register("buildToolIntegrationGradle") { +fun registerBuildToolIntegrationGradleTask( + taskName: String, + generatedProtobufArtifact: String, +): TaskProvider = + tasks.register(taskName) { group = "Verification" description = "Checks whether bom works fine with Gradle, requires preceding publishToMavenLocal in a separate Gradle invocation" workingDir = file("build-tool-integ-tests") - commandLine("./gradlew", "jar", "-Dcel.version=${project.version}") + commandLine( + "./gradlew", + "jar", + "-Dcel.version=${project.version}", + "-Dcel.generated.pb.artifact=$generatedProtobufArtifact", + ) } -val buildToolIntegrationMaven = - tasks.register("buildToolIntegrationMaven") { +fun registerBuildToolIntegrationMavenTask( + taskName: String, + generatedProtobufArtifact: String, +): TaskProvider = + tasks.register(taskName) { group = "Verification" description = "Checks whether bom works fine with Maven, requires preceding publishToMavenLocal in a separate Gradle invocation" workingDir = file("build-tool-integ-tests") - commandLine("./mvnw", "clean", "package", "-Dcel.version=${project.version}") + commandLine( + "./mvnw", + "clean", + "package", + "-Dcel.version=${project.version}", + "-Dcel.generated.pb.artifact=$generatedProtobufArtifact", + ) } +val buildToolIntegrationGradle = + registerBuildToolIntegrationGradleTask("buildToolIntegrationGradle", "cel-generated-pb") +val buildToolIntegrationGradlePb3 = + registerBuildToolIntegrationGradleTask("buildToolIntegrationGradlePb3", "cel-generated-pb3") +val buildToolIntegrationMaven = + registerBuildToolIntegrationMavenTask("buildToolIntegrationMaven", "cel-generated-pb") +val buildToolIntegrationMavenPb3 = + registerBuildToolIntegrationMavenTask("buildToolIntegrationMavenPb3", "cel-generated-pb3") + +buildToolIntegrationGradlePb3.configure { mustRunAfter(buildToolIntegrationGradle) } + +buildToolIntegrationMaven.configure { mustRunAfter(buildToolIntegrationGradlePb3) } + +buildToolIntegrationMavenPb3.configure { mustRunAfter(buildToolIntegrationMaven) } + val buildToolIntegrations = tasks.register("buildToolIntegrations") { group = "Verification" @@ -54,7 +87,9 @@ val buildToolIntegrations = "Checks whether bom works fine with build tools, requires preceding publishToMavenLocal in a separate Gradle invocation" dependsOn(buildToolIntegrationGradle) + dependsOn(buildToolIntegrationGradlePb3) dependsOn(buildToolIntegrationMaven) + dependsOn(buildToolIntegrationMavenPb3) } publishingHelper { diff --git a/conformance/build.gradle.kts b/conformance/build.gradle.kts index 0b3978cd..d1cae24b 100644 --- a/conformance/build.gradle.kts +++ b/conformance/build.gradle.kts @@ -67,6 +67,7 @@ configurations.all { exclude(group = "org.projectnessie.cel", module = "cel-gene dependencies { implementation(project(":cel-core")) + implementation(project(":cel-generated-pb3")) implementation(testFixtures(project(":cel-core"))) implementation(testFixtures(project(":cel-generated-pb3"))) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index de048d42..67a2b529 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -28,10 +28,11 @@ configurations.named("jmhImplementation") { extendsFrom(configurations.testFixtu dependencies { implementation(project(":cel-generated-antlr")) - api(project(":cel-generated-pb")) + compileOnly(project(":cel-generated-pb")) implementation(libs.agrona) + testImplementation(project(":cel-generated-pb")) testFixturesApi(platform(libs.junit.bom)) testFixturesApi(libs.bundles.junit.testing) testFixturesApi(libs.protobuf.java) diff --git a/jackson/build.gradle.kts b/jackson/build.gradle.kts index 69ef1224..480bd0ce 100644 --- a/jackson/build.gradle.kts +++ b/jackson/build.gradle.kts @@ -25,6 +25,7 @@ description = "CEL Jackson 2 support" dependencies { api(project(":cel-core")) + compileOnly(project(":cel-generated-pb")) implementation(platform(libs.jackson2.bom)) implementation("com.fasterxml.jackson.core:jackson-databind") @@ -33,6 +34,7 @@ dependencies { implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml") testImplementation(project(":cel-tools")) + testImplementation(project(":cel-generated-pb")) testAnnotationProcessor(libs.immutables.value.processor) testCompileOnly(libs.immutables.value.annotations) testImplementation(libs.findbugs.jsr305) diff --git a/jackson3/build.gradle.kts b/jackson3/build.gradle.kts index 3338184e..6d1b5d73 100644 --- a/jackson3/build.gradle.kts +++ b/jackson3/build.gradle.kts @@ -25,6 +25,7 @@ description = "CEL Jackson 3 support" dependencies { api(project(":cel-core")) + compileOnly(project(":cel-generated-pb")) implementation(platform(libs.jackson3.bom)) implementation("tools.jackson.core:jackson-databind") @@ -33,6 +34,7 @@ dependencies { implementation("tools.jackson.dataformat:jackson-dataformat-yaml") testImplementation(project(":cel-tools")) + testImplementation(project(":cel-generated-pb")) testAnnotationProcessor(libs.immutables.value.processor) testCompileOnly(libs.immutables.value.annotations) testImplementation(libs.findbugs.jsr305) diff --git a/standalone/build.gradle.kts b/standalone/build.gradle.kts index 2c1f9c7a..05544406 100644 --- a/standalone/build.gradle.kts +++ b/standalone/build.gradle.kts @@ -24,14 +24,31 @@ plugins { id("cel-conventions") } +val standaloneShadow = + configurations.create("standaloneShadow") { + isCanBeConsumed = false + isCanBeResolved = true + isTransitive = false + } + dependencies { api(project(":cel-tools")) api(project(":cel-jackson")) api(project(":cel-jackson3")) api(project(":cel-generated-antlr")) + compileOnly(project(":cel-generated-pb")) compileOnly(libs.protobuf.java) compileOnly(libs.agrona) + + standaloneShadow(project(":cel-core")) + standaloneShadow(project(":cel-tools")) + standaloneShadow(project(":cel-jackson")) + standaloneShadow(project(":cel-jackson3")) + standaloneShadow(project(":cel-generated-antlr")) + standaloneShadow(project(":cel-generated-pb")) + standaloneShadow(libs.protobuf.java) + standaloneShadow(libs.agrona) } val shadowJar = tasks.named("shadowJar") @@ -44,18 +61,7 @@ shadowJar.configure { attributes["Specification-Title"] = "Common-Expression-Language - dependency-free CEL" attributes["Specification-Version"] = libs.protobuf.java.get().version } - configurations = listOf(project.configurations.getByName("runtimeClasspath")) - dependencies { - include(project(":cel-tools")) - include(project(":cel-core")) - include(project(":cel-jackson")) - include(project(":cel-jackson3")) - include(project(":cel-generated-pb")) - include(project(":cel-generated-antlr")) - - include(dependency(libs.protobuf.java.get())) - include(dependency(libs.agrona.get())) - } + configurations = listOf(standaloneShadow) } tasks.named("compileJava").configure { finalizedBy(shadowJar) } diff --git a/tools/build.gradle.kts b/tools/build.gradle.kts index fd12d9e9..e92912de 100644 --- a/tools/build.gradle.kts +++ b/tools/build.gradle.kts @@ -28,7 +28,9 @@ apply() dependencies { api(project(":cel-core")) + compileOnly(project(":cel-generated-pb")) + testImplementation(project(":cel-generated-pb")) testImplementation(platform(libs.junit.bom)) testImplementation(libs.bundles.junit.testing) testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")