This is the backend part of the WebSocket Demo application, built with Spring Boot.
- WebSocket server implementation using Spring's WebSocket support
 - Structured message handling with a ChatMessage model
 - Support for different message types (CHAT, JOIN, LEAVE, etc.)
 - Username management and tracking
 - User count broadcasting
 - Message broadcasting to all connected clients
 - Ping/pong communication mechanism
 - Support for standalone, integrated, and Docker deployment modes
 - Integrated static resource serving for the Vue.js frontend
 
- Java 21
 - Spring Boot 3.4
 - Spring WebSocket
 - Lombok for code simplification
 - Jackson for JSON serialization/deserialization
 
model/ChatMessage.java- Structured message model with message types (using Lombok)ChatMessageHandler.java- WebSocket message handling and broadcastingWebSocketConfig.java- WebSocket configurationWebsocketSpringBackApplication.java- Main application classFrontendController.java- Controller for serving the frontendconfig/CorsConfig.java- CORS configuration for development mode
# Run with API context path for standalone mode
API_CONTEXT_PATH=/api ./mvnw spring-boot:runIn development mode, the backend runs on http://localhost:8080/api and expects the frontend to run separately.
First, build the frontend:
cd ../websocket-vue-front
npm run distThen run the backend without context path:
cd ../websocket-spring-back
API_CONTEXT_PATH= ./mvnw spring-boot:runIn this mode, the application serves both the API and the frontend from the same server.
From the project root directory:
# Default (no context path)
./build-docker.sh
docker-compose up
# Or with a context path
./build-docker.sh latest "/api"
docker-compose upThis builds and runs the entire application in a Docker container with Java 21. The application can run either with or without a context path based on the build parameters.
The application is configured to serve the Vue.js frontend from the src/main/resources/static directory. This directory is:
- Excluded from git tracking (via 
.gitignore) except for a.gitkeepfile - Automatically cleaned before each frontend build by build scripts
 - Configured to serve content at the root path (
/) 
The cleaning process:
# From build scripts
find "$STATIC_DIR" -type f -not -name ".gitkeep" -delete
find "$STATIC_DIR" -type d -empty -deleteThis ensures that no stale files remain between builds and prevents potential conflicts or outdated resources being served.
./mvnw clean packageThis produces a standalone JAR file in the target directory.
./mvnw testThe application includes various tests:
- 
Unit Tests: Verify the behavior of individual components
ChatMessageTest: Tests theChatMessagemodel class and its factory methodsChatMessageHandlerTest: Tests the WebSocket handler using mocked sessionsWebSocketConfigTest: Tests the WebSocket configuration
 - 
Integration Tests: Test the application as a whole
WebSocketIntegrationTest: Starts a server and tests connecting to the WebSocket endpoint
 
Code coverage can be generated with:
./mvnw test jacoco:reportThe coverage report will be available in target/site/jacoco/index.html.
The system implements security measures to protect against common attacks:
- Username sanitization: Removes HTML tags, scripts, and potentially harmful content from usernames.
 
private String sanitizeUsername(String username) {
    // Remove any HTML tags, scripts, and potentially harmful content
    String sanitized = username.replaceAll("<[^>]*>", "") // Remove HTML tags
                         .replaceAll("(?i)script|alert|eval|function|\\(|\\)|'|\\\"|\\\\|XSS", "") // Remove JavaScript keywords and XSS
                         .trim();
    
    // Limit length to 28 characters
    if (sanitized.length() > 28) {
        sanitized = sanitized.substring(0, 28);
    }
    
    // If empty after sanitizing, generate a default one
    if (sanitized.isEmpty()) {
        sanitized = "User-" + System.currentTimeMillis() % 10000;
    }
    
    return sanitized;
}- Secure JSON handling: Uses Jackson to parse and validate JSON messages, catching and handling errors.
 - WebSocket error handling: Properly detects and handles transport errors in WebSocket sessions.
 
Configuration is in:
src/main/resources/application.properties- Standard configurationsrc/main/resources/application-docker.properties- Docker-specific configuration
Key configuration properties:
server.port- HTTP server port (default: 8080)server.servlet.context-path- API base path (configurable viaAPI_CONTEXT_PATHenvironment variable)websocket.endpoint- WebSocket endpoint path (default: /chat)websocket.allowed-origins- Allowed origins for CORSapp.name- Application name used in welcome messagesspring.web.resources.static-locations- Location of static resourcesspring.mvc.static-path-pattern- URL pattern for static resourceswebsocket.container.max-text-message-buffer-size- WebSocket buffer size for text messageswebsocket.container.max-binary-message-buffer-size- WebSocket buffer size for binary messageswebsocket.container.max-session-idle-timeout- WebSocket session timeout
The application uses a structured ChatMessage model with Lombok:
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ChatMessage {
    private String name;            // Sender name
    private String message;         // Message content
    private String timestamp;       // ISO timestamp
    private MessageType type;       // Message type enum
    
    public enum MessageType {
        CHAT, JOIN, LEAVE, ERROR, USER_COUNT, PING, PONG
    }
    
    // Static factory methods using Builder pattern...
}This model provides:
- Type safety with the MessageType enum
 - Builder pattern for creating messages
 - Automatic getters/setters via Lombok
 - Factory methods for creating different message types
 - Timestamp tracking
 - Standard JSON serialization/deserialization
 
The application uses Spring's WebSocket support:
- 
WebSocketConfigconfigures the WebSocket endpoints at both paths:/chat- For standalone mode/api/chat- For integrated and Docker modes
 - 
ChatMessageHandlerprovides:- Connection tracking
 - Username management
 - Message broadcasting
 - Ping/pong handling
 - User join/leave notifications
 - User count broadcasting
 
 
The application includes Docker support via the Dockerfile in the project root:
- A single build stage installs both Maven and Node.js
 - The Vue.js frontend is built directly into the Spring Boot's static resources directory
 - The Spring Boot application is built with the integrated frontend
 - A final lightweight runtime image with Java 21 is created for deployment
 
This approach simplifies the build process by:
- Avoiding complex file copying between build stages
 - Ensuring reliable builds with direct integration of frontend into backend
 - Maintaining a clean static directory structure
 - Providing flexibility for different context path configurations
 
To run the application in Docker:
# From the project root, with no context path
./build-docker.sh
docker-compose up
# Or with a context path
./build-docker.sh latest "/api"
docker-compose upDocker-specific configuration is activated via the Spring profile docker in application-docker.properties.
The project uses JUnit 5 and Mockito for unit and integration testing. The testing structure includes:
- Mocks to simulate WebSocket sessions and verify interactions
 - Argument captors to inspect sent messages
 - Testing of truncation and sanitization behavior
 - Verification of error scenarios and exceptions
 - Specific test configurations, such as lenient mode for Mockito
 
The tests cover all major aspects of the application, including:
- Connection establishment and closure
 - Handling of different message types
 - Message broadcasting
 - Username sanitization
 - Transport errors and exception handling
 
- Fixed username truncation issue
 - Enhanced sanitization for improved security
 - Optimized unit tests with Mockito
 - Fixed issues in build configurations
 - Added detailed documentation