1. ¿Qué es un proceso batch?
Un proceso batch es una tarea automática para procesar un gran de volumen de datos. Este proceso se puede ejecutar sin interacción humana y repetirse periódicamente.
Qué no es un proceso batch: no es una tarea programada (un cron). Es bastante común programar un proceso batch, pero no es necesario hacerlo.
2. ¿Qué debemos tener en cuenta con un proceso batch?
- Transaccionalidad porque queremos hacer roll back cuando los datos han sido invalidados.
- Tolerancia a fallos porque no queremos que la aplicación termine cuando ocurra una excepción.
- Reintentos porque… sometimes shit happens.
- Logs y estadísticas porque de vez en cundo necesitamos saber qué ocurre dentro del proceso batch.
- Parada y arranque de los procesos batch.
- Administración web porque mola.
- Particionamiento porque el trabajo puede ser compartido entre diferentes máquinas.
Cada uno de estos aspectos será comentado más tarde. He preparado unos cuantos commits en un repo para repasar todos estos puntos mostrando las diferencias en el código.
3. Conceptos de Spring Batch
Spring Batch es un proyecto que nos proporciona un framework para desarrollar aplicaciones batch. Este proyecto tiene un largo recorrido y es el resultado de la contribución de varias empresas con mucha experiencia en procesamiento batch.
Jobs, Steps, ItemReader, ItemProcessor and ItemWriter:
En Spring Batch se ejecutan jobs que se dividen en steps. Cada step tiene un componente para obtener los objetos (ItemReader), otro para procesarlos (ItemProcessor) y uno más para persistirlos (ItemWriter). El componente de procesamiento de datos es opcional.
Normalmente necesitaremos una instancia de JobBuilderFactory para declarar el Job y un StepBuilderFactory para declarar el Step. No hay problema, Spring nos proporciona ambas.
JobExecution y JobLauncher
Un job puede ejecutarse por una instancia de JobLauncher. Durante su ejecución la información es almacenada y compartida en el JobExecutionContext y el StepExecutionContext.
El JobLauncher devuelve un JobExecution que nos da información sobre la ejecución, como por ejemplo el resultado de la misma: COMPLETED, FAILED…
JobInstance, JobParameters y RunIdIncrementer
JobInstance es la combinación de un Job y sus JobParameters. Una de las reglas de Spring Batch es que no se puede volver a ejecutar un Job si su JobExecution tiene estado COMPLETED. Sin embargo, se puede utilizar un RunIdIncrementer para ejecutar el mismo job varias veces ya que éste modifica internamente sus parámetros.
JobRepository
Spring Batch gestiona por sí sólo una base de datos con información sobre la ejecución de los jobs instanciando un bean de JobRepository. Para ello sólo necesitamos declarar la dependencia de H2 en el entorno de desarrollo.
4. Requisitos mínimos para comprobar que todo esto funciona
- Dependencia de Spring Boot Starter Batch (aquí es donde reside toda la magia).
- Dependencia del driver de la base de datos.
- Anotación @EnableBatchProcessing en la clase de configuración de Spring.
- Bean que define del job.
- Bean que define el step con una tarea que escriba un mensaje «Reading…». Cuando esa tarea devuelva un null indicará el fin de la fuente de datos y por tanto que el job ha terminado.
@Bean public Job job(Step step1) throws Exception { return jobBuilderFactory.get("job1") .incrementer(new RunIdIncrementer()) .start(step1) .build(); } @Bean public Step step1() { return stepBuilderFactory.get("step1") .tasklet(new Tasklet() { public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) { System.out.println("Reading..."); return null; } }) .build(); }
Puedes clonar el repo que he preparado para este post y ver el código añadido en el primer commit para ejecutar Spring Batch con lo mínimo necesario.
Este artículo es una traducción del que escribí hace unos meses en el blog de Fintonic Engineering.