Regarding setting JMSProperties with the help of solclient C api
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
Comments
-
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.0 -
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).
0 -
Also the page https://docs.solace.com/Solace-JMS-API/Message-Components.htm doesn't mentions anything on field JMSProperties.
0 -
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 viagetIntProperty
,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
0 -
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:.
0 -
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_FINALMy 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???
0 -
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 calledmessage
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 calledmessage
: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
1 -
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?0 -
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
0 -
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
Amol0 -
Hi @amol_p81,
In general, best practice when using maps would be to retrieve values via thekey
as different languages and library implementations may treat maps differently and many don't guarantee order. So I highly recommend retrieving via thekey
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
1