Skip to content

Use java-library plugin and api configuration for correct POM scopes#470

Merged
cbb330 merged 1 commit intolinkedin:mainfrom
cbb330:fix/java-library-pom-scopes
Feb 24, 2026
Merged

Use java-library plugin and api configuration for correct POM scopes#470
cbb330 merged 1 commit intolinkedin:mainfrom
cbb330:fix/java-library-pom-scopes

Conversation

@cbb330
Copy link
Collaborator

@cbb330 cbb330 commented Feb 24, 2026

Summary

Fix published POM metadata so that OpenHouse artifacts work correctly when consumed via standard
Maven/Gradle resolution (e.g. publishToMavenLocal + mavenLocal() repository). Currently all
transitive dependencies in published POMs have <scope>runtime</scope>, making them invisible at
compile time to standard consumers. LinkedIn's li-product plugin masks this by ignoring POM scopes
when resolving from Artifactory.

The fix switches the base convention from the java plugin to java-library (a backward-compatible
superset) and promotes consumer-facing dependencies from implementation to api, which maps to
<scope>compile</scope> in generated POMs. Internal/optional dependencies (testcontainers, H2,
logging, OkHttp, Livy, springdoc, etc.) remain as implementation (runtime scope).

Changes

  • Client-facing API Changes
  • Internal API Changes
  • Bug Fixes
  • New Features
  • Performance Improvements
  • Code Style
  • Refactoring
  • Documentation
  • Tests

Bug Fix: All 16 build.gradle and convention plugin files updated:

  • buildSrc/src/main/groovy/openhouse.java-minimal-conventions.gradle: javajava-library, mapstruct + servlet-api → api
  • buildSrc/src/main/groovy/openhouse.java-conventions.gradle: micrometer deps → api
  • buildSrc/src/main/groovy/openhouse.hadoop-conventions.gradle: hadoop-client + commons-lang3 → api
  • buildSrc/src/main/groovy/openhouse.iceberg-conventions-1.5.2.gradle: iceberg deps → api
  • buildSrc/src/main/groovy/openhouse.iceberg-conventions-1.2.gradle: iceberg deps → api
  • buildSrc/src/main/groovy/openhouse.iceberg-aws-conventions.gradle: iceberg-aws + AWS SDK → api
  • buildSrc/src/main/groovy/openhouse.iceberg-azure-conventions.gradle: azure deps → api
  • buildSrc/src/main/groovy/openhouse.springboot-conventions.gradle: Spring starters, swagger, servlet-api → api
  • cluster/storage/build.gradle, cluster/metrics/build.gradle, client/secureclient/build.gradle: project deps → api
  • services/common/build.gradle, services/tables/build.gradle, services/housetables/build.gradle, services/jobs/build.gradle, iceberg/openhouse/internalcatalog/build.gradle: project deps and consumer-facing libs → api

Testing Done

  • Manually Tested on local docker setup. Please include commands ran, and their output.
  • Added new tests for the changes made.
  • Updated existing tests to reflect the changes made.
  • No tests added or updated. Please explain why. If unsure, please feel free to ask for help.
  • Some other form of testing like staging or soak time in production. Please explain.

Build verification: ./gradlew compileJava passes across all 73 tasks.

POM verification: After ./gradlew publishToMavenLocal, inspected POMs in ~/.m2/repository/com/linkedin/openhouse/:

  • Consumer-facing deps now have <scope>compile</scope> (e.g. storage module: 20 compile-scope deps)
  • Internal deps remain <scope>runtime</scope> (e.g. storage module: 3 runtime-scope deps — gson, commons-cli, testcontainers)

End-to-end verification: li-openhouse builds successfully against locally-published SNAPSHOT artifacts using mavenLocal() — previously failed with missing compile-time types (Spring, Iceberg, slf4j).

Additional Information

  • Breaking Changes
  • Deprecations
  • Large PR broken into smaller PRs, and PR plan linked in the description.

Backward Compatibility

These changes are fully backward compatible:

  1. java-library is a strict superset of java — it adds the api configuration but doesn't remove or change anything from the java plugin. All existing build logic, tasks, and configurations continue to work identically.

  2. JAR contents are identical — the compiled bytecode doesn't change at all. api vs implementation only affects how Gradle exposes dependencies to consumers; it has zero effect on what gets compiled into the module's own JAR.

  3. Fat JARs (bootJar) are identical — Spring Boot's repackaging bundles all dependencies regardless of scope, so the deployed services contain exactly the same classes.

  4. POM metadata is the only thing that changes — dependencies that were <scope>runtime</scope> are now <scope>compile</scope> for consumer-facing deps. This is strictly more correct — it can only fix resolution for standard consumers, never break it. A dependency that was already visible at runtime remains visible; it's now also visible at compile time.

  5. li-product consumers are unaffected — LinkedIn's li-product plugin ignores POM scopes entirely when resolving from Artifactory, so the existing internal build pipeline sees no difference.

Switch base convention from java to java-library and promote
consumer-facing dependencies from implementation to api. This ensures
published POMs use compile scope for transitive dependencies that
downstream consumers need at compile time, fixing broken resolution
when artifacts are consumed via standard Maven/Gradle resolution
(e.g. mavenLocal) rather than LinkedIn's li-product plugin which
ignores POM scopes.

Dependencies kept as implementation (runtime scope in POM):
- testcontainers, H2, logging implementations, OkHttp, OpenTelemetry
  SDK, Kotlin stdlib, Livy, Netty, springdoc, spotbugs-annotations,
  JAXB runtime, MySQL connector, cron-utils, commons-cli, gson
Copy link
Collaborator

@jiang95-dev jiang95-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is cool! I had to manually convert the pom during local testing, but now it is not needed!

@cbb330 cbb330 merged commit cd1547b into linkedin:main Feb 24, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants