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.

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.


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.


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.


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.


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.


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.


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.

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