Powrót do strony głównej

Spring Batch dla raportów Excel bez timeoutów

Artykuł opisuje wdrożenie Spring Batch dla asynchronicznego generowania pakietów raportów Excel. Rozbiór kroków PRINT, ZIP, UPLOAD, CLEAN_UP z przykładami kodu. Integracja postępu z frontendem i skalowanie przez Thread Pool.

Generowanie Excel partiami: Spring Batch w produkcji
Advertisement 728x90

Przetwarzanie wsadowe raportów Excel w Spring Batch: architektura i implementacja

Spring Batch rozwiązuje problem synchronicznego generowania setek dokumentów Excel w jednym żądaniu HTTP. Framework dzieli proces na porcje, zarządza stanem i zapewnia odzyskiwanie po awariach. W rzeczywistym projekcie automatyzacji napraw silników lotniczych umożliwiło to użytkownikom uruchamianie drukowania wsadowego kart roboczych i list przewozowych bez przekroczeń czasu.

Główne komponenty Spring Batch

Job łączy cały cykl: generowanie Excel, archiwizację, przesyłanie do magazynu i czyszczenie. Step — etap przetwarzania, Tasklet — operacja atomowa.

Proces dzieli się na kroki chunk-oriented (odczyt/przetwarzanie/zapis porcjami) i tasklet-based (jedno działanie). Zapewnia to niezależność etapów i scentralizowane zarządzanie.

Google AdInline article slot

Kroki generowania raportów

Krok PRINT: tworzenie plików Excel

Dane są dzielone na porcje po 10 elementów. Każda przechodzi przez reader → processor → writer:

@Bean
@JobScope
public Step printTrpTagsStep(
        ItemReader<TrpTagForPrintModel> excelTrpTagItemReader,
        ItemProcessor<TrpTagForPrintModel, ExcelItem> excelTrpTagItemProcessor,
        ItemWriter<ExcelItem> excelTrpTagItemWriter
) {
    return new StepBuilder(BatchExcelPrintStep.PRINT.getCode(), jobRepository)

            .<TrpTagForPrintModel, ExcelItem>chunk(10)
                    .transactionManager(transactionManager)
                    .reader(excelTrpTagItemReader)
                    .processor(excelTrpTagItemProcessor)
                    .writer(excelTrpTagItemWriter)
                    .build();
}

Spring Batch śledzi writeCount dla postępu. Pliki są zapisywane w /tmp/engine/{timestamp}/zip/ z podkatalogami według typów dokumentów.

Krok ZIP: pakowanie archiwum

Tasklet skanuje katalog i tworzy ZIP standardowymi narzędziami Java.

Google AdInline article slot

Krok UPLOAD: umieszczenie w S3

Archiwum jest przesyłane do S3, a link jest zapisywany w ExecutionContext.

Krok CLEAN_UP: usuwanie danych tymczasowych

JobExecutionListener sprawdza status i czyści /tmp w przypadku sukcesu lub awarii.

Równoległość i skalowanie

Kilka Job jest uruchamianych w Thread Pool do jednoczesnego przetwarzania żądań użytkowników. Wewnątrz Job nie stosowano kroków równoległych, ale framework je obsługuje.

Google AdInline article slot

Integracja z frontendem: monitorowanie postępu

POST /trp-tag/print/excel/batch/start zwraca jobExecutionId. GET /trp-tag/print/excel/batch/{id} dostarcza status.

Postęp jest obliczany w następujący sposób:

  • PRINT: proporcjonalnie do writeCount (90% czasu).
  • Pozostałe kroki: 0% lub 100%.

Frontend otrzymuje:

  • progressPercentage dla paska.
  • currentStepNumber/totalStepsNumber.
  • status (STARTED/COMPLETED/FAILED).
  • downloadUrl.
  • failureDetails.
  • durationMillis.

Zalety wdrożenia

  • Asynchroniczność: natychmiastowa odpowiedź zamiast przekroczeń czasu.
  • Trwałość: historia w PostgreSQL bez dodatkowej infrastruktury.
  • Transakcyjność: automatyczne zarządzanie stanem, w przeciwieństwie do @Async.

Co jest ważne

  • Chunk po 10 elementów minimalizuje pamięć i zapewnia postęp.
  • WriteCount — wbudowany licznik do precyzyjnego śledzenia.
  • ExecutionContext przechowuje linki do artefaktów.
  • JobExecutionListener gwarantuje czyszczenie.
  • Thread Pool skaluje kilka Job jednocześnie.

Spring Batch nadaje się do każdego wsadowego generowania dokumentów z archiwizacją i przechowywaniem. Implementacja zajmuje mniej czasu niż niestandardowa logika z kolejkami.

— Editorial Team

Advertisement 728x90

Czytaj dalej