Esse artigo faz parte da revista Java Magazine edição 41. Clique aqui para ler todos os artigos desta edição

Imagem

Atenção: por essa edição ser muito antiga não há arquivo PDF para download.Os artigos dessa edição estão disponíveis somente através do formato HTML. 

Agendamento de tarefas em Java

Usando o melhor que o Java SE e EE oferecem

Tire o máximo proveito dos recursos de agendamento disponíveis da Java SE e Java EE, e veja como criar uma aplicação Swing de reservas usando vários design patterns

 

Neste artigo, vamos abordar os recursos de agendamento de tarefas disponíveis em Java SE e Java EE. Apresentaremos as classes Timer e TimerTask, presentes na distribuição padrão do Java SE desde a versão 1.3, e o serviço de Timer (Timer Service) acrescentado ao EJB na versão 2.1. Para ilustrar a utilização, criaremos um sistema completo de reservas com interface Swing.

 

Agendamento de tarefas

O agendamento de tarefas permite programar tarefas (Jobs) para execução em momentos específicos, ou periodicamente. Este recuso é suportado nos próprios sistemas operacionais, por exemplo através do agendador de tarefas do Windows ou utilitário cron do Linux/Unix.Veja alguns cenários onde o agendamento de tarefas é útil:

·         Realizar um backup periodicamente

·         Criar diariamente um relatório consolidado de vendas para a gerência

·         Enviar um e-mail para os usuários do sistema cuja senha tenha expirado

·         Verificar a cada cinco minutos se foram copiados novos arquivos para um determinado diretório.

 

O Java oferece elementos para o trabalho com agendamento de tarefas, tanto em sua plataforma Standard como na Enterprise, como veremos em detalhes a seguir.

 

O estudo de caso

Para ilustrar a utilização do agendamento de tarefas com Java, criamos uma aplicação de exemplo que permite a criação de tarefas de verificação automática de expiração de reservas. Poderíamos utilizar este aplicativo em qualquer sistema que trabalhe com o conceito de reserva, como por exemplo hotéis, restaurantes, teatros ou empresas aéreas. A idéia é permitir que o próprio aplicativo verifique e atualize os status de reservas expiradas.

Cada reserva é representada por um objeto da classe br.com.globalcode.model.Reserva. Esta classe tem como atributos um código, uma data de expiração, um status (PENDENTE,CONFIRMADA OU CANCELADA) e um id, que corresponde à chave primária no banco de dados. Veja o código completo na Listagem1.

O acesso aos dados persistidos para as reservas é realizado através da classe br.com.globalcode.dao.ReservasDAO. Além dos métodos diretamente relacionados à manipulação de reservas, esta classe contém os métodos para obtenção e fechamento da conexão com o banco de dados. Usualmente, estes métodos são implementados em uma classe separada, de maneira a serem compartilhados entre os diversos DAOs do aplicativo, mas no exemplo, por simplificação estão na própria ReservasDAO. A figura 1 apresenta o diagrama de classe de ReservasDAO. O código completo desta classe e de todo resto da aplicação está disponível no site da Java Magazine.

Além de reserva também criamos a classe br.com.globalcode.model.Agendamento (Listagem 2), que contém apenas uma descrição e a data e o horário do agendamento. No nosso exemplo o agendamento é sempre diário; por isso esta classe não contém o intervalo para repetição. Note também que, como a classe Agendamento não precisa ser persistida, não criamos um DAO para ela.

 

Imagem

Figura 1. Diagrama de classe de ReservasDAO

 

Listagem 1. Reserva.

 

package br.com.globalcode.model;

 

import java.text.SimpleDateFormat;

import java.util.Date;

 

public class Reserva {

 public static final SimpleDateFormat

  FORMATADOR_DATA_USUARIO = new SimpleDateFormat("dd/MM/yyyy hh:mm");

 

 private String codigo;

 private Date dataExpiracao;

 private int id;

 private int status = PENDENTE;

 

 public static final int PENDENTE= 1;

 public static final int CANCELADA= 2;

 public static final int CONFIRMADA= 3;

 

 public Reserva() {

 }

 public Reserva(String codigo. Date dataExpiracao){

  this.codigo = codigo;

  this.dataExpiracao = dataExpiracao;

 }

 

 public Reserva(int id, String codigo, Date dataExpiracao){

  this(codigo,dataExpiracao);

  this.id = id;

 }

 public Reserva(int id, String codigo, Date dataExpiracao. int status){

this(codigo,dataExpiracao);

this.id = id;

this.status = status;

 }

 

 

 public String toString(){

  return "Codigo = " + codigo + " data expiração = " + FORMATADOR_DATA_

 USUARIO.format(dataExpiracao) + " id= " + id + "status = " + status;

 }

 

//getters e setters omitidos

}

 

Listagem 2.Agendamento.

 

package br.com.globalcode.model;

 

import java.io.Serializable;

import java.text.SimpleDateFormat;

import java.util.Date;

 

public class Agendamento implements Serializable{

 

 public static final SimpleDateFormat

  FORMATADOR_DATA_USUARIO = new SimpleDateFormat("dd/MM/yyyy   hh:mm");

 private String info;

 private Date data;

 

 public Agendamento() {

 }

 public Agendamento(String info, Date data){

this.info = info;

this.data = data;

 }

 

 public String toString(){

return info + " " + FORMATADOR_DATA_USUARIO.format(data);

 }

 

 //método equals, hashcode, getters e setters omitidos

}

 

Agendamento de tarefas com Java SE

Desde a versão 1.3, estão disponíveis duas classes para o agendamento de tarefas no Java SE: java.util.Timer e java.util.TimerTask.

 

java.util.TimerTask

A classe abstrata TimerTask representa uma tarefa a ser agendada. É uma implementação de java.lang.Runnable. Portanto para criar tarefas devemos criar subclasses de TimerTask e implementar o método run(), da mesma forma que é feito quando trabalhamos com operações a serem executadas por threads. A classe permite também cancelar a tarefa (cancel()) e obter a data da sua última execução (scheduledExecutionTime()).

A classe br.com.globalcode.tasks.VerificadorReservasExpiradas ilustra um exemplo de tarefa baseada em TimerTask. Essa tarefa tem o objetivo de alterar o status de todas as reservas que expiraram até o momento. Ela utiliza a classe ReservasDAO que implementa o design pattern DAO contendo os métodos para interação com o banco de dados. Veja mais no quadro “Patterns Utilizados”. O código da classe está na Listagem 3.

 

Listagem 3. VerificadorReservasExpiradas.

 

package br.com.globalcode.tasks;

 

import br.com.globalcode.dao.ReservasDAO;

import java.sql.SQLException;

import java.util.*;

...

Quer ler esse conteúdo completo? Tenha acesso completo