Blog

Intro to Basic Publish/Subscribe Messaging

by on September 1, 2019

Publish/subscribe messaging has been around for a long time. The concept is rather simple – a program can publish a message to a queue or a topic, while another program subscribes to the queue or the topic to receive published messages. There are a lot of caveats in the model such as conditional delivery, message filtering, message transformations, etc.

In this post, we will demonstrate the most basic form of publish/subscribe messaging. One client will be publishing basic string messages, while any number of other client apps can subscribe to receive published messages. Consider the following example:

    int i = 1;
    
    while (true) {
       Backendless.Messaging.publish("default", "Message " + i++, new AsyncCallback<MessageStatus>() {
           @Override
           public void handleResponse(MessageStatus messageStatus) {
               Log.i(TAG, "Message published - " + messageStatus.getMessageId());
           }
    
           @Override
           public void handleFault(BackendlessFault fault) {
               Log.e(TAG, fault.getMessage());
           }
       });
    
       Thread.sleep(500);
    }
    

    var i = 1
    
    while (true) {
       Backendless.Messaging.publish("default", "Message " + i++, object : AsyncCallback<MessageStatus> {
           override fun handleResponse(messageStatus: MessageStatus) {
               Log.i(TAG, "Message published - ${messageStatus.messageId}")
           }
    
           override fun handleFault(fault: BackendlessFault) {
               Log.e(TAG, fault.message)
           }
       })
    
       Thread.sleep(500)
    }

    const Backendless = require('backendless')
    /*
     Or use `import Backendless from 'backendless'` for client side.
     If you don't use npm or yarn to install modules, you can add the following line
     <script src="//api.backendless.com/sdk/js/latest/backendless.min.js"></script>
     to your index.html file and use the global Backendless variable.
    */
    
    Backendless.initApp('YOUR_APP_ID', 'YOUR_JS_API_KEY')
    const publishMessages = () => {
      const requests = []
    
      for (let i = 0; i < 10; i++) { const request = Backendless.Messaging.publish('default', `Message ${ i }`) requests.push(request) } return Promise.all(requests) } const onError = error => {
      console.error('Server reported an error: ', error.message)
      console.error('error code: ', error.code)
      console.error('http status: ', error.status)
    }
    
    Promise.resolve()
      .then(publishMessages)
      .catch(onError)
    
    

    NSInteger i = 0;
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(publishMessage) userInfo:nil repeats:YES];
    
    - (void)publishMessage {
        i++;
        NSString *message = [NSString stringWithFormat:@"Message %li", (long)i];
        [Backendless.shared.messaging publishWithChannelName:@"default" message:message responseHandler:^(MessageStatus *messageStatus) {
            NSLog(@"Message published - %@", messageStatus.messageId);
        } errorHandler:^(Fault *fault) {
            NSLog(@"Error: %@", fault.message);
        }];
    }

    var i = 0
    let _ = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(publishMessage), userInfo: nil, repeats: true)
    
    @objc func publishMessage() {
        i += 1
        Backendless.shared.messaging.publish(channelName: "default", message: "Message \(i)", responseHandler: { messageStatus in
            print("Message published - \(messageStatus.messageId ?? "")")
        }, errorHandler: { fault in
            print("Error: \(fault.message ?? "")")
        })
    }

    int i = 1;
       while (true) {
         Backendless.messaging.publish("Message ${i++}", channelName: "default").then(
           (messageStatus) => print("Message published - ${messageStatus.messageId}"));
         sleep(Duration(milliseconds: 500));
       }

    Both samples above publish string messages to the “default” channel. A channel is a logical medium carrying the messages. Think of it as a pipeline connecting the publisher with the subscribers. You can use your own messaging channels in your app – Backendless lets you create any number of channels.

      Channel channel = Backendless.Messaging.subscribe("default");
      
      channel.addMessageListener(new AsyncCallback() {
         @Override
         public void handleResponse(String message) {
             Log.i(TAG, "Received message - " + message);
         }
      
         @Override
         public void handleFault(BackendlessFault fault) {
             Log.e(TAG, fault.getMessage());
         }
      });

      val channel = Backendless.Messaging.subscribe("default")
      
      channel.addMessageListener(object : AsyncCallback<String> {
         override fun handleResponse(message: String) {
             Log.i(TAG, "Received message - $message")
         }
      
         override fun handleFault(fault: BackendlessFault) {
             Log.e(TAG, fault.message)
         }
      })

      const Backendless = require('backendless')
      /*
       Or use `import Backendless from 'backendless'` for client side.
       If you don't use npm or yarn to install modules, you can add the following line
       <script src="//api.backendless.com/sdk/js/latest/backendless.min.js"></script>
       to your index.html file and use the global Backendless variable.
      */
      
      Backendless.initApp('YOUR_APP_ID', 'YOUR_JS_API_KEY')
      const channel = Backendless.Messaging.subscribe('default')
      
      const onMessage = message => {
        console.log(`Received a message - ${ JSON.stringify(message) }`)
      }
      
      channel.addMessageListener(onMessage)
      

       

      Channel *channel = [Backendless.shared.messaging subscribe];
      RTSubscription *subscription = [channel addStringMessageListenerWithResponseHandler:^(NSString *message) {
          NSLog(@"Received message - %@", message);
      } errorHandler:^(Fault *fault) {
          NSLog(@"Error: %@", fault.message);
      }];

      let channel = Backendless.shared.messaging.subscribe()
      let _ = channel.addStringMessageListener(responseHandler: { message in
          print("Received message - \(message)")
      }, errorHandler: { fault in
          print("Error: \(fault.message ?? "")")
      })

      Channel channel = await Backendless.messaging.subscribe("default");
      channel.addMessageListener((String message) => print("Received message - $message"));

      The publisher code produces the following output:

      Message published - 37243355-2DB1-95F8-FF0A-FC19DEF09D00
      Message published - BE150154-B9E1-D95C-FFC4-3ECBDB572300
      Message published - 60E00A27-9CDB-A5A3-FF17-E1E45020F300
      Message published - F139EF3B-AEB0-51F5-FFD6-74B78065D100
      Message published - DA38D9AC-7F00-652C-FFB3-58DCA660BA00
      Message published - EC8684CF-EA71-3032-FFAA-9091F6727D00
      Message published - 39ADB9ED-61D9-EDC1-FF5C-D88814C6A900
      Message published - 7EEC5EEF-95D0-903C-FF39-5A3AA3CAF700

      While the subscriber prints out the following:

      Received message - Message 40
      Received message - Message 41
      Received message - Message 42
      Received message - Message 43
      Received message - Message 44
      Received message - Message 45
      Received message - Message 46
      Received message - Message 47
      Received message - Message 48
      Received message - Message 49

      Backendless Messaging is a very powerful technology.

      Leave a Reply