Logo Spring batch

Spring Batch – co warto wiedzieć o przetwarzaniu wsadowym na początek

Spring Batch to jeden z wielu pod projektów w frameworku spring. W skrócie służy on do developowania zadań wsadowych, które mają charakter cykliczny lub zadań wykonywanych na żądanie. Mogą to być proste zadania przetwarzania np. cykliczna aktualizacja rekordów w tabeli lub bardziej skomplikowane wielo-krokowe zadania przetwarzania/importowania danych.

Jak zdefiniować joba ?

Na początek będziemy potrzebowali zależności gradlowej w projekcie spring bootowym:

A następnie możemy przejść do definicji joba. Najprostszego joba można zdefiniować w następujący sposób:

Procesor ma za zadanie przetworzenie obiektów wejściowych na wyjściowe (w tym przykładzie nie robi w zasadzie nic)

Co warto wiedzieć

Jeśli chcemy pobrać id joba, by później w jakiś sposób się do niego odwołać(zapisać lub przetwarzać) możemy skorzystać z dwóch rzeczy:

Metoda w komponencie (np. we writerze) oznaczona adnotacją @Before.

Gdy korzystamy z @Before, nasz writer powinien mieć scope @StepScop – domyślnie wszystkie beany w springu są singletonami co oznacza, że przechowywanie w nich jakiegokolwiek stanu nie jest wielowątkowo bezpieczne. Możemy zrezygnować z @StepScope wtedy gdy job nie jest uruchamiany równolegle np. uruchamiacie go wraz ze startem aplikacji, jeśli wasze joby mogą działać równolegle konieczna jest adnotacja @StepScope.

Drugi sposób to skorzystanie z listenera:

Jak pobrać informacji o jobie ?

Spring Batch przy uruchomieniu tworzy w bazie danych strukturę dla metadanych, co pozwala pobrać nam informacje o statusie joba zarówno podczas jego wykonywania jak i po zakończeniu. Możemy to zrobić poprzez skorzystanie z jobRepository, ma to jednak pewną wadę. Żeby pobrać z repozytorium dane o jobie potrzebujemy jego nazwy i parametrów uruchomieniowych i o ile nazwa joba jest w zasadzie stałą to parametry mogą już być listą różnych zmiennych, co trochę utrudnia zadanie. Ponieważ w łatwy sposób przy uruchomieniu joba możemy pobrać jedo ID to logiczne jest, że chcieli byśmy go pobrać za pomocą tego właśnie ID. Niestety korzystając z jobRepository nie jest to możliwe.

Jedyne co nam pozostaje to napisanie odpowiednich zapytania dla meta tablel spring batcha:

Żeby pobrać status joba wykonujemy następujące zapytanie:

dodatkowo możemy sprawdzić status uruchomionego joba w runtime’ie naszej aplikacji korzystając z job explorera:

Jak uruchamiać joby ?

Joby można uruchamiać na 3 sposoby:

Odpalanie wraz ze startem aplikacji, co jest domyślnym sposobem, można tym sterować za pomocą propertiesów

Kolejny sposób to odpalenie z kodu za pomocą job launchera, możemy np. wystawić sobie endpoint restowy i uruchamiać zdalnie joby. Możmy przy tym odpalać je synchronicznie (domyślny sposób) oraz asynchronicznie używając do tego asyncJobLauncher’a

Trzecim sposobem jest odpalenie joba jako zadania cron, można to zrobić na wiele sposobów np. używając dodatkowych narzędzi jak Quartz, a można też skorzystać z mechanizmu wbudowanego w springa, konfigurowanego za pomocą adnotacji.

@EnableScheduling – włącza na projekcie możliwość uruchamiania zaplanowanych zadań

@Scheduler –  pozwala skonfigurować uruchamianie zadania na różne sposoby np. @Scheduled(fixedDelay=5000) lub @Scheduled(cron=”*/5 * * * * MON-FRI”)

podobnie jak przy uruchamianiu joba z restowego endpointu korzystamy tutaj także z jobLauncher:

Zabezpieczenie przed wielokrotnym wykonaniem

Czasem chcemy się zabezpieczyć przed wielokrotnym uruchomieniem joba, możemy to zrobić w korzystając z jobExplorera

I na koniec najważniejsza rzecz – Testowanie !

Testowanie to najważniejszy element programowania i nic nie zastąpi nam dobrze działających testów automatycznych na szczęście spring udostępnia nam odpowiednie narzędzia do testowania integracyjnego jobów.

Poniżej przykładowy test integracyjny napisany przy użyciu Spock’a

 

Żródła:

http://projects.spring.io/spring-batch/
https://spring.io/guides/gs/batch-processing/
https://github.com/spring-projects/spring-batch/tree/master/spring-batch-samples

Leave a Reply

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *