How to get SDTMap properties in Spring Cloud Stream

anan1401
anan1401 Member Posts: 1
edited September 2021 in Tips and Tricks #1

We are using SDTMap to set custom application properties in one service which produce message..which uses normal springboot service. We access solace message api and create SDTMap.

In Consumer we use spring cloud stream to receive and process.

How to get SDTMap properties in Spring Cloud Stream?

Comments

  • Jeff
    Jeff Member, Employee Posts: 3 Solace Employee
    edited September 2021 #2

    Hi @anan1401,

    User properties can be directly accessed as Spring message headers.

    For example, suppose you published a message containing a string user property called some-user-property, you can then get it in your consumer as follows:

    @Bean
    public Consumer<Message<?>> sink(){
        return message -> {
            message.getHeaders().get("some-user-property", String.class);
            // other message processing
        };
    }
    

    On the other hand, if what you're asking about are SDTMap payloads, then you can get that as-if you're getting any other type of message payload.

    e.g.:

    @Bean
    public Consumer<SDTMap> sink(){
        return payload -> {
            // Do something with this SDTMap payload
        };
    }
    
  • Aaron
    Aaron Member, Administrator, Moderator, Employee Posts: 636 admin

    Huh! I didn't know that..!

  • hong
    hong Guest Posts: 480 ✭✭✭✭✭

    Hi @anan1401, FYI. I changed the question in the title to make it easier for others to find it via Google. :)

  • as63010
    as63010 Member Posts: 14

    Thanks Team for your support.
    We tested and see the output. Any way to differentiate SDTMap header with other headers?

    Example:
    Set SDTMap:

    SDTMap map = JCSMPFactory.onlyInstance().createMap();
    try {
    map.putString("Test", "Vishwa");
    map.putString("Test1", "Vishwa1");
    map.putString("Test2", "Vishwa2");
    } catch (SDTException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    message.setProperties(map);

    Spring cloud response:

    headers={solace_expiration=0, deliveryAttempt=1, solace_destination=GRACE/VCA/Initializer, solace_timeToLive=0, solace_receiveTimestamp=0, Test2=Vishwa2, target-protocol=kafka, Test1=Vishwa1, acknowledgmentCallback=com.solace.spring.cloud.stream.binder.util.JCSMPAcknowledgementCallbackFactory$JCSMPAcknowledgementCallback@422641b8, solace_discardIndication=false, Test=Vishwa, solace_dmqEligible=false, solace_priority=-1, solace_redelivered=false, solace_correlationId=25151c30-e629-47f5-b340-20f7f2397560, id=8be4f1ec-da0e-d9b9-6477-9f8cde2a04e7, contentType=application/json, timestamp=1631869287739}]

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

    Hi @as63010,

    The short answer is to do that you'd want to include your SDTMap in the payload of your message so it's kept separate OR to use a naming convention that allows you to separate the ones you want. Note that all of the Solace Message Headers start with "solace_" so you could easily filter those out.

    The longer answer:
    When you use JCSMPProperties.setProperties you are essentially setting a bunch of "User Properties" on the outgoing SMF message as defined in the javadocs. The user properties section of the SMF message is where custom headers are stored so your headers will be intermingled with custom headers added by the framework itself. When a SMF message arrives at the Solace binder we essentially read out the defined Solace headers and assign them as defined in that link and then any other user properties are just added to the Spring Message as headers as well so you can use them as desired. This is why they are all bundled together.

    @Jeff please feel free to chime in if I'm missing something here :)

  • Jeff
    Jeff Member, Employee Posts: 3 Solace Employee
    edited September 2021 #7

    As an alternative solution to what @marc suggested, you could also publish messages that have a single user property of type SDTMap and set all your custom properties in there. That way when its consumed by a Spring Cloud Stream application, those would all be grouped up under a single Spring message header.

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

    @Jeff said:
    As an alternative solution to what @marc suggested, you could also publish messages that have a single user property of type SDTMap and set all your custom properties in there. That way when its consumed by a Spring Cloud Stream application, those would all be grouped up under a single Spring message header.

    Nice, I like that idea!