Every event in Spring Community comes with a built-in real-time chat room powered by STOMP over WebSocket. When participants join an event, they can subscribe to the event’s dedicated topic channel and immediately receive messages from all other subscribers. Messages are not transient — every message is persisted to PostgreSQL the moment it is processed, so a participant who joins late can retrieve the full conversation history via a standard REST call without needing a WebSocket connection.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/CristianRR94/springCommunity/llms.txt
Use this file to discover all available pages before exploring further.
Architecture
The chat system is composed of three layers: the WebSocket transport, the STOMP message broker, and the persistence layer. Here is the flow from connection to broadcast:Connect to the WebSocket endpoint
The client opens a WebSocket connection to the
/ws-chat endpoint. This endpoint is registered by WebSocketConfig and does not use SockJS — a native WebSocket client is required.Authentication happens during the STOMP CONNECT frame: the client must include an Authorization header with a Bearer <access_token> value. The JwtChannelInterceptor intercepts the CONNECT command, extracts the token from the header, validates it via JwtProviderService, and binds the resolved username as a Principal on the WebSocket session. If the token is missing or invalid, the connection proceeds without an authenticated principal and message processing will fail.Subscribe to an event's topic
Once connected, the client subscribes to the event-specific destination:The simple in-memory broker configured under the
/topic prefix handles fan-out delivery — every subscriber to /topic/evento/{eventoId} receives a copy of each message broadcast to that destination.Send a message
The client sends a message to the application destination:The
/app prefix routes the frame to WebsocketMessageController.getMensaje(), which is annotated with @MessageMapping("/chat/{eventoId}").Controller persists and broadcasts
getMensaje() extracts the authenticated username from the injected Principal, calls mensajeService.guardarMensaje() to persist the Mensaje entity to PostgreSQL, and returns a HistorialMensajesDTO. The @SendTo("/topic/evento/{eventoId}") annotation causes Spring to broadcast the returned DTO to all subscribers of that topic automatically.Message Format
Sending: MensajeDTO
When a client sends a message it must provide aMensajeDTO JSON payload. All fields should be present; texto is validated server-side and will be rejected if blank or too long.
| Field | Type | Validation | Description |
|---|---|---|---|
texto | String | Required, max 1000 chars | The message content. |
nombreParticipante | String | — | The sender’s display name. Used to populate the history record. |
participanteId | Long | — | The sender’s participant ID. |
eventoId | Long | — | The ID of the event this message belongs to. Should match the {eventoId} in the destination path. |
Receiving: HistorialMensajesDTO
All subscribers to/topic/evento/{eventoId} receive a HistorialMensajesDTO payload for every new message. This is the same structure returned by the REST history endpoint, ensuring consistency between live and historical data.
| Field | Type | Description |
|---|---|---|
id | Long | The database-assigned ID of the persisted Mensaje record. |
texto | String | The message content. |
participanteId | Long | The sender’s participant ID. |
nombreParticipante | String | The sender’s display name at the time the message was sent. |
fechaEnvio | LocalDateTime | Server-assigned timestamp from TimestampEntity.createdAt. |
Message History
To load the full chat history for an event — for example, when a participant first opens the chat view — use the dedicated REST endpoint. This is a standard HTTP request, not a WebSocket call.HistorialMensajesDTO objects in ascending chronological order:
JavaScript Client Example
The example below uses the@stomp/stompjs library to establish a connection, load history via REST, subscribe to the event topic, and send a message. It is a complete, runnable pattern suitable for integration into any modern JavaScript framework.
WebSocket Configuration Reference
The STOMP broker is configured inWebSocketConfig with the following settings:
| Setting | Value | Description |
|---|---|---|
| WebSocket endpoint | /ws-chat | The URL clients connect to; native WebSocket only (no SockJS). |
| Application destination prefix | /app | Messages sent to /app/** are routed to @MessageMapping controllers. |
| Broker destination prefix | /topic | Messages broadcast to /topic/** are delivered to all subscribers by the simple broker. |
| Allowed origins | http://localhost:4200 | CORS policy on the WebSocket endpoint. |
| Channel interceptor | JwtChannelInterceptor | Validates the JWT on every CONNECT frame. |
Authentication is required for WebSocket connections. The
Authorization header must be present in the STOMP CONNECT frame and must carry a valid, non-expired, non-revoked token of type ACCESS. Tokens of type REFRESH are not accepted. If authentication fails silently (no principal is bound), calls to principal.getName() in the controller will throw a NullPointerException and the message will not be processed.