oscerd opened a new pull request, #28962: URL: https://github.com/apache/camel/pull/28962
Fixes [CAMEL-26252](https://issues.apache.org/jira/browse/CAMEL-26252), found while adding the catalog body types (CAMEL-24961). ## 1. A failed call gave an empty body and no exception **Was:** `GoogleCloudFunctionsProducer.callFunction` set `response.getResult()` as the body and never looked at `response.getError()`. A function whose execution failed gave an empty String and the route went on as a success. **Now:** when the `CallFunctionResponse` has an error, the exchange fails with a `CamelExchangeException`: "The function projects/.../functions/myFunction failed in execution <id>: <error>" (the execution id part only when the response has one). The `CallFunctionResponse` is set in the `CamelGoogleCloudFunctionsResponseObject` header before the exception, so an error handler can read the error and the execution id; the body is left as it was (the data sent), so a redelivery sends the same data. This holds with and without `pojoRequest`. ## 2. callFunction without a body failed with a bare NullPointerException **Was:** `setData(getBody(String.class))` passed null to protobuf, which threw a NullPointerException without a message. **Now:** no body fails with an `InvalidPayloadException` (expected type `String`) before the function is called. I chose failing over sending an empty string: `data` is a required field of `CallFunctionRequest` in the Cloud Functions v1 API, and the catalog body types already documented "no body fails". A route that wants to call a function without input can set an empty body (`""`) or `{}` explicitly. ## 3. A Map or POJO body was sent as its toString() **Was:** the body was read as String, so a Map went out as `{name=Camel}`, a List as `[a, b]` and a POJO as its `toString()`. **Now:** text (a `CharSequence`) is sent as it is, and bytes, a stream (also a stream cache or a Reader), a `File`, a `Path` and a `GenericFile` are read as text, as before. Any other body, such as a `Map`, a `List` or a POJO, is marshalled to JSON with Jackson. A body Jackson cannot marshal fails with an `InvalidPayloadException` that carries the Jackson error. The module now declares `jackson-databind` (version managed by the parent): before, only `jackson-core` was on its classpath, through google-http-client-jackson2. ## Tests - New `GoogleCloudFunctionsCallFunctionTest` (13 tests) on the module's in-process gRPC mock (`MockCloudFunctionsService`): a failed call with and without `pojoRequest`, a successful call, no body, a Map, a List and a POJO (a record) sent as JSON, and a String, bytes, a stream, a `File`, a `Path` and a `GenericFile` sent as text. - `GoogleCloudFunctionsComponentTest.callFunctionTest` and `callFunctionPojoTest` stubbed a successful response that also had an error set (`setError("error96784904")`, generated sample data); the error is removed, as such a response now fails the exchange. - With the `src/main` changes reverted, 6 of the 13 new tests fail, each on an assertion that shows the bug: the two failed-call tests (no exception), no body (a `NullPointerException` instead of an `InvalidPayloadException`), and the Map, List and POJO tests (`{name=Camel, count=2}`, `[a, b]`, `Greeting[text=Hello, count=2]`). The 7 that pass are the successful call and the text bodies, which were already read as text: they guard that the change keeps them. - Module tests: 37 tests, 0 failures, 1 skipped (skipped before this change too). ## Docs and generated files Component doc: what `callFunction` sends for each body, that no body fails, what it returns, and that a failed function fails the exchange with the response still in the header. `@BodyTypes`: the input carriers add file, map, list and pojo and the description says how each is sent; the output description says that a response with an error fails the exchange. The regenerated `google-functions.json` and the doc are copied into the catalog. Upgrade guide entry: `callFunction` fails the exchange when the function fails, a Map, List or POJO is sent as JSON, and no body fails with an `InvalidPayloadException`. ## Not changed - There is no option to keep the old behaviour (a failed call going on as a success, as `aws2-lambda` does with its function error header). **Open question:** should a `throwExceptionOnFailure`-style option be added? It would be a new feature, so I left it out. - Gson is also on the module's classpath (transitively, through the Google libraries) and would have avoided the new `jackson-databind` dependency. I used Jackson because the other Google components (firestore, secret-manager, vertexai) use it and it honours the Jackson annotations users put on their POJOs. - Bytes are still read as text: `data` is a string field of the API, so binary data cannot go through it unencoded. Main only, as the other fixes of the CAMEL-24961 follow-ups. _Claude Code on behalf of Andrea Cosentino (oscerd)_ 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
