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

gnodet pushed a commit to branch backport/29084-to-camel-4.22.x
in repository https://gitbox.apache.org/repos/asf/camel.git

commit f714ebf8274dee40041319d60b326086999b1b93
Author: Guillaume Nodet <[email protected]>
AuthorDate: Tue Nov 3 12:03:38 2026 +0000

    [backport camel-4.22.x] CAMEL-26533: camel-jpa - bind CamelJpaParameters 
header values literally
---
 .../org/apache/camel/catalog/components/jpa.json         |  2 +-
 .../META-INF/org/apache/camel/component/jpa/jpa.json     |  2 +-
 .../org/apache/camel/component/jpa/JpaConstants.java     |  3 ++-
 .../java/org/apache/camel/component/jpa/JpaProducer.java | 13 ++++++-------
 .../jpa/JpaProducerWithQueryParametersHeaderTest.java    | 16 +++++++++++++---
 .../modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc  | 10 ++++++++++
 .../builder/endpoint/dsl/JpaEndpointBuilderFactory.java  |  1 +
 7 files changed, 34 insertions(+), 13 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jpa.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jpa.json
index 93a85f144ca0..e1f729d0b72f 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jpa.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jpa.json
@@ -37,7 +37,7 @@
   },
   "headers": {
     "CamelEntityManager": { "index": 0, "kind": "header", "displayName": "", 
"group": "common", "label": "", "required": false, "javaType": 
"jakarta.persistence.EntityManager", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "The JPA EntityManager 
object.", "constantName": 
"org.apache.camel.component.jpa.JpaConstants#ENTITY_MANAGER" },
-    "CamelJpaParameters": { "index": 1, "kind": "header", "displayName": "", 
"group": "producer", "label": "producer", "required": false, "javaType": 
"Map<String, Object>", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Alternative way for passing query 
parameters as an Exchange header.", "constantName": 
"org.apache.camel.component.jpa.JpaConstants#JPA_PARAMETERS_HEADER" },
+    "CamelJpaParameters": { "index": 1, "kind": "header", "displayName": "", 
"group": "producer", "label": "producer", "required": false, "javaType": 
"Map<String, Object>", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Alternative way for passing query 
parameters as an Exchange header. The parameter values are used as-is without 
expression evaluation.", "constantName": 
"org.apache.camel.component.jpa.JpaConstants#JPA_PARAMETERS_HEADER" },
     "CamelJpaMaximumResults": { "index": 2, "kind": "header", "displayName": 
"", "group": "producer", "label": "producer", "required": false, "javaType": 
"", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Defines the maximum number of results to retrieve on the 
query; takes precedence over the value set on the endpoint, if any.", 
"constantName": 
"org.apache.camel.component.jpa.JpaConstants#JPA_MAXIMUM_RESULTS" },
     "CamelJpaFirstResult": { "index": 3, "kind": "header", "displayName": "", 
"group": "producer", "label": "producer", "required": false, "javaType": "", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Defines the position of the first result to retrieve; 
takes precedence over the value set on the endpoint, if any.", "constantName": 
"org.apache.camel.component.jpa.JpaConstants#JPA_FIRST_RESULT" }
   },
diff --git 
a/components/camel-jpa/src/generated/resources/META-INF/org/apache/camel/component/jpa/jpa.json
 
