Skip to main content

Courier Service Interface

Courier provides the functionalities like Send, Receive, Subscribe, Unsubscribe through a service interface. This is similar to how we make HTTP calls using Retrofit.

Usage

Declare a service interface for various actions like Send, Receive, Subscribe, SubscribeMultiple, Unsubscribe.

interface MessageService {
@Receive(topic = "topic/{id}/receive")
fun receive(@Path("id") identifier: String): Observable<Message>

@Send(topic = "topic/{id}/send", qos = QoS.TWO)
fun send(@Path("id") identifier: String, @Data message: Message)

@Subscribe(topic = "topic/{id}/receive", qos = QoS.ONE)
fun subscribe(@Path("id") identifier: String): Observable<Message>

@SubscribeMultiple
fun subscribe(@TopicMap topicMap: Map<String, QoS>): Observable<Message>

@Unsubscribe(topics = ["topic/{id}/receive"])
fun unsubscribe(@Path("id") identifier: String)
}

Use Courier to create an implementation of service interface.

val courierConfiguration = Courier.Configuration(
client = mqttClient,
streamAdapterFactories = listOf(RxJava2StreamAdapterFactory()),
messageAdapterFactories = listOf(GsonMessageAdapter.Factory())
)

val courier = Courier(courierConfiguration)

val messageService = courier.create<MessageService>()

Following annotations are supported for service interface.

  • @Send : A method annotation used for sending messages over the MQTT connection.

  • @Receive : A method annotation used for receiving messages over the MQTT connection. Note: The topic needs to be subscribed for receiving messages.

  • @Subscribe : A method annotation used for subscribing a single topic over the MQTT connection.

  • @SubscribeMultiple : A method annotation used for subscribing multiple topics over the MQTT connection.

  • @Unsubscribe : A method annotation used for unsubscribing topics over the MQTT connection.

  • @Path : A parameter annotation used for specifying a path variable in an MQTT topic.

  • @Data : A parameter annotation used for specifying the message object while sending a message over the MQTT connection.

  • @TopicMap : A parameter annotation used for specifying a topic map. It is always used while subscribing multiple topics.

Note : While subscribing topics using @SubscribeMultiple along with a stream, make sure that messages received on all topics follow same format or a message adapter is added for handling different format.

Topic Placeholders

Apart from @Path variables ({...}) which are substituted from method parameters, a topic can contain connection placeholders. These are resolved automatically from the established MQTT connection when the message is actually published/subscribed, so you don't have to pass these values yourself.

PlaceholderResolved with
%uThe connection's username
%cThe connection's client id
interface MessageService {
@Send(topic = "user/%u/send", qos = QoS.ONE)
fun send(@Data message: Message)

@Subscribe(topic = "client/%c/receive", qos = QoS.ONE)
fun subscribe(): Observable<Message>
}

For example, if the connection is established with username alice and client id alice-android, the topics above resolve to user/alice/send and client/alice-android/receive respectively.

Splitting a placeholder value

A placeholder value can be split by a delimiter and a single part of it can be used in the topic. The syntax is (<placeholder>,<delimiter>,<index>) where <index> is 0-based.

@Send(topic = "user/(%c,:,2)/send", qos = QoS.ONE)
fun send(@Data message: Message)

If the client id is region:tenant:device, then (%c,:,2) splits it by : into [region, tenant, device] and picks the part at index 2, resolving the topic to user/device/send. An index that is out of range results in an IllegalArgumentException.

Placeholders can be combined freely with @Path variables and plain placeholders in the same topic, e.g. user/(%c,:,0)/{id}/%u.

Note : Topic placeholders are supported in @Send, @Subscribe, @SubscribeMultiple and @Unsubscribe topics. They are not resolved for @Receive topics — a @Receive listener is registered against the topic string as-is, so use the already-resolved topic (or @Subscribe with a stream) when you need placeholder-based receiving.