Regarding setting JMSProperties with the help of solclient C api

amol_p81
amol_p81 Member Posts: 22
edited February 2022 in PubSub+ Event Broker #1

Hi,
Please let me know how can i set the JMSProperties to value (other then NULL ) via solclient C api, as presently i'm using solclient_msg_setXML for setting the Payload as XML, but the JMSProperties still has NULL e.g. below message with JMSProperties NOT NULL
JMSDeliveryMode:2,JMSDestination:Topic 't.rfds.ds.notify.int5',JMSExpiration:1588958554273,JMSMessageID:ID:fe80:0:0:0:250:56ff:fea2:2a21%eth0dff5171eb010b570:4,JMSPriority:0,JMSRedelivered,JMSTimestamp:1588785753229,JMSProperties:
{cobdate:04-MAY-2020,snapshotid:41,valuationcontextid:1b_VAR-1d,statusremarks:,brds_dsloadid:1,rowcount:331,confidence_level:.99,dsloadid:103103087,scenario_context:VaR,package_type:FINAL,horizon:1d,measure_type:VaR,feedid:65,timetaken:6431,ds_wf_status:COMPLETED,datasource:RFDS,dsname:PA HISTSIM HYBRID VAR,runtype:HISTSIM_VAR_RFG,notificationtype:DATASET,grainids:[11b54131428443c9899974420d113cf5],taskid:164,snaptype:VaR_1d_FINAL
,JMS_Solace_isXML:true,JMS_Solace_DeliverToOne:false,JMS_Solace_DeadMsgQueueEligible:false,JMS_Solace_ElidingEligible:false,Solace_JMS_Prop_IS_Reply_Message:false}
,SolPayload:{XML:len=438} }

but the message transmitted via my code:

JMSDeliveryMode:1,JMSDestination:Topic 't.rfds.ds.notify.int5',JMSExpiration:0,JMSMessageID:2,JMSPriority:0,JMSRedelivered,JMSTimestamp:0,JMSProperties:{JMS_Solace_isXML:true,JMS_Solace_DeliverToOne:false,JMS_Solace_DeadMsgQueueEligible:false,JMS_Solace_ElidingEligible:false,Solace_JMS_Prop_IS_Reply_Message:false},SolPayload:{XML:len=295} }.

Thx

Tagged:

