A real-time stock price streaming application built with Spring Boot, WebSocket/STOMP, and RabbitMQ. This API simulates a stock exchange by generating and broadcasting live stock price updates to connected clients.
The Stock Exchange API provides:
- Real-time stock price updates for 10 major tech stocks (AAPL, GOOGL, MSFT, TSLA, AMZN, NVDA, META, NFLX, AMD, INTC)
- WebSocket/STOMP messaging for instant price delivery to clients
- Multi-instance scalability using RabbitMQ as a message broker
- Historical price data stored in PostgreSQL (in this example Azure Cosmos DB for PostgreSQL)
- Horizontal scaling support for handling millions of concurrent connections
βββββββββββββββ WebSocket/STOMP ββββββββββββββββββββ
β Browser βββββββββββββββββββββββββββββββββΊ β Spring Boot App β
β Clients β /ws or /ws-stomp β (Container App) β
βββββββββββββββ ββββββββββββββββββββ
β
β STOMP/TCP
β Port 61613
βΌ
ββββββββββββββββββββ
β RabbitMQ β
β (Message Broker) β
ββββββββββββββββββββ
β
β Persist
βΌ
ββββββββββββββββββββ
β Cosmos DB β
β (PostgreSQL) β
ββββββββββββββββββββ
The API exposes WebSocket endpoints for real-time communication:
| Endpoint | Protocol | Description |
|---|---|---|
/ws |
WebSocket + SockJS | Primary endpoint with fallback support |
/ws-stomp |
WebSocket + STOMP | Alternative STOMP endpoint |
Full URL Example:
https://{host_name}:{local_port}/ws
| Endpoint | Method | Description |
|---|---|---|
/api/stocks/current |
GET | Get current prices for all stocks |
/api/stocks/{symbol} |
GET | Get current price for specific stock |
// 1. Connect to WebSocket endpoint
const socket = new SockJS('https://{host_name}:{local_port}/ws');
const stompClient = Stomp.over(socket);
// 2. Establish connection
stompClient.connect({}, function(frame) {
console.log('Connected:', frame);
// 3. Subscribe to stock updates
// Subscribe to ALL stocks
stompClient.subscribe('/exchange/amq.topic/stock.*', function(message) {
const stockPrice = JSON.parse(message.body);
console.log('Received:', stockPrice);
updateUI(stockPrice);
});
// Or subscribe to specific stock
stompClient.subscribe('/exchange/amq.topic/stock.AAPL', function(message) {
const stockPrice = JSON.parse(message.body);
console.log('AAPL:', stockPrice);
});
});Each stock price update contains:
{
"id": 12345,
"symbol": "AAPL",
"price": 175.50,
"change": 2.30,
"changePercent": 1.33,
"dayHigh": 176.80,
"dayLow": 173.20,
"openPrice": 174.00,
"previousClose": 173.20,
"volume": 5234567,
"timestamp": "2025-12-22T14:30:00Z"
}The included index.html file serves as a live demonstration dashboard for the Stock Exchange API. It showcases real-time WebSocket connectivity and provides an interactive interface for monitoring stock prices.
- Real-time Price Display: Shows live updates for all 10 stocks in a responsive grid layout
- WebSocket Connection Management: Connect/Disconnect buttons with visual status indicators
- SockJS Fallback Support: Automatically handles browsers that don't support native WebSocket
- STOMP Protocol: Uses STOMP over WebSocket for reliable message delivery
- Visual Indicators: Color-coded price changes (green for up, red for down)
- Stock Details: Displays high/low prices, volume, and last update time
- Message Counter: Tracks the number of real-time updates received
- Open
index.htmlin any modern web browser - Replace
{host_name}:{local_port}with your actual host and port's App - Click "Connect" to establish WebSocket connection
- Watch as stock prices update in real-time (every second)
The demo file requires no server installation and connects directly to your deployed Stock Exchange API, making it perfect for testing and demonstrations.
stompClient.subscribe('/exchange/amq.topic/stock.*', callback);stompClient.subscribe('/exchange/amq.topic/stock.AAPL', callback);const symbols = ['AAPL', 'GOOGL', 'MSFT'];
symbols.forEach(symbol => {
stompClient.subscribe(`/exchange/amq.topic/stock.${symbol}`, callback);
});// Subscribe to stocks starting with 'A'
stompClient.subscribe('/exchange/amq.topic/stock.A*', callback);| Variable | Description | Default |
|---|---|---|
SPRING_DATASOURCE_URL |
PostgreSQL connection string | jdbc:postgresql://localhost:5432/stockdb |
SPRING_DATASOURCE_USERNAME |
Database username | dbadmin |
SPRING_DATASOURCE_PASSWORD |
Database password | password |
RABBITMQ_STOMP_ENABLED |
Enable RabbitMQ broker | true |
RABBITMQ_HOST |
RabbitMQ hostname | localhost |
RABBITMQ_STOMP_PORT |
RabbitMQ STOMP port | 61613 |
RABBITMQ_USERNAME |
RabbitMQ username | stockadmin |
RABBITMQ_PASSWORD |
RabbitMQ password | StockExchange2024! |
stock-exchange:
update-interval: 1000 # Price update frequency (ms)
volatility: 0.02 # Price change volatility (2%)
symbols: AAPL,GOOGL,MSFT,TSLA,AMZN,NVDA,META,NFLX,AMD,INTCπ¦ Deployment to the Azure Container App (it might be used different cloud services, not only Azure)
# Get your Container App URL
az containerapp show \
--name stock-exchange-api \
--resource-group stock-exchange-rg \
--query "properties.configuration.ingress.fqdn" \
--output tsv
# View logs
az containerapp logs show \
--name stock-exchange-api \
--resource-group stock-exchange-rg \
--followThe application automatically scales based on:
- Min replicas: 2 (always-on for high availability)
- Max replicas: 10 (scales up under load)
- RabbitMQ: Distributes messages across all instances
Open browser console (F12) and run:
const socket = new SockJS('https://your-app-url.azurecontainerapps.io/ws');
const stompClient = Stomp.over(socket);
stompClient.connect({}, function() {
console.log('Connected!');
stompClient.subscribe('/exchange/amq.topic/stock.*', function(msg) {
console.log('Update:', JSON.parse(msg.body));
});
});# Get all current prices
curl https://your-app-url.azurecontainerapps.io/api/stocks/current
# Get specific stock
curl https://your-app-url.azurecontainerapps.io/api/stocks/AAPLhttp://rabbitmq-stomp-broker.eastus.azurecontainer.io:15672
Username: stockadmin
Password: StockExchange2024!
Check the "Connections" tab in RabbitMQ Management UI to see:
- Connected Spring Boot instances
- Active STOMP sessions
- Message rates and throughput
For production deployments:
- Enable HTTPS/WSS for WebSocket connections
- Implement authentication/authorization
- Use Azure Key Vault for secrets
- Configure CORS properly for your domain
- Enable rate limiting
- Use Azure Application Gateway for DDoS protection
- Spring Boot 3.x - Application framework
- Spring WebSocket - WebSocket support
- Spring STOMP - STOMP protocol
- RabbitMQ - Message broker
- PostgreSQL - Database (Azure Cosmos DB)
- SockJS - WebSocket fallback (client-side)
- STOMP.js - STOMP client (browser)
This project is for demonstration purposes.
-
Can't connect from browser
- Verify Container App is running
- Check ingress is enabled and external
- Ensure
/wsendpoint is accessible
-
No price updates received
- Check RabbitMQ container is running
- Verify RabbitMQ STOMP plugin is enabled
- Check subscription path is correct:
/exchange/amq.topic/stock.*
-
"Invalid destination" errors
- Ensure using
/exchange/amq.topic/prefix - Check RabbitMQ configuration in application.yml
- Verify STOMP relay is properly configured
- Ensure using
Enable debug logging in browser console:
stompClient.debug = function(str) {
console.log('STOMP:', str);
};For issues or questions, check the Azure Container Apps logs:
az containerapp logs show \
--name stock-exchange-api \
--resource-group stock-exchange-rg \
--follow