09 maio 2017

Agendando tarefas com o Quartz

Agendando tarefas com o Quartz

É muito comum hoje no mundo corporativo a necessidade de criar aplicações onde necessitamos executar tarefas agendadas em dias ou horários específicos. Com o quartz isso se tornou uma tarefa bem simples de ser feita.

O quartz é uma biblioteca open source voltada para aplicações Java, cuja finalidade é facilitar o seu trabalho na construção dessas tarefas que precisam serem agendadas para a sua execução.

O exemplo usado irá demonstrar além de agendar uma tarefa e como também podemos passar informações para serem processadas na execução do nosso Job.

Adicionando o Quartz no projeto

Para adicionar o quartz ao seu projeto basta incluir a sua dependência no seu gerenciador de dependências.

Gradle

Adicionar a seguinte referência no seu arquivo build.gradle.

1
compile group: 'org.quartz-scheduler', name: 'quartz', version: '2.2.1'

Colocando a mão na massa

Primeiro criamos um objeto simples onde vamos passar as informações dele ao contexto do Job e no ato da execução do Job vamos recuperar essas informações para serem processadas.

1
2
3
4
5
6
7
8
9
10
11
12
public class Person {

    private String name;

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

Para agendarmos uma tarefa futura com o quartz precisamos implementar a interface Job, onde devemos implementar o método execute, que nada mais é a implementação de nossa tarefa a ser executada.

1
2
3
4
5
6
7
8
9
10
11
public class GreetingsJob implements Job {

    @Override
    public void execute(JobExecutionContext context)
            throws JobExecutionException {
        String greetings = (String) context.getJobDetail().getJobDataMap().get("greetings");
        Person person = (Person) context.getJobDetail().getJobDataMap().get("person");
        String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        System.out.println(date + " " + greetings + person.getName());
    }
}

Quando vamos executar uma tarefa com o quartz, nos detalhes do Job criado podemos passar um mapa contendo informações que precisamos no ato de execução do mesmo.
No código acima recuperamos desse mapa dois valores, uma String e um objeto Person, que serão mostrados no console assim que o job for executado.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class JobScheduler {

    public void schedule(Person person, String greetings, int hour, int minute) {

        try {
            SchedulerFactory sf = new StdSchedulerFactory();
            Scheduler sched = sf.getScheduler();

            JobDataMap jobDataMap = new JobDataMap();
            jobDataMap.put("greetings", greetings);
            jobDataMap.put("person", person);

            JobDetail job = JobBuilder.newJob(GreetingsJob.class)
                    .setJobData(jobDataMap)
                    .withIdentity(greetings, person.getName()).build();

            Trigger trigger = TriggerBuilder
                    .newTrigger()
                    .withIdentity(greetings, person.getName())
                    .withSchedule(CronScheduleBuilder.dailyAtHourAndMinute(hour,minute)).build();

            sched.scheduleJob(job, trigger);

            sched.start();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

}

O código acima é onde toda a mágica acontece, primeiro foi criado uma instância do Scheduler que será o responsável por agendar as tarefas para a execução.

JobDataMap é o mapa contendo todas as informações que queremos usar no ato da execução e adicionamos elas nos detalhes do nosso Job.

JobDetail é onde informamos qual a classe que implementa a interface Job que deve ser usada para esse agendamento, e onde também colocamos o nosso mapa de informações o JobDataMap.

O objeto Trigger é usado para dizer o momento que o job deve ser executado, no nosso exemplo apenas dizemos que deve ser executado diariamente na determinada hora e minuto.

Depois apenas passamos essas informações ao nosso scheduler para que o mesmo possa fazer todo o resto do trabalho.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class JobSchedulerBuilder {
   
    private JobScheduler jobScheduler = new JobScheduler();
    private final Person person;
    private LocalDateTime today = LocalDateTime.now();
   
    public JobSchedulerBuilder(final Person person) {
        this.person = person;
    }
   
    public void morning() {
        String greetings = "Good morning, ";
        jobScheduler.schedule(person, greetings, today.getHour(), today.plusMinutes(1).getMinute());
    }
   
    public void afternoon() {
        String greetings = "Good Afternoon, ";
        jobScheduler.schedule(person, greetings, today.getHour(), today.plusMinutes(2).getMinute());
    }
   
    public void night() {
        String greetings = "Good night, ";
        jobScheduler.schedule(person, greetings, today.getHour(), today.plusMinutes(3).getMinute());
    }
}

Para testar o nosso exemplo foi criado uma classe contendo alguns métodos que usam uma instância do nosso JobScheduler para agendar uma tarefa a partir da hora e minutos.

1
2
3
4
5
6
7
8
9
10
public class Main {

    public static void main(String[] args) throws SchedulerException {
        Person person = new Person("Tiago");
        JobSchedulerBuilder jobSchedulerBuilder = new JobSchedulerBuilder(person);
        jobSchedulerBuilder.night();
        jobSchedulerBuilder.morning();
        jobSchedulerBuilder.afternoon();
    }
}

Após executarmos a classe principal temos a seguinte saída no console.

1
2
3
2017-05-09 10:44:00 Good morning, Tiago
2017-05-09 10:45:00 Good Afternoon, Tiago
2017-05-09 10:46:00 Good night, Tiago

Note que os métodos que programamos no nosso JobSchedulerBuilder foram programados para executar 1, 2 ou 3 minutos depois que iniciamos a nossa aplicação, e independente da ordem que foram chamados no método principal não afetará a saída no console, pois cada método só será executado de acordo com o time programado.

Conclusão

Nunca foi tão simples agendar tarefas complexas em Java. Caso precise de mais detalhes no próprio site do quartz possui uma boa documentação e uma série de exemplos e tutoriais para te auxiliar.

Código fonte

Você pode executar a seguinte linha de comando ou se preferir pode baixar o zip aqui e importar na sua IDE preferida.

1
git clone https://github.com/tiago-ferreira/dinamic-scheduler.git

Leave a Comment