reactjsnode.jsazureazureservicebus

How to establish connection from browser(client) to Azure Service Bus for sending / receiving messages from queues and topics using React JS


I am new to Azure Service Bus and I am able to create queues and topic & subscriptions and could able to send and receive messages using Azure portal. With the help of com.azure.messaging.servicebus.administration dependency we could able to create/modify queues and topics and subscription from backend(Spring boot - 2.5.0 & Java - 17) also. For doing the same we created a POC and it worked well.

Now we face challenge while establishing connection from browser (UI) to azure service bus directly. I have created one sample react JS application but couldn't able to connect from browser to azure service bus.

The error we get is given below. "azure:service-bus:connection:warning [connection-1]Error(context.error) occured on the amqp connection:"

I have used the dependencies below.

"@azure/identity":"^4.4.1", "@azure/service-bus":"^7.9.5"

Our react JS version is 16.13.1 and node JS version is 16.18.0. We need help for finding the correct dependency for for establishing the connection between azure service bus and browser from UI. Along with that it will be helpful if we get some code snippets for doing the same for a headstart.

I have tried with below code

import React, { useState } from 'react';
import { ServiceBusClient } from '@azure/service-bus';
import { setLogLevel } from '@azure/logger';

setLoglevel("verbose");

const   connectionString    =   import.meta.env.VITE_SERVICE_BUS_CONNECTION_STRING;
const   queueName           =   import.meta.env.VITE_QUEUE_NAME;
const   timeOutInMs         =   Number(import.meta.env.VITE_TIMEOUT_IN_MS) || 60000;

        console.log("connectionString is :", connectionString);
        console.log("queueName is :", queueName);
        console.log("timeOutInMs is :", timeOutInMs);

function azureServiceBusComponent() {
    
        const [responseMessage, setResponseMessage] =   useState('');
        const [receivedMessages, setReceivedMessages]   =   useState([]);
        
        const sbClient = new ServiceBusClient(connectionString, {
            webSocketOptions:   {
                webSocketEndpointPath   :   '/$servicebus/websocket',
            },
            retryOptions    :   {
                timeOutInMs :   timeOutInMs,
            }
        }); 
        
        console.log("sbClient is created:", sbClient);
        
        const   sender = sbClient.createSender(queueName);
        console.log("sender is:", sender);
        
        const sendMessage = async () => {
            
            const messages = [
            {   body:   "hello world"   },
            
            ];
            
            try{
                
                const result = await.sender.sendMessages(messages);
                console.log("result is:", result);
                    await sender.close();
                    await sbClient.close();
            }   catch(error)    {
                console.error("Error sending messages:", error);
            }   
                console.log("After Sending :", sender);
        };
        
        
        const receiveMessage = async () =>  {
            const sbClient  =   new ServiceBusClient(connectionString);
            console.log("sbClient in receiver", sbClient);
            const receiver = sbClient.createReceiver(queueName);
            console.log("receiver is", receiver);
            try {
                const messages = await receiver.receiveMessage(5, {receiveMode
                :
                "receiveAndDelete"});
                const newMessages = messages.map((msg)  =>  msg.body);
                console.log("newMessages is", newMessages);
                
                setReceivedMessages((prevMessages) => [...prevMessages, ...newMessages ]);
                
                for (let msg of messages)   {
                    await receiver.completeMessage(msg);
                }
                
                }   catch(error)    {
                console.error("Error receiving messages:", error);
                
            }   
            finally{
            
                await receiver.close;
                await sbClient.close;
            }
                
        };
                    
            
    return  (
        <div>   
            <h2>Send Message to Azure Service Bus </h2>
            <button onClick={sendMessage}>Send Messages</button>
            {responseMessage && <p>{responseMessage}</p>}
            {<div>
                <h3>Received Messages</h3>
                <button onClick={receiveMessage}>Receive Messages</button>
                <ul>
                {receivedMessages.map((msg, index) =>   (
                    <li key = {index}>{msg}</li>
                    ))}
                    </ul>
                </div>}
        </div>
        
    );
    
    
}

export default azureServiceBusComponent;

Solution

  • I successfully sent and received messages to and from Azure Service Bus Queue using the Vite React.js application from the browser (UI) directly.

    Here is the complete code from the GitHub Repository.

    Code :

    AzureServiceBusComponent.jsx :

    import React, { useState } from 'react';
    import { ServiceBusClient } from '@azure/service-bus';
    import { setLogLevel } from '@azure/logger';
    
    setLogLevel('verbose');
    const safeTrim = (value) => (value || '').trim();
    const connectionString = safeTrim(import.meta.env.VITE_SERVICE_BUS_CONNECTION_STRING);
    const queueName = safeTrim(import.meta.env.VITE_QUEUE_NAME);
    const timeOutInMs = Number(import.meta.env.VITE_TIMEOUT_IN_MS) || 60000;
    
    console.log('connectionString is:', connectionString);
    console.log('queueName is:', queueName);
    console.log('timeOutInMs is:', timeOutInMs);
    
    function AzureServiceBusComponent() {
        const [responseMessage, setResponseMessage] = useState('');
        const [receivedMessages, setReceivedMessages] = useState([]);
        const sbClient = new ServiceBusClient(connectionString, {
            retryOptions: {
                timeoutInMs: timeOutInMs,
            },
        });
    
        const sender = sbClient.createSender(queueName);
        const sendMessage = async () => {
            try {
                await sender.sendMessages({ body: 'Hello World!' });
                setResponseMessage('Message sent successfully!');
            } catch (error) {
                console.error('Error sending messages:', error);
            }
        };
    
        const receiveMessage = async () => {
            const receiver = sbClient.createReceiver(queueName);
            try {
                const messages = await receiver.receiveMessages(5, { receiveMode: 'receiveAndDelete' });
                const newMessages = messages.map((msg) => msg.body);
                setReceivedMessages((prev) => [...prev, ...newMessages]);
                for (let msg of messages) {
                    await receiver.completeMessage(msg);
                }
            } catch (error) {
                console.error('Error receiving messages:', error);
            } finally {
                await receiver.close();
                await sbClient.close();
            }
        };
    
        return (
            <div>
                <h2>Send Message to Azure Service Bus</h2>
                <button onClick={sendMessage}>Send Message</button>
                {responseMessage && <p>{responseMessage}</p>}
                <div>
                    <h3>Received Messages</h3>
                    <button onClick={receiveMessage}>Receive Messages</button>
                    <ul>
                        {receivedMessages.map((msg, index) => (
                            <li key={index}>{msg}</li>
                        ))}
                    </ul>
                </div>
            </div>
        );
    }
    export default AzureServiceBusComponent;
    

    App.jsx :

    import React from 'react';
    import AzureServiceBusComponent from './components/AzureServiceBusComponent';
    const App = () => {
      return (
        <div>
          <h1>Azure Service Bus Test</h1>
          <AzureServiceBusComponent />
        </div>
      );
    };
    export default App;
    

    .env :

    VITE_SERVICE_BUS_CONNECTION_STRING=<ServiceBusQueueConnec>
    VITE_QUEUE_NAME=<queueName>
    VITE_TIMEOUT_IN_MS=60000
    

    Output :

    enter image description here

    Browser Output :

    I have sent and received messages to Azure Service Bus queues as shown below.

    enter image description here

    Azure Portal :

    I received the following message in the Azure Service Bus Queue when I sent it from the application via the browser (UI).

    enter image description here