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

oscerd 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 f3e8a71d27f5 CAMEL-23461: camel-aws-bedrock - applyGuardrail reads 
guardrail identifier from wrong header (#23151)
f3e8a71d27f5 is described below

commit f3e8a71d27f57e36abe7721300f2ecd737683925
Author: Andrea Cosentino <[email protected]>
AuthorDate: Tue May 12 15:28:03 2026 +0200

    CAMEL-23461: camel-aws-bedrock - applyGuardrail reads guardrail identifier 
from wrong header (#23151)
    
    The applyGuardrail producer was reading the guardrail identifier from
    CamelAwsBedrockGuardrailConfig as a String, but that header is documented as
    GuardrailConfiguration and is consumed as such by converse / converseStream.
    Routes mixing the two operations silently produced a null identifier and
    fell back to the endpoint configuration only.
    
    Introduce a dedicated CamelAwsBedrockGuardrailIdentifier header
    (BedrockConstants.GUARDRAIL_IDENTIFIER, typed String) for applyGuardrail.
    GUARDRAIL_CONFIG stays reserved for converse / converseStream.
    
    Adds a unit test (mocked BedrockRuntimeClient, no AWS access required)
    covering endpoint fallback, the new header, the regression where
    GUARDRAIL_CONFIG must not corrupt the applyGuardrail request, and the
    missing-identifier failure path. Component docs, the 4.21 upgrade guide,
    and the regenerated catalog/metadata/endpoint-DSL artifacts are updated
    accordingly.
    
    Closes #23151
---
 .../camel/catalog/components/aws-bedrock.json      |  13 +-
 .../aws2/bedrock/runtime/aws-bedrock.json          |  13 +-
 .../src/main/docs/aws-bedrock-component.adoc       |   1 +
 .../aws2/bedrock/runtime/BedrockConstants.java     |   2 +
 .../aws2/bedrock/runtime/BedrockProducer.java      |   3 +-
 .../bedrock/runtime/BedrockApplyGuardrailTest.java | 172 +++++++++++++++++++++
 .../ROOT/pages/camel-4x-upgrade-guide-4_21.adoc    |  10 ++
 .../dsl/BedrockEndpointBuilderFactory.java         |  12 ++
 8 files changed, 213 insertions(+), 13 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws-bedrock.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws-bedrock.json
index 90b1c4cba800..1c7145bfba86 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws-bedrock.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws-bedrock.json
@@ -71,12 +71,13 @@
     "CamelAwsBedrockConverseUsage": { "index": 13, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "TokenUsage", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The usage metrics from 
Converse API response", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#CONVERSE_USAGE"
 },
     "CamelAwsBedrockConverseOutputMessage": { "index": 14, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Message", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The output message from Converse API 
response", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#CONVERSE_OUTPUT_MESSAGE"
 },
     "CamelAwsBedrockGuardrailConfig": { "index": 15, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "GuardrailConfiguration", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "The guardrail 
configuration to apply to the request", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_CONFIG"
 },
-    "CamelAwsBedrockGuardrailContent": { "index": 16, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "List<GuardrailContentBlock>", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
content blocks for ApplyGuardrail operation", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_CONTENT"
 },
-    "CamelAwsBedrockGuardrailSource": { "index": 17, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The source type for ApplyGuardrail 
operation (INPUT or OUTPUT)", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_SOURCE"
 },
-    "CamelAwsBedrockGuardrailOutput": { "index": 18, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "GuardrailAssessment", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The guardrail assessment 
output from the response", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_OUTPUT"
 },
-    "CamelAwsBedrockGuardrailTrace": { "index": 19, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "GuardrailTrace", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The trace information from 
guardrail evaluation", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_TRACE"
 },
-    "CamelAwsBedrockGuardrailAssessments": { "index": 20, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "List<GuardrailAssessment>", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
guardrail assessments from ApplyGuardrail response", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_ASSESSMENTS"
 },
-    "CamelAwsBedrockGuardrailUsage": { "index": 21, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "GuardrailUsage", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The guardrail usage 
metrics from ApplyGuardrail response", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_USAGE"
 }
+    "CamelAwsBedrockGuardrailIdentifier": { "index": 16, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The guardrail identifier to use for the 
ApplyGuardrail operation", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_IDENTIFIER"
 },
+    "CamelAwsBedrockGuardrailContent": { "index": 17, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "List<GuardrailContentBlock>", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
content blocks for ApplyGuardrail operation", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_CONTENT"
 },
+    "CamelAwsBedrockGuardrailSource": { "index": 18, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The source type for ApplyGuardrail 
operation (INPUT or OUTPUT)", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_SOURCE"
 },
+    "CamelAwsBedrockGuardrailOutput": { "index": 19, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "GuardrailAssessment", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The guardrail assessment 
output from the response", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_OUTPUT"
 },
+    "CamelAwsBedrockGuardrailTrace": { "index": 20, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "GuardrailTrace", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The trace information from 
guardrail evaluation", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_TRACE"
 },
+    "CamelAwsBedrockGuardrailAssessments": { "index": 21, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "List<GuardrailAssessment>", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
guardrail assessments from ApplyGuardrail response", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_ASSESSMENTS"
 },
+    "CamelAwsBedrockGuardrailUsage": { "index": 22, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "GuardrailUsage", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The guardrail usage 
metrics from ApplyGuardrail response", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_USAGE"
 }
   },
   "properties": {
     "label": { "index": 0, "kind": "path", "displayName": "Label", "group": 
"producer", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "configurationClass": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConfiguration", 
"configurationField": "configuration", "description": "Logical name" },
diff --git 
a/components/camel-aws/camel-aws-bedrock/src/generated/resources/META-INF/org/apache/camel/component/aws2/bedrock/runtime/aws-bedrock.json
 
b/components/camel-aws/camel-aws-bedrock/src/generated/resources/META-INF/org/apache/camel/component/aws2/bedrock/runtime/aws-bedrock.json
index 90b1c4cba800..1c7145bfba86 100644
--- 
a/components/camel-aws/camel-aws-bedrock/src/generated/resources/META-INF/org/apache/camel/component/aws2/bedrock/runtime/aws-bedrock.json
+++ 
b/components/camel-aws/camel-aws-bedrock/src/generated/resources/META-INF/org/apache/camel/component/aws2/bedrock/runtime/aws-bedrock.json
@@ -71,12 +71,13 @@
     "CamelAwsBedrockConverseUsage": { "index": 13, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "TokenUsage", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The usage metrics from 
Converse API response", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#CONVERSE_USAGE"
 },
     "CamelAwsBedrockConverseOutputMessage": { "index": 14, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Message", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The output message from Converse API 
response", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#CONVERSE_OUTPUT_MESSAGE"
 },
     "CamelAwsBedrockGuardrailConfig": { "index": 15, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "GuardrailConfiguration", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "The guardrail 
configuration to apply to the request", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_CONFIG"
 },
-    "CamelAwsBedrockGuardrailContent": { "index": 16, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "List<GuardrailContentBlock>", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
content blocks for ApplyGuardrail operation", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_CONTENT"
 },
-    "CamelAwsBedrockGuardrailSource": { "index": 17, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The source type for ApplyGuardrail 
operation (INPUT or OUTPUT)", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_SOURCE"
 },
-    "CamelAwsBedrockGuardrailOutput": { "index": 18, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "GuardrailAssessment", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The guardrail assessment 
output from the response", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_OUTPUT"
 },
-    "CamelAwsBedrockGuardrailTrace": { "index": 19, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "GuardrailTrace", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The trace information from 
guardrail evaluation", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_TRACE"
 },
-    "CamelAwsBedrockGuardrailAssessments": { "index": 20, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "List<GuardrailAssessment>", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
guardrail assessments from ApplyGuardrail response", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_ASSESSMENTS"
 },
-    "CamelAwsBedrockGuardrailUsage": { "index": 21, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "GuardrailUsage", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The guardrail usage 
metrics from ApplyGuardrail response", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_USAGE"
 }
+    "CamelAwsBedrockGuardrailIdentifier": { "index": 16, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The guardrail identifier to use for the 
ApplyGuardrail operation", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_IDENTIFIER"
 },
+    "CamelAwsBedrockGuardrailContent": { "index": 17, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "List<GuardrailContentBlock>", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
content blocks for ApplyGuardrail operation", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_CONTENT"
 },
+    "CamelAwsBedrockGuardrailSource": { "index": 18, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The source type for ApplyGuardrail 
operation (INPUT or OUTPUT)", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_SOURCE"
 },
+    "CamelAwsBedrockGuardrailOutput": { "index": 19, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "GuardrailAssessment", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The guardrail assessment 
output from the response", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_OUTPUT"
 },
+    "CamelAwsBedrockGuardrailTrace": { "index": 20, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "GuardrailTrace", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The trace information from 
guardrail evaluation", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_TRACE"
 },
+    "CamelAwsBedrockGuardrailAssessments": { "index": 21, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "List<GuardrailAssessment>", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
guardrail assessments from ApplyGuardrail response", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_ASSESSMENTS"
 },
+    "CamelAwsBedrockGuardrailUsage": { "index": 22, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "GuardrailUsage", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The guardrail usage 
metrics from ApplyGuardrail response", "constantName": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConstants#GUARDRAIL_USAGE"
 }
   },
   "properties": {
     "label": { "index": 0, "kind": "path", "displayName": "Label", "group": 
"producer", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "configurationClass": 
"org.apache.camel.component.aws2.bedrock.runtime.BedrockConfiguration", 
"configurationField": "configuration", "description": "Logical name" },
diff --git 
a/components/camel-aws/camel-aws-bedrock/src/main/docs/aws-bedrock-component.adoc
 
b/components/camel-aws/camel-aws-bedrock/src/main/docs/aws-bedrock-component.adoc
index 598590a6e8f8..591da05643ee 100644
--- 
a/components/camel-aws/camel-aws-bedrock/src/main/docs/aws-bedrock-component.adoc
+++ 
b/components/camel-aws/camel-aws-bedrock/src/main/docs/aws-bedrock-component.adoc
@@ -803,6 +803,7 @@ The Camel AWS Bedrock component provides comprehensive 
support for guardrails th
 *Message-level Configuration* (per-message override via headers):
 
 - `CamelAwsBedrockGuardrailConfig`: GuardrailConfiguration object for converse 
operations
+- `CamelAwsBedrockGuardrailIdentifier`: Guardrail identifier String for the 
applyGuardrail operation (overrides the endpoint `guardrailIdentifier`)
 - `CamelAwsBedrockGuardrailContent`: Content blocks for applyGuardrail 
operation
 - `CamelAwsBedrockGuardrailSource`: Source type - "INPUT" or "OUTPUT" for 
applyGuardrail
 
diff --git 
a/components/camel-aws/camel-aws-bedrock/src/main/java/org/apache/camel/component/aws2/bedrock/runtime/BedrockConstants.java
 
b/components/camel-aws/camel-aws-bedrock/src/main/java/org/apache/camel/component/aws2/bedrock/runtime/BedrockConstants.java
index 9feeb736cc3d..0ab3692e5775 100644
--- 
a/components/camel-aws/camel-aws-bedrock/src/main/java/org/apache/camel/component/aws2/bedrock/runtime/BedrockConstants.java
+++ 
b/components/camel-aws/camel-aws-bedrock/src/main/java/org/apache/camel/component/aws2/bedrock/runtime/BedrockConstants.java
@@ -55,6 +55,8 @@ public interface BedrockConstants {
     String CONVERSE_OUTPUT_MESSAGE = "CamelAwsBedrockConverseOutputMessage";
     @Metadata(description = "The guardrail configuration to apply to the 
request", javaType = "GuardrailConfiguration")
     String GUARDRAIL_CONFIG = "CamelAwsBedrockGuardrailConfig";
+    @Metadata(description = "The guardrail identifier to use for the 
ApplyGuardrail operation", javaType = "String")
+    String GUARDRAIL_IDENTIFIER = "CamelAwsBedrockGuardrailIdentifier";
     @Metadata(description = "The content blocks for ApplyGuardrail operation", 
javaType = "List<GuardrailContentBlock>")
     String GUARDRAIL_CONTENT = "CamelAwsBedrockGuardrailContent";
     @Metadata(description = "The source type for ApplyGuardrail operation 
(INPUT or OUTPUT)", javaType = "String")
diff --git 
a/components/camel-aws/camel-aws-bedrock/src/main/java/org/apache/camel/component/aws2/bedrock/runtime/BedrockProducer.java
 
b/components/camel-aws/camel-aws-bedrock/src/main/java/org/apache/camel/component/aws2/bedrock/runtime/BedrockProducer.java
index edc967263986..1c40bc6cc730 100644
--- 
a/components/camel-aws/camel-aws-bedrock/src/main/java/org/apache/camel/component/aws2/bedrock/runtime/BedrockProducer.java
+++ 
b/components/camel-aws/camel-aws-bedrock/src/main/java/org/apache/camel/component/aws2/bedrock/runtime/BedrockProducer.java
@@ -816,7 +816,8 @@ public class BedrockProducer extends DefaultProducer {
                     = ApplyGuardrailRequest.builder();
 
             // Guardrail identifier from header or configuration
-            String guardrailIdentifier = 
exchange.getMessage().getHeader(BedrockConstants.GUARDRAIL_CONFIG, 
String.class);
+            String guardrailIdentifier
+                    = 
exchange.getMessage().getHeader(BedrockConstants.GUARDRAIL_IDENTIFIER, 
String.class);
             if (ObjectHelper.isEmpty(guardrailIdentifier)) {
                 guardrailIdentifier = 
getConfiguration().getGuardrailIdentifier();
             }
diff --git 
a/components/camel-aws/camel-aws-bedrock/src/test/java/org/apache/camel/component/aws2/bedrock/runtime/BedrockApplyGuardrailTest.java
 
b/components/camel-aws/camel-aws-bedrock/src/test/java/org/apache/camel/component/aws2/bedrock/runtime/BedrockApplyGuardrailTest.java
new file mode 100644
index 000000000000..c0e0a05418cc
--- /dev/null
+++ 
b/components/camel-aws/camel-aws-bedrock/src/test/java/org/apache/camel/component/aws2/bedrock/runtime/BedrockApplyGuardrailTest.java
@@ -0,0 +1,172 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.aws2.bedrock.runtime;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.support.SimpleRegistry;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import software.amazon.awssdk.services.bedrockruntime.BedrockRuntimeClient;
+import 
software.amazon.awssdk.services.bedrockruntime.model.ApplyGuardrailRequest;
+import 
software.amazon.awssdk.services.bedrockruntime.model.ApplyGuardrailResponse;
+import software.amazon.awssdk.services.bedrockruntime.model.GuardrailAction;
+import 
software.amazon.awssdk.services.bedrockruntime.model.GuardrailConfiguration;
+import 
software.amazon.awssdk.services.bedrockruntime.model.GuardrailContentBlock;
+import software.amazon.awssdk.services.bedrockruntime.model.GuardrailTextBlock;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.lenient;
+
+/**
+ * Unit tests for the {@code applyGuardrail} producer operation. Uses a mocked 
{@link BedrockRuntimeClient} so the test
+ * exercises only the producer's request-building logic — no AWS credentials 
or network access required.
+ */
+@ExtendWith(MockitoExtension.class)
+public class BedrockApplyGuardrailTest {
+
+    @Mock
+    private BedrockRuntimeClient client;
+
+    private CamelContext camelContext;
+    private ProducerTemplate template;
+    private AtomicReference<ApplyGuardrailRequest> capturedRequest;
+
+    @BeforeEach
+    public void setup() throws Exception {
+        capturedRequest = new AtomicReference<>();
+        lenient().doAnswer(invocation -> {
+            capturedRequest.set(invocation.getArgument(0, 
ApplyGuardrailRequest.class));
+            return 
ApplyGuardrailResponse.builder().action(GuardrailAction.NONE).build();
+        }).when(client).applyGuardrail(any(ApplyGuardrailRequest.class));
+
+        SimpleRegistry registry = new SimpleRegistry();
+        registry.bind("bedrockClient", client);
+        camelContext = new DefaultCamelContext(registry);
+        camelContext.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:apply-guardrail-config")
+                        .to("aws-bedrock://label"
+                            + "?bedrockRuntimeClient=#bedrockClient"
+                            + "&operation=applyGuardrail"
+                            + "&guardrailIdentifier=endpoint-guardrail-id"
+                            + "&guardrailVersion=1"
+                            + "&region=us-east-1"
+                            + "&accessKey=unused"
+                            + "&secretKey=unused");
+
+                from("direct:apply-guardrail-no-config")
+                        .to("aws-bedrock://label2"
+                            + "?bedrockRuntimeClient=#bedrockClient"
+                            + "&operation=applyGuardrail"
+                            + "&region=us-east-1"
+                            + "&accessKey=unused"
+                            + "&secretKey=unused");
+            }
+        });
+        camelContext.start();
+        template = camelContext.createProducerTemplate();
+    }
+
+    @AfterEach
+    public void teardown() {
+        if (template != null) {
+            template.stop();
+        }
+        if (camelContext != null) {
+            camelContext.stop();
+        }
+    }
+
+    @Test
+    public void applyGuardrailUsesEndpointGuardrailIdentifierWhenNoHeader() {
+        template.send("direct:apply-guardrail-config",
+                exchange -> 
exchange.getMessage().setHeader(BedrockConstants.GUARDRAIL_CONTENT, 
sampleContent()));
+
+        ApplyGuardrailRequest request = capturedRequest.get();
+        assertNotNull(request, "Producer must have invoked the bedrock 
client");
+        assertEquals("endpoint-guardrail-id", request.guardrailIdentifier(),
+                "Identifier should fall back to the endpoint configuration 
when no header is set");
+    }
+
+    @Test
+    public void applyGuardrailUsesGuardrailIdentifierHeaderWhenSet() {
+        template.send("direct:apply-guardrail-config", exchange -> {
+            
exchange.getMessage().setHeader(BedrockConstants.GUARDRAIL_IDENTIFIER, 
"header-guardrail-id");
+            
exchange.getMessage().setHeader(BedrockConstants.GUARDRAIL_CONTENT, 
sampleContent());
+        });
+
+        ApplyGuardrailRequest request = capturedRequest.get();
+        assertNotNull(request);
+        assertEquals("header-guardrail-id", request.guardrailIdentifier(),
+                "Identifier should be read from the 
CamelAwsBedrockGuardrailIdentifier header");
+    }
+
+    @Test
+    public void applyGuardrailDoesNotReadIdentifierFromGuardrailConfigHeader() 
{
+        // GUARDRAIL_CONFIG carries a GuardrailConfiguration (used by 
converse), not a String identifier.
+        // Setting it must not corrupt the applyGuardrail request — the 
endpoint identifier must still be used.
+        template.send("direct:apply-guardrail-config", exchange -> {
+            GuardrailConfiguration converseConfig = 
GuardrailConfiguration.builder()
+                    .guardrailIdentifier("converse-guardrail-id")
+                    .guardrailVersion("DRAFT")
+                    .build();
+            exchange.getMessage().setHeader(BedrockConstants.GUARDRAIL_CONFIG, 
converseConfig);
+            
exchange.getMessage().setHeader(BedrockConstants.GUARDRAIL_CONTENT, 
sampleContent());
+        });
+
+        ApplyGuardrailRequest request = capturedRequest.get();
+        assertNotNull(request);
+        assertEquals("endpoint-guardrail-id", request.guardrailIdentifier(),
+                "applyGuardrail must not consume the GuardrailConfiguration 
from CamelAwsBedrockGuardrailConfig");
+    }
+
+    @Test
+    public void applyGuardrailFailsWhenGuardrailIdentifierIsMissing() {
+        Exchange exchange = template.send("direct:apply-guardrail-no-config",
+                ex -> 
ex.getMessage().setHeader(BedrockConstants.GUARDRAIL_CONTENT, sampleContent()));
+        Throwable cause = exchange.getException();
+        assertNotNull(cause, "Producer should fail when no guardrailIdentifier 
is provided");
+        assertInstanceOf(IllegalArgumentException.class, cause);
+        assertTrue(cause.getMessage().contains("guardrailIdentifier"),
+                "Error message should mention guardrailIdentifier — was: " + 
cause.getMessage());
+    }
+
+    private static List<GuardrailContentBlock> sampleContent() {
+        List<GuardrailContentBlock> content = new ArrayList<>();
+        content.add(GuardrailContentBlock.builder()
+                .text(GuardrailTextBlock.builder().text("test").build())
+                .build());
+        return content;
+    }
+}
diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_21.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_21.adoc
index 02af0fb2e1fc..e2e840641219 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_21.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_21.adoc
@@ -268,6 +268,16 @@ What it means is that, from now on, the final user or any 
third party dependency
 
 This is just an informative note, there is not action expected by the final 
user.
 
+=== camel-aws-bedrock
+
+The `applyGuardrail` producer operation now reads the guardrail identifier 
from a new dedicated header
+`CamelAwsBedrockGuardrailIdentifier` (constant 
`BedrockConstants.GUARDRAIL_IDENTIFIER`, typed `String`)
+instead of `CamelAwsBedrockGuardrailConfig`. The 
`CamelAwsBedrockGuardrailConfig` header is typed
+`GuardrailConfiguration` and is reserved for the `converse` and 
`converseStream` operations; the
+previous code path silently produced `null` whenever a route mixed `converse` 
and `applyGuardrail`
+calls. If you were not setting the guardrail identifier via header, the 
endpoint-level
+`guardrailIdentifier` option continues to work without changes.
+
 === camel-nats
 
 Fixed the JetStream consumer pull subscription mode (which is the default) so 
that messages are
diff --git 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/BedrockEndpointBuilderFactory.java
 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/BedrockEndpointBuilderFactory.java
index d7f8ed869fa4..a71c596ec0db 100644
--- 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/BedrockEndpointBuilderFactory.java
+++ 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/BedrockEndpointBuilderFactory.java
@@ -944,6 +944,18 @@ public interface BedrockEndpointBuilderFactory {
         public String awsBedrockGuardrailConfig() {
             return "CamelAwsBedrockGuardrailConfig";
         }
+        /**
+         * The guardrail identifier to use for the ApplyGuardrail operation.
+         * 
+         * The option is a: {@code String} type.
+         * 
+         * Group: producer
+         * 
+         * @return the name of the header {@code 
AwsBedrockGuardrailIdentifier}.
+         */
+        public String awsBedrockGuardrailIdentifier() {
+            return "CamelAwsBedrockGuardrailIdentifier";
+        }
         /**
          * The content blocks for ApplyGuardrail operation.
          * 

Reply via email to