Blog

How to Save Published Messages in Your Database

by on May 21, 2018

In this article, we’ll talk about Backendless publish-subscribe messaging. One of the more common questions we receive is, “How can I get messages long after they are published?” The default mechanism in Backendless keeps messages in the published channel for a short period of time only (around a minute). This becomes a problem if a subscriber needs to have access to the messages after that time period has passed.

This article describes an approach for storing published messages in Backendless Database in order to keep published messages accessible even when they are no longer present in a messaging channel.

Publish-subscribe is a Backendless messaging pattern. The main idea here is to exchange data between a publisher* and subscriber** within a messaging channel***.

publisher – a program using the Publishing API to send messages to a channel.
** subscriber – a program using the Subscription API to receive messages from a channel.
*** channel – a logical intermediary “transporting” the messages.

In order to keep messages accessible for an infinite amount of time, you can save messages into the Backendless Database right after they are published. To accomplish this, we’ll need to combine the Data Service API and theafterPublish event handler (which can be added in the Business Logic (Cloud Code) tab of your Backendless application).
handlerConfig
Once it’s added, just download theafterPublish handler code from the ‘Download’ menu (you can select JavaScript or Java). Then open the generated project in any IDE and add the code to store published messages in a Backendless data table.

@Asset( "chatRoom" )
public class DefaultChannelEventHandler extends com.backendless.servercode.extension.MessagingExtender
{
@Override
public void afterPublish( RunnerContext context, Object message, PublishOptions publishOptions, DeliveryOptions deliveryOptions, ExecutionResult<MessageStatus> result ) throws Exception
{
  String publisher = publishOptions.getPublisherId();
  String messageData = message.toString();
  HashMap savedMessage = new HashMap();
  savedMessage.put("publisher", publisher);
  savedMessage.put("messageData", messageData);
  Backendless.Data.of("ChatHistory").save(savedMessage);
}
}

Alternatively, theafterPublish event handler can be added and deployed to the cloud without any coding at all using Codeless business logic. Here are the steps of how it can be done:

1. Add a new Codeless event handler Selection_1432. When the handler is saved, the Codeless designer will be opened. Add the following blocks to your Codeless logic. When done, click the ‘DEPLOY MODEL’ button.
Selection_144
Voila!

To avoid nulls, every message should be published with a not null value for the publisherId:

public void publishMessage()
{
PublishOptions publishOptions = new PublishOptions();
publishOptions.setPublisherId("Jack");
String message = "Hello, this is my first message!";
Backendless.Messaging.publish("chatRoom", message, publishOptions);
}

For this scenario, we’ll need to create a data table (Data > APP TABLES in your Backendless application) called ‘ChatHistory’ and define the following schema in it:

  • Column publisher of type String.
  • Column messageData of type String.

dataTable
Once code for the handler is added, deploy the handler code to the cloud using the following command in your IDE terminal:
./bin/Deploy.sh

Now that the handler is deployed, every new message published to the chatRoom channel will be stored in a dedicated data table and will be accessible whenever needed by calling an API to retrieve data from a table:

public void retrieveMessageHistory()
{
DataQueryBuilder dataQuery = DataQueryBuilder.create();
dataQuery.setOffset(0);
dataQuery.setPageSize(100);
dataQuery.setSortBy("created");
Backendless.Data.of("ChatHistory").find(dataQuery, new AsyncCallback<List<Map>>()
{
  @Override
  public void handleResponse(List<Map> response)
  {
    for (Map message:response)
      System.out.println("Publisher: " + message.get("publisher") + "\n" + "Message data: " + message.get("messageData") + "\n" + "Posted at " + message.get("created")+ "\n\n");
  }
  @Override
  public void handleFault(BackendlessFault fault)
  {
    System.out.println("Error retrieving message History: " + fault.getMessage());
  }
});
}

You will receive the following output:

Publisher: Jack
Message data: Hello, this is my first message!
Posted at Mon May 21 19:53:13 EEST 2018
Publisher: Jack
Message data: And this is the second one
Posted at Mon May 21 19:53:40 EEST 2018
Publisher: Mike
Message data: Hi, Jack!
Posted at Mon May 21 19:54:13 EEST 2018

Leave a Reply