fix(extensions): make the Spark example resolvable, and fail the build when a service has no implementation - #930
Merged
Conversation
…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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Found while analysing #907.
The Spark example cannot resolve its own service
ExtensionBridgeImpl.findImplementationClasstriesServiceLoaderfirst, then falls back toliteral FQN concatenation —
ifaceName + "Impl".btrace-hadoop…hadoop.api.HadoopApi…hadoop.impl.HadoopApiImplbtrace-spark…spark.api.SparkApi…spark.impl.SparkApiImplWith no provider file the convention resolves
…spark.api.SparkApiImpl, which does not exist, solookup returns null and injection fails. The two examples have the identical
api/impllayout;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.
validateServiceApisnow verifies that every declared service has an implementation the runtimecan actually find, and fails the build naming the service when it does not.
The check accepts either route the runtime accepts — the exact
<serviceFqcn>Implname, or aprovider file naming a class that exists — and fires only when both are absent. It deliberately
does not express a preference between them: an
api/implpackage split is legitimate and iswhat the extension guidance encourages, it simply requires the provider declaration.
Verification
Both directions, since a gate that cannot fail is worse than no gate:
btrace-sparkbefore the fix:No implementation found for declared service(s): [org.example.btrace.spark.api.SparkApi]btrace-hadoop, whose only difference is the provider file.btrace-ext-test.:btrace-gradle-plugin:testandspotlessCheckpass.🤖 Generated with Claude Code
This change is