CAMEL-24649: Add unmatched request handler to REST OpenAPI component - #26203
CAMEL-24649: Add unmatched request handler to REST OpenAPI component#26203ullgren wants to merge 1 commit into
Conversation
davsclaus
left a comment
There was a problem hiding this comment.
Review
Thanks for this Pontus — nice piece of work. The extension point follows the exact idiom the JIRA asked for (lookupUnmatchedRequestHandler() mirrors RestBindingAdviceFactory.lookupRestClientRequestValidator()), the default handler reproduces the previous behaviour verbatim so there is no regression for existing users, both doc copies are in sync, and the tests cover default and custom handlers for both status codes.
Verification performed
| Check | Result |
|---|---|
mvn verify in components/camel-rest-openapi (build cache disabled) |
pass |
| Test totals | 148 run, 0 failures / errors / skipped |
New RestOpenApiUnmatchedRequestHandlerTest |
5 tests pass |
mvn formatter:format impsort:sort |
no diff produced |
src/main/docs vs catalog/.../docs mirror |
byte-identical |
xref:manual::registry.adoc target |
resolves |
Prior-art check: the 404/405 block dates back to 447dcd3c4571 (CAMEL-20557, the original contract-first implementation), so this change does not revert any later intentional decision.
No blocking issues. Three inline notes below, plus these three that are not tied to a single line:
Should the interface live in camel-api rather than the component?
components/camel-rest-postman/src/main/java/org/apache/camel/component/rest/postman/RestPostmanProcessor.java#L117-L125 contains a byte-identical 404/405 block. The precedent the JIRA cites, RestClientRequestValidator, lives in core/camel-api under org.apache.camel.spi rather than in a component. Putting this interface there instead would let camel-rest-postman reuse it, rather than growing a second, incompatible handler SPI later. Component-local is defensible for a first cut — mainly flagging it so the choice is deliberate.
No @UriParam endpoint option
The sibling extension point on this same component, restOpenapiProcessorStrategy, is exposed as @UriParam(label = "consumer,advanced") on RestOpenApiEndpoint, which gives per-endpoint configuration plus catalog and tooling discoverability. The new handler is resolved once per CamelContext, so two rest-openapi endpoints in one context cannot use different handlers. RestClientRequestValidator is registry-only too, so this matches the model you were asked to follow — but the in-component precedent points the other way. Your call.
Commit body
Commit 91dd59f has a meaningful subject but an empty body, while the PR checklist ticks "each commit has a meaningful subject line and body". Minor, but easy to fill in on the next push.
Note: the PR is still a draft and CI has not run yet, so I have not identified reviewers — that step applies once it is marked ready for review.
Scope: this is a rules-and-conventions review against the project's .oss-ai-helper-rules/ and CLAUDE.md, backed by a real local build and test run. It is not a substitute for CodeRabbit, Sourcery, or SonarCloud static analysis.
Claude Code on behalf of davsclaus
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
| private final String apiContextPath; | ||
| private final List<RestConsumerContextPathMatcher.ConsumerPath<Operation>> paths = new ArrayList<>(); | ||
| private final RestOpenapiProcessorStrategy restOpenapiProcessorStrategy; | ||
| private RestOpenApiUnmatchedRequestHandler unmatchedRequestHandler; |
There was a problem hiding this comment.
Defensive nit: this field is assigned only in afterPropertiesConfigured(), and RestOpenApiEndpoint.createConsumer() wires that callback conditionally:
if (consumer instanceof PlatformHttpConsumerAware phca) {
phca.registerAfterConfigured(openApiProcessor);
}Today PlatformHttpComponent is the only RestOpenApiConsumerFactory in the tree, so the callback always fires and this is unreachable in practice. But the previous inline code had no such dependency: where it would have degraded to a plain 404, this would NPE. Initialising the field at declaration removes the whole class of risk for free, and afterPropertiesConfigured() still overwrites it with the resolved handler.
| private RestOpenApiUnmatchedRequestHandler unmatchedRequestHandler; | |
| private RestOpenApiUnmatchedRequestHandler unmatchedRequestHandler = new DefaultRestOpenApiUnmatchedRequestHandler(); |
| */ | ||
| public interface RestOpenApiUnmatchedRequestHandler { | ||
|
|
||
| String FACTORY = "rest-openapi-unmatched-request-handler-factory"; |
There was a problem hiding this comment.
Test gap: the factory-finder route this constant enables is public contract but has no test coverage — all five new tests go through the registry path. A small test registering a META-INF/services/org/apache/camel/rest-openapi-unmatched-request-handler-factory resource would lock the constant's value in.
Related, worth being aware of rather than a defect: CamelContextHelper.findSingleByType returns null when more than one handler is registered, so two beans of this type silently fall back to the default with no warning. That is consistent with how RestClientRequestValidator behaves, so no change needed in the code — but see my note on the docs.
| with HTTP 404, and a request that matches a path but not the HTTP method is answered with HTTP 405 and an | ||
| `Allow` header listing the allowed methods. In both cases the response body is empty. | ||
|
|
||
| To return a custom response, for example a JSON error body, register a bean in the |
There was a problem hiding this comment.
Docs nit: this documents only the registry route, but lookupUnmatchedRequestHandler() also supports the META-INF/services factory-finder route via RestOpenApiUnmatchedRequestHandler.FACTORY. It is also worth stating that exactly one such bean may be registered — findSingleByType returns null for two or more, silently falling back to the default handler.
One extra sentence here would cover both. (Remember to mirror any change into the catalog/camel-catalog/.../docs/ copy — you already have that right in this PR.)
Description
Adding a unmatched request handler allowing for library users to customize the response that REST OpenAPI component sends back when the request does not match any operation in the OAS.
Target
mainbranch)Tracking
Apache Camel coding standards and style
I checked that each commit in the pull request has a meaningful subject line and body.
I have run
mvn clean install -DskipTestslocally from root folder and I have committed all auto-generated changes.AI-assisted contributions
Co-authored-bytrailers) and the PR description identifies the AI tool used.