Por que eu devo ler este artigo:Neste artigo apresentamos a nova API da Java EE 7 para o desenvolvimento de processos em lote, a API de batch applications (JSR 352). Para isto, explicamos a problemática do desenvolvimento deste tipo de operação e mostramos como a API lida com boa parte das dificuldades deste contexto. Em seguida, demonstramos por meio de uma aplicação exemplo como proceder para se programar um processo batch utilizando essa tecnologia.

Aplicações corporativas muitas vezes são construídas para lidar com processos que envolvem grandes volumes de dados. Neste cenário, é normal que apareça a necessidade de desenvolvimento de processos em lote. Por causa disso, é importante para todos os desenvolvedores Java conhecer a API que se tornará a padrão para a criação de processos desse tipo.
Autores: Renan de Melo Oliveira, Julien Renaut e Marcelo Takeshi Fukushima

O desenvolvimento de software permitiu que diversas tarefas antes consideradas impossíveis se tornassem não só possíveis, mas também viáveis. Vivemos na era da informação onde o acesso a uma quantidade de dados virtualmente infinita está ao alcance de um clique. Hoje podemos realizar transferências bancárias entre diferentes bancos que são finalizadas em minutos, falar com voz e vídeo com um grupo de dezenas de pessoas distribuídas no mundo inteiro e realizar cálculos com uma velocidade surpreendente. No entanto, computacionalmente falando, manipular tamanha quantidade de dados é um desafio.

No mercado de aplicações corporativas é comum a necessidade de lidar com volumes massivos de dados. Processar manualmente estes dados é repetitivo e burocrático, gerando assim pouco valor para as empresas. No entanto, com os avanços obtidos nos últimos anos, tanto em hardware como software, hoje é possível automatizar muitos destes processos de forma a diminuir custos e aumentar a confiabilidade das informações extraídas.

Atualmente, uma das necessidades mais comuns em grandes operações de software é o desenvolvimento de processos batch (em lote). Processos batch são operações realizadas por um sistema que não necessitam de interação direta com o usuário. Estes processos são caracterizados por lidarem com um grande volume de dados e normalmente são executados em um período diferente do horário comercial – durante a madrugada por exemplo. Diversos fatores relacionados às áreas de negócio destas empresas justificam essa necessidade, como a integração com outros sistemas, sumarização de operações financeiras realizadas durante o dia, ou mesmo limpezas periódicas.

A versão mais recente da Java Enterprise Edition (Java EE 7) incluiu a JSR 352 (Batch Applications for the Java Platform), uma biblioteca para desenvolvimento de processos em lote de forma fácil e padronizada. Esta API permite definir, executar e acompanhar processos batch em um container compatível como o GlassFish 4.

Neste artigo, iremos implementar um processo batch para simular o fechamento de faturas de um sistema bancário, o FaturaWeb. O processo será composto por algumas etapas como conversão de valores em dólar e totalização dos lançamentos para uma fatura. Para isso, usaremos algumas das funcionalidades básicas da API, como a definição de uma tarefa e seus componentes, assim como o disparo e acompanhamento do processo como um todo.

Necessidades e problemas de processos em lote

Para compreendermos as vantagens desta API da forma como foi proposta, é importante avaliarmos os problemas inerentes de processos batch. Esta reflexão é essencial para sabermos como lidar melhor com este tipo de operação.

Um processo em lote, como já foi dito, é caracterizado por não necessitar de interação com o usuário, podendo ser executado de forma assíncrona. Uma operação assíncrona não exige que o componente chamador espere o término da execução para prosseguir com o restante das instruções. Desta forma, uma operação assíncrona pode realizar um processamento demorado sem que isto impacte a experiência do usuário, pois o mesmo não ficará “travado” esperando a resposta da operação. Além disso, ao contrário do caso síncrono, a partir do momento em que o usuário requisita ou agenda a execução de um processo em lote, o mesmo perde o contato direto com a execução deste, dificultando o acompanhamento e a administração da tarefa.

No entanto, por serem assíncronos e normalmente demorados, é importante permitir que o usuário possa monitorar o andamento dos processos batch. Essa importância também se aplica em casos em que ocorrem erros por conta de pré-condições externas não satisfeitas, como a falta de dados oriundos de fontes externas, ou mesmo falhas de rede e quedas de energia. Para contornar tais problemas, a API permite que processos com erro possam ser reiniciados, seja do início ou do ponto onde pararam.

Igualmente importante é saber se um processo batch foi concluído antes de se realizar alguma operação de negócio. Por exemplo, o cálculo do valor da cota de um fundo de investimento é fundamental para determinar o valor disponível para resgate de um cliente. Portanto, enquanto o processo batch responsável pelo cálculo desta cota não terminar, o investidor não poderá realizar o resgate.

O controle transacional dos processos em lote também demanda um planejamento cuidadoso. Há casos em que a tarefa inteira deva ser executada em uma transação única e também casos em que commits parciais devam ser realizados durante a operação.

