Ответ
При невозможности подключиться к внешнему микросервису следует выбрасывать непроверяемое (unchecked) исключение, унаследованное от RuntimeException.
Почему RuntimeException?
- Восстановление на уровне клиента невозможно. Вызывающий код (например, контроллер) не может «починить» сетевое соединение или недоступный сервис.
- Соответствие семантике. Это ошибка времени выполнения, а не ошибка в логике программы, которую можно проверить на этапе компиляции.
- Уменьшение шаблонного кода. Избегает принудительного объявления
throwsили обработки вtry-catchтам, где это не имеет смысла.
Рекомендуемая практика: Создать доменное непроверяемое исключение, например, ServiceUnavailableException или ExternalServiceIntegrationException.
public class ServiceUnavailableException extends RuntimeException {
public ServiceUnavailableException(String serviceName, Throwable cause) {
super(String.format("Service '%s' is temporarily unavailable", serviceName), cause);
}
}
// Использование в сервисе
public class BookingService {
public Booking createBooking(BookingRequest request) {
try {
// Вызов внешнего микросервиса
inventoryServiceClient.reserveItems(request.getItems());
} catch (ConnectException | SocketTimeoutException e) {
// Обертывание в доменное исключение с контекстом
throw new ServiceUnavailableException("InventoryService", e);
}
// ... дальнейшая логика
}
}
Такое исключение затем можно перехватить на уровне глобального обработчика (например, @ControllerAdvice в Spring) и преобразовать в соответствующий HTTP-статус (например, 503 Service Unavailable).