Acknowledge message using ID

lilyevsky
lilyevsky Member Posts: 6

I usually acknowledge messages explicitly using BytesXMLMessage.ackMessage() method.
This is pretty convenient, because I don't need to worry about how it is done in the implementation. However, there is one essential problem: I need to have the message object around when I want to call the ackMessage(). In my specific scenario (which may be actually very common), I extract data from the message and do some processing, and I want to acknowledge it only if everything goes without errors. I saw somewhere in Solace API documentation that it is not recommended to cache messages; in any case, keeping them around for too long is a waste of memory. Besides, under Flink environment which I am using, with all that checkpoint infrastructure, keeping Solace messages is very problematic.
Here is my question: can I just save a little piece of that message (some sort of ID) which I can later use to do the ack? I believe that when I call ackMessage(), inside it uses some ID to send to the broker anyway, it should not need the whole message.

Comments

  • lilyevsky
    lilyevsky Member Posts: 6

    I think I found the solution.
    In my code I use synchronous consumer of the FlowReceiver type, I get it like this:
    flow = session.createFlow(null, flowProperties);
    It appears that the actual runtime type of it is FlowHandleImpl, which can be cast to interface FlowHandle:
    flowHandle = (FlowHandle) flow;
    Then, from each message I can retrieve message ID, using getMessageIdLong() method. Then I use flowHandle to send the ack:
    flowHandle.sendSingleAck(id, true);
    Not sure about the second parameter, should I set it to false?
    Anyway, I tested it and it works.

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

    Hey @lilyevsky . Slowly getting around to responding to your various posts. Thanks for pointing out this (unofficial) way of being able to ACK a message based on an ID. It's something we're discussing internally at Solace about supporting officially, so maybe in the future, who knows? But yeah, I've been using JCSMP for quite a few years and never figured this out, so VERY COOL!

    I also mentioned it in my weekly Twitch livestream. And apologies for butchering your name! :cry:
    https://www.youtube.com/watch?v=6fW_u_s6RDI&t=2505s

  • dmueller
    dmueller Member Posts: 2
    edited June 2023 #4
    Hi @lilyevsky and @Aaron, is this still the way to go? I couldn't find any other solution to ack the messages without having the Message object itself. However, for me the `flowHandle.sendSingleAck(ackMessageId, true);` doesn't work. The message is not being removed from Queue. Could someone provide a "more complete" example code? Thanks for your help.

    Edit: Here's my code:

    long MESSAGE_ID_TO_ACK = 3163170561L;

    JCSMPProperties properties = new JCSMPProperties();
    properties.setProperty(JCSMPProperties.HOST, "...");
    properties.setProperty(JCSMPProperties.USERNAME, "...");
    properties.setProperty(JCSMPProperties.PASSWORD, "...");
    properties.setProperty(JCSMPProperties.VPN_NAME, "...");
    properties.setProperty(JCSMPProperties.MESSAGE_ACK_MODE, JCSMPProperties.SUPPORTED_MESSAGE_ACK_CLIENT);

    JCSMPSession session = JCSMPFactory.onlyInstance().createSession(properties);
    session.connect();

    Queue queue = JCSMPFactory.onlyInstance().createQueue("my-queue-name");
    ConsumerFlowProperties flowProperties = new ConsumerFlowProperties();
    flowProperties.setEndpoint(queue);

    FlowReceiver flowReceiver = session.createFlow(null, flowProperties);
    flowReceiver.start();

    FlowHandle flowHandle = (FlowHandle) flowReceiver;
    flowHandle.sendSingleAck(MESSAGE_ID_TO_ACK, true);

    while(true) {
    //
    }
  • dmueller
    dmueller Member Posts: 2

    @lilyevsky @Aaron Can you help?

  • plalit
    plalit Member Posts: 1
    The same is happening to me

    If I provide a listener to flow then it seems to be working fine

    FlowReceiver flowReceiver = session.createFlow(new QueueFlowListener(), flowProperties);
    flowReceiver.start();

    My use case is like this :

    Messages are consumed by different application and once these are consumed, messageid will be sent to some other application to acknowledge

    Please help on how to achieve this
  • Aaron
    Aaron Member, Administrator, Moderator, Employee Posts: 497 admin

    Hi team. Thanks for the comments on this older thread. I had totally forgotten about this API quirk. I'm 99% sure since this method in JCSMP is undocumented, it's not intended for use. So (officially) I can't recommend this way of doing things.

    But, due to your comments, I've asked internally to our Product Line Management if/what are the plans on providing such a feature. I can totally see some use cases for this, just wanting to ACK using an ID of some sort. So as of right now, this isn't possible, but will come back here with an update when I hear one.

  • Tankarakesh
    Tankarakesh Member Posts: 1

    @Aaron @amackenzie any update on this ?