Além do que já foi citado, também é desejável que os recursos computacionais do ambiente sejam corretamente utilizados, sejam eles diversos núcleos de processamento ou diversas máquinas em um cluster. Porém, pode não ser trivial lidar com processamento paralelo no contexto de processos em lote, pois muitas vezes queremos que apenas parte de um processo seja executada em paralelo, enquanto outras partes precisam ser executadas de forma sequencial.

Em resumo, quando desenvolvemos processos batch nos deparamos com diversas necessidades e problemas. A seguir começaremos o detalhamento da API de processos batch mostrando como os requisitos listados são supridos.

Funcionamento básico da API

A API de batches nos permite definir tarefas (jobs). Cada job representa a configuração de um processo em lote e descreve de forma geral qual é o conjunto de etapas (steps) que devem ser realizadas durante a execução deste processo. Mais à frente iremos explicar mais detalhadamente como desenvolver uma aplicação batch, porém, de forma geral, esta API nos possibilita realizar as seguintes operações:

· Definição de tarefas (jobs), etapas (steps) e elementos de decisão (decisions) em nossas aplicações, sendo um processo batch representado por um job, que por sua vez consiste em um conjunto de steps inter-relacionados;

· Definição de um processo batch por meio de um fluxo completo de passos em um arquivo de configuração;

· Informação de status para cada execução de processo;

· Execução de processos e a continuação de processos interrompidos por meio de um controlador unificado;

· Tratamento de erros;

· Possibilidade de processamento paralelo de partes específicas do processo ou da operação como um todo;

· Controle transacional integrado ao container (de forma automática em muitos casos).

Nota: Já existem outras implementações de processos batch no mercado visando prover os itens supracitados, como Spring Batch e IBM WebSphere Compute Grid. No entanto, a JSR 352 é uma evolução e padronização dessas bibliotecas e não por acaso as empresas citadas fazem parte do Expert Group desta JSR.

A criação desta API tem como objetivo facilitar a construção e parametrização de processos em lote através da definição de um fluxo de etapas (steps). Estas etapas são descritas em um arquivo XML por meio de uma linguagem chamada JSL (Job Specification Language) de modo que cada processo em lote deve ser descrito em um arquivo XML separado. As etapas que compõem um processo podem ser implementadas de duas formas diferentes:

1. Processamento baseado em chunks: Esta opção é a mais flexível para o uso da API, no entanto, é explicitamente separada em três fases: 1) Leitura dos dados; 2) Processamento dos dados; e, 3) Escrita dos dados;

2. Processamento simples (Batchlet): Esta é uma opção mais simples, que delega para apenas uma classe a execução de toda a etapa.

A existência desses dois tipos de etapas (chunks e batchlets) permite que o desenvolvedor escolha a implementação mais adequada de acordo com a ação a ser executada. As características de cada etapa, como seu tipo, são indicadas no momento da definição da tarefa (job), realizada via JSL e melhor detalhada posteriormente no artigo.

As etapas baseadas em chunks são as que se beneficiam de mais recursos da API, porém são um pouco mais trabalhosas de serem implementadas. Uma das funcionalidades disponíveis para chunks é o particionamento da etapa para que seja executada em tarefas paralelas. Desta forma utilizamos melhor os diversos núcleos de processamento de um servidor, aproveitando melhor os recursos disponíveis e possivelmente acelerando a execução da etapa.

Ao particionarmos uma etapa do tipo chunk em tarefas paralelas a API também permite que estas tarefas sejam paradas, reiniciadas ou mesmo descartadas. Isto é possível porque a API possui uma estrutura de checkpoint que armazena o estado da execução das tarefas, guardando o estado da etapa para que esta possa ser reiniciada posteriormente, caso necessário.

Por todos estes conceitos estarem abstraídos pela API de processos batch, desenvolver aplicações que se beneficiem deste modelo de programação tornou-se mais fácil. Além disto, por estarmos em um container Java EE 7, ganhamos automaticamente a integração com outros recursos desta especificação, como acesso fácil ao banco de dados via JPA (Java Persistence API), injeção de dependências com CDI (Contexts and Dependendy Injection), agendadores de tarefas (Scheduler), etc.

Preparando o ambiente

Preparar um ambiente de desenvolvimento para se criar uma aplicação Java EE 7 é uma tarefa simples. Basta fazermos o download do JDK 7 e do GlassFish 4 versão full, servidor de aplicação de referência da especificação Java EE.

Além disto, para facilitar o desenvolvimento, iremos utilizar o Eclipse para a escrita de nosso código, o Maven como ferramenta de construção e controle de dependências do projeto, e o M2E, plugin do Eclipse que facilita a integração do Eclipse com o Maven.

Dentre as tecnologias empregadas para o nosso exemplo, iremos descrever apenas a instalação do GlassFish 4, visto que os outros já são amplamente adotados em grande parte dos projetos Java. Para mais detalhes sobre a instalação do Maven e do M2E, veja a seção Links.

Quer ler esse conteúdo completo? Tenha acesso completo