This is an automated email from the ASF dual-hosted git repository.
oscerd pushed a commit to branch camel-4.18.x
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-4.18.x by this push:
new e22edbb569e7 CAMEL-23461: camel-aws-bedrock - applyGuardrail reads
guardrail identifier from wrong header (#23161)
e22edbb569e7 is described below
commit e22edbb569e76f83a8c5e8786020d8ca519b8263
Author: Andrea Cosentino <[email protected]>
AuthorDate: Wed May 13 09:02:45 2026 +0200
CAMEL-23461: camel-aws-bedrock - applyGuardrail reads guardrail identifier
from wrong header (#23161)
Backport of #23151 onto camel-4.18.x.
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.
Backport notes:
- Upgrade-guide entry placed under "Upgrading from 4.18.2 to 4.18.3" in
camel-4x-upgrade-guide-4_18.adoc.
- mockito-junit-jupiter added as test-scoped dependency on
camel-aws-bedrock.
- The matching entry on main's camel-4x-upgrade-guide-4_18.adoc will follow
in a doc-sync PR per project convention.
Closes #23161
---
.../camel/catalog/components/aws-bedrock.json | 13 +-
components/camel-aws/camel-aws-bedrock/pom.xml | 6 +
.../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_18.adoc | 10 ++
.../dsl/BedrockEndpointBuilderFactory.java | 12 ++
9 files changed, 219 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 835631434514..0281e4dfd925 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/pom.xml
b/components/camel-aws/camel-aws-bedrock/pom.xml
index cfc8d86bc30b..0b35ee2d2583 100644
--- a/components/camel-aws/camel-aws-bedrock/pom.xml
+++ b/components/camel-aws/camel-aws-bedrock/pom.xml
@@ -103,5 +103,11 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-junit-jupiter</artifactId>
+ <version>${mockito-version}</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
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 835631434514..0281e4dfd925 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 cac050a892a0..e3959f387e8e 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
@@ -806,7 +806,8 @@ public class BedrockProducer extends DefaultProducer {
=
software.amazon.awssdk.services.bedrockruntime.model.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"
+ + "®ion=us-east-1"
+ + "&accessKey=unused"
+ + "&secretKey=unused");
+
+ from("direct:apply-guardrail-no-config")
+ .to("aws-bedrock://label2"
+ + "?bedrockRuntimeClient=#bedrockClient"
+ + "&operation=applyGuardrail"
+ + "®ion=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_18.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_18.adoc
index e891799b75ab..eb2683ca3721 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_18.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_18.adoc
@@ -13,6 +13,16 @@ See the xref:camel-upgrade-recipes-tool.adoc[documentation]
page for details.
== Upgrading from 4.18.2 to 4.18.3
+=== 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-hazelcast
Hazelcast instances created and managed by Camel (when no user-supplied
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.
*