Spring Integration provides inbound and outbound channel adapters to support the Message Queueing Telemetry Transport (MQTT) protocol.
You need to include this dependency into your project:
Maven.
<dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-mqtt</artifactId> <version>5.1.2.RELEASE</version> </dependency>
Gradle.
compile "org.springframework.integration:spring-integration-mqtt:5.1.2.RELEASE"
The current implementation uses the Eclipse Paho MQTT Client library.
Configuration of both adapters is achieved using the DefaultMqttPahoClientFactory
.
Refer to the Paho documentation for more information about configuration options.
Note | |
---|---|
We recommend configuring an |
The inbound channel adapter is implemented by the MqttPahoMessageDrivenChannelAdapter
.
For convenience, you can configure it by using the namespace.
A minimal configuration might be as follows:
<bean id="clientFactory" class="org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory"> <property name="connectionOptions"> <bean class="org.eclipse.paho.client.mqttv3.MqttConnectOptions"> <property name="userName" value="${mqtt.username}"/> <property name="password" value="${mqtt.password}"/> </bean> </property> </bean> <int-mqtt:message-driven-channel-adapter id="mqttInbound" client-id="${mqtt.default.client.id}.src" url="${mqtt.url}" topics="sometopic" client-factory="clientFactory" channel="output"/>
The following listing shows the available attributes:
<int-mqtt:message-driven-channel-adapter id="oneTopicAdapter" client-id="foo" url="tcp://localhost:1883" topics="bar,baz" qos="1,2" converter="myConverter" client-factory="clientFactory" send-timeout="123" error-channel="errors" recovery-interval="10000" channel="out" />
The client ID. | |
The broker URL. | |
A comma-separated list of topics from which this adapter receives messages. | |
A comma-separated list of QoS values. It can be a single value that is applied to all topics or a value for each topic (in which case, the lists must be the same length). | |
An
| |
The client factory. | |
The send timeout.
It applies only if the channel might block (such as a bounded | |
The error channel.
Downstream exceptions are sent to this channel, if supplied, in an | |
The recovery interval.
It controls the interval at which the adapter attempts to reconnect after a failure. It defaults to |
Note | |
---|---|
Starting with version 4.1, you can omit the URL.
Instead, you can provide the server URIs in the |
Starting with version 4.2.2, an MqttSubscribedEvent
is published when the adapter successfully subscribes to the topics.
MqttConnectionFailedEvent
events are published when the connection or subscription fails.
These events can be received by a bean that implements ApplicationListener
.
Also, a new property called recoveryInterval
controls the interval at which the adapter attempts to reconnect after a failure.
It defaults to 10000ms
(ten seconds).
Note | |
---|---|
Prior to version 4.2.3, the client always unsubscribed when the adapter was stopped.
This was incorrect because, if the client QOS is greater than 0, we need to keep the subscription active so that messages arriving
while the adapter is stopped are delivered on the next start.
This also requires setting the Starting with version 4.2.3, the adapter does not unsubscribe (by default) if the This behavior can be overridden by setting the To revert to the pre-4.2.3 behavior, use |
Important | |
---|---|
Starting with version 5.0, the |
Starting with version 4.1, you can programmatically change the topics to which the adapter is subscribed.
Spring Integration provides the addTopic()
and removeTopic()
methods.
When adding topics, you can optionally specify the QoS
(default: 1).
You can also modify the topics by sending an appropriate message to a <control-bus/>
with an appropriate payload — for example: "myMqttAdapter.addTopic('foo', 1)"
.
Stopping and starting the adapter has no effect on the topic list (it does not revert to the original settings in the configuration). The changes are not retained beyond the life cycle of the application context. A new application context reverts to the configured settings.
Changing the topics while the adapter is stopped (or disconnected from the broker) takes effect the next time a connection is established.
The following Spring Boot application shows an example of how to configure the inbound adapter with Java configuration:
@SpringBootApplication public class MqttJavaApplication { public static void main(String[] args) { new SpringApplicationBuilder(MqttJavaApplication.class) .web(false) .run(args); } @Bean public MessageChannel mqttInputChannel() { return new DirectChannel(); } @Bean public MessageProducer inbound() { MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter("tcp://localhost:1883", "testClient", "topic1", "topic2"); adapter.setCompletionTimeout(5000); adapter.setConverter(new DefaultPahoMessageConverter()); adapter.setQos(1); adapter.setOutputChannel(mqttInputChannel()); return adapter; } @Bean @ServiceActivator(inputChannel = "mqttInputChannel") public MessageHandler handler() { return new MessageHandler() { @Override public void handleMessage(Message<?> message) throws MessagingException { System.out.println(message.getPayload()); } }; } }
The following Spring Boot application provides an example of configuring the inbound adapter with the Java DSL:
@SpringBootApplication public class MqttJavaApplication { public static void main(String[] args) { new SpringApplicationBuilder(MqttJavaApplication.class) .web(false) .run(args); } @Bean public IntegrationFlow mqttInbound() { return IntegrationFlows.from( new MqttPahoMessageDrivenChannelAdapter("tcp://localhost:1883", "testClient", "topic1", "topic2");) .handle(m -> System.out.println(m.getPayload())) .get(); } }
The outbound channel adapter is implemented by the MqttPahoMessageHandler
, which is wrapped in a ConsumerEndpoint
.
For convenience, you can configure it by using the namespace.
Starting with version 4.1, the adapter supports asynchronous send operations, avoiding blocking until the delivery is confirmed. You can emit application events to enable applications to confirm delivery if desired.
The following listing shows the attributes available for an outbound channel adapter:
<int-mqtt:outbound-channel-adapter id="withConverter" client-id="foo" url="tcp://localhost:1883" converter="myConverter" client-factory="clientFactory" default-qos="1" qos-expression="" default-retained="true" retained-expression="" default-topic="bar" topic-expression="" async="false" async-events="false" channel="target" />
The client ID. | |
The broker URL. | |
An
| |
The client factory. | |
The default quality of service. It is used if no | |
An expression to evaluate to determine the qos.
The default is | |
The default value of the retained flag. It is used if no | |
An expression to evaluate to determine the retained boolean.
The default is | |
The default topic to which the message is sent (used if no | |
An expression to evaluate to determine the destination topic.
The default is | |
When | |
When |
Note | |
---|---|
Starting with version 4.1, the URL can be omitted. Instead, the server URIs can be provided in the |
The following Spring Boot application show an example of how to configure the outbound adapter with Java configuration:
@SpringBootApplication @IntegrationComponentScan public class MqttJavaApplication { public static void main(String[] args) { ConfigurableApplicationContext context = new SpringApplicationBuilder(MqttJavaApplication.class) .web(false) .run(args); MyGateway gateway = context.getBean(MyGateway.class); gateway.sendToMqtt("foo"); } @Bean public MqttPahoClientFactory mqttClientFactory() { DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory(); MqttConnectOptions options = new MqttConnectOptions(); options.setServerURIs(new String[] { "tcp://host1:1883", "tcp://host2:1883" }); options.setUserName("username"); options.setPassword("password".toCharArray()); factory.setConnectionOptions(options); return factory; } @Bean @ServiceActivator(inputChannel = "mqttOutboundChannel") public MessageHandler mqttOutbound() { MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler("testClient", mqttClientFactory()); messageHandler.setAsync(true); messageHandler.setDefaultTopic("testTopic"); return messageHandler; } @Bean public MessageChannel mqttOutboundChannel() { return new DirectChannel(); } @MessagingGateway(defaultRequestChannel = "mqttOutboundChannel") public interface MyGateway { void sendToMqtt(String data); } }
The following Spring Boot application provides an example of configuring the outbound adapter with the Java DSL:
@SpringBootApplication public class MqttJavaApplication { public static void main(String[] args) { new SpringApplicationBuilder(MqttJavaApplication.class) .web(false) .run(args); } @Bean public IntegrationFlow mqttOutboundFlow() { return f -> f.handle(new MqttPahoMessageHandler("tcp://host1:1883", "someMqttClient")); } }