How to access SDTMap from InBoundMessage

Sid
Sid Member Posts: 3

Hi, I would like to know that how can we get the SDTMap from an InBoundMessage ( with the new Solace API using the DirectMessageReceiver ). Since, the InBoundMessage wraps around the BytesXMLMessage but doesnt expose BytesXMLMessage as such from it. I have a producer that is sending SDTMap with some properties in it and need to receive it properly on the consumer to extract the same. I am using the PubSubPlus new API.

Any thoughts ?

Comments

  • Tamimi
    Tamimi Member, Administrator, Employee Posts: 529 admin
    edited February 2023 #2

    Hey @Sid - have you looked into using the MessageToSDTMapConverter class? You can also use getMap which returns the SDTMap value mapped to the specified key.

  • Aaron
    Aaron Member, Administrator, Moderator, Employee Posts: 579 admin

    Is the SDTMap in your payload (i.e. a "MapMessage") or in the User Properties? Are any of your values in the map non-Strings? Like ints or floats or other..?

  • Sid
    Sid Member Posts: 3

    Thanks for your responses.

    To make the use case a bit clearer, some code snippets as below :

    Producer side

    // build the solace message
    BytesMessage solaceMessage = JCSMPFactory.onlyInstance().createMessage(BytesMessage.class);
    SDTMap map = JCSMPFactory.onlyInstance().createMap();
    IndexedRecord avroDtoPayload = null;
    if ( envelope.getMessage() != null ){
        avroDtoPayload = (IndexedRecord) envelope.getMessage();
    }
    map.putObject("schema", avroDtoPayload.getClass());
    solaceMessage.setProperties(map);
    solaceMessage.setData(AvroSerialisationUtil.serialise(avroDtoPayload));
    

    Need to recreate the same SDTMap on the receiver side :

    public void onMessage(InboundMessage inboundMessage) {
        // TODO:
        try {
               //SDTMap map = inboundMessage.getPropperties(); doesnt work..
              //BytesXMlMessage used to have the getProperties() that used to return the SDTMap.
             //Is there a way to get the BytesXMlMessage from InboundMessage()
    
            //payload is fine.
            byte[] messageBytes = inboundMessage.getPayloadAsBytes();
    

    So, the problem statement is to make the same SDTMap from an InboundMessage ( and NOT using BytesXMLMessage ).

  • Aaron
    Aaron Member, Administrator, Moderator, Employee Posts: 579 admin
    edited February 2023 #5

    Hi @Sid..! I'm trying to reproduce your setup, and having an issue. So you're setting the User Property map in your JCSMP publisher, and trying to fetch/deserialize it on the new Java API side.

    But I don't seem to be having any luck trying to set a Class object in my JCSMP user props. I'm getting this:

    map.putObject("schema", avroDtoPayload.getClass());

    Exception in thread "main" java.lang.IllegalArgumentException: Invalid type as value - Class
    	at com.solacesystems.jcsmp.impl.sdt.MapImpl.putObject(MapImpl.java:438)
    	at com.solace.samples.jcsmp.HelloWorld.main(HelloWorld.java:130)
    

    I tried with a couple different classes, all the same result. Does IndexedRecord override the getClass() method to provide some serializable object? How is that working for you??

    But anyhow: it won't work anyway on the consumer side. The new Java API (as of current v1.1) has a restriction that it only supports String values in the user properties. I've asked this to be extended to support some of the other primitives, but I doubt it would support Object types.

    So I gotta ask: could you not pass a schema ID or something else instead? Why pass the actual Class object? And let me know how your JCSMP code works??

  • Sid
    Sid Member Posts: 3

    Thanks Aaron.

    No, I can’t pass the schemaID as the setup we have doesn’t have a schema registry running.

    Can you please give me an example as to how to set in an outbound message properties and payload, just want to be consistent on the producer side to use the new API as well. Tx