Comments

  • TomF
    TomF Member, Employee Posts: 406 Solace Employee

    Hi @amol_p81, I'd be interested to know why you're trying to set JMS properties on a message and then sending it via the C CAPI. Is there a reason you're using C and not JMS? Is the receiver a JMS receiver?
    In any event, solclient_msg_setXML sets the XML Data portion of a message see API reference entry. This is almost certainly not what you want to do, as it appears (although I'm not certain) that you're trying to set some JMS properties. Is this correct? Could you tell us which properties you'd like to set?
    If you use the C API you're sending the message in SMF format. You can attach a JMS receiver and get the messages in JMS format, but Solace has to map between SMF headers and JMS headers. You can read more about the SMF to JMS header and property mappings in the message components documentation - it has a rather nice example of how you'd send in C using solClient_msg_setCorrelationId and get that in JMS with message.getJMSCorrelationID.

  • amol_p81
    amol_p81 Member Posts: 22

    Yes Tom, the receiver is a JMS receiver and they want few of the fields to be set. For e.g JMSMessageID (have set via setApplicationMessageId) and 2nd one is JMSProperties , which i tried via changing the format of message from Byte to xml but didn't worked out (they need text message only).

  • amol_p81
    amol_p81 Member Posts: 22

    Also the page https://docs.solace.com/Solace-JMS-API/Message-Components.htm doesn't mentions anything on field JMSProperties.

  • marc
    marc Member, Administrator, Moderator, Employee Posts: 914 admin
    edited May 2020 #5

    Hey @amol_p81,
    In the C API ignore the name "JMSProperties" and just set each property separately. When this gets mapped to the JMS message they'll be retrievable via getIntProperty, getStringProperty, etc.

    I simulated this using sdkperf_java b/c my machine isn't setup for c dev right now (but sdkperf_java uses SMF just like the C API)
    sdkperf_java.sh -cip localhost:55555 -cu default@default -cp default -ptl abc/topic2 -mn 1 -mr 1 -cpl Int,snapshotid,521

    Then on the JMS side you should be able to get a list of JMS Properties available and query them in your onMessage. For example,

        @Override
        public void onMessage(Message message) {
            try {
                System.out.println("Message received.");
                    System.out.println(("snapshotid:" + Integer.toString(message.getSgetIntProperty("snapshotid"))));
                System.out.printf("Message Content:%n%s%n", SolJmsUtility.dumpMessage(message));
            } catch (JMSException ex) {
                System.out.println("Error processing incoming message.");
                ex.printStackTrace();
            }
        }
    

    Output from running that..

    Message received.
    snapshotid:521
    
    Message Content:
    JMSDeliveryMode:                        1
    JMSDestination:                         Topic 'abc/topic2'
    JMSExpiration:                          0
    JMSPriority:                            0
    JMSDeliveryCount:                       1
    JMSTimestamp:                           0
    JMSProperties:                          {snapshotid:521,JMS_Solace_DeliverToOne:false,JMS_Solace_DeadMsgQueueEligible:false,JMS_Solace_ElidingEligible:false,JMS_Solace_MsgDiscardIndication:false,Solace_JMS_Prop_IS_Reply_Message:false,JMSXDeliveryCount:1}
    Destination:                            Topic 'abc/topic2'
    Class Of Service:                       USER_COS_1
    DeliveryMode:                           DIRECT
    Message Id:                             4
    User Property Map:                      1 entries
      Key 'snapshotid' (Integer): 521
    
  • amol_p81
    amol_p81 Member Posts: 22

    ok, will the createUserPropertyMap serve the same purpose?

  • amol_p81
    amol_p81 Member Posts: 22

    For setting JMSProperties, i have used solClient_msg_setXml , solClient_msg_setBinaryAttachment and solClient_msg_setBinaryAttachmentString which seems inappropriate.
    Which one would be correct function to send/publish text messages in C api?

  • amol_p81
    amol_p81 Member Posts: 22

    I need to send "cobdate:04-MAY-2020,snapshotid:41,valuationcontextid:1b_VAR-1d,statusremarks:,brds_dsloadid:1,rowcount:331,confidence_level:.99,dsloadid:103103087,scenario_context:VaR,package_type:FINAL,horizon:1d,measure_type:VaR,feedid:65,timetaken:6431,ds_wf_status:COMPLETED,datasource:RFDS,dsname:PA HISTSIM HYBRID VAR,runtype:HISTSIM_VAR_RFG,notificationtype:DATASET,grainids:[11b54131428443c9899974420d113cf5],taskid:164,snaptype:VaR_1d_FINAL" as a complete message and this should be visible after JMSProperties.
    To achieve this via C, i have used solclient_msg_createUserPropertyMap and solclient_container_addString which seems to have set value for JMSProperties, however i'm getting one extra field which needs to be discarded i.e. JMS receiver shows following:
    JMSProperties:{message:cobdate:04-MAY-2020,snapshotid:41,valuationcontextid:1b_VAR-1d,statusremarks:,brds_dsloadid:1,rowcount:331,confidence_level:.99,dsloadid:103103087,scenario_context:VaR,package_type:FINAL,horizon:1d,measure_type:VaR,feedid:65,timetaken:6431,ds_wf_status:COMPLETED,datasource:RFDS,dsname:PA HISTSIM HYBRID VAR,runtype:HISTSIM_VAR_RFG,notificationtype:DATASET,grainids:[11b54131428443c9899974420d113cf5],taskid:164,snaptype:VaR_1d_FINAL.

    Just before sending i'm doing something as below:
    //in below text_p contains the complete string which should be displayed after JMSProperties.
    solclient_container_addString (container, text_p, "message");

    Any pointers to get rid of message:.

  • amol_p81
    amol_p81 Member Posts: 22

    In order to achieve value of JMSProperties getting displayed i have used fns solClient_msg_createUserPropertyMap and solClient_container_addString, however now in properties i see extra field message:.

    JMSProperties:
    {message:cobdate:04-MAY-2020,snapshotid:41,valuationcontextid:1b_VAR-1d,statusremarks:,brds_dsloadid:1,rowcount:331,confidence_level:.99,dsloadid:103103087,scenario_context:VaR,package_type:FINAL,horizon:1d,measure_type:VaR,feedid:65,timetaken:6431,ds_wf_status:COMPLETED,datasource:RFDS,dsname:PA HISTSIM HYBRID VAR,runtype:HISTSIM_VAR_RFG,notificationtype:DATASET,grainids:[11b54131428443c9899974420d113cf5],taskid:164,snaptype:VaR_1d_FINAL

    My code has something as below:

    // messageField has textMessage starting from cobdate till VaR_1d_FINAL
    solClient_container_addString ( userPropContainer, messageField, "message" )

    Any pointers how to get rid of message: after JMSProperties???

  • marc
    marc Member, Administrator, Moderator, Employee Posts: 914 admin
    edited May 2020 #10

    Hi @amol_p81,
    It seems like you're really close! You're correct that you'll want to use a Map so you can have key value pairs in the properties section of your message so they can be translated to JMSProperties. Currently if I'm following your posts correctly it looks like you're creating a map and then adding 1 property called message which contains a string value that contains all your info. But I think what you want to do is set individual key/value pairs for each piece of info that you want available as a JMSProperty instead of setting them all as one called message:

    You can approach this similar to the following:
    Create your map

        /* Create the message independent Map. */
        if ( ( rc = solClient_container_createMap ( &userPropContainer, map, sizeof ( map ) ) ) != SOLCLIENT_OK ) {
            common_handleError ( rc, "solClient_container_createMap()" );
            goto sessionConnected;
        }
    

    Add each of your properties (cobdate:04-MAY-2020, snapshotid:41, valuationcontextid:1b_VAR-1d, etc)

      /* Populate the Map with a string. */
            if ( ( rc = solClient_container_addString ( userPropContainer, "value", "key" ) ) != SOLCLIENT_OK ) {
                common_handleError ( rc, "solClient_container_addString()" );
                goto freeMessage;
            }
    

    Set the map as the user properties in the message to allow them to be retrieved as JMSProperties

        /* Set the user property map attachment that is to be the Map. */
            if ( ( rc = solClient_msg_setUserPropertyMap ( msg_p, userPropContainer ) ) != SOLCLIENT_OK ) {
                common_handleError ( rc, "solClient_msg_setUserPropertyMap()" );
                goto freeMessage;
            }
    

    -Marc

  • amol_p81
    amol_p81 Member Posts: 22

    Yes, Mark followed the mentioned approach and seems to be fine now.

  • amol_p81
    amol_p81 Member Posts: 22
    edited May 2020 #12

    However needed additional information on SOLCLIENT_DELIVERY_MODE_DIRECT , when i set this as delivery mode i don't receive any acknowledgement back.
    Only for SOLCLIENT_DELIVERY_MODE_PERSISTENT i receive acknowledgement.
    Any clue for getting acknowledgement back in SOLCLIENT_DELIVERY_MODE_DIRECT?

  • marc
    marc Member, Administrator, Moderator, Employee Posts: 914 admin

    Hey @amol_p81,
    Awesome, glad you were able to get properties passing properly from your app using the C API to the one using JMS.

    As for the follow-up question, what you are seeing here is by design and you have the option to choose between two different qualities of service (QoS).

    • Event producers can send event messages using a guaranteed QoS by setting the message’s Persistent Delivery Mode to Persistent. This flag instructs the broker to reply to the producer with an acknowledgment when the broker has stored the message in durable storage (including HA and / or DR replication).
    • When event messages arrive at the broker with Persistent Delivery Mode set to Direct, the message is placed at the tail of the Non-Persistent Event Stream and no acknowledgement is sent to the producer.

    Depending on your choice of QoS the events pass through the broker differently. This page goes into a lot of detail on that: https://docs.solace.com/PubSub-ConceptMaps/Event-Stream-Maps.htm

    -Marc

  • amol_p81
    amol_p81 Member Posts: 22

    Marc,
    Regarding using maps for setting JMSProperties, i'm using functions solClient_msg_createUserPropertyMap and solClient_container_addString only, however the order of inserting into map is different then when retrieved /seen at JMS receiver.
    Can you please update how the map is getting sorted i.e. cobdate:, run_id: are displayed first at receiver side despite being inserted towards end when inserting into Map?

    Regards
    Amol

  • marc
    marc Member, Administrator, Moderator, Employee Posts: 914 admin

    Hi @amol_p81,
    In general, best practice when using maps would be to retrieve values via the key as different languages and library implementations may treat maps differently and many don't guarantee order. So I highly recommend retrieving via the key and not relying on order of the properties in the map.

    To get a bit more info I also talked to someone on our engineering team and the C SDK serializes the map as it is being created, and consequently if read by the C sdk properties should be retrieved in the same order. That said, the JCSMP/JMS APIs convert the serialized map from the wire into an actual map-object which is going to be implementation dependent and insertion order of properties may not be maintained as you're seeing.

    -Marc