2

How can I publish messages with different topics programmatically?

<mqtt:outbound-channel-adapter id="mqttOut" 
    auto-startup="true" 
    client-id="foo"
    url="tcp://localhost:1883"
    client-factory="clientFactory"
    default-qos="0"
    default-retained="false"
    default-topic="bar"
    async="true"
    async-events="true" />

I tried Spring integration MQTT publish & subscribe to multiple topics, but were not able to configure.

Also tried with MqttPahoMessageHandlerAdapter which has a publish() but protected.

Going with org.eclipse.paho.client.mqttv3.MqttAsyncClient and org.eclipse.paho.client.mqttv3.MqttCallback is very easy. But I would like to stick with spring all the way.

Appreciate if somebody can points me to a correct direction.

Community
  • 1
  • 1
sura2k
  • 7,365
  • 13
  • 61
  • 80

2 Answers2

2

You can do that with Spring Integration anyway! Having a lot of EIP components implementation and Spring power on board (injection, SpEL etc,), plus switching on a bit of imagination, we can reach any end-application requirements even without any Java code.

So, <mqtt:outbound-channel-adapter> allows determine topic at runtime. Instead of default-topic you should supply MqttHeaders.TOPIC MessageHeader.

So, if you have a requirement to send the same message to several topics, you just build a copy of that message for each topic. The <splitter> can help us:

<int:splitter input-channel="enricheMessage" output-channel="sendMessage" apply-sequence="false">
    <int-groovy:script>
        ['topic1', 'topic2', 'topic3'].collect {
            org.springframework.integration.support.MessageBuilder.withPayload(payload)
                    .copyHeaders(headers)
                    .setHeader(org.springframework.integration.mqtt.support.MqttHeaders.TOPIC, it)
                    .build()
        }
    </int-groovy:script>
</int:splitter>

sendMessage can be ExecutorChannel to achieve the parallel publishing.

UPDATE

You can achieve the same iteration and message enrichment logic with similar Java code using ref and method on <splitter>. Of course, we can do that even with SpEL , but it will look a bit complex with Collection Projection.

Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
  • My topics get generated dynamically at run-time as per my scenario. I have 0 knowledge of groovy :(. I'm trying to achieve is, a server (a thread) should be able to send messages to dynamic topics when it requires. For example, I want to publish set of messages at 23:59 midnight to topic 'a', 'b' and 'c'. I next day, these topics may get changed. – sura2k May 09 '15 at 08:16
  • 1
    So, you can do that by some Java code. And use `ref` and `method` on the ``. And do exactly the same what I shown with Groovy code: iterate over your dynamic topics and return the `List>` with appropriate `MqttHeaders.TOPIC` header for each of them. Unfortunately `` (Gary's sample) won't help you... – Artem Bilan May 09 '15 at 08:20
  • Can you explain why did you choose ``? Does `` has any extra feature than ``? In the spring docs **The Splitter is a component whose role is to partition a message in several parts, and send the resulting messages to be processed independently.**. In this case I don't have any message to partition. But I have several messages to send. – sura2k May 09 '15 at 08:44
  • 1
    With `` you must have the fixed subscribers with predefined `topics`. With `` you will have several messages and send all of them to the same adapter with their own `topic`. Right, it looks a bit scary to split it that way, but there is no choice to distribute the same message for several runtime topics. – Artem Bilan May 09 '15 at 08:59
  • But I'm able to send them right now with ``. If you can check just now on http://mqttdashboard.com/dashboard, you can see multiple topics in this `publish_subscribe_channel//` format. Im just looping `` ftom 200 to 230. '` is like a random number. – sura2k May 09 '15 at 09:05
  • Same `` as in the question + adding the `channel`. So now it is `` with `` as Gary mentioned. Nothing more in the config. In a Thread I have this `@Autowired(required=true) private MessageChannel toMqtt;`. In that Thread I loop `toMqtt.send(message);` where each looping `message` has its own `MqttHeaders.TOPIC`. – sura2k May 09 '15 at 10:02
  • 1
    Well, you exactly did the same iteration which I pointed in my answer. What is the gain of ` ` here? You have the same `` and only one. Gary mentioned it because he suggested to have several ``s for each topic. – Artem Bilan May 09 '15 at 11:24
  • Understood just now what you were trying to say. Actually I do not need ``. So If I start again, I do not need `` or ``. It works with just ``. But you pointed out parallel publishing. I'm interested in this phrase **sendMessage can be ExecutorChannel to achieve the parallel publishing** in your answer. I may have 10000 subscribers and each of them may subscribe to a separate topic. Is there any advantage of having a `` because of this scale (number of subscribers and number of topics)? – sura2k May 09 '15 at 12:10
  • Ideally, it would be better do not use Messaging API from your code (e.g. `messageChannel.send()`). That's because `` helps you to hide your API and just rely on the standard component behavior. – Artem Bilan May 09 '15 at 15:54
2

Declare a <publish-subscribe-channel id="toMqtt" />; set it as the channel attribute on each outbound channel adapter; the message will be sent to each adapter.

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • Thank you very much. It is working. Also I tried with a `` and a ``. This worked too. But I had to remove `async-events="true"` from the `` – sura2k May 09 '15 at 08:05