davsclaus opened a new pull request, #29024: URL: https://github.com/apache/camel/pull/29024
Fixes [CAMEL-26196](https://issues.apache.org/jira/browse/CAMEL-26196). ### 1. pojoRequest=true with a body of the wrong type did nothing **Was:** every pojoRequest create/update operation (24 of them, such as `createUser`, `updateRealm`, `createOrganization`) did `if (payload instanceof XxxRepresentation)`. For a String or Map body there was no call to Keycloak, no error, and the body was kept. **Now:** a new `getPojoRequest(exchange, type)` gets the representation. Another type is converted: first by a Camel type converter, then a `Map` (such as unmarshalled JSON) or JSON text (String, byte[], InputStream) is mapped with Keycloak's own `JsonSerialization`. A body that does not convert, or invalid JSON, fails with an `InvalidPayloadException` for the expected type. ### 2. A failed create or delete was no error, and its Response was never closed **Was:** the operations that give the jakarta `Response` as body set it without looking at the status, so a 409 (already exists) or 404 (not found) completed the exchange. The Response was never closed, so its HTTP connection was not released. `deleteOrganization`, `removeOrganizationMember` and `unlinkOrganizationIdentityProvider` ignored their Response the same way. **Now:** a new `checkResponse(response, operation)` fails on a status other than 2xx with a `jakarta.ws.rs.WebApplicationException` that carries the Response (message: `Keycloak createUser failed with status 409: <Keycloak error text>`), and always closes the Response. This is the same exception type the Keycloak admin client throws for the operations that do not return a Response (for example `NotFoundException` from `updateUser`), so one `onException(WebApplicationException.class)` covers them all. The body is still the `Response`, now closed. With RESTEasy, `getStatus()`, `getLocation()` and `getHeaderString("Location")` work after `close()`, so routes that read the id of the created resource from the Location header keep working (the `KeycloakTestInfraIT` tests that do so pass against a real Keycloak). Only `readEntity` fails, and a 201/204 has no entity. Covered: createUser, deleteUser, createGroup, createClient, createClientScope, createIdentityProvider, createResource, createResourcePolicy, createResourcePermission, createOrganization, updateOrganization, addOrganizationMember, linkOrganizationIdentityProvider, deleteOrganization, removeOrganizationMember, unlinkOrganizationIdentityProvider. ### 3. bulkCreateUsers with a List of Map failed with a raw ClassCastException **Was:** `bulkCreateUsers` and `bulkUpdateUsers` cast the List (body or `CamelKeycloakUsers` header) to `List<UserRepresentation>`; a List of Map failed with a `ClassCastException` in the loop. **Now:** each element is converted the same way as in 1. An element that does not convert fails the exchange with an `IllegalArgumentException` that names the index and `UserRepresentation`, before any call to Keycloak. On the same lines: `bulkCreateUsers` and `bulkDeleteUsers` counted a 409 or 404 as a `success`. They now use `checkResponse`, so such an item is `failed` with its `statusCode` (and the exchange fails unless `CamelKeycloakContinueOnError` is true). `bulkDeleteUsers` also closes the Response when the call throws. ### Tests - New `KeycloakProducerPojoRequestAndResponseTest` (14 tests, Mockito, no Keycloak needed): JSON text and Map bodies, wrong type and invalid JSON, 409/404 for createUser, createGroup, deleteUser and deleteOrganization, the Response is closed on success and failure, bulk create/update from a List of Map and JSON text, a wrong element, and 409/404 items in bulk create/delete. All 14 fail without the fix. - `KeycloakProducerTest`: the shared mocked Response now returns status 201, and the three organization delete tests stub the Response of `delete()`. - Module: 161 unit tests pass; the ITs that ran against Keycloak from test-infra pass too (133 run, 31 skipped as before). ### Docs - `keycloak-producer.adoc`: new sections "Representation bodies" and "Results of create and delete operations"; the bulk result example shows a failed item with its `statusCode`. - `@BodyTypes` text of producerIn and producerOut updated (the old one documented the no-op and "a 409 or 404 is no error"); `keycloak.json` regenerated and copied to the catalog, with the producer doc page. - Upgrade guide 4.24: new `camel-keycloak` section, since a 409/404 now fails the exchange, the Response body is closed, and a pojoRequest body that did nothing now converts or fails. ### Not changed - The body of these operations stays the `Response` (closed), rather than becoming the created id or a text, so the body type and routes that read the status or Location header do not change. - Operations whose admin client methods return `void` or a representation already fail on an error status (the client throws), so they are untouched. _Claude Code on behalf of Claus Ibsen (davsclaus)_ 🤖 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]
