0Pricing
WebSockets & Real-Time Systems with Spring · درس

التعامل السلس مع أخطاء WebSocket

نفّذوا آليات قوية للتعامل مع أخطاء WebSocket على جانب الخادم والعميل.

التعامل السلس مع أخطاء WebSocket درس مجاني في WebSockets & Real-Time Systems with Spring على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في WebSockets & Real-Time Systems with Spring، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة WebSockets & Real-Time Systems with Spring 4 دروس في المجموع.

بعض أجزاء هذا الدرس لم تُترجم بعد وتظهر باللغة الإنجليزية.

Intro to WebSocket Errors

Real-time applications, powered by WebSockets, need robust error handling. Just like any other software, things can go wrong!

Understanding and gracefully managing errors is crucial for a smooth user experience and a stable application. This lesson will cover common error types and how to handle them effectively.

Client-Side Error Types

Errors can occur on the client side (e.g., browser or mobile app) due to various reasons:

  • Network Issues: Disconnected internet, firewall blocks.
  • Server Problems: Server crash, unhandled exceptions on the server side.
  • Protocol Violations: Sending malformed data that the server rejects.
  • Client-Side Logic: Errors in processing received messages.

These often manifest as connection drops or messages failing to send/receive.

Handling Client 'onerror' Event

In JavaScript, the WebSocket API provides an onerror event listener. This event fires when a communication error occurs.

While onerror indicates a problem, it often doesn't provide detailed information. It's usually followed by an onclose event, which offers more specific status codes and reasons for the connection termination.

Client Error Handling Example

Here's how you might set up basic error and close handlers on the client side using JavaScript:

Notice how onclose provides more context with event.code and event.reason.

const ws = new WebSocket("ws://localhost:8080/my-ws");

ws.onopen = () => {
  console.log("Connected!");
};

ws.onmessage = (event) => {
  console.log(`Received: ${event.data}`);
};

ws.onerror = (error) => {
  console.error("WebSocket Error: ", error);
  // This is a generic error, often followed by onclose
};

ws.onclose = (event) => {
  if (event.wasClean) {
    console.log(`Closed cleanly, code=${event.code}, reason=${event.reason}`);
  } else {
    console.error(`Connection died, code=${event.code}, reason=${event.reason}`);
    // Handle unexpected closure, e.g., attempt reconnect
  }
};

// To trigger an error, try connecting to a non-existent port or URL.

Server-Side Error Scenarios

On the server, particularly in a Spring WebSocket application, errors can arise from:

  • Message Processing: Exceptions thrown by your @MessageMapping methods.
  • Authentication/Authorization: Security failures preventing message delivery.
  • Broker Issues: Problems connecting to or interacting with an external STOMP message broker.
  • Transport Errors: Low-level network issues or protocol violations (e.g., malformed frames).

Handling these prevents server crashes and provides meaningful feedback to clients.

Spring WebSocket Error Handling

Spring provides powerful mechanisms to manage server-side WebSocket errors:

  • @MessageExceptionHandler: For exceptions occurring during STOMP message processing in your controllers.
  • WebSocketHandlerDecoratorFactory: To intercept and handle errors related to the WebSocket connection lifecycle and transport.

These allow you to centralize error logic and respond appropriately.

Using @MessageExceptionHandler

The @MessageExceptionHandler annotation works similarly to @ExceptionHandler in REST controllers. It catches exceptions thrown by methods annotated with @MessageMapping.

You can define methods that handle specific exception types and send a custom error message back to the client, often to a dedicated error topic.

Try sending a message containing "error" to see the exception handler in action.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.handler.annotation.MessageExceptionHandler;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.stereotype.Controller;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

@SpringBootApplication
public class ErrorHandlingApp {
    public static void main(String[] args) {
        SpringApplication.run(ErrorHandlingApp.class, args);
    }
}

@Configuration
@EnableWebSocketMessageBroker
class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws").withSockJS();
    }
}

@Controller
class ChatController {
    @MessageMapping("/hello")
    @SendTo("/topic/greetings")
    public String greeting(String message) throws Exception {
        if (message.contains("error")) {
            throw new IllegalArgumentException("Message contains 'error' keyword!");
        }
        return "Hello, " + message + "!";
    }

    @MessageExceptionHandler
    @SendTo("/topic/errors")
    public String handleIllegalArgumentException(IllegalArgumentException ex) {
        return "Error: " + ex.getMessage();
    }
}

WebSocketHandlerDecoratorFactory

For errors outside of specific @MessageMapping methods, such as low-level transport errors or issues during connection establishment/closure, you can use a WebSocketHandlerDecoratorFactory.

