DOUBL3P
DOUBL3P

Reputation: 291

MQTT PAHO - MessageId for confirmation of successful message delivery

I develop an application with org.eclipse.paho.client.mqttv3 version 1.2.0 in Java. To indentify a message which is sent to the mqtt broker via the messageID of iMqttDeliveryToken.

Step 1 - publish a message:

ObjectMapper objectMapper = new ObjectMapper();
MqttMessage mqttMessage = new MqttMessage();
mqttMessage.setPayload(objectMapper.writeValueAsString(myObject).getBytes()); 
mqttMessage.setQos(1);
IMqttDeliveryToken iMqttDeliveryToken = this.client.publish("/myTopic", mqttMessage);

Step 2 - save message in database:

Out of the IMqttDeliveryToken I get the messageID. This I use to save and indentify the message in a database.

Step 3 - wait that deliveryComplete callback is called:

This offers me the same IMqttDeliveryToken where I get the messageId again.

@Override
   public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
      // delete the database entry via messageId from database
}

The problem is that Step3 can be faster than Step2. So the callback is called before my entry is saved in the database. I need to know the messageId before sending the message to save it before the callback can be called. I am not able to generate the messageId by my self and set it like this:

mqttMessage.setId(555);

MQTT generates a own messageId. So my questions:

  1. Is it possible to set a own messageId?
  2. Can I get the messageId which is genererated by the mqtt client before I publish?

Upvotes: 2

Views: 1866

Answers (1)

Alexander Farber
Alexander Farber

Reputation: 23038

Do not use the MQTT id of the message generated by Paho library - because it

  1. is delivered too late for your needs
  2. might get repeated if you send large amount of messages.

Instead, use your own id (maybe even autogenerated by your database) and pass it as a user-defined context object when publishing:

Long databaseId = 42;
ObjectMapper objectMapper = new ObjectMapper();
MqttMessage mqttMessage = new MqttMessage();
mqttMessage.setPayload(objectMapper.writeValueAsString(myObject).getBytes()); 
mqttMessage.setQos(1);
this.client.publish("/myTopic", mqttMessage, databaseId, mPublishCallback);

Later you can retrieve the id in the publish callback methods:

private final IMqttActionListener mPublishCallback = new IMqttActionListener() {
    @Override
    public void onSuccess(IMqttToken publishToken) {
        Long databaseId = (Long) publishToken.getUserContext();
    }

    @Override
    public void onFailure(IMqttToken publishToken, Throwable ex) {
        Long databaseId = (Long) publishToken.getUserContext();
    }
};

Also, are you using synchronous client? I prefer using IMqttAsyncClient

Upvotes: 2

Related Questions