This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new a9487d588336 docs: camel-keycloak - the audit trail example gives the 
JDBC component an SQL insert, not the JSON record (#28336)
a9487d588336 is described below

commit a9487d5883367582b738d0066250ed822427ba7a
Author: Claus Ibsen <[email protected]>
AuthorDate: Sun Oct 25 16:16:22 2026 +0100

    docs: camel-keycloak - the audit trail example gives the JDBC component an 
SQL insert, not the JSON record (#28336)
    
    The audit trail example of the consumer page sent the JSON audit record to
    jdbc:dataSource as the message body, which the JDBC component runs as SQL.
    The example now sets an SQL insert as the body and passes the record in the
    CamelJdbcParameters header as the values of its named parameters.
    
    - Every named parameter gets a value, so an admin event without auth details
      inserts nulls instead of failing on a missing key.
    - The YAML tab builds the record with the Simple map function, instead of a
      JSON text that marshal then encoded a second time, and reads the auth
      details with the null-safe form ${body?.authDetails?.userId}.
    - The timestamp is the epoch millis of the event, as in the JSON, so it
      binds on any JDBC driver; the doc says the event time is in epoch 
milliseconds.
    - The catalog copy of the page is updated.
    
    Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../camel/catalog/docs/keycloak-consumer.adoc      | 55 +++++++++++++++-------
 .../src/main/docs/keycloak-consumer.adoc           | 55 +++++++++++++++-------
 2 files changed, 78 insertions(+), 32 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/keycloak-consumer.adoc
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/keycloak-consumer.adoc
index 7764059ee2e0..3f9c0a668ab9 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/keycloak-consumer.adoc
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/keycloak-consumer.adoc
@@ -452,6 +452,12 @@ YAML::
 
 === Audit Trail
 
+The route below sends each admin event as a JSON audit record to Kafka, and 
inserts the same record into an
+`audit_trail` table with the xref:ROOT:jdbc-component.adoc[JDBC] component. 
The JDBC component runs the SQL in the
+message body, and with `useHeadersAsParameters=true` it takes the values of 
the named parameters (`:?name`) from the
+`CamelJdbcParameters` header. The `timestamp` is the time of the event as 
Keycloak gives it, in milliseconds since the
+epoch, the same in the JSON record and in the table, so the `event_time` 
column is a `BIGINT`.
+
 [tabs]
 ====
 Java::
@@ -466,23 +472,26 @@ from("keycloak:adminEvents"
      + "&delay=10000")
     .process(exchange -> {
         AdminEventRepresentation event = 
exchange.getIn().getBody(AdminEventRepresentation.class);
+        AuthDetailsRepresentation authDetails = event.getAuthDetails();
 
-        // Build audit record
+        // Build audit record (every named parameter of the SQL insert needs a 
value, null included)
         Map<String, Object> auditRecord = new HashMap<>();
-        auditRecord.put("timestamp", new Date(event.getTime()));
+        auditRecord.put("timestamp", event.getTime());
         auditRecord.put("operation", event.getOperationType());
         auditRecord.put("resourceType", event.getResourceType());
         auditRecord.put("resourcePath", event.getResourcePath());
-
-        if (event.getAuthDetails() != null) {
-            auditRecord.put("userId", event.getAuthDetails().getUserId());
-            auditRecord.put("ipAddress", 
event.getAuthDetails().getIpAddress());
-        }
+        auditRecord.put("userId", authDetails != null ? 
authDetails.getUserId() : null);
+        auditRecord.put("ipAddress", authDetails != null ? 
authDetails.getIpAddress() : null);
 
         exchange.getIn().setBody(auditRecord);
+        // the values of the named parameters of the SQL insert
+        exchange.getIn().setHeader("CamelJdbcParameters", auditRecord);
     })
     .marshal().json()
     .to("kafka:audit-trail?brokers=localhost:9092")
+    // the JDBC component runs the SQL in the message body
+    .setBody(constant("insert into audit_trail (event_time, operation, 
resource_type, resource_path, user_id, ip_address)"
+                      + " values (:?timestamp, :?operation, :?resourceType, 
:?resourcePath, :?userId, :?ipAddress)"))
     .to("jdbc:dataSource?useHeadersAsParameters=true");
 ----
 
@@ -500,22 +509,36 @@ YAML::
         maxResults=100&
         delay=10000
       steps:
+        # build the audit record (every named parameter of the SQL insert 
needs a value, null included)
         - setBody:
-            simple: >
-              {
-                "timestamp": ${body.time},
-                "operation": "${body.operationType}",
-                "resourceType": "${body.resourceType}",
-                "resourcePath": "${body.resourcePath}",
-                "userId": "${body.authDetails.userId}",
-                "ipAddress": "${body.authDetails.ipAddress}"
-              }
+            expression:
+              simple:
+                expression: >-
+                  ${map(timestamp,${body.time},
+                  operation,${body.operationType},
+                  resourceType,${body.resourceType},
+                  resourcePath,${body.resourcePath},
+                  userId,${body?.authDetails?.userId},
+                  ipAddress,${body?.authDetails?.ipAddress})}
+        # the values of the named parameters of the SQL insert
+        - setHeader:
+            name: CamelJdbcParameters
+            expression:
+              simple:
+                expression: "${body}"
         - marshal:
             json: {}
         - to:
             uri: kafka:audit-trail
             parameters:
               brokers: "localhost:9092"
