Spring Batch: A ferramenta de automação Java
- Eduardo Nepomuceno da Rocha
- 1 de fev. de 2024
- 3 min de leitura
Recentemente me deparei com uma demanda de cliente para a qual, a princípio, imaginava ter uma solução em software praticamente pronta já formulada. O cliente pediu uma automação de envio de e-mails de relatórios customizados. O Spring Boot possui uma dependência Java Mail Sender, que é uma excelente ferramenta de envio de e-mails (apresentarei em posts seguintes). Então imaginava basicamente que deveria criar uma função que faria o envio de e-mails periodicamente e uma função para geração de relatórios, a qual poderia ser um pouco verbosa, porém sem grandes impedimentos técnicos. Reparei ao esboçar o projeto que tal tarefa não seria tão simples. Eu deveria criar uma função, disponibilizá-la ao Spring Boot, utilizar uma função que fizesse aquela thread dormir durante x dias, etc. Como engenheiro de software, fui pesquisar uma melhor maneira e encontrei a ferramenta Spring Batch. Falo mais dela a seguir, mas confesso que fiquei surpreso de ter conversado com outros desenvolvedores Java e eles também não conhecerem. Uma ferramenta com tanto potencial e menos utilizada do que poderia esperar ao analisar seu potencial.
O SPRING BATCH
O Spring Batch atualmente está na versão 5. É importante mencionar isto, pois a maioria dos tutuoriais na internet ainda utiliza o Spring Batch 4, mas ele só é compatível com Spring Boot 2 (importante mencionar, já que essas ferramentas são usadas no mais das vezes em conjunto). Atualmente a versão do Spring Boot em trabalho é a versão 3, que utiliza Java 17 adiante, e ela só é compatível com Spring Batch 5. Possuem algumas diferenças em relação à injeção de componentes e principalmente em relação ao jdbc. O Spring Batch 5 exige implementação de banco, enquanto o 4 não.
Sistemas batch são sistemas automatizados de processamento de uma massa significativa de dados. Para utilizar o Spring Batch, ele deve ser adicionado no pom do seu projeto Maven. No geral, recomenda-se utilizar diretamente com Spring Boot, mas não é uma exigência estritamente necessária.
Configuração
Todo projeto SpringBatch tem uma tarefa(Job). Você deve configurar essa tarefa. Um trabalho pode ter mais de um passo. E cada passo segue tipicamente uma sequência de leitura de dados, processamento e escrita.

O Job Repository mantém o estado compartilhado com outros componentes da solução. O step representa uma etapa do processo. Se o step for baseado em chunk(pedaços), ele terá etapas de leitura, processamento e escrita. Se for uma tarefa simples, será baseado em tasklets. O Job Launcher executa o job de fato, considerando fatores como a forma de execução, validação de parâmetros, restart e outras propriedades da execução.
Apresento a seguir um projeto básico e tradicional com o famoso exemplo "Olá Mundo" nas versões 4 e 5:
// Sample with v4
@Configuration
@EnableBatchProcessing
public class MyStepConfig {
@Autowired
private StepBuilderFactory stepBuilderFactory;
@Bean
public Step myStep() {
return this.stepBuilderFactory.get("myStep")
.tasklet(..) // or .chunk()
.build();
}
}
// Sample with v5
@Configuration
public class MyStepConfig {
@Bean
public Tasklet myTasklet() {
return new MyTasklet();
}
@Bean
public Step myStep(JobRepository jobRepository, Tasklet myTasklet, PlatformTransactionManager transactionManager) {
return new StepBuilder("myStep", jobRepository)
.tasklet(myTasklet, transactionManager) // or .chunk(chunkSize, transactionManager)
.build();
}
}
Repare que na versão trabalhe-se com injeção do StepBuilderFactory para criar o passo, enquanto na versão 5, é feito via Bean pelo próprio pro desenvolvedor (particularmente não achei vantajoso). Como a versão 5 deve ter conexão com banco, um objeto característico (no caso o PlarformTransacationManager do H2) é necessário, assim como o jobRepository do próprio Spring Batch para manter os estados. O nome é criado dentro do próprio construtor, diferentemente da versão 4, no qual é uma função. Ambos utilizam lambda para descrever o passo ou tarefa.
Entremos de fato na tarefa "Olá, mundo":
@Configuration
public class BatchConfig {
@Bean
public Job job(JobRepository jobRepository, Step step){
return new JobBuilder("job", jobRepository)
.start(step)
.build();
}
@Bean
public Step step(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("step", jobRepository)
.tasklet((StepContribution contribution, ChunkContext chunkContext) -> {
System.out.println("Ola, mundo!");
return RepeatStatus.FINISHED;
}, transactionManager)
.build();
}
}
O que significa isso? Ao configurar tal batch com uma job específica, essa job será executada de maneira automática sempre que a aplicação for aberta. Isso é uma excelente maneira de servidores utilizarem disparos de e-mail promocionais, geração de faturas e outras funções necessárias que trabalham com massas de dados periodicamente. Repare que nessa implementação de Olá Mundo do Batch 5, temos uma tarefa com apenas um passo, que é o System.out.println. Obviamente, é apenas uma exemplicação, mas imagine tarefas de geração de cartões de crédito: Precisará interagir com o extrato do cartão, ir no back-end acessar os dados do último mês, disparar um e-mail ao usuário com a fatura final. Não seria essa uma tarefa rotineira? Portanto, eis o papel do Spring Batch dentro da aplicação, fazendo toda a automação desse processo, que é feito para milhões de usuários mensalmente. Abaixo deixo um outro exemplo sugerido na plataforma Baeldung:
Comentários