🎄 Happy Holidays! 🥳

Most of Solace is closed December 24–January 1 so our employees can spend time with their families. We will re-open Thursday, January 2, 2024. Please expect slower response times during this period and open a support ticket for anything needing immediate assistance.

Happy Holidays!

Please note: most of Solace is closed December 25–January 2, and will re-open Tuesday, January 3, 2023.

URGENT-Iterate through Solace Message Queue

sumeet
sumeet Member Posts: 6
Hi All,
We have read data from SOLACE queue in .Net using C# . However we are unable to iterate through SOLACE queue messages as we are not receiving Message ID or datetime.
Hence if any one could able to loop through the QUEUE message then please share the code snippet.
Thanks in advance
Sumeet

Best Answers

  • nicholasdgoodman
    nicholasdgoodman Member, Employee Posts: 43 Solace Employee
    #2 Answer ✓

    From the code snippet you have shown, can I assume that this originates from the SolaceSamples/solace-samples-dotnet GitHub repository, perhaps from QueueConsumer.cs? (here).

    If so, then this sample is designed to only receive one message from a queue before exiting. This due to the fact that QueueConsumer.Run method is executed on the main application thread. As soon as his method exits, the application will close. The Run method is put in a suspended state while waiting for the wait handle to complete: WaitEventWaitHandle.WaitOne().

    The message handler method,HandleMessageEvent, is invoked on a separate dispatcher thread and it calls WaitEventWaitHandle.Set() which signals the Run method to continue, causing the application to terminate.

    If you wish to continue reading messages from the queue, do not signal the wait handle or exit the application: simply comment out or delete the .Set call at the end of that method. You must keep one foreground thread alive at all times, as the Solace dispatcher thread runs as a background thread.

    I also observe you have commented out the Ack call - and that is fine if you wish to receive the messages without removing them from the queue, up to a point. Eventually, the broker will stop delivering messages when there are too many unacknowledged messages on a single consumer. If you wish to see all the messages and leave them on the broker, the preferred pattern is a queue browser instead.

  • nicholasdgoodman
    nicholasdgoodman Member, Employee Posts: 43 Solace Employee
    #3 Answer ✓

    Hello again @sumeet,

    What does the publisher look like? (Is it also .NET?) What you may be seeing is a payload header which is automatically inserted when the publisher has specified a "text" payload or SDT (struct) payload instead of a raw, binary one.

    Do you have access to the publisher code and can verify or modify it? Otherwise, there is a way of decoding this information correctly on receiver side in C#. I will have to look it up, though.

