Here is the App.jsx, all the packages are installed:
import React, { useState, useEffect, useRef } from 'react';
import SockJS from 'sockjs-client';
import { Client } from '@stomp/stompjs';
function App() {
const [messages, setMessages] = useState([]);
const [inputMessage, setInputMessage] = useState('');
const [senderName, setSenderName] = useState('');
const [isConnected, setIsConnected] = useState(false);
// Use a ref to keep track of the stompClient instance across renders
const stompClientRef = useRef(null);
useEffect(() => {
// 1. Initialize SockJS connection matching Spring Boot endpoint
const socket = new SockJS('http://localhost:8080/ws');
// 2. Create Stomp Client Configuration
const client = new Client({
webSocketFactory: () => socket,
reconnectDelay: 5000, // Auto-reconnect if connection drops
onConnect: () => {
setIsConnected(true);
console.log('Connected to WebSocket server');
// 3. Subscribe to the public topic to receive broadcasted messages
client.subscribe('/topic/messages', (message) => {
if (message.body) {
const parsedMessage = JSON.parse(message.body);
setMessages((prev) => [...prev, parsedMessage]);
}
});
},
onDisconnect: () => {
setIsConnected(false);
console.log('Disconnected');
},
onStompError: (frame) => {
console.error('Broker error: ' + frame.headers['message']);
}
});
// 4. Activate the connection
client.activate();
stompClientRef.current = client;
// Cleanup connection when component unmounts
return () => {
if (stompClientRef.current) {
stompClientRef.current.deactivate();
}
};
}, []);
const sendMessage = (e) => {
e.preventDefault();
if (!inputMessage.trim() || !senderName.trim()) return;
// Check if client is active and connected before publishing
if (stompClientRef.current && stompClientRef.current.connected) {
const chatMessage = {
sender: senderName,
content: inputMessage,
};
// Publish to the Spring mapping endpoint
stompClientRef.current.publish({
destination: '/app/chat',
body: JSON.stringify(chatMessage),
});
setInputMessage('');
}
};
return (
<div style={{ padding: '20px', fontFamily: 'Arial' }}>
<h2>Spring Boot + React WebSocket Chat</h2>
<p>Status: <strong>{isConnected ? '🟢 Connected' : '🔴 Disconnected'}</strong></p>
<div style={{ marginBottom: '10px' }}>
<input
type="text"
placeholder="Your Name"
value={senderName}
onChange={(e) => setSenderName(e.target.value)}
style={{ marginRight: '10px', padding: '5px' }}
/>
</div>
<div style={{ border: '1px solid #ccc', height: '300px', overflowY: 'scroll', padding: '10px', marginBottom: '10px' }}>
{messages.map((msg, index) => (
<div key={index} style={{ margin: '5px 0' }}>
<strong>{msg.sender}:</strong> {msg.content}
</div>
))}
</div>
<form onSubmit={sendMessage}>
<input
type="text"
placeholder="Type a message..."
value={inputMessage}
onChange={(e) => setInputMessage(e.target.value)}
style={{ width: '70%', padding: '5px', marginRight: '10px' }}
/>
<button type="submit" disabled={!isConnected} style={{ padding: '5px 15px' }}>
Send
</button>
</form>
</div>
);
}
export default App;
Here is the Spring Boot controller. I even added @CrossOrigin, to allow all headers and all origins but that also didn't work:
@CrossOrigin(origins = "*", allowedHeaders = "*")
@RestController
public class ChatController {
// When a client sends a message to /app/chat, this method is triggered
@MessageMapping("/chat")
// The return value is automatically broadcasted to all subscribers of /topic/messages
@SendTo("/topic/messages")
public ChatMessage sendMessage(ChatMessage message) {
return message;
}
}
I tried to add this in the application.properties, but still nothing changed.
spring.application.name=SpringBootReact_WebSocketConnectionapp.cors.allowed-origins=${CORS_ALLOWED_ORIGINS:http://localhost:5173}
Code compiles successfully, but websocket connection is not established.
When running the react app in browser both chrome and edge, I see WebSocket is not connected and getting following errors in console as shown in this screenshot.
Here are the logs from Spring Boot application after loading the web page:
2026-09-25T15:11:04.041+05:30 INFO 19804 --- [SpringBootReact_WebSocketConnection] [MessageBroker-1] o.s.w.s.c.WebSocketMessageBrokerStats : WebSocketSession[0 current WS(0)-HttpStream(0)-HttpPoll(0), 0 total, 0 closed abnormally (0 connect failure, 0 send limit, 0 transport error)], stompSubProtocol[processed CONNECT(0)-CONNECTED(0)-DISCONNECT(0)], stompBrokerRelay[null], inboundChannel[pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0], outboundChannel[pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0], sockJsScheduler[pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 0]
