The Adventuretube backend is designed with a clear separation of exception types, handling responsibilities, and architectural patterns to support robust, scalable microservices. There are two primary layers of exception management in the system:
1. Checked Exceptions (Handled with try-catch
)
These are exceptions that represent recoverable or gracefully degradable failures, such as I/O problems, API call failures, or invalid system states. They are explicitly caught with try-catch
blocks and handled locally.
✅ Purpose:
Recoverable operations (e.g.,
IOException
,RestClientException
)Fallback scenarios (e.g., default values, retry logic)
Graceful degradation without user impact
✅ Design Rules:
These exceptions implement or extend
ErrorCode
interface or enum.They are handled explicitly inside service or utility methods.
Useful for controlling low-level flows like system integration, file reading, etc.
2. Business / Domain-Specific Exceptions (Handled with @ControllerAdvice
)
This is the core of Adventuretube’s exception strategy. These exceptions reflect domain-specific failures that are expected and should be handled globally across the application.
All business-related exceptions are managed centrally through a Global Exception Handler, which acts as a unified point of exception processing using Spring’s annotation-based mechanism. This ensures that all domain exceptions — regardless of where they originate — are translated into consistent, structured HTTP responses without duplicating handling logic across services.
The centralized exception handler leverages @ControllerAdvice
and @ExceptionHandler
to catch all custom exceptions and convert them into standard ServiceResponse
outputs.
This is the core of Adventuretube’s exception strategy. These exceptions reflect domain-specific failures that are expected and should be handled globally across the application.
✅ Purpose:
Domain integrity errors (e.g., duplicate user, invalid credentials)
Authorization and JWT validation issues
Microservice-specific workflows (e.g., member registration failure, token save error)
✅ Design Rules:
These exceptions **extend **
RuntimeException
for clean propagation.They are all handled centrally using Spring’s
@ControllerAdvice
global exception handler.Each is associated with a service-specific
ErrorCode
enum (e.g.,AuthErrorCode
,MemberErrorCode
).The response is wrapped in a unified
ServiceResponse
object.
✅ Why Unchecked?
Avoids polluting service logic with excessive
try-catch
Treats business errors as “expected outcomes” rather than code-level faults
🧬 ErrorCode Enum Design Pattern
All exceptions are classified using an ErrorCode
enum system.
🏗 Structure:
There is a **base enum or interface **
ErrorCode
for all checked system exceptions.Each module defines its own enum (e.g.,
AuthErrorCode
,MemberErrorCode
) that implements or extends ****************ErrorCode
.
public interface ErrorCode {
String getMessage();
HttpStatus getHttpStatus();
}
public enum AuthErrorCode implements ErrorCode {
USER_NOT_FOUND("User not found", HttpStatus.NOT_FOUND),
TOKEN_EXPIRED("Token expired", HttpStatus.UNAUTHORIZED),
MEMBER_REGISTRATION_FAILED("Failed to register member", HttpStatus.INTERNAL_SERVER_ERROR);
// ...
}
📌 Summary of Exception Strategy
Layer | Example | Type | Handling Approach |
---|---|---|---|
System Integration Failure | IOException | Checked | try-catch + fallback |
External Service Timeout | RestClientException | Checked | Retry or recovery logic |
Business Rule Violation | UserNotFoundException | Runtime (custom) | @ControllerAdvice |
JWT Expired | TokenExpiredException | Runtime (custom) | @ControllerAdvice |
Duplicate Registration | EmailDuplicationException | Runtime (custom) | @ControllerAdvice |
This architectural approach allows Adventuretube microservices to:
Keep business logic clean and intention-revealing
Avoid overuse of
try-catch
clutterCentralize error management and maintain consistent error responses
Use clear enums to trace the origin and nature of failures
This structure ensures scalability and maintainability as the platform grows across modules.