Skip to content

fix(extensions): make the Spark example resolvable, and fail the build when a service has no implementation - #930

Merged
jbachorik merged 2 commits into
developfrom
agent/fix-spark-example-provider
Jul 28, 2026
Merged

fix(extensions): make the Spark example resolvable, and fail the build when a service has no implementation#930
jbachorik merged 2 commits into
developfrom
agent/fix-spark-example-provider

Conversation

@jbachorik

@jbachorik jbachorik commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Found while analysing #907.

The Spark example cannot resolve its own service

ExtensionBridgeImpl.findImplementationClass tries ServiceLoader first, then falls back to
literal FQN concatenationifaceName + "Impl".

Example Interface Implementation Provider file Resolves
btrace-hadoop …hadoop.api.HadoopApi …hadoop.impl.HadoopApiImpl present yes
btrace-spark …spark.api.SparkApi …spark.impl.SparkApiImpl none no

With no provider file the convention resolves …spark.api.SparkApiImpl, which does not exist, so
lookup returns null and injection fails. The two examples have the identical api/impl layout;
the only difference is that Hadoop declares its provider.

Adds the equivalent declaration for Spark.

Nothing caught it, so the build now does

The extension compiles, packages, installs and loads. Only injection fails, at the probe call
site, a long way from the cause — the same failure mode observed live while walking the migration
for #906.

validateServiceApis now verifies that every declared service has an implementation the runtime
can actually find, and fails the build naming the service when it does not.

The check accepts either route the runtime accepts — the exact <serviceFqcn>Impl name, or a
provider file naming a class that exists — and fires only when both are absent. It deliberately
does not express a preference between them: an api/impl package split is legitimate and is
what the extension guidance encourages, it simply requires the provider declaration.

Verification

Both directions, since a gate that cannot fail is worse than no gate:

  • Fails on btrace-spark before the fix:
    No implementation found for declared service(s): [org.example.btrace.spark.api.SparkApi]
  • Passes on btrace-hadoop, whose only difference is the provider file.
  • Passes on all eight shipped extensions and btrace-ext-test.
  • :btrace-gradle-plugin:test and spotlessCheck pass.
  • The provider declaration is present in the packaged impl jar, where the runtime looks for it.

🤖 Generated with Claude Code


This change is Reviewable

…d when a service has no implementation

The Spark example could not resolve its own service. Its interface is
org.example.btrace.spark.api.SparkApi and its implementation is
org.example.btrace.spark.impl.SparkApiImpl, with no provider declaration.
Implementation lookup tries ServiceLoader and then the exact name
<serviceFqcn>Impl, so it looked for org.example.btrace.spark.api.SparkApiImpl,
which does not exist. Injection would have failed at the probe call site.

The Hadoop example has the same api/impl package layout and works, because it
ships the provider declaration. Add the equivalent one for Spark.

Nothing caught this. The extension compiles, packages, installs and loads; only
injection fails, and it fails in the probe rather than anywhere near the cause.
So validateServiceApis now checks that every declared service has an
implementation the runtime can actually find, by either accepted route, and
fails the build naming the service when neither is present.

The check is deliberately permissive: it accepts the exact-name convention or a
provider file naming a class that exists, and fires only when both are absent.
Verified it fails on the Spark example before this fix, passes on the Hadoop
example whose only difference is the provider file, and passes on all eight
shipped extensions.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 28, 2026 09:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Copilot AI review requested due to automatic review settings July 28, 2026 17:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@jbachorik
jbachorik merged commit 1348f1b into develop Jul 28, 2026
40 of 42 checks passed
@jbachorik
jbachorik deleted the agent/fix-spark-example-provider branch July 28, 2026 19:44
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