This factory allows you to wrap the default WebSocketHandler with your custom logic, intercepting events like handleTransportError or afterConnectionClosed for robust logging or custom responses.

Implementing a Decorator

Here's an example of implementing a WebSocketHandlerDecoratorFactory. It wraps the standard handler to add custom logging for connection events and transport errors.

This allows you to react to issues that might not be caught by @MessageExceptionHandler, like a sudden client disconnect.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import org.springframework.web.socket.handler.WebSocketHandlerDecorator;
import org.springframework.web.socket.handler.WebSocketHandlerDecoratorFactory;

@SpringBootApplication
@EnableWebSocket
public class DecoratorApp implements WebSocketConfigurer {
    public static void main(String[] args) {
        SpringApplication.run(DecoratorApp.class, args);
    }

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(myHandler(), "/ws-decorator").setAllowedOrigins("*");
    }

    public WebSocketHandler myHandler() {
        return new TextWebSocketHandler() {
            @Override
            public void afterConnectionEstablished(WebSocketSession session) throws Exception {
                System.out.println("Handler: Connection established for " + session.getId());
            }
            @Override
            public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
                System.out.println("Handler: Connection closed for " + session.getId() + " with status " + status);
            }
        };
    }

    @org.springframework.context.annotation.Bean
    public WebSocketHandlerDecoratorFactory decoratorFactory() {
        return (handler) -> new WebSocketHandlerDecorator(handler) {
            @Override
            public void afterConnectionEstablished(WebSocketSession session) throws Exception {
                System.out.println("Decorator: Client connected: " + session.getId());
                super.afterConnectionEstablished(session);
            }
            @Override
            public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
                System.err.println("Decorator: Transport error for session " + session.getId() + ": " + exception.getMessage());
                // You could send a generic error message to the client here if session is still open
                super.handleTransportError(session, exception);
            }
            @Override
            public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
                System.out.println("Decorator: Client disconnected: " + session.getId() + ", Status: " + closeStatus.getCode());
                super.afterConnectionClosed(session, closeStatus);
            }
        };
    }
}

Error Handling Best Practices

To build truly robust WebSocket applications, consider these best practices:

  • Log Everything: Use a robust logging framework (e.g., SLF4J/Logback) to capture all errors, warnings, and important events.
  • User Feedback: Provide clear, user-friendly messages on the client side when errors occur, avoiding technical jargon.
  • Graceful Degradation: If a specific feature fails, ensure the rest of the application remains functional.
  • Custom Error Messages: Never expose raw stack traces or internal server details to clients.
  • Monitoring: Implement monitoring tools to track connection health and error rates.

Error Handling Challenge

You've learned about various ways to handle WebSocket errors on both the client and server. Let's test your understanding!

Recap: Handling Errors Gracefully

In this lesson, we explored the critical topic of handling WebSocket errors. We covered:

  • Common client-side errors and how to use onerror and onclose.
  • Server-side error scenarios in Spring.
  • Utilizing @MessageExceptionHandler for STOMP message processing errors.
  • Implementing WebSocketHandlerDecoratorFactory for connection lifecycle and transport errors.
  • Key best practices for building robust, error-tolerant real-time applications.

Mastering error handling is vital for creating reliable and user-friendly WebSocket services.

الأسئلة الشائعة

هل درس «التعامل السلس مع أخطاء WebSocket» مجاني؟

نعم — نص درس «التعامل السلس مع أخطاء WebSocket» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة WebSockets & Real-Time Systems with Spring، انتقل إلى CoddyKit PRO. تتضمن دورة WebSockets & Real-Time Systems with Spring 4 دروس في المجموع.

ماذا ستتعلم في «التعامل السلس مع أخطاء WebSocket»؟

نفّذوا آليات قوية للتعامل مع أخطاء WebSocket على جانب الخادم والعميل. تتمرن على WebSockets & Real-Time Systems with Spring مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ WebSockets & Real-Time Systems with Spring؟

لا تُشترط خبرة سابقة. WebSockets & Real-Time Systems with Spring على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.

كم من الوقت يستغرق درس «التعامل السلس مع أخطاء WebSocket»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس WebSockets & Real-Time Systems with Spring هذا؟

نعم. كل درس في WebSockets & Real-Time Systems with Spring يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. التعامل السلس مع أخطاء WebSocket
  2. إدارة دورة حياة الاتصال
  3. إعادة المحاولة والبدائل
  4. نبضات القلب وإبقاء الاتصال حيًا باستخدام Ping/Pong
← العودة إلى WebSockets & Real-Time Systems with Spring