Как была организована интеграция данных из нескольких источников в вашем проекте?

«Как была организована интеграция данных из нескольких источников в вашем проекте?» — вопрос из категории Архитектура, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Архитектура строилась на основе паттерна Адаптер (Adapter) и Агрегатор (Aggregator), что обеспечивало гибкость и единообразие обработки.

1. Определение общего контракта:

public interface DataSource {
    List<DataRecord> fetchData() throws DataFetchException;
}

2. Реализация адаптеров для каждого источника: Каждый адаптер инкапсулировал специфичную логику подключения, аутентификации и парсинга.

@Component
public class RestApiAdapter implements DataSource {
    @Override
    public List<DataRecord> fetchData() {
        // Вызов REST API, десериализация JSON в DataRecord
    }
}

@Component
public class DatabaseAdapter implements DataSource {
    @Override
    public List<DataRecord> fetchData() {
        // Выполнение SQL-запроса, маппинг ResultSet в DataRecord
    }
}

3. Агрегация данных: Сервис-агрегатор собирал данные от всех источников.

@Service
public class DataAggregationService {
    private final List<DataSource> dataSources;

    public List<DataRecord> collectAllData() {
        return dataSources.parallelStream() // Параллельный вызов
                .map(this::fetchSafely)    // Обработка ошибок по источнику
                .flatMap(Collection::stream)
                .collect(Collectors.toList());
    }

    private List<DataRecord> fetchSafely(DataSource source) {
        try {
            return source.fetchData();
        } catch (DataFetchException e) {
            log.error("Failed to fetch from source: " + source, e);
            return List.of(); // Возвращаем пустой список, не ломая весь процесс
        }
    }
}

Дополнительные механизмы для надежности:

  • Асинхронность: Использование CompletableFuture или реактивных стримов для параллельных запросов.
  • Повторные попытки (Retry): Применение @Retryable (Spring Retry) или резервных стратегий для неустойчивых источников.
  • Кэширование: Кэширование ответов источников, которые редко обновляются.