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

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


The following commit(s) were added to refs/heads/main by this push:
     new 56ec4ca59d3 NIFI-16421 Fixed ConsumeMQTT loses the in-flight message 
on reconnect… (#11780)
56ec4ca59d3 is described below

commit 56ec4ca59d3710faf3f4159b3b3a1761cafb1b86
Author: Peter Turcsanyi <[email protected]>
AuthorDate: Fri Oct 9 11:54:09 2026 +0200

    NIFI-16421 Fixed ConsumeMQTT loses the in-flight message on reconnect… 
(#11780)
    
    * NIFI-16421 Fixed ConsumeMQTT loses the in-flight message on reconnect 
with Resume Session
---
 .../apache/nifi/processors/mqtt/ConsumeMQTT.java   |  3 ++-
 .../mqtt/adapters/HiveMqV5ClientAdapter.java       | 25 ++++++++++++----------
 .../mqtt/adapters/PahoMqttClientAdapter.java       | 11 +++++++---
 .../nifi/processors/mqtt/common/MqttClient.java    | 11 ++++++++--
 .../nifi/processors/mqtt/TestConsumeMQTT.java      | 19 ++++++++++++++++
 .../processors/mqtt/common/MqttTestClient.java     |  6 +++++-
 6 files changed, 57 insertions(+), 18 deletions(-)

diff --git 
a/nifi-extension-bundles/nifi-mqtt-bundle/nifi-mqtt-processors/src/main/java/org/apache/nifi/processors/mqtt/ConsumeMQTT.java
 
b/nifi-extension-bundles/nifi-mqtt-bundle/nifi-mqtt-processors/src/main/java/org/apache/nifi/processors/mqtt/ConsumeMQTT.java
index 7763eb8a4c9..4faa1d005b2 100644
--- 
a/nifi-extension-bundles/nifi-mqtt-bundle/nifi-mqtt-processors/src/main/java/org/apache/nifi/processors/mqtt/ConsumeMQTT.java
+++ 
b/nifi-extension-bundles/nifi-mqtt-bundle/nifi-mqtt-processors/src/main/java/org/apache/nifi/processors/mqtt/ConsumeMQTT.java
@@ -388,8 +388,9 @@ public class ConsumeMQTT extends AbstractMQTTProcessor {
         // non-null but not connected, so we need to handle each case and only 
create a new client when it is null
         try {
             mqttClient = createMqttClient();
+            mqttClient.setReceivedMessageHandler(this::handleReceivedMessage);
             mqttClient.connect();
-            mqttClient.subscribe(topicPrefix + topicFilter, qos, 
this::handleReceivedMessage);
+            mqttClient.subscribe(topicPrefix + topicFilter, qos);
         } catch (Exception e) {
             logger.error("Connection failed to {}. Yielding processor", 
clientProperties.getRawBrokerUris(), e);
             mqttClient = null; // prevent stuck processor when subscribe fails
diff --git 
a/nifi-extension-bundles/nifi-mqtt-bundle/nifi-mqtt-processors/src/main/java/org/apache/nifi/processors/mqtt/adapters/HiveMqV5ClientAdapter.java
 
b/nifi-extension-bundles/nifi-mqtt-bundle/nifi-mqtt-processors/src/main/java/org/apache/nifi/processors/mqtt/adapters/HiveMqV5ClientAdapter.java
index 8894bbbef49..fc892cda5a8 100644
--- 
a/nifi-extension-bundles/nifi-mqtt-bundle/nifi-mqtt-processors/src/main/java/org/apache/nifi/processors/mqtt/adapters/HiveMqV5ClientAdapter.java
+++ 
b/nifi-extension-bundles/nifi-mqtt-bundle/nifi-mqtt-processors/src/main/java/org/apache/nifi/processors/mqtt/adapters/HiveMqV5ClientAdapter.java
@@ -16,6 +16,7 @@
  */
 package org.apache.nifi.processors.mqtt.adapters;
 
+import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
 import com.hivemq.client.mqtt.datatypes.MqttQos;
 import com.hivemq.client.mqtt.mqtt5.Mqtt5BlockingClient;
 import com.hivemq.client.mqtt.mqtt5.Mqtt5Client;
@@ -128,24 +129,14 @@ public class HiveMqV5ClientAdapter implements MqttClient {
     }
 
     @Override
-    public void subscribe(String topicFilter, int qos, 
ReceivedMqttMessageHandler handler) {
+    public void subscribe(String topicFilter, int qos) {
         logger.debug("Subscribing to {} with QoS: {}", topicFilter, qos);
 
         CompletableFuture<Mqtt5SubAck> futureAck = 
mqtt5BlockingClient.toAsync().subscribeWith()
                 .topicFilter(topicFilter)
                 .qos(Objects.requireNonNull(MqttQos.fromCode(qos)))
-                .callback(mqtt5Publish -> {
-                    final ReceivedMqttMessage receivedMessage = new 
ReceivedMqttMessage(
-                            mqtt5Publish.getPayloadAsBytes(),
-                            mqtt5Publish.getQos().getCode(),
-                            mqtt5Publish.isRetain(),
-                            mqtt5Publish.getTopic().toString());
-                    handler.handleReceivedMessage(receivedMessage);
-                })
                 .send();
 
-        // Setting "listener" callback is only possible with async client, 
though sending subscribe message
-        // should happen in a blocking way to make sure the processor is 
blocked until ack is not arrived.
         try {
             final Mqtt5SubAck ack = 
futureAck.get(clientProperties.getConnectionTimeout(), TimeUnit.SECONDS);
             logger.debug("Received mqtt5 subscribe ack: {}", ack);
@@ -154,6 +145,18 @@ public class HiveMqV5ClientAdapter implements MqttClient {
         }
     }
 
+    @Override
+    public void setReceivedMessageHandler(ReceivedMqttMessageHandler handler) {
+        mqtt5BlockingClient.toAsync().publishes(MqttGlobalPublishFilter.ALL, 
mqtt5Publish -> {
+            final ReceivedMqttMessage receivedMessage = new 
ReceivedMqttMessage(
+                    mqtt5Publish.getPayloadAsBytes(),
+                    mqtt5Publish.getQos().getCode(),
+                    mqtt5Publish.isRetain(),
+                    mqtt5Publish.getTopic().toString());
+            handler.handleReceivedMessage(receivedMessage);
+        });
+    }
+
     private static Mqtt5BlockingClient createClient(URI brokerUri, 
MqttClientProperties clientProperties, ComponentLog logger) throws TlsException 
{
         logger.debug("Creating Mqtt v5 client");
 
diff --git 
a/nifi-extension-bundles/nifi-mqtt-bundle/nifi-mqtt-processors/src/main/java/org/apache/nifi/processors/mqtt/adapters/PahoMqttClientAdapter.java
 
b/nifi-extension-bundles/nifi-mqtt-bundle/nifi-mqtt-processors/src/main/java/org/apache/nifi/processors/mqtt/adapters/PahoMqttClientAdapter.java
index ddef128eb94..96cd82159e2 100644
--- 
a/nifi-extension-bundles/nifi-mqtt-bundle/nifi-mqtt-processors/src/main/java/org/apache/nifi/processors/mqtt/adapters/PahoMqttClientAdapter.java
+++ 
b/nifi-extension-bundles/nifi-mqtt-bundle/nifi-mqtt-processors/src/main/java/org/apache/nifi/processors/mqtt/adapters/PahoMqttClientAdapter.java
@@ -123,11 +123,9 @@ public class PahoMqttClientAdapter implements MqttClient {
     }
 
     @Override
-    public void subscribe(String topicFilter, int qos, 
ReceivedMqttMessageHandler handler) {
+    public void subscribe(String topicFilter, int qos) {
         logger.debug("Subscribing to {} with QoS: {}", topicFilter, qos);
 
-        client.setCallback(new ConsumerMqttCallback(handler));
-
         try {
             client.subscribe(topicFilter, qos);
         } catch (org.eclipse.paho.client.mqttv3.MqttException e) {
@@ -135,6 +133,13 @@ public class PahoMqttClientAdapter implements MqttClient {
         }
     }
 
+    @Override
+    public void setReceivedMessageHandler(ReceivedMqttMessageHandler handler) {
+        logger.debug("Registering received message handler");
+
+        client.setCallback(new ConsumerMqttCallback(handler));
+    }
+
     private static org.eclipse.paho.client.mqttv3.MqttClient createClient(URI 
brokerUri, MqttClientProperties clientProperties, ComponentLog logger) {
         logger.debug("Creating Mqtt v3 client");
 
diff --git 
a/nifi-extension-bundles/nifi-mqtt-bundle/nifi-mqtt-processors/src/main/java/org/apache/nifi/processors/mqtt/common/MqttClient.java
 
b/nifi-extension-bundles/nifi-mqtt-bundle/nifi-mqtt-processors/src/main/java/org/apache/nifi/processors/mqtt/common/MqttClient.java
index 2b5c949531d..7c0a9376c26 100644
--- 
a/nifi-extension-bundles/nifi-mqtt-bundle/nifi-mqtt-processors/src/main/java/org/apache/nifi/processors/mqtt/common/MqttClient.java
+++ 
b/nifi-extension-bundles/nifi-mqtt-bundle/nifi-mqtt-processors/src/main/java/org/apache/nifi/processors/mqtt/common/MqttClient.java
@@ -57,7 +57,14 @@ public interface MqttClient {
      *            published at a lower quality of service will be received at 
the published
      *            QoS. Messages published at a higher quality of service will 
be received using
      *            the QoS specified on the subscribe.
-     * @param handler that further processes the message received by the client
      */
-    void subscribe(String topicFilter, int qos, ReceivedMqttMessageHandler 
handler);
+    void subscribe(String topicFilter, int qos);
+
+    /**
+     * Sets the handler to process received MQTT messages.
+     * It must be set before the client is connected to the broker, otherwise 
messages may be lost when a persistent session is used.
+     *
+     * @param handler the handler to process received MQTT messages
+     */
+    void setReceivedMessageHandler(ReceivedMqttMessageHandler handler);
 }
diff --git 
a/nifi-extension-bundles/nifi-mqtt-bundle/nifi-mqtt-processors/src/test/java/org/apache/nifi/processors/mqtt/TestConsumeMQTT.java
 
b/nifi-extension-bundles/nifi-mqtt-bundle/nifi-mqtt-processors/src/test/java/org/apache/nifi/processors/mqtt/TestConsumeMQTT.java
index ce3eed059e0..97d986b138b 100644
--- 
a/nifi-extension-bundles/nifi-mqtt-bundle/nifi-mqtt-processors/src/test/java/org/apache/nifi/processors/mqtt/TestConsumeMQTT.java
+++ 
b/nifi-extension-bundles/nifi-mqtt-bundle/nifi-mqtt-processors/src/test/java/org/apache/nifi/processors/mqtt/TestConsumeMQTT.java
@@ -647,6 +647,25 @@ public class TestConsumeMQTT {
         assertTrue(mqttQueue.contains(mock));
     }
 
+    @Test
+    void testConsumeMessageDeliveredOnConnect() throws Exception {
+        mqttTestClient = new 
MqttTestClient(MqttTestClient.ConnectType.Subscriber) {
+            @Override
+            public void connect() {
+                super.connect();
+                publishMessage(STRING_MESSAGE, AT_LEAST_ONCE);
+            }
+        };
+        testRunner = initializeTestRunner(mqttTestClient);
+
+        testRunner.run();
+
+        final List<MockFlowFile> flowFiles = 
testRunner.getFlowFilesForRelationship(ConsumeMQTT.REL_MESSAGE);
+        assertEquals(1, flowFiles.size());
+        final MockFlowFile flowFile = flowFiles.getFirst();
+        flowFile.assertContentEquals(STRING_MESSAGE);
+    }
+
     @Test
     void addTopicAttributesWithMultipleTopicSegments() {
         final String topic = "home/livingroom/temperature";
diff --git 
a/nifi-extension-bundles/nifi-mqtt-bundle/nifi-mqtt-processors/src/test/java/org/apache/nifi/processors/mqtt/common/MqttTestClient.java
 
b/nifi-extension-bundles/nifi-mqtt-bundle/nifi-mqtt-processors/src/test/java/org/apache/nifi/processors/mqtt/common/MqttTestClient.java
index 3941bedf8a8..c69e48906f2 100644
--- 
a/nifi-extension-bundles/nifi-mqtt-bundle/nifi-mqtt-processors/src/test/java/org/apache/nifi/processors/mqtt/common/MqttTestClient.java
+++ 
b/nifi-extension-bundles/nifi-mqtt-bundle/nifi-mqtt-processors/src/test/java/org/apache/nifi/processors/mqtt/common/MqttTestClient.java
@@ -73,9 +73,13 @@ public class MqttTestClient implements MqttClient {
     }
 
     @Override
-    public void subscribe(String topicFilter, int qos, 
ReceivedMqttMessageHandler handler) {
+    public void subscribe(String topicFilter, int qos) {
         subscribedTopic = topicFilter;
         subscribedQos = qos;
+    }
+
+    @Override
+    public void setReceivedMessageHandler(ReceivedMqttMessageHandler handler) {
         receivedMqttMessageHandler = handler;
     }
 

Reply via email to