b/components/camel-jpa/src/generated/resources/META-INF/org/apache/camel/component/jpa/jpa.json
index 93a85f144ca0..e1f729d0b72f 100644
--- 
a/components/camel-jpa/src/generated/resources/META-INF/org/apache/camel/component/jpa/jpa.json
+++ 
b/components/camel-jpa/src/generated/resources/META-INF/org/apache/camel/component/jpa/jpa.json
@@ -37,7 +37,7 @@
   },
   "headers": {
     "CamelEntityManager": { "index": 0, "kind": "header", "displayName": "", 
"group": "common", "label": "", "required": false, "javaType": 
"jakarta.persistence.EntityManager", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "The JPA EntityManager 
object.", "constantName": 
"org.apache.camel.component.jpa.JpaConstants#ENTITY_MANAGER" },
-    "CamelJpaParameters": { "index": 1, "kind": "header", "displayName": "", 
"group": "producer", "label": "producer", "required": false, "javaType": 
"Map<String, Object>", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Alternative way for passing query 
parameters as an Exchange header.", "constantName": 
"org.apache.camel.component.jpa.JpaConstants#JPA_PARAMETERS_HEADER" },
+    "CamelJpaParameters": { "index": 1, "kind": "header", "displayName": "", 
"group": "producer", "label": "producer", "required": false, "javaType": 
"Map<String, Object>", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Alternative way for passing query 
parameters as an Exchange header. The parameter values are used as-is without 
expression evaluation.", "constantName": 
"org.apache.camel.component.jpa.JpaConstants#JPA_PARAMETERS_HEADER" },
     "CamelJpaMaximumResults": { "index": 2, "kind": "header", "displayName": 
"", "group": "producer", "label": "producer", "required": false, "javaType": 
"", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Defines the maximum number of results to retrieve on the 
query; takes precedence over the value set on the endpoint, if any.", 
"constantName": 
"org.apache.camel.component.jpa.JpaConstants#JPA_MAXIMUM_RESULTS" },
     "CamelJpaFirstResult": { "index": 3, "kind": "header", "displayName": "", 
"group": "producer", "label": "producer", "required": false, "javaType": "", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Defines the position of the first result to retrieve; 
takes precedence over the value set on the endpoint, if any.", "constantName": 
"org.apache.camel.component.jpa.JpaConstants#JPA_FIRST_RESULT" }
   },
diff --git 
a/components/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaConstants.java
 