Answers

  • nicholasdgoodman
    nicholasdgoodman Member, Employee Posts: 43 Solace Employee

    Greetings Sumeet,

    A few questions: when you say iterate through the queue messages, are you looking to consume messages off the queue (e.g. to dequeue them), or do you mean you would like to read messages within a queue and leave them in place?

    If are are receiving data from the queue, then the requisite headers should also be available within the same message received callback - assuming the headers were set in the first place. Do note that the majority of the ID and timestamp fields are unused by default, and must be specified by the publisher either at connection time or when the message was first published. The one exception to this is IMessage.ReplicationGroupMessageId which is assigned by the broker for all guaranteed (queued) messages.

    Can you provide some more clarity on what you are trying to do and perhaps share some minimal code showing what is not working?

  • sumeet
    sumeet Member Posts: 6

    Hi Nicholas,

    When I say Iterate It means- say for example there are 10 messages in SOLACE queue(having Mesaage ID and dateTimestamp visible on Solace Management Console ) and we need to loop through them from oldest to Newest. Then what should be the ideal approach.

    (Also consume messages off the queue or leave msgs. in queue after reading is what we have achieved already)

    1)Best Approach to reading message list
    What could be the correct way to loop as currently we tried is session.createflow. Below is the code snippet

    Along with below session property
    SocketReceiveBufferSizeInBytes = 8000000 to receive all the queue messages.

    Also we are trying to explore QueueBrowser. Can you pls let us know if this is a better technique of reading a list of multiple messages( https://docs.solace.com/API/Solace-JMS-API/Browsing-Messages.htm )

    If possible can you share code snippet for c#.

    *************************************************************************
    Thanks a lot for sharing below information :)

    Thanks,
    Sumeet

  • nicholasdgoodman
    nicholasdgoodman Member, Employee Posts: 43 Solace Employee
    #6 Answer ✓

    From the code snippet you have shown, can I assume that this originates from the SolaceSamples/solace-samples-dotnet GitHub repository, perhaps from QueueConsumer.cs? (here).

    If so, then this sample is designed to only receive one message from a queue before exiting. This due to the fact that QueueConsumer.Run method is executed on the main application thread. As soon as his method exits, the application will close. The Run method is put in a suspended state while waiting for the wait handle to complete: WaitEventWaitHandle.WaitOne().

    The message handler method,HandleMessageEvent, is invoked on a separate dispatcher thread and it calls WaitEventWaitHandle.Set() which signals the Run method to continue, causing the application to terminate.

    If you wish to continue reading messages from the queue, do not signal the wait handle or exit the application: simply comment out or delete the .Set call at the end of that method. You must keep one foreground thread alive at all times, as the Solace dispatcher thread runs as a background thread.

    I also observe you have commented out the Ack call - and that is fine if you wish to receive the messages without removing them from the queue, up to a point. Eventually, the broker will stop delivering messages when there are too many unacknowledged messages on a single consumer. If you wish to see all the messages and leave them on the broker, the preferred pattern is a queue browser instead.

  • nicholasdgoodman
    nicholasdgoodman Member, Employee Posts: 43 Solace Employee
    edited September 2023 #7

    Please find a modified version of the QueueConsumer sample, below, which will read all messages from a queue until the user presses a key to close the application:

        static void Run(string host, string vpnname, string username, string password)
        {
            try
            {
                // Initialize Solace Systems Messaging API with logging to console at Warning level
                var props = new ContextFactoryProperties() { SolClientLogLevel = SolLogLevel.Warning };
                props.LogToConsoleError();
                ContextFactory.Instance.Init(props);
    
                // Define context and session properties
                var contextProperties = new ContextProperties();
                var sessionProperties = new SessionProperties()
                {
                    Host = host,
                    VPNName = vpnname,
                    UserName = username,
                    Password = password,
                    ConnectRetries = DefaultConnectRetries,
                };
                var queueName = "Q/tutorial";
                var flowProperties = new FlowProperties()
                {
                    AckMode = MessageAckMode.ClientAck
                };
    
                // Create context and session instances
                using (var context = ContextFactory.Instance.CreateContext(contextProperties, null))
                using (var session = context.CreateSession(sessionProperties, null, null))
                {
                    // Connect to the Solace messaging router
                    Console.WriteLine($"Connecting as {username}@{vpnname} on {host}...");
                    var connectResult = session.Connect();
    
                    if (connectResult == ReturnCode.SOLCLIENT_OK)
                    {
                        Console.WriteLine("Session successfully connected.");
    
                        using (var queue = ContextFactory.Instance.CreateQueue(queueName))
                        using (var flow = session.CreateFlow(flowProperties, queue, null, HandleMessageEvent, HandleFlowEvent))
                        {
                            flow.Start();
    
                            Console.WriteLine($"Waiting for a message in the queue '{queueName}'...");
                            Console.WriteLine($"Press any key to exit. ----------------------");
                            Console.WriteLine();
                            Console.ReadKey(true);
                        }
                    }
                    else
                    {
                        Console.WriteLine($"Error connecting, return code: {connectResult}");
                    }
                }
                        
            }
            finally
            {
                // Dispose Solace Systems Messaging API
                ContextFactory.Instance.Cleanup();
            }
            Console.WriteLine("Finished.");
        }
        static void HandleMessageEvent(object source, MessageEventArgs args)
        {
            var flow = source as IFlow;
    
            // Received a message
            Console.WriteLine("Received message.");
            using (IMessage message = args.Message)
            {
                // Expecting the message content as a binary attachment
                Console.WriteLine($"Message content: {Encoding.UTF8.GetString(message.BinaryAttachment)}");
                // ACK the message
                flow.Ack(message.ADMessageId);
            }
        }
    

  • sumeet
    sumeet Member Posts: 6

    Hi Nicholas,
    Yes the code sample belongs fron Solacesample-dotnet.

    Have tried commenting // WaitEventWaitHandle.Set();
    And could able to loop through.

    Will also Analyse the above queueconsumer sample and keep you posted.
    Well Thanks you for all the help and support!


    Thanks,

    Sumeet

  • sumeet
    sumeet Member Posts: 6
    edited October 2023 #9

    hi @nicholasdgoodman ,
    Hope you are fine.
    I am facing illegal character issue while Deserialize the queue message at my end .how to overcome it. Please suggest
    Below is the string in bold
    \u001f\0\u0004�y{"e

    Thanks,

    Sumeet Joshi

  • sumeet
    sumeet Member Posts: 6

    hi @nicholasdgoodman ,
    Hope you are fine.
    I am facing illegal character issue while Deserialize the queue message at my end .how to overcome it. Please suggest
    Below is the string in bold
    \u001f\0\u0004�y{"e

    Thanks,

    Sumeet Joshi

  • nicholasdgoodman
    nicholasdgoodman Member, Employee Posts: 43 Solace Employee
    #11 Answer ✓

    Hello again @sumeet,

    What does the publisher look like? (Is it also .NET?) What you may be seeing is a payload header which is automatically inserted when the publisher has specified a "text" payload or SDT (struct) payload instead of a raw, binary one.

    Do you have access to the publisher code and can verify or modify it? Otherwise, there is a way of decoding this information correctly on receiver side in C#. I will have to look it up, though.

  • sumeet
    sumeet Member Posts: 6

    Hi @nicholasdgoodman ,
    Publisher is on JAVA.
    Not having access to pub code. Have decode it using ASCII characters list for now. Thanks for the assistance.

    Regards,

    Sumeet