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 51c03c533f3d CAMEL-26264: camel-consul - fire an event without body, 
no Optional in the body, and CamelConsulResult for every action (#29104)
51c03c533f3d is described below

commit 51c03c533f3d0635f7897205db2ee7c73897100d
Author: Claus Ibsen <[email protected]>
AuthorDate: Wed Nov 4 19:59:29 2026 +0100

    CAMEL-26264: camel-consul - fire an event without body, no Optional in the 
body, and CamelConsulResult for every action (#29104)
    
    - CAMEL-26264: camel-consul - fire an event without body, no Optional in 
the body, and CamelConsulResult for every action
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../apache/camel/catalog/components/consul.json    |   4 +-
 .../ConsulAgentProducerInvokeOnHeaderFactory.java  |   8 +-
 .../ConsulStatusProducerInvokeOnHeaderFactory.java |   4 +-
 .../org/apache/camel/component/consul/consul.json  |   4 +-
 .../camel/component/consul/ConsulEndpoint.java     |  22 ++-
 .../consul/endpoint/ConsulAgentProducer.java       |  18 +-
 .../consul/endpoint/ConsulCatalogProducer.java     |   4 +-
 .../consul/endpoint/ConsulEventProducer.java       |  15 +-
 .../consul/endpoint/ConsulKeyValueProducer.java    |   3 +-
 .../endpoint/ConsulPreparedQueryProducer.java      |   4 +-
 .../consul/endpoint/ConsulSessionProducer.java     |   5 +-
 .../consul/endpoint/ConsulStatusProducer.java      |   8 +-
 .../component/consul/ConsulProducerResultTest.java | 210 +++++++++++++++++++++
 .../ROOT/pages/camel-4x-upgrade-guide-4_24.adoc    |  14 ++
 14 files changed, 280 insertions(+), 43 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/consul.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/consul.json
index 5e1b82d6b738..2a6518e65be3 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/consul.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/consul.json
@@ -86,8 +86,8 @@
   },
   "bodyTypes": {
     "consumerOut": { "carriers": [ "text", "null" ], "description": "The kv 
consumer: the value of the key (of each key under it with recursive) base64 
encoded as Consul stores it, decoded with valueAsString=true, with the key, 
flags and indexes in headers; null for a key without value. The event consumer: 
the payload of the event as text, with its name and id in headers" },
-    "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": "action", 
"value": "PUT", "carriers": [ "text", "bytes", "stream", "file", "value", 
"null" ] }, { "option": "action", "value": "LOCK", "carriers": [ "text", 
"bytes", "stream", "file", "value", "null" ] }, { "option": "action", "value": 
"FIRE", "carriers": [ "text", "bytes", "stream", "file", "value" ] }, { 
"option": "action", "value": "REGISTER", "carriers": [ "pojo" ] }, { "option": 
"action", "value": "CREATE", "carrie [...]
-    "producerOut": { "carriers": [ "pojo", "list", "map", "text", "unchanged" 
], "byOption": [ { "option": "action", "value": "CHECKS", "carriers": [ "map", 
"list" ] }, { "option": "action", "value": "SERVICES", "carriers": [ "map" ] }, 
{ "option": "action", "value": "MEMBERS", "carriers": [ "list" ] }, { "option": 
"action", "value": "AGENT", "carriers": [ "pojo" ], "javaType": 
"org.kiwiproject.consul.model.agent.Agent" }, { "option": "action", "value": 
"REGISTER", "carriers": [ "unchang [...]
+    "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": "action", 
"value": "PUT", "carriers": [ "text", "bytes", "stream", "file", "value", 
"null" ] }, { "option": "action", "value": "LOCK", "carriers": [ "text", 
"bytes", "stream", "file", "value", "null" ] }, { "option": "action", "value": 
"FIRE", "carriers": [ "text", "bytes", "stream", "file", "value", "null" ] }, { 
"option": "action", "value": "REGISTER", "carriers": [ "pojo" ] }, { "option": 
"action", "value": "CREATE", [...]
+    "producerOut": { "carriers": [ "pojo", "list", "map", "text", "unchanged" 
], "byOption": [ { "option": "action", "value": "CHECKS", "carriers": [ "map", 
"list" ] }, { "option": "action", "value": "SERVICES", "carriers": [ "map" ] }, 
{ "option": "action", "value": "MEMBERS", "carriers": [ "list" ] }, { "option": 
"action", "value": "AGENT", "carriers": [ "pojo" ], "javaType": 
"org.kiwiproject.consul.model.agent.Agent" }, { "option": "action", "value": 
"REGISTER", "carriers": [ "unchang [...]
   },
   "properties": {
     "apiEndpoint": { "index": 0, "kind": "path", "displayName": "Api 
Endpoint", "group": "common", "label": "", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The API endpoint" },
diff --git 
a/components/camel-consul/src/generated/java/org/apache/camel/component/consul/endpoint/ConsulAgentProducerInvokeOnHeaderFactory.java
 
b/components/camel-consul/src/generated/java/org/apache/camel/component/consul/endpoint/ConsulAgentProducerInvokeOnHeaderFactory.java
index 952cf410e234..6a039b46350c 100644
--- 
a/components/camel-consul/src/generated/java/org/apache/camel/component/consul/endpoint/ConsulAgentProducerInvokeOnHeaderFactory.java
+++ 
b/components/camel-consul/src/generated/java/org/apache/camel/component/consul/endpoint/ConsulAgentProducerInvokeOnHeaderFactory.java
@@ -20,17 +20,17 @@ public class ConsulAgentProducerInvokeOnHeaderFactory 
implements InvokeOnHeaderS
         org.apache.camel.component.consul.endpoint.ConsulAgentProducer target 
= (org.apache.camel.component.consul.endpoint.ConsulAgentProducer) obj;
         switch (key) {
         case "agent":
-        case "AGENT": return target.invokeAgent(exchange.getMessage());
+        case "AGENT": target.invokeAgent(exchange.getMessage()); return null;
         case "checks":
-        case "CHECKS": return target.invokeChecks(exchange.getMessage());
+        case "CHECKS": target.invokeChecks(exchange.getMessage()); return null;
         case "deregister":
         case "DEREGISTER": target.invokeDeregister(exchange.getMessage()); 
return null;
         case "members":
-        case "MEMBERS": return target.invokeMembers(exchange.getMessage());
+        case "MEMBERS": target.invokeMembers(exchange.getMessage()); return 
null;
         case "register":
         case "REGISTER": target.invokeRegister(exchange.getMessage()); return 
null;
         case "services":
-        case "SERVICES": return target.invokeServices(exchange.getMessage());
+        case "SERVICES": target.invokeServices(exchange.getMessage()); return 
null;
         default: return InvokeOnHeaderStrategy.NO_METHOD;
         }
     }
diff --git 
a/components/camel-consul/src/generated/java/org/apache/camel/component/consul/endpoint/ConsulStatusProducerInvokeOnHeaderFactory.java
 
b/components/camel-consul/src/generated/java/org/apache/camel/component/consul/endpoint/ConsulStatusProducerInvokeOnHeaderFactory.java
index 7fcecb1871a4..32cc476de20d 100644
--- 
a/components/camel-consul/src/generated/java/org/apache/camel/component/consul/endpoint/ConsulStatusProducerInvokeOnHeaderFactory.java
+++ 
b/components/camel-consul/src/generated/java/org/apache/camel/component/consul/endpoint/ConsulStatusProducerInvokeOnHeaderFactory.java
@@ -20,9 +20,9 @@ public class ConsulStatusProducerInvokeOnHeaderFactory 
implements InvokeOnHeader
         org.apache.camel.component.consul.endpoint.ConsulStatusProducer target 
= (org.apache.camel.component.consul.endpoint.ConsulStatusProducer) obj;
         switch (key) {
         case "leader":
-        case "LEADER": return target.invokeChecks(exchange.getMessage());
+        case "LEADER": target.invokeChecks(exchange.getMessage()); return null;
         case "peers":
-        case "PEERS": return target.invokePeers(exchange.getMessage());
+        case "PEERS": target.invokePeers(exchange.getMessage()); return null;
         default: return InvokeOnHeaderStrategy.NO_METHOD;
         }
     }
diff --git 
a/components/camel-consul/src/generated/resources/META-INF/org/apache/camel/component/consul/consul.json
 
b/components/camel-consul/src/generated/resources/META-INF/org/apache/camel/component/consul/consul.json
index 5e1b82d6b738..2a6518e65be3 100644
--- 
a/components/camel-consul/src/generated/resources/META-INF/org/apache/camel/component/consul/consul.json
+++ 
b/components/camel-consul/src/generated/resources/META-INF/org/apache/camel/component/consul/consul.json
@@ -86,8 +86,8 @@
   },
   "bodyTypes": {
     "consumerOut": { "carriers": [ "text", "null" ], "description": "The kv 
consumer: the value of the key (of each key under it with recursive) base64 
encoded as Consul stores it, decoded with valueAsString=true, with the key, 
flags and indexes in headers; null for a key without value. The event consumer: 
the payload of the event as text, with its name and id in headers" },
-    "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": "action", 
"value": "PUT", "carriers": [ "text", "bytes", "stream", "file", "value", 
"null" ] }, { "option": "action", "value": "LOCK", "carriers": [ "text", 
"bytes", "stream", "file", "value", "null" ] }, { "option": "action", "value": 
"FIRE", "carriers": [ "text", "bytes", "stream", "file", "value" ] }, { 
"option": "action", "value": "REGISTER", "carriers": [ "pojo" ] }, { "option": 
"action", "value": "CREATE", "carrie [...]
-    "producerOut": { "carriers": [ "pojo", "list", "map", "text", "unchanged" 
], "byOption": [ { "option": "action", "value": "CHECKS", "carriers": [ "map", 
"list" ] }, { "option": "action", "value": "SERVICES", "carriers": [ "map" ] }, 
{ "option": "action", "value": "MEMBERS", "carriers": [ "list" ] }, { "option": 
"action", "value": "AGENT", "carriers": [ "pojo" ], "javaType": 
"org.kiwiproject.consul.model.agent.Agent" }, { "option": "action", "value": 
"REGISTER", "carriers": [ "unchang [...]
+    "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": "action", 
"value": "PUT", "carriers": [ "text", "bytes", "stream", "file", "value", 
"null" ] }, { "option": "action", "value": "LOCK", "carriers": [ "text", 
"bytes", "stream", "file", "value", "null" ] }, { "option": "action", "value": 
"FIRE", "carriers": [ "text", "bytes", "stream", "file", "value", "null" ] }, { 
"option": "action", "value": "REGISTER", "carriers": [ "pojo" ] }, { "option": 
"action", "value": "CREATE", [...]
+    "producerOut": { "carriers": [ "pojo", "list", "map", "text", "unchanged" 
], "byOption": [ { "option": "action", "value": "CHECKS", "carriers": [ "map", 
"list" ] }, { "option": "action", "value": "SERVICES", "carriers": [ "map" ] }, 
{ "option": "action", "value": "MEMBERS", "carriers": [ "list" ] }, { "option": 
"action", "value": "AGENT", "carriers": [ "pojo" ], "javaType": 
"org.kiwiproject.consul.model.agent.Agent" }, { "option": "action", "value": 
"REGISTER", "carriers": [ "unchang [...]
   },
   "properties": {
     "apiEndpoint": { "index": 0, "kind": "path", "displayName": "Api 
Endpoint", "group": "common", "label": "", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The API endpoint" },
diff --git 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulEndpoint.java
 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulEndpoint.java
index 798e4155ea8c..3a4987f393e1 100644
--- 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulEndpoint.java
+++ 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulEndpoint.java
@@ -54,12 +54,13 @@ import org.kiwiproject.consul.Consul;
                                                                  Carrier.TEXT, 
Carrier.BYTES, Carrier.STREAM, Carrier.FILE,
                                                                  
Carrier.VALUE, Carrier.NULL }),
                                           @BodyType.When(option = "action", 
value = "FIRE", carriers = {
-                                                  Carrier.TEXT, Carrier.BYTES, 
Carrier.STREAM, Carrier.FILE, Carrier.VALUE }),
+                                                  Carrier.TEXT, Carrier.BYTES, 
Carrier.STREAM, Carrier.FILE, Carrier.VALUE,
+                                                  Carrier.NULL }),
                                           @BodyType.When(option = "action", 
value = "REGISTER", carriers = Carrier.POJO),
                                           @BodyType.When(option = "action", 
value = "CREATE", carriers = Carrier.POJO) },
                                   description = "PUT and LOCK store the body 
converted to text as the value, and FIRE sends it"
-                                                + " as the payload: a Map or a 
POJO is stored as its toString, so marshal it"
-                                                + " first. REGISTER, 
DEREGISTER of catalog and CREATE take the model object of"
+                                                + " as the payload (an event 
without payload for a null body): a Map or a POJO"
+                                                + " is stored as its toString, 
so marshal it first. REGISTER, DEREGISTER of catalog and CREATE take the model 
object of"
                                                 + " the Consul client, such as 
a Registration or a Session; the session and"
                                                 + " prepared query actions 
read the id from the body when its header is not set;"
                                                 + " the other actions take 
their input from headers"),
@@ -79,8 +80,9 @@ import org.kiwiproject.consul.Consul;
                                                           carriers = { 
Carrier.POJO, Carrier.TEXT, Carrier.UNCHANGED }),
                                            @BodyType.When(option = "action", 
value = "GET_VALUES", carriers = Carrier.LIST),
                                            @BodyType.When(option = "action", 
value = "GET_KEYS", carriers = Carrier.LIST),
-                                           @BodyType.When(option = "action", 
value = "GET_SESSIONS", carriers = Carrier.POJO,
-                                                          javaType = 
"java.util.Optional<java.lang.String>"),
+                                           @BodyType.When(option = "action", 
value = "GET_SESSIONS",
+                                                          carriers = { 
Carrier.TEXT, Carrier.UNCHANGED },
+                                                          javaType = 
"java.lang.String"),
                                            @BodyType.When(option = "action", 
value = "DELETE_KEY",
                                                           carriers = 
Carrier.UNCHANGED),
                                            @BodyType.When(option = "action", 
value = "DELETE_KEYS",
@@ -105,10 +107,12 @@ import org.kiwiproject.consul.Consul;
                                                           carriers = { 
Carrier.POJO, Carrier.UNCHANGED }),
                                            @BodyType.When(option = "action", 
value = "LIST",
                                                           carriers = { 
Carrier.POJO, Carrier.LIST }),
-                                           @BodyType.When(option = "action", 
value = "RENEW", carriers = Carrier.POJO,
-                                                          javaType = 
"java.util.Optional<org.kiwiproject.consul.model.session.SessionInfo>"),
-                                           @BodyType.When(option = "action", 
value = "GET", carriers = Carrier.POJO,
-                                                          javaType = 
"java.util.Optional<org.kiwiproject.consul.model.query.StoredQuery>"),
+                                           @BodyType.When(option = "action", 
value = "RENEW",
+                                                          carriers = { 
Carrier.POJO, Carrier.UNCHANGED },
+                                                          javaType = 
"org.kiwiproject.consul.model.session.SessionInfo"),
+                                           @BodyType.When(option = "action", 
value = "GET",
+                                                          carriers = { 
Carrier.POJO, Carrier.UNCHANGED },
+                                                          javaType = 
"org.kiwiproject.consul.model.query.StoredQuery"),
                                            @BodyType.When(option = "action", 
value = "EXECUTE", carriers = Carrier.POJO,
                                                           javaType = 
"org.kiwiproject.consul.model.query.QueryResults"),
                                            @BodyType.When(option = "action", 
value = "FIRE", carriers = Carrier.POJO,
diff --git 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulAgentProducer.java
 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulAgentProducer.java
index e9e1ead1fc17..648b6dddd4c1 100644
--- 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulAgentProducer.java
+++ 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulAgentProducer.java
@@ -32,34 +32,36 @@ public final class ConsulAgentProducer extends 
AbstractConsulProducer<AgentClien
     }
 
     @InvokeOnHeader("CHECKS")
-    public Object invokeChecks(Message message) throws Exception {
-        return getClient().getChecks();
+    public void invokeChecks(Message message) throws Exception {
+        setBodyAndResult(message, getClient().getChecks());
     }
 
     @InvokeOnHeader("SERVICES")
-    public Object invokeServices(Message message) throws Exception {
-        return getClient().getServices();
+    public void invokeServices(Message message) throws Exception {
+        setBodyAndResult(message, getClient().getServices());
     }
 
     @InvokeOnHeader("MEMBERS")
-    public Object invokeMembers(Message message) throws Exception {
-        return getClient().getMembers();
+    public void invokeMembers(Message message) throws Exception {
+        setBodyAndResult(message, getClient().getMembers());
     }
 
     @InvokeOnHeader("AGENT")
-    public Object invokeAgent(Message message) throws Exception {
-        return getClient().getAgent();
+    public void invokeAgent(Message message) throws Exception {
+        setBodyAndResult(message, getClient().getAgent());
     }
 
     @InvokeOnHeader("REGISTER")
     public void invokeRegister(Message message) throws Exception {
         getClient().register(message.getMandatoryBody(Registration.class));
+        setBodyAndResult(message, null, true);
     }
 
     @InvokeOnHeader("DEREGISTER")
     public void invokeDeregister(Message message) throws Exception {
         getClient().deregister(getMandatoryHeader(message, 
ConsulConstants.CONSUL_SERVICE_ID, String.class),
                 buildQueryOptions(message, getConfiguration()));
+        setBodyAndResult(message, null, true);
     }
 
 }
diff --git 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulCatalogProducer.java
 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulCatalogProducer.java
index 7278f8ff6e4f..910e5b0d9c19 100644
--- 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulCatalogProducer.java
+++ 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulCatalogProducer.java
@@ -35,13 +35,13 @@ public final class ConsulCatalogProducer extends 
AbstractConsulProducer<CatalogC
     @InvokeOnHeader(ConsulCatalogActions.REGISTER)
     protected void register(Message message) throws Exception {
         
getClient().register(message.getMandatoryBody(CatalogRegistration.class));
-        setBodyAndResult(message, null);
+        setBodyAndResult(message, null, true);
     }
 
     @InvokeOnHeader(ConsulCatalogActions.DEREGISTER)
     protected void deregister(Message message) throws Exception {
         
getClient().deregister(message.getMandatoryBody(CatalogDeregistration.class));
-        setBodyAndResult(message, null);
+        setBodyAndResult(message, null, true);
     }
 
     @InvokeOnHeader(ConsulCatalogActions.LIST_DATACENTERS)
diff --git 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulEventProducer.java
 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulEventProducer.java
index 472626f22944..8bfa59e14b3c 100644
--- 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulEventProducer.java
+++ 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulEventProducer.java
@@ -34,11 +34,16 @@ public final class ConsulEventProducer extends 
AbstractConsulProducer<EventClien
 
     @InvokeOnHeader(ConsulEventActions.FIRE)
     protected void fire(Message message) throws Exception {
-        setBodyAndResult(message,
-                getClient().fireEvent(
-                        getMandatoryHeader(message, 
ConsulConstants.CONSUL_KEY, getConfiguration().getKey(), String.class),
-                        message.getHeader(ConsulConstants.CONSUL_OPTIONS, 
EventOptions.BLANK, EventOptions.class),
-                        message.getBody(String.class)));
+        String name = getMandatoryHeader(message, ConsulConstants.CONSUL_KEY, 
getConfiguration().getKey(), String.class);
+        EventOptions options = 
message.getHeader(ConsulConstants.CONSUL_OPTIONS, EventOptions.BLANK, 
EventOptions.class);
+        String payload = message.getBody(String.class);
+
+        // the event has no payload when the message has no body
+        if (payload == null) {
+            setBodyAndResult(message, getClient().fireEvent(name, options));
+        } else {
+            setBodyAndResult(message, getClient().fireEvent(name, options, 
payload));
+        }
     }
 
     @InvokeOnHeader(ConsulEventActions.LIST)
diff --git 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulKeyValueProducer.java
 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulKeyValueProducer.java
index 69626d430fb6..fd320a009484 100644
--- 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulKeyValueProducer.java
+++ 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulKeyValueProducer.java
@@ -91,7 +91,8 @@ public final class ConsulKeyValueProducer extends 
AbstractConsulProducer<KeyValu
     @InvokeOnHeader(ConsulKeyValueActions.GET_SESSIONS)
     protected void getSessions(Message message) throws Exception {
         setBodyAndResult(message, getClient().getSession(
-                getMandatoryHeader(message, ConsulConstants.CONSUL_KEY, 
getConfiguration().getKey(), String.class)));
+                getMandatoryHeader(message, ConsulConstants.CONSUL_KEY, 
getConfiguration().getKey(), String.class))
+                .orElse(null));
     }
 
     @InvokeOnHeader(ConsulKeyValueActions.DELETE_KEY)
diff --git 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulPreparedQueryProducer.java
 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulPreparedQueryProducer.java
index 14422a03913b..80568786424f 100644
--- 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulPreparedQueryProducer.java
+++ 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulPreparedQueryProducer.java
@@ -42,9 +42,9 @@ public final class ConsulPreparedQueryProducer extends 
AbstractConsulProducer<Pr
         String id = 
message.getHeader(ConsulConstants.CONSUL_PREPARED_QUERY_ID, String.class);
 
         if (ObjectHelper.isEmpty(id)) {
-            setBodyAndResult(message, 
getClient().getPreparedQuery(message.getMandatoryBody(String.class)));
+            setBodyAndResult(message, 
getClient().getPreparedQuery(message.getMandatoryBody(String.class)).orElse(null));
         } else {
-            setBodyAndResult(message, getClient().getPreparedQuery(id));
+            setBodyAndResult(message, 
getClient().getPreparedQuery(id).orElse(null));
         }
     }
 
diff --git 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulSessionProducer.java
 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulSessionProducer.java
index 9f22f7ad4a19..7225a7674a90 100644
--- 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulSessionProducer.java
+++ 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulSessionProducer.java
@@ -79,10 +79,11 @@ public final class ConsulSessionProducer extends 
AbstractConsulProducer<SessionC
         if (ObjectHelper.isEmpty(sessionId)) {
             setBodyAndResult(message,
                     
getClient().renewSession(message.getHeader(ConsulConstants.CONSUL_DATACENTER, 
String.class),
-                            message.getMandatoryBody(String.class)));
+                            
message.getMandatoryBody(String.class)).orElse(null));
         } else {
             setBodyAndResult(message,
-                    
getClient().renewSession(message.getHeader(ConsulConstants.CONSUL_DATACENTER, 
String.class), sessionId));
+                    
getClient().renewSession(message.getHeader(ConsulConstants.CONSUL_DATACENTER, 
String.class), sessionId)
+                            .orElse(null));
         }
     }
 }
diff --git 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulStatusProducer.java
 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulStatusProducer.java
index c8adf1549573..f557223a8e3b 100644
--- 
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulStatusProducer.java
+++ 
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/endpoint/ConsulStatusProducer.java
@@ -30,13 +30,13 @@ public final class ConsulStatusProducer extends 
AbstractConsulProducer<StatusCli
     }
 
     @InvokeOnHeader("LEADER")
-    public Object invokeChecks(Message message) throws Exception {
-        return getClient().getLeader();
+    public void invokeChecks(Message message) throws Exception {
+        setBodyAndResult(message, getClient().getLeader());
     }
 
     @InvokeOnHeader("PEERS")
-    public Object invokePeers(Message message) throws Exception {
-        return getClient().getPeers();
+    public void invokePeers(Message message) throws Exception {
+        setBodyAndResult(message, getClient().getPeers());
     }
 
 }
diff --git 
a/components/camel-consul/src/test/java/org/apache/camel/component/consul/ConsulProducerResultTest.java
 
b/components/camel-consul/src/test/java/org/apache/camel/component/consul/ConsulProducerResultTest.java
new file mode 100644
index 000000000000..d4ad13b95db5
--- /dev/null
+++ 
b/components/camel-consul/src/test/java/org/apache/camel/component/consul/ConsulProducerResultTest.java
@@ -0,0 +1,210 @@
+/*
+ * 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.consul;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.Exchange;
+import org.apache.camel.component.consul.endpoint.ConsulAgentActions;
+import org.apache.camel.component.consul.endpoint.ConsulCatalogActions;
+import org.apache.camel.component.consul.endpoint.ConsulEventActions;
+import org.apache.camel.component.consul.endpoint.ConsulKeyValueActions;
+import org.apache.camel.component.consul.endpoint.ConsulPreparedQueryActions;
+import org.apache.camel.component.consul.endpoint.ConsulSessionActions;
+import org.apache.camel.component.consul.endpoint.ConsulStatusActions;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+import org.kiwiproject.consul.AgentClient;
+import org.kiwiproject.consul.CatalogClient;
+import org.kiwiproject.consul.Consul;
+import org.kiwiproject.consul.EventClient;
+import org.kiwiproject.consul.KeyValueClient;
+import org.kiwiproject.consul.PreparedQueryClient;
+import org.kiwiproject.consul.SessionClient;
+import org.kiwiproject.consul.StatusClient;
+import org.kiwiproject.consul.model.agent.Registration;
+import org.kiwiproject.consul.model.catalog.CatalogRegistration;
+import org.kiwiproject.consul.model.event.Event;
+import org.kiwiproject.consul.model.health.Service;
+import org.kiwiproject.consul.model.query.StoredQuery;
+import org.kiwiproject.consul.model.session.SessionInfo;
+import org.kiwiproject.consul.option.EventOptions;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * The producers set the response of the Consul client as the body, without 
the Optional of the client, and the outcome
+ * in the CamelConsulResult header.
+ */
+public class ConsulProducerResultTest extends CamelTestSupport {
+
+    private final EventClient eventClient = mock(EventClient.class);
+    private final KeyValueClient keyValueClient = mock(KeyValueClient.class);
+    private final SessionClient sessionClient = mock(SessionClient.class);
+    private final PreparedQueryClient preparedQueryClient = 
mock(PreparedQueryClient.class);
+    private final AgentClient agentClient = mock(AgentClient.class);
+    private final StatusClient statusClient = mock(StatusClient.class);
+    private final CatalogClient catalogClient = mock(CatalogClient.class);
+
+    @BindToRegistry("consul")
+    public Consul consul() {
+        Consul consul = mock(Consul.class);
+        when(consul.eventClient()).thenReturn(eventClient);
+        when(consul.keyValueClient()).thenReturn(keyValueClient);
+        when(consul.sessionClient()).thenReturn(sessionClient);
+        when(consul.preparedQueryClient()).thenReturn(preparedQueryClient);
+        when(consul.agentClient()).thenReturn(agentClient);
+        when(consul.statusClient()).thenReturn(statusClient);
+        when(consul.catalogClient()).thenReturn(catalogClient);
+        return consul;
+    }
+
+    @Test
+    public void testFireWithoutBody() {
+        Event event = mock(Event.class);
+        when(eventClient.fireEvent(eq("my-event"), 
any(EventOptions.class))).thenReturn(event);
+
+        Exchange out = 
send("consul:event?consulClient=#consul&key=my-event&action=" + 
ConsulEventActions.FIRE, null);
+
+        // no payload: the client must not be called with a null payload, 
which fails in okhttp
+        verify(eventClient, never()).fireEvent(anyString(), 
any(EventOptions.class), isNull());
+        assertSame(event, out.getMessage().getBody());
+        assertEquals(true, 
out.getMessage().getHeader(ConsulConstants.CONSUL_RESULT));
+    }
+
+    @Test
+    public void testFireWithBody() {
+        Event event = mock(Event.class);
+        when(eventClient.fireEvent(eq("my-event"), any(EventOptions.class), 
eq("hello"))).thenReturn(event);
+
+        Exchange out = 
send("consul:event?consulClient=#consul&key=my-event&action=" + 
ConsulEventActions.FIRE, "hello");
+
+        assertSame(event, out.getMessage().getBody());
+        assertEquals(true, 
out.getMessage().getHeader(ConsulConstants.CONSUL_RESULT));
+    }
+
+    @Test
+    public void testGetSessions() {
+        
when(keyValueClient.getSession("locked")).thenReturn(Optional.of("session-1"));
+        when(keyValueClient.getSession("free")).thenReturn(Optional.empty());
+
+        Exchange out = 
send("consul:kv?consulClient=#consul&key=locked&action=" + 
ConsulKeyValueActions.GET_SESSIONS,
+                "input");
+        assertEquals("session-1", out.getMessage().getBody());
+        assertEquals(true, 
out.getMessage().getHeader(ConsulConstants.CONSUL_RESULT));
+
+        out = send("consul:kv?consulClient=#consul&key=free&action=" + 
ConsulKeyValueActions.GET_SESSIONS, "input");
+        assertEquals("input", out.getMessage().getBody());
+        assertEquals(false, 
out.getMessage().getHeader(ConsulConstants.CONSUL_RESULT));
+    }
+
+    @Test
+    public void testRenewSession() {
+        SessionInfo info = mock(SessionInfo.class);
+        when(sessionClient.renewSession(isNull(), 
eq("session-1"))).thenReturn(Optional.of(info));
+        when(sessionClient.renewSession(isNull(), 
eq("session-2"))).thenReturn(Optional.empty());
+
+        Exchange out = send("consul:session?consulClient=#consul&action=" + 
ConsulSessionActions.RENEW, "session-1");
+        assertSame(info, out.getMessage().getBody());
+        assertEquals(true, 
out.getMessage().getHeader(ConsulConstants.CONSUL_RESULT));
+
+        out = send("consul:session?consulClient=#consul&action=" + 
ConsulSessionActions.RENEW, "session-2");
+        assertEquals("session-2", out.getMessage().getBody());
+        assertEquals(false, 
out.getMessage().getHeader(ConsulConstants.CONSUL_RESULT));
+    }
+
+    @Test
+    public void testGetPreparedQuery() {
+        StoredQuery query = mock(StoredQuery.class);
+        
when(preparedQueryClient.getPreparedQuery("query-1")).thenReturn(Optional.of(query));
+        
when(preparedQueryClient.getPreparedQuery("query-2")).thenReturn(Optional.empty());
+
+        Exchange out = 
send("consul:preparedQuery?consulClient=#consul&action=" + 
ConsulPreparedQueryActions.GET,
+                "query-1");
+        assertSame(query, out.getMessage().getBody());
+        assertEquals(true, 
out.getMessage().getHeader(ConsulConstants.CONSUL_RESULT));
+
+        out = send("consul:preparedQuery?consulClient=#consul&action=" + 
ConsulPreparedQueryActions.GET, "query-2");
+        assertEquals("query-2", out.getMessage().getBody());
+        assertEquals(false, 
out.getMessage().getHeader(ConsulConstants.CONSUL_RESULT));
+    }
+
+    @Test
+    public void testAgentActions() {
+        Map<String, Service> services = Map.of("foo", mock(Service.class));
+        when(agentClient.getServices()).thenReturn(services);
+
+        Exchange out = send("consul:agent?consulClient=#consul&action=" + 
ConsulAgentActions.SERVICES, null);
+        assertSame(services, out.getMessage().getBody());
+        assertEquals(true, 
out.getMessage().getHeader(ConsulConstants.CONSUL_RESULT));
+
+        Registration registration = mock(Registration.class);
+        out = send("consul:agent?consulClient=#consul&action=" + 
ConsulAgentActions.REGISTER, registration);
+        verify(agentClient).register(registration);
+        assertSame(registration, out.getMessage().getBody());
+        assertEquals(true, 
out.getMessage().getHeader(ConsulConstants.CONSUL_RESULT));
+
+        out = template.request("consul:agent?consulClient=#consul&action=" + 
ConsulAgentActions.DEREGISTER,
+                e -> 
e.getMessage().setHeader(ConsulConstants.CONSUL_SERVICE_ID, "foo-1"));
+        verify(agentClient).deregister(eq("foo-1"), any());
+        assertEquals(true, 
out.getMessage().getHeader(ConsulConstants.CONSUL_RESULT));
+    }
+
+    @Test
+    public void testStatusActions() {
+        when(statusClient.getLeader()).thenReturn("10.0.0.1:8300");
+        when(statusClient.getPeers()).thenReturn(List.of("10.0.0.1:8300"));
+
+        Exchange out = send("consul:status?consulClient=#consul&action=" + 
ConsulStatusActions.LEADER, null);
+        assertEquals("10.0.0.1:8300", out.getMessage().getBody());
+        assertEquals(true, 
out.getMessage().getHeader(ConsulConstants.CONSUL_RESULT));
+
+        out = send("consul:status?consulClient=#consul&action=" + 
ConsulStatusActions.PEERS, null);
+        assertEquals(List.of("10.0.0.1:8300"), out.getMessage().getBody());
+        assertEquals(true, 
out.getMessage().getHeader(ConsulConstants.CONSUL_RESULT));
+    }
+
+    @Test
+    public void testCatalogRegister() {
+        CatalogRegistration registration = mock(CatalogRegistration.class);
+
+        Exchange out = send("consul:catalog?consulClient=#consul&action=" + 
ConsulCatalogActions.REGISTER, registration);
+
+        verify(catalogClient).register(registration);
+        assertEquals(true, 
out.getMessage().getHeader(ConsulConstants.CONSUL_RESULT));
+    }
+
+    private Exchange send(String uri, Object body) {
+        Exchange out = template.request(uri, e -> 
e.getMessage().setBody(body));
+        if (out.getException() != null) {
+            throw new AssertionError("The exchange failed", 
out.getException());
+        }
+        return out;
+    }
+}
diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
index a0c871966604..d6da752a051d 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
@@ -913,6 +913,20 @@ receives such a body as a `String`.
 A `null` body is now published as a JSON `null` that the subscribed clients 
receive. Before, the message had no data,
 so the clients took it for the reply of a publish and never received it, while 
the exchange succeeded.
 
+=== camel-consul - no Optional in the body, and the CamelConsulResult header 
of every action
+
+The `GET_SESSIONS` action of `consul:kv`, the `RENEW` action of 
`consul:session` and the `GET` action of
+`consul:preparedQuery` set the `java.util.Optional` of the Consul client as 
the body, and the `CamelConsulResult`
+header was always `true`. The body is now the value itself: the session id as 
a `String`, the `SessionInfo` or the
+`StoredQuery`. When there is none, the body is unchanged and 
`CamelConsulResult` is `false`, as with the `INFO` action
+of `consul:session`.
+
+The actions of `consul:agent` and `consul:status` now set the 
`CamelConsulResult` header, as the other actions do.
+`REGISTER` and `DEREGISTER` of `consul:catalog` now set it to `true` instead 
of `false`.
+
+The `FIRE` action of `consul:event` with a message without body failed with a 
`NullPointerException`. It now fires the
+event without payload.
+
 === camel-aws - the HTTP client is no longer looked up on the classpath
 
 The camel-aws components now set the HTTP client of the AWS SDK clients they 
create for their endpoints: the Apache 5

Reply via email to