In another post, we described a feature for conditional pub/sub message delivery using SQL selectors. With that (selector) approach, the publisher must attach headers to the message and the subscriber uses an SQL-based condition that references header names and values. In addition to selectors, Backendless supports another type of conditional delivery – subtopics.
Consider the following example:
A message with an announcement from Microsoft is published to the topic stocks.nasdaq.msft. Another message from IBM is published to stocks.nyse.ibm. Suppose a subscriber wants to receive all messages related to stock announcements. In this case, they subscribe to the stocks.* subtopic.
Another subscriber is interested in all Nasdaq announcements. That subscriber subscribes to the stocks.nasdaq.* subtopic. Finally, to receive Microsoft announcements, a subscriber would use the stocks.nasdaq.msft subtopic. As you can see, Backendless uses the federated subtopic structure for message filtering/delivery.
The sample below shows how to use subtopics in the Backendless messaging API:
Asynchronous API sample (Android and Plain Java):
AsyncCallback<MessageStatus> publishCallback = new AsyncCallback<MessageStatus>()
{
@Override
public void handleResponse( MessageStatus messageStatus )
{
System.out.println( "Message published - " + messageStatus.getMessageId() );
}
@Override
public void handleFault( BackendlessFault backendlessFault )
{
System.out.println( "Server reported an error " + backendlessFault.getMessage() );
}
};
while( true )
{
// *********************************************************************************************************
// publish message 1 to subtopic "news.dallas.sports"
// *********************************************************************************************************
NewsMessage newsMessage1 = new NewsMessage();
newsMessage1.teaser = "Dallas Cowboys project tab in Frisco: $168 million and climbing";
newsMessage1.details = "The price tag for the publicly owned portion of Dallas Cowboys development in Frisco has hit $168 million and continues to grow as the project takes shape";
newsMessage1.newsURL = "http://friscoblog.dallasnews.com/2015/03/dallas-cowboys-project-tab-in-frisco-168-million-and-climbing.html/";
PublishOptions publishOptions1 = new PublishOptions();
publishOptions1.setSubtopic( "news.dallas.sports" );
Backendless.Messaging.publish( "MyAppChannel", newsMessage1, publishOptions1, publishCallback );
// *********************************************************************************************************
// publish message 2 to subtopic "news.us.technology"
// *********************************************************************************************************
NewsMessage newsMessage = new NewsMessage();
newsMessage.teaser = "Magic Leap Demo Flaunts Augmented Reality";
newsMessage.details = "In the latest \"OMG, I want one!\" news, startup Magic Leap on Thursday teased its advanced augmented reality tech";
newsMessage.newsURL = "http://www.pcmag.com/article2/0,2817,2478526,00.asp";
PublishOptions publishOptions2 = new PublishOptions();
publishOptions2.setSubtopic( "news.us.technology" );
Backendless.Messaging.publish( "MyAppChannel", newsMessage, publishOptions2, publishCallback );
Thread.sleep( 500 );
}
Synchronous API sample (Plain Java only):
while( true )
{
// *********************************************************************************************************
// publish message 1 to subtopic "news.dallas.sports"
// *********************************************************************************************************
NewsMessage newsMessage1 = new NewsMessage();
newsMessage1.teaser = "Dallas Cowboys project tab in Frisco: $168 million and climbing";
newsMessage1.details = "The price tag for the publicly owned portion of Dallas Cowboys development in Frisco has hit $168 million and continues to grow as the project takes shape";
newsMessage1.newsURL = "http://friscoblog.dallasnews.com/2015/03/dallas-cowboys-project-tab-in-frisco-168-million-and-climbing.html/";
PublishOptions publishOptions1 = new PublishOptions();
publishOptions1.setSubtopic( "news.dallas.sports" );
MessageStatus messageStatus = Backendless.Messaging.publish( "MyAppChannel", newsMessage1, publishOptions1 );
System.out.println( "Message published - " + messageStatus.getMessageId() );
// *********************************************************************************************************
// publish message 2 to subtopic "news.us.technology"
// *********************************************************************************************************
NewsMessage newsMessage = new NewsMessage();
newsMessage.teaser = "Magic Leap Demo Flaunts Augmented Reality";
newsMessage.details = "In the latest \"OMG, I want one!\" news, startup Magic Leap on Thursday teased its advanced augmented reality tech";
newsMessage.newsURL = "http://www.pcmag.com/article2/0,2817,2478526,00.asp";
PublishOptions publishOptions2 = new PublishOptions();
publishOptions2.setSubtopic( "news.us.technology" );
messageStatus = Backendless.Messaging.publish( "MyAppChannel", newsMessage, publishOptions2 );
System.out.println( "Message published - " + messageStatus.getMessageId() );
Thread.sleep( 500 );
}
The code above publishes two messages to the news.dallas.sports and news.us.technology topics. Also, notice the published message is a custom strongly-typed object (as opposed to a primitive data type or a string). The code below subscribes to receive messages published to the news.* subtopic.
When you run that code, it will receive both messages from the publisher. However, if you modify the subscriber to receive messages from the news.us.* subtopic, it will receive only one of them (repeatedly, though, as the messages are published in a loop):
AsyncCallback<List<Message>> subscriptionResponder = new AsyncCallback<List<Message>>()
{
@Override
public void handleResponse( List<Message> messages )
{
Iterator<Message> messageIterator = messages.iterator();
while( messageIterator.hasNext() )
{
Message message = messageIterator.next();
NewsMessage newsMessage = (NewsMessage) message.getData();
System.out.println( String.format( "Received message - %s\n\tHeadline - %s\n\tDetails - %s\n\tURL - %s",
message.getMessageId(), newsMessage.teaser, newsMessage.details, newsMessage.newsURL ) );
}
}
@Override
public void handleFault( BackendlessFault backendlessFault )
{
System.out.println( "Server reported an error " + backendlessFault.getMessage() );
}
};
SubscriptionOptions subscriptionOptions = new SubscriptionOptions();
subscriptionOptions.setSubtopic( "news.*" );
Backendless.Messaging.subscribe( "MyAppChannel", subscriptionResponder, subscriptionOptions );
Enjoy!