b/components/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaConstants.java
index 4273b1394f46..9cc7cbf04fa6 100644
--- 
a/components/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaConstants.java
+++ 
b/components/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaConstants.java
@@ -26,7 +26,8 @@ public final class JpaConstants {
 
     @Metadata(description = "The JPA `EntityManager` object.", javaType = 
"jakarta.persistence.EntityManager")
     public static final String ENTITY_MANAGER = Exchange.JPA_ENTITY_MANAGER;
-    @Metadata(label = "producer", description = "Alternative way for passing 
query parameters as an Exchange header.",
+    @Metadata(label = "producer",
+              description = "Alternative way for passing query parameters as 
an Exchange header. The parameter values are used as-is without expression 
evaluation.",
               javaType = "Map<String, Object>")
     public static final String JPA_PARAMETERS_HEADER = "CamelJpaParameters";
     @Metadata(label = "producer", description = "Defines the maximum number of 
results to retrieve on the query; " +
diff --git 
a/components/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaProducer.java
 
b/components/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaProducer.java
index b0b0ac831aa3..81065da0724b 100644
--- 
a/components/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaProducer.java
+++ 
b/components/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaProducer.java
@@ -201,20 +201,19 @@ public class JpaProducer extends DefaultProducer {
             query.setFirstResult(firstResult);
         }
         // setup the parameters
-        Map<String, ?> params;
         if (parameters != null) {
-            params = parameters;
-        } else {
-            params = 
exchange.getIn().getHeader(JpaConstants.JPA_PARAMETERS_HEADER, Map.class);
-        }
-        if (params != null) {
-            params.forEach((key, value) -> {
+            parameters.forEach((key, value) -> {
                 Object resolvedValue = value;
                 if (value instanceof String str) {
                     resolvedValue = 
simple.createExpression(str).evaluate(exchange, Object.class);
                 }
                 query.setParameter(key, resolvedValue);
             });
+        } else {
+            Map<String, ?> params = 
exchange.getIn().getHeader(JpaConstants.JPA_PARAMETERS_HEADER, Map.class);
+            if (params != null) {
+                params.forEach(query::setParameter);
+            }
         }
     }
 
diff --git 
a/components/camel-jpa/src/test/java/org/apache/camel/processor/jpa/JpaProducerWithQueryParametersHeaderTest.java
 
b/components/camel-jpa/src/test/java/org/apache/camel/processor/jpa/JpaProducerWithQueryParametersHeaderTest.java
index 4ee30bfb0be3..1ff35a4c9fa4 100644
--- 
a/components/camel-jpa/src/test/java/org/apache/camel/processor/jpa/JpaProducerWithQueryParametersHeaderTest.java
+++ 
b/components/camel-jpa/src/test/java/org/apache/camel/processor/jpa/JpaProducerWithQueryParametersHeaderTest.java
@@ -46,17 +46,27 @@ public class JpaProducerWithQueryParametersHeaderTest {
         Customer c2 = new Customer();
         c2.setName("Dummy");
         template.sendBody("direct:addCustomer", c2);
+        Customer c3 = new Customer();
+        c3.setName("${body}");
+        template.sendBody("direct:addCustomer", c3);
 
         Map<String, Object> params = new HashMap<>();
-        params.put("custName", "${body}");
+        params.put("custName", "Willem");
 
-        List list = template.requestBodyAndHeader("direct:namedQuery", 
"Willem", JpaConstants.JPA_PARAMETERS_HEADER, params,
+        List list = template.requestBodyAndHeader("direct:namedQuery", "foo", 
JpaConstants.JPA_PARAMETERS_HEADER, params,
                 List.class);
         assertEquals(1, list.size());
         assertEquals("Willem", ((Customer) list.get(0)).getName());
 
+        // String parameter values in header must be treated literally and not 
evaluated as Simple expressions
+        params.put("custName", "${body}");
+        list = template.requestBodyAndHeader("direct:namedQuery", "Willem", 
JpaConstants.JPA_PARAMETERS_HEADER, params,
+                List.class);
+        assertEquals(1, list.size());
+        assertEquals("${body}", ((Customer) list.get(0)).getName());
+
         int integer = template.requestBody("direct:deleteCustomers", null, 
int.class);
-        assertEquals(2, integer);
+        assertEquals(3, integer);
     }
 
     @BeforeEach
diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc
index 75842677ea21..61d16611ad0f 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc
@@ -11,6 +11,16 @@ Note that manual migration is still required.
 See the xref:camel-upgrade-recipes-tool.adoc[documentation] page for details.
 ====
 
+== Upgrading from 4.22.3 to 4.22.4
+
+=== camel-jpa - query parameters from CamelJpaParameters header are bound 
literally
+
+In previous versions, string values supplied in the `CamelJpaParameters` 
header map were evaluated as Simple expressions by the JPA producer.
+
+Starting in 4.22.4, parameter values provided via the `CamelJpaParameters` 
header are used as-is and bound literally as query parameters without 
expression evaluation. The endpoint URI option `parameters` continues to 
support Simple expression evaluation for route-configured parameters.
+
+Routes that previously relied on evaluating Simple expressions within the 
`CamelJpaParameters` header should evaluate those expressions in the route 
before setting the header value.
+
 == Upgrading from 4.22.2 to 4.22.3
 
 === camel-as2 - server/listen - signature and MIC over the message as received
diff --git 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/JpaEndpointBuilderFactory.java
 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/JpaEndpointBuilderFactory.java
index 84096d374ac2..a057578ec82b 100644
--- 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/JpaEndpointBuilderFactory.java
+++ 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/JpaEndpointBuilderFactory.java
@@ -2273,6 +2273,7 @@ public interface JpaEndpointBuilderFactory {
         }
         /**
          * Alternative way for passing query parameters as an Exchange header.
+         * The parameter values are used as-is without expression evaluation.
          * 
          * The option is a: {@code Map<String, Object>} type.
          * 

Reply via email to