From 280eb29f628b52162b1de03389c96d65b9cf0342 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Wed, 7 Dec 2022 08:56:40 -0500 Subject: [PATCH] GH-3959: MqttConFailedEvent for normal disconnect (#3961) * GH-3959: MqttConFailedEvent for normal disconnect Fixes https://github.com/spring-projects/spring-integration/issues/3959 The `MqttCallback.disconnected(MqttDisconnectResponse)` in Paho v5 client is also called when server initiates a disconnection. In this case that `MqttDisconnectResponse` does not have a `cause` value * Modify `MqttConnectionFailedEvent` to make a `cause` property optional * Fix `Mqttv5PahoMessageDrivenChannelAdapter` & `Mqttv5PahoMessageHandler` to not check for `cause`, but emit an `MqttConnectionFailedEvent` for any `disconnected()` calls Unfortunately current Paho v3 client does not call `connectionLost()` for normal disconnections and we cannot react for this callback with an `MqttConnectionFailedEvent` **Cherry-pick to `5.5.x`** * Fix language in doc Co-authored-by: Gary Russell Co-authored-by: Gary Russell --- .../mqtt/event/MqttConnectionFailedEvent.java | 15 +++++++++++++-- .../mqtt/event/MqttIntegrationEvent.java | 9 ++++++--- .../Mqttv5PahoMessageDrivenChannelAdapter.java | 2 +- .../mqtt/outbound/Mqttv5PahoMessageHandler.java | 2 +- src/reference/asciidoc/mqtt.adoc | 1 + 5 files changed, 22 insertions(+), 7 deletions(-) diff --git a/spring-integration-mqtt/src/main/java/org/springframework/integration/mqtt/event/MqttConnectionFailedEvent.java b/spring-integration-mqtt/src/main/java/org/springframework/integration/mqtt/event/MqttConnectionFailedEvent.java index 0accc30daa..c337e312e9 100644 --- a/spring-integration-mqtt/src/main/java/org/springframework/integration/mqtt/event/MqttConnectionFailedEvent.java +++ b/spring-integration-mqtt/src/main/java/org/springframework/integration/mqtt/event/MqttConnectionFailedEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,15 +16,26 @@ package org.springframework.integration.mqtt.event; +import org.springframework.lang.Nullable; + /** + * The {@link MqttIntegrationEvent} to notify about lost connection to the server. + * When normal disconnection is happened (initiated by the server), the {@code cause} is null. + * * @author Gary Russell + * @author Artem Bilan + * * @since 4.2.2 * */ @SuppressWarnings("serial") public class MqttConnectionFailedEvent extends MqttIntegrationEvent { - public MqttConnectionFailedEvent(Object source, Throwable cause) { + public MqttConnectionFailedEvent(Object source) { + super(source); + } + + public MqttConnectionFailedEvent(Object source, @Nullable Throwable cause) { super(source, cause); } diff --git a/spring-integration-mqtt/src/main/java/org/springframework/integration/mqtt/event/MqttIntegrationEvent.java b/spring-integration-mqtt/src/main/java/org/springframework/integration/mqtt/event/MqttIntegrationEvent.java index b8cb024774..aeb9f58507 100644 --- a/spring-integration-mqtt/src/main/java/org/springframework/integration/mqtt/event/MqttIntegrationEvent.java +++ b/spring-integration-mqtt/src/main/java/org/springframework/integration/mqtt/event/MqttIntegrationEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,12 +17,15 @@ package org.springframework.integration.mqtt.event; import org.springframework.integration.events.IntegrationEvent; +import org.springframework.lang.Nullable; /** - * Base class for Mqtt Events. For {@link #getSourceAsType()}, you should use a sub type + * Base class for Mqtt Events. For {@link #getSourceAsType()}, you should use a subtype * of {@link org.springframework.integration.mqtt.core.MqttComponent} for the receiving * variable. + * * @author Gary Russell + * @author Artem Bilan * * @since 4.1 */ @@ -33,7 +36,7 @@ public abstract class MqttIntegrationEvent extends IntegrationEvent { super(source); } - public MqttIntegrationEvent(Object source, Throwable cause) { + public MqttIntegrationEvent(Object source, @Nullable Throwable cause) { super(source, cause); } diff --git a/spring-integration-mqtt/src/main/java/org/springframework/integration/mqtt/inbound/Mqttv5PahoMessageDrivenChannelAdapter.java b/spring-integration-mqtt/src/main/java/org/springframework/integration/mqtt/inbound/Mqttv5PahoMessageDrivenChannelAdapter.java index f353028277..62d37815e4 100644 --- a/spring-integration-mqtt/src/main/java/org/springframework/integration/mqtt/inbound/Mqttv5PahoMessageDrivenChannelAdapter.java +++ b/spring-integration-mqtt/src/main/java/org/springframework/integration/mqtt/inbound/Mqttv5PahoMessageDrivenChannelAdapter.java @@ -292,7 +292,7 @@ public class Mqttv5PahoMessageDrivenChannelAdapter extends AbstractMqttMessageDr public void disconnected(MqttDisconnectResponse disconnectResponse) { MqttException cause = disconnectResponse.getException(); ApplicationEventPublisher applicationEventPublisher = getApplicationEventPublisher(); - if (cause != null && applicationEventPublisher != null) { + if (applicationEventPublisher != null) { applicationEventPublisher.publishEvent(new MqttConnectionFailedEvent(this, cause)); } } diff --git a/spring-integration-mqtt/src/main/java/org/springframework/integration/mqtt/outbound/Mqttv5PahoMessageHandler.java b/spring-integration-mqtt/src/main/java/org/springframework/integration/mqtt/outbound/Mqttv5PahoMessageHandler.java index 46908724b6..619569ffd6 100644 --- a/spring-integration-mqtt/src/main/java/org/springframework/integration/mqtt/outbound/Mqttv5PahoMessageHandler.java +++ b/spring-integration-mqtt/src/main/java/org/springframework/integration/mqtt/outbound/Mqttv5PahoMessageHandler.java @@ -274,7 +274,7 @@ public class Mqttv5PahoMessageHandler extends AbstractMqttMessageHandler public void disconnected(MqttDisconnectResponse disconnectResponse) { MqttException cause = disconnectResponse.getException(); ApplicationEventPublisher applicationEventPublisher = getApplicationEventPublisher(); - if (cause != null && applicationEventPublisher != null) { + if (applicationEventPublisher != null) { applicationEventPublisher.publishEvent(new MqttConnectionFailedEvent(this, cause)); } } diff --git a/src/reference/asciidoc/mqtt.adoc b/src/reference/asciidoc/mqtt.adoc index 655b2e0dbb..800aa79828 100644 --- a/src/reference/asciidoc/mqtt.adoc +++ b/src/reference/asciidoc/mqtt.adoc @@ -404,6 +404,7 @@ public class MqttJavaApplication { Certain application events are published by the adapters. * `MqttConnectionFailedEvent` - published by both adapters if we fail to connect or a connection is subsequently lost. +For the MQTT v5 Paho client, this event is also emitted when the server performs a normal disconnection, in which case the `cause` of the lost connection is `null`. * `MqttMessageSentEvent` - published by the outbound adapter when a message has been sent, if running in asynchronous mode. * `MqttMessageDeliveredEvent` - published by the outbound adapter when the client indicates that a message has been delivered, if running in asynchronous mode. * `MqttSubscribedEvent` - published by the inbound adapter after subscribing to the topics.