Introdução ao Quartz Enterprise Job Scheduler


Neste artigo apresento um estudo sobre a ferramenta de agendamento de tarefas Quartz. Este estudo foi desenvolvido para o Instituto de Tecnologia Aplicada e Inovação, onde atuo como Analista de Sistemas, visando uma introdução e explicação sobre os principais conceitos do Quartz, para utilização em um projeto.

Introdução

O Quartz é um serviço de agendamento de tarefas que pode ser integrado, ou utilizado virtualmente, em qualquer aplicação Java SE ou Java EE. A ferramenta pode ser utilizada para criar agendas simples ou complexas que executam dezenas, centenas ou até milhares de tarefas, as quais são definidas utilizando componentes padrão da plataforma Java, que são codificados para suprir as necessidades da aplicação. O Quartz Scheduler fornece diversos recursos corporativos, como suporte a transações JTA ou clusterização.

Scheduler

O Scheduler é o componente principal do Quartz, e é responsável por gerenciar a execução de jobs (tarefas). A partir do Scheduler o desenvolvedor pode agendar, iniciar a execução e parar a execução de jobs. Para construir um Scheduler deve-se utilizar uma classe que implementa o padrão de projeto Factory, no Quartz representado pela interface SchedulerFactory. Existem duas classes que implementam esta interface: StdSchedulerFactory e DirectSchedulerFactory. A primeira classe permite a utilização de um arquivo properties para configuração e a segunda implementa um segundo padrão de projeto: o Singleton.

Após obter um Scheduler, pode-se iniciar a execução do agendamento a partir do método start(), agendar novos jobs com o método scheduleJob() e parar o agendador com o método shutdown(). Ao se agendar um job com o método scheduleJob(), é necessário definir dois parâmetros:

  • O primeiro define o job que será executado, representado pela interface Job;
  • O segundo define o trigger, representado pela interface Trigger, que corresponde às condições de agendamento para execução do job em questão.

Job

Um job é uma tarefa a ser executada, que no Quartz nada mais é do que uma classe que implementa a interface Job, e que agrega todo o código necessário para fazer a funcionalidade específica do job em questão. Um job pode também receber parâmetros para seu correto funcionamento e isso é feito a partir da classe JobDetail.

Ao se implementar a interface Job, deve-se implementar também o método execute(), que recebe como parâmetro um JobExecutionContext e lança uma exceção do tipo JobExecutionException. Dentro do método execute() estará todo o código referente ao job em questão. Um exemplo de job é uma varredura automática de spams em um e-mail, ou, uma busca por tags duplicadas de um produto para limpeza em um banco de dados de algum comércio eletrônico.

Para a criação de um job é utilizada a classe JobBuilder, que define a classe do job implementado a partir do método newJob(), a identidade do job no método withIdentity() e a instanciação do mesmo no método build().

Trigger

Um objeto trigger é utilizado para disparar a execução de jobs. Quando um job é agendado, é feita a instância de um trigger e suas propriedades são configuradas para satisfazer o agendamento necessário para a aplicação. Existem alguns triggers pré-definidos na biblioteca Quartz, como, por exemplo, o SimpleTrigger e o CronTrigger.

Para a construção de um trigger é utilizada a classe TriggerBuild que implementa métodos utilizando Domain Specific Language (DSL) e permite a configuração dos dados do trigger, como, por exemplo, sua identidade a partir do método withIdentity(), seus dados de agendamento a partir do método withSchedule(), e a instanciação do trigger a partir do método build(). O método build() retorna uma classe que implementa a interface Trigger.

O CronTrigger é um tipo de trigger que é útil para agendamentos baseados em calendários, como, por exemplo, “uma execução deve ocorrer às quartas e quintas às 12:00h” ou “uma execução deve ocorrer todos os dias às 08:00h”, e assim por diante.

Um CronTrigger é construído ao se definir no método “TriggerBuild.withSchedule” um agendamento do tipo CronSchedule. Este tipo de agendamento é construído a partir do método estático cronSchedule da classe CronScheduleBuilder que recebe como parâmetro uma expressão cron.

Para formar uma expressão cron, alguns requisitos devem ser satisfeitos. Primeiramente deve-se conhecer a ordem dos parâmetros:

  • Segundos;
  • Minutos;
  • Horas;
  • Dia do mês;
  • Mês;
  • Dia da semana;
  • Ano (opcional).

Por exemplo, uma expressão cron que será executada todas às quartas-feiras às 12:00PM é escrita da seguinte forma: “0 0 12 ? * WED”. Outro exemplo de expressão demonstra uma tarefa executada todos os dias, às 08:00AM e 12:00PM: “0 0 8,12 * * *”.

Exemplo

Para ilustrar todos os conceitos apresentados anteriormente foi desenvolvido um exemplo simples, que simula a utilização de um CronTrigger e define um job customizado que implementa a interface Job.

Este job será responsável por exibir uma mensagem de texto simples indicando que foi executado a cada 10 segundos todos os dias. O código do job foi definido conforme a listagem abaixo.

public class MyJob implements Job {
    @Override
    public void execute(JobExecutionContext context)
            throws JobExecutionException {
        System.err.println("Servico executado conforme agendamento");
    }
}

A classe principal que faz a execução deste job foi definida conforme a listagem a baixo.

public class Main {
    public static void main(String[] args) {
        try {
            SchedulerFactory schedFact = new StdSchedulerFactory();
            Scheduler sched = schedFact.getScheduler();
            sched.start();

            JobDetail job = JobBuilder.newJob(MyJob.class)
                .withIdentity("myJob", "group1")
                .build();

            Trigger trigger = TriggerBuilder
                .newTrigger()
                .withIdentity("myTrigger", "group1")
                .withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ?"))
                .build();

            sched.scheduleJob(job, trigger);
        } catch (Exception e) {
            System.out.println("erro");
            e.printStackTrace();
        }
    }
}

Neste exemplo de código é obtido uma instância de Scheduler a partir da Factory StdSchedulerFactory, o agendamento é iniciado, é criado um novo job do tipo MyJob, um novo CronTrigger que possui a expressão cron “0/10 * * * * ?” que significa “a cada 10 segundos”, e o job é agendado conforme o trigger criado.

Conclusão

Apesar de ser um exemplo simples, com ele é possível verificar o funcionamento de cada componente necessário para a execução de um job agendado, e a partir dele é possível ver sua aplicabilidade no cenário de alguma aplicação que tenha estas necessidades.

Referências