A realtime chat backend application built with Spring Boot, supporting:
- JWT Authentication (register, login, logout)
- Public and room-based chat via WebSocket/STOMP
- Online/offline presence tracking with heartbeat mechanism
- Multi-source data storage: MySQL (auth), MongoDB (chat rooms/messages), Redis (presence cache)
- Fast deployment with Docker Compose
- โ Java 21 โ Latest JDK with virtual threads, records, pattern matching
- ๐ฑ Spring Boot 3.2.x โ Standard web framework, auto-config, embedded server
- ๐ Spring Security + JWT โ Authentication, authorization, token-based auth (stateless)
- ๐ Spring WebSocket (STOMP + SockJS) โ Realtime 2-way communication with fallback for older browsers
- ๐๏ธ Spring Data JPA + Hibernate โ ORM, manage MySQL entities (User, Auth)
- ๐ Spring Data MongoDB โ NoSQL, store documents (Chat messages + Rooms)
- ๐ด Spring Data Redis โ In-memory cache, fast presence tracking
- ๐ฌ MySQL 8.4 โ Relational DB, auth + user data
- ๐ MongoDB 7 โ Document DB, chat history + room metadata
- โก Redis 7 โ Cache + pub/sub, user online status
- ๐ญ Docker Compose โ Run infra services for local app development (MySQL, MongoDB, Redis)
- ๐ฆ Maven 3.9 โ Build tool, dependency management
- ๐ชถ Lombok โ Reduce boilerplate (auto-generate getters, setters, constructors)
- ๐ JJWT 0.12.6 โ JWT library for signing/verifying tokens
- ๐งช JUnit 5 + Spring Boot Test โ Unit & integration testing
com.minichat/
โโโ auth/ ๐ Authentication & Authorization
โ โโโ controller/ REST: /api/auth/register, login, logout
โ โโโ dto/ Request/Response payloads
โ โโโ model/ AppUser, Role entities
โ โโโ repository/ JPA repository for users
โ โโโ security/ JWT filter, service, custom UserDetailsService
โ โโโ service/ Auth business logic
โ
โโโ chat/ ๐ฌ Chat & Presence
โ โโโ controller/ REST: /api/rooms, WebSocket: /app/...
โ โโโ dto/ CreateRoomRequest, JoinRoomRequest, etc
โ โโโ event/ UserPresenceEvent (publish/subscribe)
โ โโโ listener/ Event listeners, WebSocket listeners
โ โโโ model/ ChatMessage, ChatRoom, UserPresence, BaseEntity
โ โโโ repository/ MongoDB, MySQL, Redis repositories
โ โโโ service/ ChatService, RoomService, PresenceService
โ
โโโ config/ โ๏ธ Configuration
โ โโโ auth/ SecurityConfig (JWT filter chain)
โ โโโ websocket/ WebSocketConfig (STOMP endpoint, broker)
โ
โโโ shared/ ๐ง Shared Utilities
โโโ error/ Exception handler, custom exceptions
โโโ response/ BaseResponse, ResponseFactory
POST /api/auth/registerโ Create new account, hash password, save to MySQLPOST /api/auth/loginโ Authenticate user, issue JWT token (24h TTL)POST /api/auth/logoutโ Mark user offline, clear presence cache
POST /api/roomsโ Create chat room, persist metadata to MongoDBPOST /api/rooms/{roomId}/joinโ User joins room, add to membershipGET /api/roomsโ List all roomsGET /api/rooms/{roomId}โ Get room details (name, members, created_at)
- WebSocket endpoint:
/ws(STOMP over SockJS) - Send message:
POST /app/chat.sendMessageโ broadcast to/topic/public - Join announcement:
POST /app/chat.addUserโ announce join to/topic/public - All connected users receive messages instantly
- Send to room:
POST /app/room/{roomId}/sendโ broadcast to/topic/rooms/{roomId} - Join room:
POST /app/room/{roomId}/joinโ announce join within room topic - Messages persist in MongoDB
- Only users in the room receive messages (not global broadcast)
- User online tracking: Store presence record (username, timestamp) in Redis
- Heartbeat: Client sends
POST /app/presence.heartbeatperiodically (every 30s) - Auto offline: If no heartbeat for >30s โ mark offline, trigger event
- Event listener: Spring event listener publishes UserPresenceEvent, notifies web clients
- โ Java 21 JDK
- ๐ฆ Maven 3.9+
- ๐ฌ MySQL 8.x running locally
- ๐ MongoDB 7.x running locally
- โก Redis 7.x running locally
Default settings in src/main/resources/application.yml:
spring:
datasource:
url: jdbc:mysql://localhost:3306/mini_chat_auth
username: root
password: root
data:
mongodb:
uri: mongodb://localhost:27017/mini_chat
redis:
host: localhost
port: 6379mvn clean spring-boot:runApp runs by default at: http://localhost:8080
docker compose up -d| Service | Port | Note |
|---|---|---|
| MySQL | 3306:3306 | Auth database |
| MongoDB | 27017:27017 | Document DB |
| Redis | 6379:6379 | Cache + Presence |
# View infra logs
docker compose logs -fmvn clean spring-boot:runApp endpoint: http://localhost:8080
# Stop all services
docker compose down
# Stop & remove volumes
docker compose down -v- Endpoint:
ws://localhost:8080/ws(STOMP over SockJS) - Tools: Postman, Socket.io Client, web browser + stomp.js library
CLIENT SUBSCRIBE: /topic/public
CLIENT SEND:
destination: /app/chat.sendMessage
body: {
"sender": "alice",
"content": "Hello everyone!"
}
SERVER BROADCAST: /topic/public
{
"sender": "alice",
"content": "Hello everyone!",
"timestamp": "2025-03-17T10:30:00Z"
}
CLIENT SUBSCRIBE: /topic/rooms/room-123
CLIENT SEND:
destination: /app/room/room-123/send
body: {
"sender": "bob",
"content": "Room message"
}
SERVER BROADCAST: /topic/rooms/room-123
{
"sender": "bob",
"roomId": "room-123",
"content": "Room message",
"timestamp": "2025-03-17T10:31:00Z"
}
CLIENT SEND (every 30s):
destination: /app/presence.heartbeat
body: { "username": "alice" }
SERVER:
- Update Redis presence: alice โ timestamp
- Trigger UserPresenceEvent
- Auto clear offline after 30s timeout
๐ mini-chat
โโโ ๐ pom.xml Maven build configuration
โโโ ๐ docker-compose.yml Orchestrate infra services (MySQL, MongoDB, Redis)
โโโ ๐ README.md This file
โโโ ๐ .gitignore Ignore build, IDE, env files
โ
โโโ ๐ src/main/java/com/minichat
โโโ ๐ MiniChatApplication.java Spring Boot entry point
โ
โโโ ๐ auth/ ๐ Authentication
โ โโโ controller/
โ โโโ dto/
โ โโโ model/
โ โโโ repository/
โ โโโ security/
โ โโโ service/
โ
โโโ ๐ chat/ ๐ฌ Chat & Presence
โ โโโ controller/
โ โโโ dto/
โ โโโ event/
โ โโโ listener/
โ โโโ model/
โ โโโ repository/
โ โโโ service/
โ
โโโ ๐ config/ โ๏ธ Configuration
โ โโโ auth/
โ โโโ websocket/
โ
โโโ ๐ shared/ ๐ง Shared Utils
โโโ error/
โโโ response/
- โ Never hardcode JWT secret, DB password in
application.yml - โ
Use environment variables for production:
export APP_JWT_SECRET=your-long-secret-key export SPRING_DATASOURCE_PASSWORD=your-db-password export SPRING_DATA_REDIS_PASSWORD=your-redis-password
- โ Never commit
.envfile (add to.gitignore) - โ Use Docker secrets or Kubernetes ConfigMap for production deployments
app:
jwt:
secret: 12345678901234567890123456789012 # Min 32 chars
expiration-ms: 86400000 # 24 hours- Persistent chat history + pagination (MongoDB query with limits)
- Search messages by keyword/date range
- Archive old messages
- Direct messaging (1-on-1 private chat)
- Group chat (multiple members per room)
- Message edit/delete (soft delete + version tracking)
- Read receipts (message seen status per user)
- Typing indicators (broadcast when user is typing)
- User custom status (away, do not disturb, online)
- Per-room presence (detailed tracking of who's in which room)
- Last seen timestamp (when user last logged in)
- Push notifications (Firebase Cloud Messaging)
- Email alerts for missed messages
- In-app notification center
- Rate limiting (max messages per user per minute)
- Mute/block users
- Room admin controls (ban, kick, permission management)
- Message audit log (track edit/delete history)
- User activity statistics
- Message volume metrics
- Performance monitoring (WebSocket connection count)
- Error tracking integration (Sentry/DataDog)