Part 1:Exception Handling Foundation: HTTP Mapping & Priority Order

🎯 Part 1: Foundation – HTTP Mapping & Priority Order

Building robust exception handling starts with understanding the fundamental mapping between business scenarios and HTTP status codes. This foundation ensures your microservices communicate errors consistently and clearly.

The Critical Priority Order

In microservices, exception handling order is crucial for system resilience and performance. Getting this wrong can lead to wasted processing, unclear error messages, and difficult debugging.

Priority Order Rule !!!!

Always follow this order:

  1. Dependency Check FIRST β†’ HTTP 5xx (Check external services)
  2. Business Validation SECOND β†’ HTTP 4xx (Validate input/rules)
  3. Unknown Errors LAST β†’ HTTP 500 (Catch-all)

Why This Order Matters

βœ…

Avoids wasted processing
When systems are down, fail fast instead of running expensive validations
βœ…

Provides clear error classification
It helps quickly identify system vs business issues
βœ…

Enables proper monitoring
Different alert thresholds for system failures vs business rule violations
βœ…

Prevents cascading failures
Stops requests early when dependent services are unavailable

Complete HTTP Status Mapping

Understanding which HTTP status codes to use for different scenarios is fundamental to building consistent APIs.

Success Responses (2xx)

// 201 CREATED - Resource successfully created
UserRegistered β†’ HTTP 201
MemberRegistered β†’ HTTP 201
TokenGenerated β†’ HTTP 201

// 200 OK - Successful operation
LoginSuccess β†’ HTTP 200
DataRetrieved β†’ HTTP 200
UserUpdated β†’ HTTP 200

Client Errors (4xx)

// 404 NOT FOUND - Resource doesn't exist
UserNotFoundException β†’ HTTP 404
TokenNotFoundException β†’ HTTP 404
ResourceNotFoundException β†’ HTTP 404

// 409 CONFLICT - Business rule violation
DuplicateException β†’ HTTP 409 (email already exists)
ConflictException β†’ HTTP 409 (resource state conflict)

// 401 UNAUTHORIZED - Authentication failure
TokenExpiredException β†’ HTTP 401
InvalidCredentialsException β†’ HTTP 401
UnauthorizedException β†’ HTTP 401

// 400 BAD REQUEST - Invalid input
ValidationException β†’ HTTP 400
MalformedRequestException β†’ HTTP 400
InvalidParameterException β†’ HTTP 400

// 403 FORBIDDEN - Insufficient permissions
AccessDeniedException β†’ HTTP 403
InsufficientPrivilegesException β†’ HTTP 403

Server Errors (5xx)

// 500 INTERNAL SERVER ERROR - System failures
TokenSaveFailedException β†’ HTTP 500
MemberServiceException β†’ HTTP 500
DatabaseConnectionException β†’ HTTP 500

// 503 SERVICE UNAVAILABLE - Dependencies down
ServiceUnavailableException β†’ HTTP 503
ExternalServiceException β†’ HTTP 503

// 502 BAD GATEWAY - External service errors
UpstreamServiceException β†’ HTTP 502
GatewayException β†’ HTTP 502

ErrorCode Enum Implementation

The ErrorCode enum is the foundation of consistent exception handling. It maps business scenarios to HTTP status codes and provides reusable error definitions.

Basic ErrorCode Structure

public interface ErrorCode {
    String getMessage();
    HttpStatus getHttpStatus();
    String name();
}

Service-Specific Implementation

@Getter
public enum MemberErrorCode implements ErrorCode {
    // 4xx Client Errors
    USER_NOT_FOUND("User not found", HttpStatus.NOT_FOUND),
    USER_EMAIL_DUPLICATE("User already exists with the provided email", HttpStatus.CONFLICT),
    INVALID_TOKEN("Invalid authentication token", HttpStatus.UNAUTHORIZED),
    ACCESS_DENIED("Insufficient permissions to perform this action", HttpStatus.FORBIDDEN),
    INVALID_INPUT("Invalid input parameters", HttpStatus.BAD_REQUEST),
    
    // 5xx Server Errors  
    TOKEN_SAVE_FAILED("Failed to save token during login", HttpStatus.INTERNAL_SERVER_ERROR),
    MEMBER_REGISTRATION_FAILED("Failed to register member", HttpStatus.INTERNAL_SERVER_ERROR),
    DATABASE_CONNECTION_ERROR("Database connection failed", HttpStatus.INTERNAL_SERVER_ERROR),
    EXTERNAL_SERVICE_ERROR("External service unavailable", HttpStatus.SERVICE_UNAVAILABLE),
    INTERNAL_ERROR("Unknown error occurred", HttpStatus.INTERNAL_SERVER_ERROR);
    
    private final String message;
    private final HttpStatus httpStatus;
    
    MemberErrorCode(String message, HttpStatus httpStatus) {
        this.message = message;
        this.httpStatus = httpStatus;
    }
}

Priority Order in Practice

Let’s see how the priority order works in a real-world example. Here’s how we implement user creation with proper exception handling:

Real-World Implementation: createUser() Method

@Service
public class MemberService {
    
    public Member createUser(CreateUserRequest request) {
        // 1. DEPENDENCY CHECK FIRST (5xx if fails)
        if (!databaseService.isAvailable()) {
            throw new ServiceUnavailableException(EXTERNAL_SERVICE_ERROR);
        }
        
        if (!emailService.isAvailable()) {
            throw new ServiceUnavailableException(EXTERNAL_SERVICE_ERROR);
        }
        
        // 2. BUSINESS VALIDATION SECOND (4xx if fails)
        if (request.getEmail() == null || request.getEmail().trim().isEmpty()) {
            throw new ValidationException(INVALID_INPUT);
        }
        
        if (memberRepository.findByEmail(request.getEmail()).isPresent()) {
            throw new DuplicateException(USER_EMAIL_DUPLICATE);
        }
        
        // 3. IMPLEMENTATION (5xx if unexpected error)
        try {
            Member member = memberMapper.createRequestToMember(request);
            Member savedMember = memberRepository.save(member);
            
            // Send welcome email (non-blocking)
            emailService.sendWelcomeEmail(savedMember.getEmail());
            
            return savedMember;
        } catch (DataAccessException ex) {
            log.error("Database error during user creation: {}", ex.getMessage());
            throw new ServiceException(MEMBER_REGISTRATION_FAILED);
        } catch (Exception ex) {
            log.error("Unexpected error during user creation: {}", ex.getMessage());
            throw new ServiceException(INTERNAL_ERROR);
        }
    }
}

Key Takeaways

Foundation Concepts Mastered

  • HTTP status codes map directly to business scenarios
    2xx for success, 4xx for client errors, 5xx for server errors
  • Priority order prevents unnecessary processing
    Dependencies β†’ Business β†’ Unknown ensures efficient error handling
  • ErrorCode enums provide consistency across services
    Centralized error definitions with uniform HTTP status mapping
  • Real-world implementation patterns work in production
    Service-specific error codes with contextual error messages

πŸ”— Continue Your Journey

Leave a Comment

Your email address will not be published. Required fields are marked *