Design and a develop a simple two-way communication chat app, such that there are 2 windows-
1. Admin window - Here a new user can be registered in the system & display the list of all registered users. In this window, admin can select a user and send a message. Also chat history should be shopwn for the selected user such that sent & received messages are shown in time sorted order.
2. User window - Here user will receive all the unread messages from admin as Alerts. Also a chat history should be shown for the sent and received messages.
Note - Login/Logout option is not required, so decide your own about the way when multiple users use the same window on the same system.
Below is a simple design created which can further be enhanced as per requirements-
1. Executive Summary
Below blog is the architecture for a lightweight, bi-directional, stateful messaging system designed to link an Admin console with dynamic user sessions.
Rather than relying on formal authentication (such as OAuth2 or Session Cookies), user identity is dynamically bound to the email value entered in a client-side text field.
Three key additions to the Admin Console:
2. System Architecture & Flow Analysis
The system relies on a dual-protocol backend:
2.1. Dynamic Session Handshake & Message Routing
Unlike typical web applications where the security context is anchored to a session ID, identity here is completely fluid and bound to the active email text field.
Routing logic in MessageController.processMessage():
if receiver == '[email protected]' => /topic/admin-alerts
else => /queue/user-alerts/<receiver>
=> /topic/admin-sent (if sender is admin)
The /topic/admin-sent broadcast, lets the Admin Console history panel reflect outgoing
messages in real time without requiring a REST round-trip after each send.
2.2. Admin Console Layout
The Admin Console is now a three-column layout:
1. Admin window - Here a new user can be registered in the system & display the list of all registered users. In this window, admin can select a user and send a message. Also chat history should be shopwn for the selected user such that sent & received messages are shown in time sorted order.
2. User window - Here user will receive all the unread messages from admin as Alerts. Also a chat history should be shown for the sent and received messages.
Note - Login/Logout option is not required, so decide your own about the way when multiple users use the same window on the same system.
Below is a simple design created which can further be enhanced as per requirements-
1. Executive Summary
Below blog is the architecture for a lightweight, bi-directional, stateful messaging system designed to link an Admin console with dynamic user sessions.
Rather than relying on formal authentication (such as OAuth2 or Session Cookies), user identity is dynamically bound to the email value entered in a client-side text field.
Three key additions to the Admin Console:
- A persistent User Registry panel that allows the admin to register or remove user email addresses independently of message history.
- A Live Message History panel on the right that shows all sent and received messages in real time, labelled with direction (to/from) and filterable by email address.
- A dedicated UserRegistryController and RegisteredUser JPA entity to support the new registry REST endpoints.
2. System Architecture & Flow Analysis
The system relies on a dual-protocol backend:
- REST (Representational State Transfer) API: Used for synchronous operations — initial state synchronisation, message delivery acknowledgement, historical conversation log retrieval, and user registry management.
- WebSockets with STOMP (Simple Text Oriented Messaging Protocol): Used for high-speed, real-time message dispatch to active web clients and real-time echo of outgoing admin messages to the history panel.
2.1. Dynamic Session Handshake & Message Routing
Unlike typical web applications where the security context is anchored to a session ID, identity here is completely fluid and bound to the active email text field.
Routing logic in MessageController.processMessage():
if receiver == '[email protected]' => /topic/admin-alerts
else => /queue/user-alerts/<receiver>
=> /topic/admin-sent (if sender is admin)
The /topic/admin-sent broadcast, lets the Admin Console history panel reflect outgoing
messages in real time without requiring a REST round-trip after each send.
2.2. Admin Console Layout
The Admin Console is now a three-column layout:
3. Database Design
A relational, file-based H2 database schema is optimal here.
3.1. Entity Schema: messages
A relational, file-based H2 database schema is optimal here.
3.1. Entity Schema: messages
3.2. Entity Schema: registered_users
Stores admin-managed user email registrations independently from message history.
Users can be pre-registered before they send any messages.
Stores admin-managed user email registrations independently from message history.
Users can be pre-registered before they send any messages.
3.3. Structural Optimisation Constraints
4. API Design Specifications
4.1. User Registry Endpoints
- Composite Index: IDX_MSG_RCV_READ on (receiver_email, is_read) — prevents full-table scans during high-frequency unread-fetch queries.
- Unique constraint on registered_users.email — enforced at database level to prevent duplicate registrations without relying solely on application-level checks.
- No foreign keys / joins — single denormalised messages table eliminates join penalties; the registered_users table is intentionally decoupled.
4. API Design Specifications
4.1. User Registry Endpoints
POST /api/users/register response codes:
4.2. Message Endpoints
- 201 Created — email was newly registered
- 409 Conflict — email already exists in registry
- 400 Bad Request — email field is missing or blank
4.2. Message Endpoints
The GET /api/messages/all endpoint powers the Admin Console right-panel history feed on initial load.
4.3. Endpoint: Acknowledge Message Read — Security Logic
Server-side validation protects data integrity against client-side tampering:
Message msg = repository.findById(payload.messageId);
if (!msg.getReceiverEmail().equalsIgnoreCase(payload.clientSessionEmail)) {
return HTTP 403 Forbidden; // Identity mismatch — abort
}
msg.setRead(true);
repository.save(msg);
return HTTP 204 No Content;
5. WebSocket / STOMP Reference
Endpoint: ws://localhost:8080/ws/stomp (SockJS fallback enabled)
4.3. Endpoint: Acknowledge Message Read — Security Logic
Server-side validation protects data integrity against client-side tampering:
Message msg = repository.findById(payload.messageId);
if (!msg.getReceiverEmail().equalsIgnoreCase(payload.clientSessionEmail)) {
return HTTP 403 Forbidden; // Identity mismatch — abort
}
msg.setRead(true);
repository.save(msg);
return HTTP 204 No Content;
5. WebSocket / STOMP Reference
Endpoint: ws://localhost:8080/ws/stomp (SockJS fallback enabled)
6. Architectural Diagrams
6.1. Sequence Diagram:
Admin Console Interaction
Admin loads console → fetches /api/users and /api/messages/all → subscribes to /topic/admin-alerts and /topic/admin-sent.
Admin registers a user → POST /api/users/register → registry panel refreshes via GET /api/users.
Admin selects a user card → target email pre-filled → GET /api/messages/history loads that conversation in the right panel.
Admin sends a message → WebSocket /app/send-message → server persists → routes to /queue/user-alerts/<email/id> + echoes on /topic/admin-sent → right panel live feed updates.
User sends a message → WebSocket /app/send-message → server persists → routes to /topic/admin-alerts → right panel live feed updates + toast notification fires.
6.2. State Transition Diagram: Alert Event Status
[ Message Generated ] → UNREAD (default)
REST POST /api/messages/ack → identity validation →
YES match → READ (permanent)
NO mismatch → HTTP 403 Forbidden (state unchanged)
6.3. Frontend Module Architecture
The Admin Console JavaScript is now structured around four responsibilities:
7. Architectural Trade-offs & Analysis
6.1. Sequence Diagram:
Admin Console Interaction
Admin loads console → fetches /api/users and /api/messages/all → subscribes to /topic/admin-alerts and /topic/admin-sent.
Admin registers a user → POST /api/users/register → registry panel refreshes via GET /api/users.
Admin selects a user card → target email pre-filled → GET /api/messages/history loads that conversation in the right panel.
Admin sends a message → WebSocket /app/send-message → server persists → routes to /queue/user-alerts/<email/id> + echoes on /topic/admin-sent → right panel live feed updates.
User sends a message → WebSocket /app/send-message → server persists → routes to /topic/admin-alerts → right panel live feed updates + toast notification fires.
6.2. State Transition Diagram: Alert Event Status
[ Message Generated ] → UNREAD (default)
REST POST /api/messages/ack → identity validation →
YES match → READ (permanent)
NO mismatch → HTTP 403 Forbidden (state unchanged)
6.3. Frontend Module Architecture
The Admin Console JavaScript is now structured around four responsibilities:
- WebSocket management — connectWebSocket(), setWsStatus()
- Message dispatch — dispatchMessage() via STOMP /app/send-message
- History feed — pushToHistory(), renderHistory(), filterHistoryDisplay(), refreshHistory()
- User registry — fetchUserRegistry(), renderUserList(), registerUser(), removeUser(), removeUserByEmail()
7. Architectural Trade-offs & Analysis
RSS Feed