Progress
External Program
Interfaces


Pub/Sub Messaging Examples

The Pub/Sub examples consist of sets of subscribers and publishers. You should run each messaging example interactively from its own window. Launch the subscriber first, because the message is discarded if the publisher publishes the message before there are any subscribers to the topic (or any durable subscriptions).

The path for the messaging examples depends on your operating system. The paths are:

Windows
UNIX
%DLC%\src\samples\sonicmq\adapter\
examples\example*.p 
$DLC\src\samples\sonicmq\adapter\
examples\example*.p 

Publishing and Subscribing With a TextMessage

Examples 1 and 2 demonstrate basic Pub/Sub messaging. Example 1 publishes a TextMessage to a topic and Example 2 subscribes to a topic and receives a TextMessage.

Follow these steps to run Examples 1 and 2:

  1. Run example2.p (1 of 2) so the subscriber is running before you publish.
  2. example2.p
    /* Subscribes and receives a Text message. */ 
    DEFINE VARIABLE pubsubsession AS HANDLE. 
    DEFINE VARIABLE consumerH AS HANDLE. 
    /* Creates a session object. */ 
    RUN jms/pubsubsession.p PERSISTENT SET pubsubsession("-H localhost -S 
    5162 "). 
    RUN setBrokerURL IN pubsubsession ("localhost:2506"). 
    RUN beginSession IN pubsubsession. 
    /* Subscribe to the GolfTopic topic. Messages are handled by the 
       "golfHandler" internal procedure. 
    */ 
    RUN createMessageConsumer IN pubsubsession ( 
                      THIS-PROCEDURE, /* This proc will handle it */ 
                      "golfHandler",  /* name of internal procedure */ 
                      OUTPUT consumerH). 
    RUN subscribe IN pubsubsession (
                  "GolfTopic",     /* name of topic */ 
                  ?,               /* Subscription is not durable */ 
                  ?,               /* No message selector */ 
                  no,              /* Want my own messages too */ 
                  consumerH).      /* Handles the incoming messages*/ 
    /* Start receiving messages */ 
    RUN startReceiveMessages IN pubsubsession. 
    /* Wait to receive the messages. Any other IO-blocked statements can be
       used for receiving messages.  
    */ 
    WAIT-FOR u1 OF THIS-PROCEDURE. 
    
    PROCEDURE golfHandler: 
    DEFINE INPUT PARAMETER messageH AS HANDLE.  
    DEFINE INPUT PARAMETER msgConsumerH AS HANDLE. 
    DEFINE OUTPUT PARAMETER replyH AS HANDLE. 
    /* Display the message - we assume that reply is not required. */ 
    DISPLAY "Message text: " DYNAMIC-FUNCTION('getText':U IN messageH) 
      FORMAT "x(70)". 
    RUN deleteMessage IN messageH. 
    APPLY "U1" TO THIS-PROCEDURE.  
    END. 
    

  3. Run example1.p to publish the TextMessage to a topic.
  4. example1.p
    /* Publishes A Text message. */ 
    DEFINE VARIABLE pubsubsession AS HANDLE. 
    DEFINE VARIABLE messageH AS HANDLE. 
    /* Creates a session object. */ 
    RUN  jms/pubsubsession.p PERSISTENT SET pubsubsession ("-H localhost -S 
    5162 "). 
    RUN setBrokerURL IN pubsubsession ("localhost:2506"). 
    RUN beginSession IN pubsubsession. 
    /* Create a text message */ 
    RUN createTextMessage IN pubsubsession (OUTPUT messageH).  
    RUN setText IN messageH ("Golf shoes on sale today"). 
    /* Publish the message on the "GolfTopic" topic */ 
    RUN publish IN pubsubsession ("GolfTopic", messageH, ?, ?, ?). 
    RUN deleteMessage IN messageH. 
    RUN deleteSession IN pubsubsession. 
    

Publishing With Message Properties and Subscribing Selectively

Example 3 publishes a TextMessage from Super Golf Center to Sub Par Golf using setStringProperty. Example 4 subscribes to a topic and only receives messages addressed to “Sub Par Golf” (by passing a selector to the Subscribe call).

Follow these steps to run Examples 3 and 4:

  1. Run example4.p (1 of 2) first so the subscriber is running before you publish.
  2. example4.p
    /* Receives a Text message with the "TO" property equals to "Sub Par Golf" 
    */ 
    DEFINE VARIABLE pubsubsession AS HANDLE. 
    DEFINE VARIABLE consumerH AS HANDLE. 
    /* Creates a session object. */ 
    RUN  jms/pubsubsession.p PERSISTENT SET pubsubsession ("-H localhost -S 
    5162 "). 
    RUN setBrokerURL IN pubsubsession ("localhost:2506"). 
    RUN beginSession IN pubsubsession. 
    /* Subscribes to the GolfTopic topic. Messages are handled by the 
       "golfHandler" internal procedure.  */ 
    RUN createMessageConsumer IN pubsubsession ( 
                          THIS-PROCEDURE,    /* This proc will handle it */ 
                                 "golfHandler",      /* name of internal procedure */ 
                          OUTPUT consumerH). 
    RUN subscribe IN pubsubsession (
                 "GolfTopic",           /* name of topic */ 
                 ?,                     /* Subscription is not durable */ 
                    "TO = 'Sub Par Golf'",  /* Only messages from Sub Par Golf */ 
                 no,                    /* Want my own messages too */ 
                 consumerH).            /* Handles the incoming messages */ 
    /* Start receiving messages */ 
    RUN startReceiveMessages IN pubsubsession. 
    /* Wait to receive the messages. Any other IO-blocked statements can be
       used for receiving messages.  
    */ 
    WAIT-FOR u1 OF THIS-PROCEDURE. 
    
    PROCEDURE golfHandler: 
    DEFINE INPUT PARAMETER messageH AS HANDLE. 
    DEFINE INPUT PARAMETER msgConsumerH AS HANDLE. 
    DEFINE OUTPUT PARAMETER replyH AS HANDLE. 
    /* Display the message - we assume that reply is not required. */ 
    DISPLAY "Message text: " DYNAMIC-FUNCTION('getText':U IN messageH) 
                             FORMAT "X(30)" 
            "Message from: " DYNAMIC-FUNCTION('getCharProperty':U IN messageH, 
                                               "FROM"). 
    RUN deleteMessage IN messageH. 
    APPLY "U1" TO THIS-PROCEDURE. 
    END. 
    

    example3.p
    /* Publishes a Text message with properties. */ 
    DEFINE VARIABLE pubsubsession AS HANDLE. 
    DEFINE VARIABLE messageH AS HANDLE. 
    /* Creates a session object. */ 
    RUN  jms/pubsubsession.p PERSISTENT SET pubsubsession ("-H localhost -S 
    5162 "). 
    RUN setBrokerURL IN pubsubsession ("localhost:2506"). 
    RUN beginSession IN pubsubsession. 
    /* Create a text message */ 
    RUN createTextMessage IN pubsubsession (OUTPUT messageH). 
    RUN setText IN messageH ("Golf shoes on sale today."). 
    /* Set the "FROM:" and the "TO:" properties */ 
    RUN setStringProperty IN messageH ("FROM", "Super Golf Center"). 
    RUN setStringProperty IN messageH ("TO", "Sub Par Golf"). 
    /* Publish the message on to the golf topic */ 
    RUN publish IN pubsubsession ("GolfTopic", messageH, ?, ?, ?). 
    

Publishing With a Reply Handle, Subscribing, and Receiving an Automatic Reply

Examples 5, 6, and 7 illustrate publishing with a reply handle and receiving an automatic reply. Example 5 subscribes with an automatic reply mechanism. It can only reply to messages that have the JMSReplyTo header field. Example 6 subscribes with explicit reply by calling publish directly. It can only reply to messages that have the JMSReplyTo header field. Example 7 publishes using requestReply for receiving reply messages from subscribers. It populates the JMSReplyTo header field automatically.

Follow these steps to run Examples 5, 6, and 7:

  1. Run example5.p (1 of 2) so the subscriber is running before you publish.
  2. example5.p
    /* Using the automatic reply mechanism. Note that the received message
       must have a JMSReplyTo header field for this to work. Example7 can be
       used to receive the reply.  */ 
    DEFINE VARIABLE pubsubsession AS HANDLE. 
    DEFINE VARIABLE consumerH AS HANDLE. 
    /* Creates a session object. */ 
    RUN  jms/pubsubsession.p PERSISTENT SET pubsubsession ("-H localhost -S 
    5162 "). 
    RUN setBrokerURL IN pubsubsession ("localhost:2506"). 
    RUN beginSession IN pubsubsession. 
    /* Subscribe to the GolfTopic topic. Messages are handled by the 
       "golfHandler" internal procedure.  */ 
    RUN createMessageConsumer IN pubsubsession ( 
                          THIS-PROCEDURE,    /* This proc will handle it */ 
                                 "golfHandler",      /* name of internal procedure */ 
                          OUTPUT consumerH). 
    RUN subscribe IN pubsubsession (
                             "GolfTopic",  /* name of topic */ 
                                 ?,              /* Subscription is not durable */ 
                             ?,            /* No message selector */ 
                             no,           /* Want my own messages too */ 
                             consumerH).   /* Handles the messages */ 
    /* Start receiving messages */ 
    RUN startReceiveMessages IN pubsubsession. 
    /* Wait forever to receive messages since "u1" is never applied.  */ 
    WAIT-FOR u1 OF THIS-PROCEDURE. 
    
    PROCEDURE golfHandler: 
    DEFINE INPUT PARAMETER messageH AS HANDLE. 
    DEFINE INPUT PARAMETER msgConsumerH AS HANDLE. 
    DEFINE OUTPUT PARAMETER replyH AS HANDLE. 
    /* Creates a reply message. The reply is published automatically when
       control returns to the 4GL-JMS implementation. 
    */ 
    DISPLAY DYNAMIC-FUNCTION('getText':U IN messageH) format "x(60)". 
    IF DYNAMIC-FUNCTION('hasReplyTo':U IN messageH) THEN  
      DO: 
        RUN createTextMessage IN pubsubsession (OUTPUT replyH). 
        RUN setText IN replyH ("Will bid. Send data in sportsXML format."). 
      END. 
    RUN deleteMessage IN messageH. 
    END. 
    

  3. Run example6.p (1 of 2) to subscribe with explicit reply by calling publish directly.
  4. example6.p
    /* Replying explicitly. Note that the received message must 
       have a JMSReplyTo header field for this to work. Example7 can be used 
       to receive the reply.  */ 
    DEFINE VARIABLE pubsubsession AS HANDLE. 
    DEFINE VARIABLE msgConsumer AS HANDLE. 
    /* Creates a session object. */ 
    RUN  jms/pubsubsession.p PERSISTENT SET pubsubsession ("-H localhost -S 
    5162 "). 
    RUN setBrokerURL IN pubsubsession ("localhost:2506"). 
    RUN beginSession IN pubsubsession. 
    RUN createMessageConsumer IN pubsubsession ( 
                           THIS-PROCEDURE,   /* This proc will handle it */ 
                                 "messageHandler", /* name of internal procedure */ 
                           OUTPUT msgConsumer). 
    RUN subscribe IN pubsubsession (
                                   "GolfTopic", 
                                   ?,  /* No durable subscription */ 
                                   ?,  /* No message selector */ 
                                    no, /* Want to get my own publications */ 
                                   msgConsumer). 
    RUN startReceiveMessages IN pubsubsession. 
    /* Wait forever to receive messages since "u1" is never applied.  */ 
    WAIT-FOR u1 OF THIS-PROCEDURE. 
    RUN deleteSession IN pubsubsession. 
    
    PROCEDURE messageHandler: 
    DEFINE INPUT PARAMETER messageH AS HANDLE NO-UNDO. 
    DEFINE INPUT PARAMETER messageConsumerH AS HANDLE NO-UNDO. 
    DEFINE OUTPUT PARAMETER autoReplyH AS HANDLE NO-UNDO.
      /* Not used in this example */ 
    DEFINE VARIABLE replyH AS HANDLE. 
    DISPLAY DYNAMIC-FUNCTION('getText':U IN messageH) format "x(60)". 
    IF NOT DYNAMIC-FUNCTION('hasReplyTo':U IN messageH) THEN RETURN. 
    /* Publishes a reply explicitly - using the publish call. */ 
    RUN createTextMessage IN pubsubsession (OUTPUT replyH). 
    RUN setText IN replyH("Will bid. Send data in sportsXML format."). 
    RUN publish IN pubsubsession (DYNAMIC-FUNCTION('getJMSReplyTo':U IN
      messageH), replyH, ?, ?, ?). 
    RUN deleteMessage IN messageH. 
    END. 
    

  5. Run example7.p (1 of 2) to publish using requestReply for receiving reply messages from subscribers. It populates the JMSReplyTo header field automatically.
  6. example7.p
    /* Publishes a message and receives a reply. */ 
    DEFINE VARIABLE pubsubsession AS HANDLE. 
    DEFINE VARIABLE consumerH AS HANDLE. 
    DEFINE VARIABLE messageH AS HANDLE. 
    /* Creates a session object. */ 
    RUN  jms/pubsubsession.p PERSISTENT SET pubsubsession ("-H localhost -S 
    5162 "). 
    RUN setBrokerURL IN pubsubsession ("localhost:2506"). 
    RUN beginSession IN pubsubsession. 
    /* Start receiving messages */ 
    RUN startReceiveMessages IN pubsubsession. 
    /* Create a text message */ 
    RUN createTextMessage IN pubsubsession (OUTPUT messageH). 
    RUN setText IN messageH ("Golf shoes on sale today."). 
    /* Creates a consumer for the reply  */ 
    RUN createMessageConsumer IN pubsubsession ( 
                          THIS-PROCEDURE, /* This proc will handle it */ 
                          "golfHandler",  /* name of internal procedure */ 
                          OUTPUT consumerH). 
    /* Publish the message onto the Golf topic. Handle the reply in the  
       golfHandler internal procedure.  
    */ 
    RUN requestReply IN pubsubsession ( 
                               "GolfTopic", 
                                messageH, 
                                ?,           /* No reply selector. */ 
                                consumerH, ?, ?, ?).  
    /* Wait forever to receive messages since "u1" is never applied.  */ 
    WAIT-FOR u1 OF THIS-PROCEDURE. 
    
    PROCEDURE golfHandler: 
    DEFINE INPUT PARAMETER replyH AS HANDLE. 
    DEFINE INPUT PARAMETER msgConsumerH AS HANDLE. 
    DEFINE OUTPUT PARAMETER responseH AS HANDLE. 
    /* Display the reply - we are not sending a response. */ 
    DISPLAY "reply text: " DYNAMIC-FUNCTION('getText':U IN replyH)
      FORMAT "X(30)". 
    RUN deleteMessage IN replyH. 
    END. 
    

Publishing, Receiving, and Processing a StreamMessage

Examples 8 and 9 publish, receive, and process a StreamMessage.

Follow these steps to run Examples 8 and 9:

  1. Connect to the Sports database.
  2. Run example9.p (1 of 2) to receive the StreamMessage containing the customer names and numbers.
  3. example9.p
    /* Receives a Stream message. */ 
    DEFINE VARIABLE pubsubsession AS HANDLE. 
    DEFINE VARIABLE consumerH AS HANDLE. 
    /* Creates a session object. */ 
    RUN  jms/pubsubsession.p PERSISTENT SET pubsubsession ("-H localhost -S 
    5162 "). 
    RUN setBrokerURL IN pubsubsession ("localhost:2506"). 
    RUN beginSession IN pubsubsession. 
    /* Subscribe to the newCustomers topic. The newCustHandler internal
       procedure handles the list of new customers. 
    */ 
    RUN createMessageConsumer IN pubsubsession ( 
                        THIS-PROCEDURE,    /* This proc will handle it */ 
                        "newCustHandler",  /* name of internal procedure */ 
                        OUTPUT consumerH). 
    RUN subscribe IN pubsubsession (
                         "NewCustomers", /* name of topic */ 
                          ?,             /* Subscription is not durable*/ 
                          ?,             /* No message selector. */ 
                          no,            /* Want my own messages too */ 
                          consumerH).    /* handles the messages */ 
    /* Start receiving messages */ 
    RUN startReceiveMessages IN pubsubsession. 
    /* Wait to receive the messages. Any other IO-blocked statements can be
       used for receiving messages.
    */ 
    WAIT-FOR u1 OF THIS-PROCEDURE. 
    
    PROCEDURE newCustHandler: 
    DEFINE INPUT PARAMETER messageH AS HANDLE. 
    DEFINE INPUT PARAMETER msgConsumerH AS HANDLE. 
    DEFINE OUTPUT PARAMETER replyH AS HANDLE. 
    /* Display the stream of customer names and customer numbers. */ 
    /* The moveToNext function moves the cursor to the next item in */ 
    /* the stream and returns the data type of that item.          */ 
    /* We assume the reply is not required. */ 
    IF NOT  DYNAMIC-FUNCTION('getMessageType':U IN messageH) = 
    "StreamMessage" 
         THEN RETURN. 
    /* Note that the 'moveToNext' functions returns the item's data type. */ 
     DO WHILE NOT  DYNAMIC-FUNCTION('endOfStream':U IN messageH) WITH DOWN: 
        DISPLAY DYNAMIC-FUNCTION('moveToNext':U IN messageH)   
                DYNAMIC-FUNCTION('readChar':U IN messageH)  
                DYNAMIC-FUNCTION('moveToNext':U IN messageH)   
                DYNAMIC-FUNCTION('readInt':U IN messageH). 
        DOWN. 
     END. 
    RUN deleteMessage IN messageH. 
    APPLY "U1" TO THIS-PROCEDURE. 
    END. /* newCustHandler */ 
    

  4. Run example8.p to publish a StreamMessage containing customer names and numbers.
  5. example8.p 
    /* Publishing a Stream message. */ 
    DEFINE VARIABLE pubsubsession AS HANDLE. 
    DEFINE VARIABLE messageH AS HANDLE. 
    /* Creates a session object. */ 
    RUN  jms/pubsubsession.p PERSISTENT SET pubsubsession ("-H localhost -S 
    5162 "). 
    RUN setBrokerURL IN pubsubsession ("localhost:2506"). 
    RUN beginSession IN pubsubsession. 
    /* Create a stream message */ 
    RUN createStreamMessage IN pubsubsession (OUTPUT messageH). 
    /* Load the message with a list of customer names and cust-nums. */ 
    FOR EACH customer: 
       RUN writeString IN messageH (customer.name). 
       RUN writeInt IN messageH (customer.cust-num). 
    END. 
    /* Publish the message on the NewCustomers topic. */ 
    RUN publish IN pubsubsession ("NewCustomers", messageH, ?, ?, ?). 
    

Publishing, Receiving, and Parsing an XMLMessage

Examples 10 and 11 create, publish, receive, and parse an XMLMessage.

Follow these steps to run Examples 10 and 11:

  1. Run example11.p (1 of 3) so the subscriber is running before you publish.This example subscribes, receives, and parses an XML message.
  2. example11.p
    /* Receives and parse an XML message. */ 
    DEFINE VARIABLE pubsubsession AS HANDLE. 
    DEFINE VARIABLE msgConsumer1 AS HANDLE. 
    DEFINE VARIABLE stillWaiting AS LOGICAL INIT yes. 
    DEFINE VARIABLE msgNum AS INT INIT 0. 
    RUN  jms/pubsubsession.p PERSISTENT SET pubsubsession ("-H localhost -S 
    5162 "). 
    RUN setBrokerURL IN pubsubsession ("localhost:2506"). 
    RUN beginSession IN pubsubsession. 
    RUN createMessageConsumer IN pubsubsession 
          (THIS-PROCEDURE, "messageHandler", OUTPUT msgConsumer1). 
    RUN subscribe IN pubsubsession ("people", 
                                    ?,  
                                    ?, 
                                    no,  
                                    msgConsumer1) NO-ERROR. 
    RUN startReceiveMessages IN pubsubsession. 
    RUN waitForMessages IN pubsubsession ("inWait", THIS-PROCEDURE, ?). 
    RUN deleteSession IN pubsubsession. 
    
    PROCEDURE messageHandler: 
    DEFINE INPUT PARAMETER messageH AS HANDLE NO-UNDO. 
    DEFINE INPUT PARAMETER messageConsumerH AS HANDLE NO-UNDO. 
    DEFINE OUTPUT PARAMETER replyH AS HANDLE NO-UNDO. 
    DEFINE VAR memptrDoc AS MEMPTR.  
    DEFINE VAR hdoc AS HANDLE. 
    DEFINE VAR hRoot AS HANDLE. 
    DEFINE VAR xmlText AS CHAR. 
    DEFINE VAR indx AS INT. 
    CREATE X-DOCUMENT hdoc. 
    CREATE X-NODEREF hRoot. 
    SET-SIZE(memptrDoc) = 400000. /* The size is an estimate. */ 
    indx = 1. 
    DO WHILE NOT  DYNAMIC-FUNCTION('endOfStream' IN messageH): 
      xmlText = DYNAMIC-FUNCTION('getTextSegment':U IN messageH). 
      PUT-STRING(memptrDoc, indx)  =  xmlText. 
      indx = indx + LENGTH(xmlText). 
    END. 
    hdoc:LOAD("memptr", memptrDoc, FALSE). 
    hdoc:GET-DOCUMENT-ELEMENT(hRoot). 
    RUN getPeople(hRoot, 1). 
    RUN deleteMessage IN messageH. 
    SET-SIZE(memptrDoc) = 0. 
    stillWaiting = false. 
    END. 
    
    /* Displays the XML node names and XML text. */ 
    PROCEDURE getPeople: 
    DEFINE INPUT PARAMETER hParent AS HANDLE. 
    DEFINE INPUT PARAMETER level AS INT. 
    DEFINE VAR i AS INT. 
    DEFINE VAR  hNoderef AS HANDLE. 
    CREATE X-NODEREF hNoderef. 
    REPEAT i = 1 TO hParent:NUM-CHILDREN. 
          hParent:GET-CHILD(hNoderef,i). 
          IF hNoderef:NAME = "#text" THEN 
             MESSAGE "Text: " hNoderef:NODE-VALUE. 
          ELSE 
             MESSAGE "Node name: " hNoderef:NAME. 
          RUN getPeople(hNoderef, (level + 1)). 
    END. 
    DELETE OBJECT hNoderef. 
    END. 
    
    FUNCTION inWait RETURNS LOGICAL. 
    RETURN stillWaiting. 
    END. 
    

  3. Run example10.p to create and publish an XML message with the data of 100 people.
  4. example10.p 
    /* Publishes an XML message. */ 
    DEFINE VARIABLE pubsubsession AS HANDLE. 
    DEFINE VARIABLE mesgH AS HANDLE. 
    DEFINE VARIABLE person AS CHAR INIT "". 
    DEFINE VARIABLE i AS INT. 
    RUN  jms/pubsubsession.p PERSISTENT SET pubsubsession ("-H localhost -S 
    5162 "). 
    RUN setBrokerURL IN pubsubsession ("localhost:2506"). 
    RUN beginSession IN pubsubsession. 
    RUN createXMLMessage IN pubsubsession (OUTPUT mesgH). 
    
    /* Creates an XML message with 100 people. */ 
    RUN appendText IN mesgH('<?xml version="1.0" '). 
    RUN appendText IN mesgH("encoding='ISO8859-1' ?>"). 
    RUN appendText IN mesgH("<personnel>"). 
    REPEAT i = 1 TO 100: 
      person =            "<person>". 
      person = person +     "<name>". 
      person = person +         "<family>SecondName</family>". 
      person = person +         "<given>FirstName" + STRING(i) +  "</given>". 
      person = person +      "</name>". 
      person = person +     "<email>myEmail@subpargolf.com</email>". 
      person = person +  "</person>". 
      RUN appendText IN mesgH(person). 
    END. 
    RUN appendText IN mesgH("</personnel>"). 
    RUN publish IN pubsubsession ("people", mesgH, ?, ?, ?). 
    RUN deleteMessage IN mesgH. 
    RUN deleteSession IN pubsubsession. 
    

Publishing, Subscribing, and Receiving an XML Document In a BytesMessage

Examples 12 and 13 use a MEMPTR variable to publish and receive an XML document in a BytesMessage to prevent code-page conversions. The code pages of the document and the 4GL client do not have to match.

Follow these steps to run Examples 12 and 13:

  1. Run example13.p (1 of 2) to subscribe and receive a BytesMessage containing an XML document.
  2. example13.p
    /* Receives an XML document in a Bytes message. */ 
    DEFINE VARIABLE pubsubsession AS HANDLE. 
    DEFINE VARIABLE msgConsumer1 AS HANDLE. 
    DEFINE VARIABLE stillWaiting AS LOGICAL INIT yes. 
    RUN  jms/pubsubsession.p PERSISTENT SET pubsubsession ("-H localhost -S 
    5162 "). 
    RUN setBrokerURL IN pubsubsession ("localhost:2506"). 
    RUN beginSession IN pubsubsession. 
    RUN createMessageConsumer IN pubsubsession(THIS-PROCEDURE, 
      "messageHandler", 
      OUTPUT msgConsumer1). 
    RUN subscribe IN pubsubsession ( 
                       "xmlTopic", 
                       ?,          /* Not a durable subscription */ 
                       ?,          /* No message selector. */ 
                       no,         /* noLocal */ 
                       msgConsumer1) NO-ERROR. 
    RUN startReceiveMessages IN pubsubsession. 
    RUN waitForMessages IN pubsubsession ("inWait", THIS-PROCEDURE, ?). 
    RUN deleteSession IN pubsubsession. 
    
    PROCEDURE messageHandler: 
    DEFINE INPUT PARAMETER messageH AS HANDLE NO-UNDO. 
    DEFINE INPUT PARAMETER messageConsumerH AS HANDLE NO-UNDO. 
    DEFINE OUTPUT PARAMETER replyH AS HANDLE NO-UNDO. 
    DEFINE VAR memptrDoc AS MEMPTR.  
    DEFINE VAR hdoc AS HANDLE. 
    DEFINE VAR hRoot AS HANDLE. 
    memptrDoc = DYNAMIC-FUNCTION('getMemptr':U IN messageH). 
    CREATE X-DOCUMENT hdoc. 
    CREATE X-NODEREF hRoot. 
    hdoc:LOAD("memptr", memptrDoc, FALSE). 
    hdoc:GET-DOCUMENT-ELEMENT(hRoot). 
    RUN GetChildren(hRoot, 1). 
    RUN deleteMessage IN messageH. 
    stillWaiting = false. 
    END. 
    
    PROCEDURE GetChildren: 
    DEFINE INPUT PARAMETER hParent AS HANDLE. 
    DEFINE INPUT PARAMETER level AS INT. 
    DEFINE VAR i AS INT. 
    DEFINE VAR  hNoderef AS HANDLE. 
    CREATE X-NODEREF hNoderef. 
    REPEAT i = 1 TO hParent:NUM-CHILDREN. 
          hParent:GET-CHILD(hNoderef,i). 
          IF hNoderef:NAME = "#text" THEN 
             MESSAGE "Node text: " hNoderef:NODE-VALUE. 
          ELSE 
             MESSAGE "Node name: " hNoderef:NAME. 
          RUN GetChildren(hNoderef, (level + 1)). 
    END. 
    DELETE OBJECT hNoderef. 
    END. 
    
    FUNCTION inWait RETURNS LOGICAL. 
    RETURN stillWaiting. 
    END. 
    

  3. Run example12.p to publish the BytesMessage containing an XML document.
  4. example12.p
    /* Publishes an XML document in a Bytes message. */ 
    DEFINE VARIABLE pubsubsession AS HANDLE. 
    DEFINE VARIABLE mesgH AS HANDLE. 
    DEFINE VARIABLE memVal AS MEMPTR. 
    DEFINE VAR hdoc AS HANDLE. 
    RUN  jms/pubsubsession.p PERSISTENT SET pubsubsession ("-H localhost -S 
    5162 "). 
    RUN setBrokerURL IN pubsubsession ("localhost:2506"). 
    RUN beginSession IN pubsubsession. 
    RUN createBytesMessage IN pubsubsession (OUTPUT mesgH). 
    CREATE X-DOCUMENT hdoc. 
    hdoc:LOAD("file", "personal.xml", FALSE). 
    hdoc:SAVE("memptr", memVal). 
    RUN setMemptr IN mesgH(memVal, ?, ?). 
    RUN publish IN pubsubsession ("xmlTopic", mesgH, ?, ?, ?). 
    SET-SIZE(memVal) = 0. 
    RUN deleteMessage IN mesgH. 
    RUN deleteSession IN pubsubsession. 
    
    /* 
     The personal.xml document: 
    <?xml version="1.0" encoding='UTF-8' ?> 
    <personnel> 
      <person id="Irving.Nigrini"> 
        <name><family>Nigrini</family> <given>Irving</given></name> 
        <email>inigrini@subpargolf.com</email> 
        <link manager="Thomas.Roy"/> 
      </person> 
      <person id="Jules.Nigrini"> 
        <name><family>Nigrini</family> <given>Jules</given></name> 
        <email>jnigrini@subpargolf.com</email> 
        <link manager="Thomas.Roy"/> 
      </person> 
    </personnel> 
    */ 
    

Publishing, Subscribing, and Receiving the Customer Table In a StreamMessage

Examples 14 and 15 use RAW transfer to publish, subscribe, and receive the customer table in a StreamMessage. Example 14 publishes the customer table in a StreamMessage; each customer record is a bytes item. Example 15 subscribes and receives the customer table in a StreamMessage; each customer record is a bytes item.

Follow these steps to run Examples 14 and 15:

  1. Start a server for the Sports database. Each client must connect to the database in multi-user mode.
  2. Run example15.p (1 of 2) so the subscriber is running before you publish.
  3. example15.p
    /* Receives the customer table in a Stream message. */ 
    DEFINE VARIABLE pubsubsession AS HANDLE. 
    DEFINE VARIABLE msgConsumer1 AS HANDLE. 
    DEFINE TEMP-TABLE custt LIKE customer. 
    RUN  jms/pubsubsession.p PERSISTENT SET pubsubsession  
     ("-H localhost -S 5162 "). 
    RUN setBrokerURL IN pubsubsession ("localhost:2506"). 
    RUN beginSession IN pubsubsession. 
    RUN createMessageConsumer IN pubsubsession(THIS-PROCEDURE, 
    "messageHandler", 
                                                 OUTPUT msgConsumer1). 
    RUN subscribe IN pubsubsession (
                      "topic1", 
                      ?,      /* Not a durable subscription */ 
                      ?,      /* No message selector */ 
                      no,     /* noLocal */ 
                      msgConsumer1). 
    RUN startReceiveMessages IN pubsubsession. 
    WAIT-FOR u1 OF THIS-PROCEDURE. 
    FOR EACH custt: 
        DISPLAY custt with 2 column. 
    END. 
    RUN deleteSession IN pubsubsession. 
    
    PROCEDURE messageHandler: 
    DEFINE INPUT PARAMETER messageH AS HANDLE NO-UNDO. 
    DEFINE INPUT PARAMETER messageConsumerH AS HANDLE NO-UNDO. 
    DEFINE OUTPUT PARAMETER replyH AS HANDLE NO-UNDO. 
    DEFINE VAR rawCust AS RAW. 
    DO WHILE NOT  DYNAMIC-FUNCTION('endOfStream' IN messageH): 
        DYNAMIC-FUNCTION('moveToNext':U IN messageH). 
        rawCust = DYNAMIC-FUNCTION('readBytesToRaw':U IN messageH). 
        RAW-TRANSFER rawCust TO custt. 
        RELEASE custt. 
    END. 
    RUN deleteMessage IN messageH. 
    APPLY "U1" TO THIS-PROCEDURE. 
    END. 
    

    example14.p 
    /* Publishes the customer table in a Stream message. */ 
    DEFINE VARIABLE pubsubsession AS HANDLE. 
    DEFINE VARIABLE mesgH AS HANDLE. 
    DEFINE VARIABLE rawCust AS RAW. 
    RUN  jms/pubsubsession.p PERSISTENT SET pubsubsession ("-H localhost -S 
    5162 "). 
    RUN setBrokerURL IN pubsubsession ("localhost:2506"). 
    RUN beginSession IN pubsubsession. 
    RUN createStreamMessage IN pubsubsession (OUTPUT mesgH). 
    FOR EACH customer: 
        RAW-TRANSFER customer TO rawCust. 
        RUN writeBytesFromRaw IN mesgH(rawCust). 
    END. 
    RUN publish IN pubsubsession ("topic1", mesgH, ?, ?, ?). 
    RUN deleteMessage IN mesgH. 
    RUN deleteSession IN pubsubsession. 
    

Publishing and Receiving a Group Of Messages In a Transaction

Examples 22 and 23 publish and receive a group of messages in a single transaction. Example 22 creates a session that is transacted for sending and Example 23 creates a session that is transacted for receiving.

Follow these steps to publish and receive a group of messages in a transaction:

  1. Run example23.p (1 of 2) so the subscriber is running before you publish.
  2. example23.p
    /* Subscribes and receives three messages in a single transaction. */ 
    DEFINE VARIABLE pubsubsession AS HANDLE. 
    DEFINE VARIABLE consumerH AS HANDLE. 
    DEFINE VARIABLE msgNum AS INT INIT 0. 
    /* Creates a transaction for receiving session. */ 
    RUN  jms/pubsubsession.p PERSISTENT SET pubsubsession ("-H localhost -S 
    5162 "). 
    RUN setBrokerURL IN pubsubsession ("localhost:2506"). 
    RUN setTransactedReceive IN pubsubsession. 
    RUN beginSession IN pubsubsession. 
    /* Subscribe to the TestTopic topic. Messages are handled by the 
       "msgHandler" internal procedure. 
    */ 
    RUN createMessageConsumer IN pubsubsession ( 
                   THIS-PROCEDURE,   /* This proc will handle it */ 
                   "msgHandler",     /* name of internal procedure */ 
                   OUTPUT consumerH). 
    RUN subscribe IN pubsubsession (
                        "TestTopic",  /* name of topic */ 
                        ?,            /* Subscription is not durable */ 
                        ?,            /* No message selector */ 
                        no,           /* Want my own messages too */ 
                        consumerH).   /* Handles the incoming messages*/ 
    /* Start receiving messages */ 
    RUN startReceiveMessages IN pubsubsession. 
    /* Wait to receive the three messages. */ 
    WAIT-FOR u1 OF THIS-PROCEDURE. 
    
    PROCEDURE msgHandler: 
    DEFINE INPUT PARAMETER messageH AS HANDLE.  
    DEFINE INPUT PARAMETER msgConsumerH AS HANDLE. 
    DEFINE OUTPUT PARAMETER replyH AS HANDLE. 
    /* Display the message - we assume that reply is not required. */ 
    DISPLAY "Message text: " DYNAMIC-FUNCTION('getText':U IN messageH) 
      FORMAT "x(70)". 
    RUN deleteMessage IN messageH. 
    msgNum = msgNum + 1. 
    /* Commit the reception of the three messages. */ 
    IF msgNum = 3 THEN 
    DO: 
      RUN commitReceive IN pubsubsession. 
      message "committed!". 
      APPLY "U1" TO THIS-PROCEDURE.  
    END. 
    END. 
    

  3. Run example22.p to subscribe and receive messages from example22.p in a single transaction.
  4. example22.p 
    /* Publishes A group of Text messages in a single transaction. */ 
    DEFINE VARIABLE pubsubsession AS HANDLE. 
    DEFINE VARIABLE messageH AS HANDLE. 
    /* Creates a transcated for sending session. */ 
    RUN  jms/pubsubsession.p PERSISTENT SET pubsubsession ("-H localhost -S 
    5162 "). 
    RUN setBrokerURL IN pubsubsession ("localhost:2506"). 
    RUN setTransactedSend IN pubsubsession. 
    RUN beginSession IN pubsubsession. 
    /* Create a text message */ 
    RUN createTextMessage IN pubsubsession (OUTPUT messageH).  
    /* Publish three messages */ 
    RUN setText IN messageH ("message1"). 
    RUN publish IN pubsubsession ("TestTopic", messageH, ?, ?, ?). 
    RUN setText IN messageH ("message2"). 
    RUN publish IN pubsubsession ("TestTopic", messageH, ?, ?, ?). 
    RUN setText IN messageH ("message3"). 
    RUN publish IN pubsubsession ("TestTopic", messageH, ?, ?, ?). 
    /* Commit the publication of the messages. */ 
    RUN commitSend IN pubsubsession. 
    RUN deleteMessage IN messageH. 
    RUN deleteSession IN pubsubsession. 
    

Installing an Error Handler To Handle an Asynchronous Error

Example 16 installs an error handler to detect a JMS server communication loss.

Follow these steps to install an error handler to handle an asynchronous error:

  1. Run example16.p.
  2. example16.p
    /* Installs an error handler to deal with a JMS server communication loss. 
    */ 
    DEFINE VARIABLE pubsubsession AS HANDLE. 
    DEFINE VARIABLE errorConsumer AS HANDLE. 
    DEFINE VARIABLE jmsIsOk AS LOGICAL INIT yes. 
    RUN  jms/pubsubsession.p PERSISTENT SET pubsubsession ("-H localhost -S 
    5162 "). 
    RUN setBrokerURL IN pubsubsession ("localhost:2506"). 
    RUN beginSession IN pubsubsession. 
    RUN createMessageConsumer IN pubsubsession(THIS-PROCEDURE,
      "errorHandler", 
      OUTPUT errorConsumer). 
    RUN setErrorHandler IN pubsubsession (errorConsumer). 
    RUN startReceiveMessages IN pubsubsession. 
    /* Wait forever for messages until the connection with the JMS server is
       lost with error code "-5" (shutdown the SonicMQ broker to simulate
       that). 
    */ 
    RUN waitForMessages IN pubsubsession ("inWait", THIS-PROCEDURE, ?). 
    IF NOT jmsIsOk THEN  
    DO: 
        MESSAGE "Disocnnectiong from JMS Server... "VIEW-AS ALERT-BOX. 
        RUN deleteSession IN pubsubsession. 
    END. 
    
    FUNCTION inWait RETURNS LOGICAL. 
    RETURN jmsIsOk. 
    END. 
    
    PROCEDURE errorHandler: 
    DEFINE INPUT PARAMETER messageH AS HANDLE NO-UNDO. 
    DEFINE INPUT PARAMETER messageConsumerH AS HANDLE NO-UNDO. 
    DEFINE OUTPUT PARAMETER replyH AS HANDLE NO-UNDO. 
    DEFINE VAR errorCode AS CHAR NO-UNDO. 
    DEFINE VAR errorText AS CHAR NO-UNDO. 
    ASSIGN
      errorCode =  DYNAMIC-FUNCTION
        ('getCharProperty':U IN messageH, "errorCode") 
    errorText = DYNAMIC-FUNCTION('getText':U IN messageH). 
    RUN deleteMessage IN messageH. 
    MESSAGE errorText errorCode VIEW-AS ALERT-BOX. 
    IF errorCode = "-5" THEN 
        jmsIsOk = no. 
    END. 
    

  3. Shut down the SonicMQ broker to simulate the communication loss.
Installing an Error Handler For Synchronous Errors

The procedure in example17.p publishes a TextMessage to a nonexistent topic and handles the error conditions.

example17.p
/* Publishes A Text message to an illegal topic name and handles the   
   error conditions. */ 
DEFINE VARIABLE pubsubsession AS HANDLE. 
DEFINE VARIABLE messageH AS HANDLE. 
DEFINE VARIABLE Successful-publish AS LOGICAL INIT false. 
/* Creates a session object. */ 
RUN  jms/pubsubsession.p PERSISTENT SET pubsubsession ("-H localhost -S 5162 
"). 
RUN setNoErrorDisplay IN pubsubsession (true). 
RUN setBrokerURL IN pubsubsession ("localhost:2506"). 
RUN beginSession IN pubsubsession. 
/* Create a text message */ 
RUN createTextMessage IN pubsubsession (OUTPUT messageH).  
RUN setText IN messageH ("Golf shoes on sale today."). 
/* Publish the message on the illegal '*' topic */ 
DO ON ERROR UNDO, LEAVE: 
  RUN publish IN pubsubsession ("*", messageH, ?, ?, ?). 
  Successful-publish = true. 
END. 
If NOT Successful-publish THEN 
    MESSAGE "Failed to publish to topic '*': " RETURN-VALUE VIEW-AS ALERT-BOX. 
RUN deleteMessage IN messageH. 
RUN deleteSession IN pubsubsession. 


Copyright © 2004 Progress Software Corporation
www.progress.com
Voice: (781) 280-4000
Fax: (781) 280-4095