+        # the JDBC component runs the SQL in the message body
+        - setBody:
+            expression:
+              constant:
+                expression: >-
+                  insert into audit_trail (event_time, operation, 
resource_type, resource_path, user_id, ip_address)
+                  values (:?timestamp, :?operation, :?resourceType, 
:?resourcePath, :?userId, :?ipAddress)
         - to:
             uri: jdbc:dataSource
             parameters:
diff --git a/components/camel-keycloak/src/main/docs/keycloak-consumer.adoc 
b/components/camel-keycloak/src/main/docs/keycloak-consumer.adoc
index 7764059ee2e0..3f9c0a668ab9 100644
--- a/components/camel-keycloak/src/main/docs/keycloak-consumer.adoc
+++ b/components/camel-keycloak/src/main/docs/keycloak-consumer.adoc
@@ -452,6 +452,12 @@ YAML::
 
 === Audit Trail
 
+The route below sends each admin event as a JSON audit record to Kafka, and 
inserts the same record into an
+`audit_trail` table with the xref:ROOT:jdbc-component.adoc[JDBC] component. 
The JDBC component runs the SQL in the
+message body, and with `useHeadersAsParameters=true` it takes the values of 
the named parameters (`:?name`) from the
+`CamelJdbcParameters` header. The `timestamp` is the time of the event as 
Keycloak gives it, in milliseconds since the
+epoch, the same in the JSON record and in the table, so the `event_time` 
column is a `BIGINT`.
+
 [tabs]
 ====
 Java::
@@ -466,23 +472,26 @@ from("keycloak:adminEvents"
      + "&delay=10000")
     .process(exchange -> {
         AdminEventRepresentation event = 
exchange.getIn().getBody(AdminEventRepresentation.class);
+        AuthDetailsRepresentation authDetails = event.getAuthDetails();
 
-        // Build audit record
+        // Build audit record (every named parameter of the SQL insert needs a 
value, null included)
         Map<String, Object> auditRecord = new HashMap<>();
-        auditRecord.put("timestamp", new Date(event.getTime()));
+        auditRecord.put("timestamp", event.getTime());
         auditRecord.put("operation", event.getOperationType());
         auditRecord.put("resourceType", event.getResourceType());
         auditRecord.put("resourcePath", event.getResourcePath());
-
-        if (event.getAuthDetails() != null) {
-            auditRecord.put("userId", event.getAuthDetails().getUserId());
-            auditRecord.put("ipAddress", 
event.getAuthDetails().getIpAddress());
-        }
+        auditRecord.put("userId", authDetails != null ? 
authDetails.getUserId() : null);
+        auditRecord.put("ipAddress", authDetails != null ? 
authDetails.getIpAddress() : null);
 
         exchange.getIn().setBody(auditRecord);
+        // the values of the named parameters of the SQL insert
+        exchange.getIn().setHeader("CamelJdbcParameters", auditRecord);
     })
     .marshal().json()
     .to("kafka:audit-trail?brokers=localhost:9092")
+    // the JDBC component runs the SQL in the message body
+    .setBody(constant("insert into audit_trail (event_time, operation, 
resource_type, resource_path, user_id, ip_address)"
+                      + " values (:?timestamp, :?operation, :?resourceType, 
:?resourcePath, :?userId, :?ipAddress)"))
     .to("jdbc:dataSource?useHeadersAsParameters=true");
 ----
 
@@ -500,22 +509,36 @@ YAML::
         maxResults=100&
         delay=10000
       steps:
+        # build the audit record (every named parameter of the SQL insert 
needs a value, null included)
         - setBody:
-            simple: >
-              {
-                "timestamp": ${body.time},
-                "operation": "${body.operationType}",
-                "resourceType": "${body.resourceType}",
-                "resourcePath": "${body.resourcePath}",
-                "userId": "${body.authDetails.userId}",
-                "ipAddress": "${body.authDetails.ipAddress}"
-              }
+            expression:
+              simple:
+                expression: >-
+                  ${map(timestamp,${body.time},
+                  operation,${body.operationType},
+                  resourceType,${body.resourceType},
+                  resourcePath,${body.resourcePath},
+                  userId,${body?.authDetails?.userId},
+                  ipAddress,${body?.authDetails?.ipAddress})}
+        # the values of the named parameters of the SQL insert
+        - setHeader:
+            name: CamelJdbcParameters
+            expression:
+              simple:
+                expression: "${body}"
         - marshal:
             json: {}
         - to:
             uri: kafka:audit-trail
             parameters:
               brokers: "localhost:9092"
+        # the JDBC component runs the SQL in the message body
+        - setBody:
+            expression:
+              constant:
+                expression: >-
+                  insert into audit_trail (event_time, operation, 
resource_type, resource_path, user_id, ip_address)
+                  values (:?timestamp, :?operation, :?resourceType, 
:?resourcePath, :?userId, :?ipAddress)
         - to:
             uri: jdbc:dataSource
             parameters:

Reply via email to