solacesolace-mq

Solace Request-Response issues while using across platforms ( C# and JAVA )


I am attempting to implement Request-Response in Solace.

However RR-Requestor is written in C# whereas the code for the RR-Responder is written in JAVA.

I’ve 2 issues:

  1. After the message is successfully sent by the Solace C# API, it is received by a JAVA application. I happen to receive the message in BytesXMLMessage structure. How do I convert the message to String? message.dump() gives me the entire details.

  2. When I send a reply message, .NET application receives the message with some additional unwanted characters.

Code used in the JAVA side:

    //After session is created
    XMLMessageConsumer consumer = session.getMessageConsumer(new RequestHandler());
    XMLMessageProducer producer = session.getMessageProducer(new PrintingPubCallback());
    consumer.start();
    session.addSubscription(
            JCSMPFactory.onlyInstance().createTopic("Test_Response_Queue"),
            true);
    class RequestHandler implements XMLMessageListener {

    private void sendReply(BytesXMLMessage request, BytesXMLMessage reply)
            throws JCSMPException {

        producer.sendReply(request, reply);

    }

    public void onException(JCSMPException arg0) {
        // TODO Auto-generated method stub

    }

    public void onReceive(BytesXMLMessage message) {
        System.out.println("Received request message, trying to parse it");

        System.out.println(message.dump());

        try {

            TextMessage textMessage = JCSMPFactory.onlyInstance()
                    .createMessage(TextMessage.class);

            final String text = "Reply from JAVA, text message!!";
            textMessage.setText(text);

            sendReply(message, textMessage);

        } catch (JCSMPException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

And in the .NET side

            // Create the request message
        IMessage requestMessage = ContextFactory.Instance.CreateMessage();
        requestMessage.Destination = ContextFactory.Instance.CreateTopic("Test_Response_Queue");
        requestMessage.DeliveryMode = MessageDeliveryMode.Direct; /* explicitly set to MessageDeliveryMode.Direct */
        //IStreamContainer stream = SDTUtils.CreateStream(requestMessage, 256);
        //stream.AddString("Hello from Linux!!");
        requestMessage.BinaryAttachment = Encoding.ASCII.GetBytes("Hello from Linux!!");

        // Send the request message to the service or RRDirectReplier
        IMessage replyMessage = null;
        int timeout = 2000; /* 2 secs*/
        Console.WriteLine("\nSending  request message, waiting for {0} msecs for a reply (make sure that RRDirectReply is running) ...", timeout);

        if (session.SendRequest(requestMessage, out replyMessage, 2000) == ReturnCode.SOLCLIENT_OK)
        {
            // Got a reply, format and print the response message
            Console.WriteLine("\nGot reply message");
            String str = Encoding.ASCII.GetString(replyMessage.BinaryAttachment);
            Console.WriteLine(str);
        }
        else
        {
            Console.WriteLine("Request failed");
        }
        if (requestMessage != null)
        {
            // It is a good practice to dispose of messages once done using them
            requestMessage.Dispose();
        }

Reply contains additional characters in the string received. See the image below.

enter image description here

Any idea?

Thanks.


Solution

  • There are several methods to send/receive strings between the different APIs, and here are 2 possible methods.

    1. Convert the string to an array of bytes and attach it as a binary payload to the Solace message.

    .NET send:

    IMessage message = ContextFactory.Instance.CreateMessage();
    message.Destination = topic;
    message.BinaryAttachment = Encoding.UTF8.GetBytes("My .NET String");
    session.Send(message);
    

    Java receive:

    // assuming that message is a reference to a received message
    if(message.getAttachmentByteBuffer() != null) {
        byte[] messageBinaryPayload = message.getAttachmentByteBuffer().array();
        try {
            String myReceivedText = new String(messageBinaryPayload, "UTF-8");
            System.out.println("Received String = " + myReceivedText);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
    else {
        // No binary attachment in message - application needs to decide what to do next.
    }
    

    Java send:

    String myJavaString = "My Java String";
    BytesXMLMessage message = JCSMPFactory.onlyInstance().createMessage(BytesXMLMessage.class);
    message.writeAttachment(myJavaString.getBytes(Charset.forName("UTF-8")));
    producer.send(message, topic);
    

    .NET receive:

    // assuming that message is a reference to a received message
    byte[] messageBinaryPayload = message.BinaryAttachment;
    
    if(messageBinaryPayload != null) {
        string myReceivedString = System.Text.Encoding.UTF8.GetString(messageBinaryPayload);
        Console.WriteLine("Received String = " + myReceivedString);
    }
    else {
        // No binary attachment in message - application needs to decide what to do next.
    }
    

    2. Send and receive the string as a TextMessage

    .NET send:

    IMessage message = ContextFactory.Instance.CreateMessage();
    message.Destination = topic;
    SDTUtils.SetText(message, "My .NET String");
    session.Send(message);
    

    Java receive:

    // assuming that message is a reference to a received message
    if (message instanceof TextMessage) {
        String myReceivedString = ((TextMessage) message).getText();
        System.out.println("Received String = " + myReceivedString);
    } 
    else {
        // Message is not a TextMessage - application needs to decide what to do next.
    }
    

    Java send:

    TextMessage message = JCSMPFactory.onlyInstance().createMessage(TextMessage.class);
    message.setText("My Java String");
    producer.send(message, topic);
    

    .NET receive:

    // assuming that message is a reference to a received message
    String myReceivedString = SDTUtils.GetText(message);
    if (myReceivedString != null) {
        // Message is an TextMessage
        Console.WriteLine("Received String = " + myReceivedString);
    }
    else {
        // Message is not a TextMessage - application needs to decide what to do next.
    }