Back-End

29 nov, 2012

Entenda como funciona o Quartz Enterprise Job Scheduler

Publicidade

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 que executam milhares de tarefas, que 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.

O Scheduler é o componente principal do Quartz e é o responsável por gerenciar a execução de jobs. A partir dele, o desenvolvedor pode agendar, iniciar e parar as execuções. 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 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 scheduleJob() e parar o agendador com o 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.

O que é um 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. Ele pode, também, receber parâmetros para seu funcionamento correto e isso é feito a partir da classe JobDetail.

Ao 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, utiliza-se a classe JobBuilder, que define a classe do job implementado a partir do método newJob(), a identidade no método withIdentity() e a instanciação do mesmo no build().

O que é o trigger?

Um objeto trigger é utilizado para disparar a execução de jobs. Quando um job é agendado, a instância de um trigger é feita 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 o 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(). Esse último 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. Ele é construído quando se define um agendamento do tipo CronSchedule no método TriggerBuild.withSchedule. 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:

  1. Segundos;
  2. Minutos;
  3. Horas;
  4. Dia do mês;
  5. Mês;
  6. Dia da semana;
  7. 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. Ele será responsável por exibir uma mensagem de texto simples indicando que foi executado a cada dez 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, obtem-se uma instância de Scheduler a partir da Factory StdSchedulerFactory. O agendamento é iniciado, depois cria-se um novo job, do tipo MyJob, um novo CronTrigger que possui a expressão cron “0/10 * * * * ?”, que significa “a cada dez 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