Lejdi Prifti

0 %
Lejdi Prifti
Software Engineer
Web3 Developer
ML Practitioner
  • Residence:
    Albania
  • City:
    Tirana
  • Email:
    info@lejdiprifti.com
English
Italian
French
Spring
React & Angular
Machine Learning
Docker & Kubernetes
AWS & Cloud
Team Player
Communication
Time Management
  • Java, JavaScript, Python
  • AWS, Kubernetes, Azure
  • Bootstrap, Materialize
  • Stylus, Sass, Less
  • Blockchain, Ethereum, Solidity
  • React, React Native, Flutter
  • GIT knowledge
  • Machine Learning, Deep Learning
0

No products in the basket.

Configuring WebSocket in Spring-Boot and React

15. October 2023

In this article, I am going to describe step-by-step how you can configure WebSocket in Spring Boot and use it with React.

Dependencies

We only need two dependencies since I’m trying to minimize the number of dependencies required to a minimum.

				
					<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <scope>provided</scope>
    </dependency>
</dependencies>
				
			

WebSocket Configuration

Next, we will go and create the WebSocketConfig configuration class. It implements the WebSocketMessageBrokerConfigurer and is annotated with Configuration and EnableWebSocketMessageBroker .

Configurationindicates that the class is a Spring configuration class, and it’s used to define Spring beans and configurations for the application.

@EnableWebSocketMessageBrokerenables WebSocket-based messaging within the application and configures it as a message broker.

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}

@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/")
.setAllowedOrigins("http://localhost:3000")
.withSockJS();
}
}

Now, let’s look at the methods within the WebSocketConfig class:

Configure the message broker

  • configureMessageBroker(MessageBrokerRegistry config): This method is used to configure the message broker for the WebSocket.

config.enableSimpleBroker("/topic") enables a simple message broker that allows clients to subscribe to and receive messages from the specified destination prefix, which is /topic. Messages sent by the server to topics starting with /topic will be broadcasted to connected clients.

config.setApplicationDestinationPrefixes("/app") sets the application destination prefix. Clients can send messages to destinations that start with this prefix. For example, a client can send a message to /app/destination.

Register the Stomp endpoint

  • registerStompEndpoints(StompEndpointRegistry registry) registers a Stomp (Simple Text Oriented Messaging Protocol) endpoint that clients can connect to.

registry.addEndpoint("/")registers the root endpoint (i.e., “/”) as the WebSocket endpoint. Clients can connect to this endpoint to establish WebSocket connections and we will see how in the React app.

withSockJS()enables SockJS support, which is a JavaScript library that provides a WebSocket-like interface for browsers that don’t support WebSocket directly. This allows broader client compatibility.

SpringBoot Controller

Let’s create a simple controller. @Controller indicates that this class is a Spring MVC controller. It handles WebSocket requests.

@MessageMapping("/chat/{chatId}")indicates that it handles messages sent to the specified WebSocket destination. The @SendTo("/topic/chat/{chatId}") annotation specifies the destination to which the method will send the response. This is where the client on React will be listening to.

@DestinationVariable String chatId extracts the chatId from the destination path.

@Payload Message<UserText> message extracts the message payload from the incoming message.

				
					@Slf4j
@Controller
public class WebSocketController {

 private final Map<String, List<UserText>> chats = new HashMap<>();

 @MessageMapping("/chat/{chatId}")
 @SendTo("/topic/chat/{chatId}")
 public List<UserText> sendMessageWithWebsocket(@DestinationVariable String chatId,
   @Payload Message<UserText> message) {
  log.info("new message arrived in chat with id {}", chatId);
  List<UserText> messages = this.chats.getOrDefault(chatId, new ArrayList<UserText>());
  messages.add(message.getPayload());
  chats.put(chatId, messages);
  return messages;
 }
}
				
			

Here, we store the messages in an array called messages and then store that array in a map with the chat ID as its identifier. Using the annotation @DestinationVariable, we can obtain the chat ID. Every user will subscribe to a different conversation and only view the messages in that chat.

Start your application and run the following command in terminal to check if you can connect successfully to the WebSocket endpoint.

				
					wscat -c ws://localhost:8080/websocket
				
			

Build simple React app

To connect to React, we will need the following dependency:

npm install --save @stomp/stompjs

Let’s edit the App.tsx to suit our needs. What we do here, is that we define the WebSocket broker url which connects to our server. Afterwards, we configure the client on line 20 and specify what it must execute when it connects for the first time in line 25. In line 37, we activate the client. All this is done inside the useEffect whenever the chatId changes. 

Finally, in line 56, whenever the button is clicked, we send the message in the topic we configured before. In this case, the message is hard coded but it can be easily retried from an input element. 

				
					import { Client } from '@stomp/stompjs';
import { useEffect, useState } from 'react';
import './App.css';
import logo from './logo.svg';

function App() {
  let client: Client | null = null;

  const [chatId, setChatId] = useState("")

  useEffect(() => {
    // Create a WebSocket connection

    client = new Client();

    // Configure the WebSocket endpoint URL
    const websocketUrl = 'ws://localhost:8080/websocket'; // Replace with your WebSocket endpoint URL

    // Connect to the WebSocket server
    client.configure({
      brokerURL: websocketUrl,
      debug: function (str) {
        console.log(str);
      },
      onConnect: () => {
        // Perform actions after successful connection
        const destination = `/topic/chat/${chatId}`; // Specify the destination for the server-side message handler
        client && client.subscribe(destination, (message) => {
          console.log('Received message:', JSON.parse(message.body));
          // Process the received message as needed
        });
      },
      // You can add more event handlers and configuration options as needed
    });

    // Connect to the WebSocket server
    client.activate();


    // Clean up the connection on component unmount
    return () => {
      client && client.deactivate();
    };
  }, [chatId]);


  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          <input type='text' aria-label='ChatId' onChange={(event) => {
            console.log(event)
            setChatId(event.target.value)
          }}></input>
          <button onClick={() => {
            const destination = `/app/chat/${chatId}`; // Specify the destination for the server-side message handler
            const message = 'Hello, server!'; // Specify the message to send
            if (client != null) {
              client.publish({
                destination,
                body: JSON.stringify({
                  data: message,
                  userId: 1 // Specify a user ID
                }),
              });
            }
          }}>Send</button>
        </p>
      </header>
    </div>
  );
}

export default App;
				
			

This is how you can configure WebSocket in Spring Boot and use it with React. If you liked the article, consider sharing or donating.

For contact, drop a message in contact page.

Thank you!

Buy Me A Coffee
Posted in SpringBootTags:
3 Comments
  • […] Configuring WebSocket in Spring-Boot and React […]

    22:49 16. October 2023 Reply
  • Hamdi

    Does the conversation persist after the application is restarted or if the WebSocket server is disconnected ?
    Do we need a database to store the messages ?

    16:02 5. February 2024 Reply
    • No, the conversation does not persist. The moment a message arrives it must be saved in a database in order to achieve persistence.

      17:46 6. February 2024 Reply
Write a comment