Múltiplos Agendamentos - Quartz

Minha aplicação tem uma agenda e preciso criar alarmes para avisar o usuário quando alguma atividade vencer.
Estou tentando utilizar a biblioteca Quartz e estou tendo dificuldades em agendar os alarmes.
Minha ideia inicial é, quando o usuário entrar na aplicação, o sistema listará todas as atividades pendentes e então criará Schedules com o Quartz para que dispare um alerta quando a atividade vencer.
Segue o teste que estou fazendo:

public static void main(String[] args) {
        List<Atividade> atividades = new AtividadesDAO().listarAtividadesDia();
        for (Atividade atividade : atividades) {
            new TesteAgendamento().agendamento(atividade);
        }
    }
public class TesteAgendamento implements Job {

    public void agendamento(Atividade atividade) {
        try {
            Scheduler scheduler = new StdSchedulerFactory().getScheduler();

            String[] horaAtv = atividade.getHoraInicialAtividade().split(":");
            int hora = Integer.parseInt((horaAtv[0])) + 1;
            int idatv = atividade.getIdatv();
            JobDetail job = JobBuilder
                    .newJob(TesteAgendamento.class)
                    .withIdentity(String.valueOf(idatv), "grupo01")
                    .build();
            Trigger trigger = TriggerBuilder
                    .newTrigger()
                    .withIdentity(String.valueOf(idatv), "grupo01")
                    .withSchedule(CronScheduleBuilder.cronSchedule("0 " + horaAtv[1] + " " + hora + " * * ?"))
                    .build();

            scheduler.getContext().put("idatv", idatv);
            scheduler.getContext().put("atividade" + idatv, atividade);
            scheduler.scheduleJob(job, trigger);
            scheduler.start();
        } catch (SchedulerException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public void execute(JobExecutionContext context) {
        try {
            SchedulerContext schedulerContext = context.getScheduler().getContext();
            int idatv = (int) schedulerContext.get("idatv");
            Atividade atividade = (Atividade) schedulerContext.get("atividade" + idatv);
            System.out.println("Atividade " + idatv + " - " + atividade.getDataInicialAtividade() + " " + atividade.getHoraInicialAtividade());

        } catch (SchedulerException e) {
            throw new RuntimeException(e);
        }
    }
}

Ao entrar na aplicação, é feito uma consulta no BD de quantas atividades tem para vencer.
Se houver 3 atividades, deve criar 3 agendamentos (Scheduler) para informar ao usuário no momento do vencimento.

O código acima faz os 3 agendamentos (Scheduler) e chama exatamente no momento do agendado, porém sempre mostra o último horário agendado.

Exemplo:
“Agendamento 1 = 16:00”
“Agendamento 2 = 16:01”
“Agendamento 3 = 16:02”

O resultado fica:
Ás 16:00 o alerta é => “Agendamento 3 = 16:02”
Ás 16:01 o alerta é => “Agendamento 3 = 16:02”
Ás 16:02 o alerta é => “Agendamento 3 = 16:02”

Por favor, alguém poderia me dar uma ajuda com esta questão?
Muito obrigado

Mostra o código deste método

Olá @pmlm, este método é responsável pela consulta das atividades no BD.
Segue o código. O metodo está simplificado, mas basicamente é o que esta abaixo.

public List<Atividades> listarAtividadesDia() {
        List<Atividades> retorno;
        Transaction transaction = null;
        Session session = getSession();
        try {
            transaction = getTransaction(session);
                retorno = session.createCriteria(Atividades.class)
                        .list();

            if (!transaction.wasCommitted()) {
                transaction.commit();
            }

        } catch (RuntimeException erro) {
            if (transaction != null) {
                try {
                    transaction.rollback();
                } catch (Exception ex) {
                    System.err.println("==> ERRO AO FAZER ROLLBACK 'Atividades': " + ex);
                }
            }
            System.err.println("==> ERRO ORIGINAL AO EXECUTAR A QUERY 'Atividades': " + erro);
            throw erro;

        } finally {
            session.close();
        }
        return retorno;
    }

O objectivo era perceber se não estavas erradamente a reusar o mesmo objecto ao adicionar a uma lista em vez de criar objectos novos. Mas se estas a usar Criteria não adicionas os objectos à lista explicitamente, logo não será esse o problema.

Parece-me que o problema poderá estar aqui. Estás a adicionar informação ao contexto do scheduler (que deve ser partilhado entre os jobs) e não a um job específico.

Você está correto. O problema estava ao atribuir a atividade aos Scheduler. Atribui a atividade ao Job e deu certo, as atividades foram chamadas conforme o horário previstos.

Segue o código atualizado e funcinal:

public static void main(String[] args) {
        List<Atividades> atividades = new InPipeAtividadesDAO().listarAtividadesDia();

        try {

            for (Atividades atividade : atividades) {
                String[] horaAtv = atividade.getHoraInicialAtividade().split(":");
                int hora = Integer.parseInt((horaAtv[0])) + 1;
                int idatv = atividade.getIdatv();

                JobDataMap jobDataMap = new JobDataMap();
                jobDataMap.put("idatv", idatv);
                jobDataMap.put("atividade", atividade);

                JobDetail job = JobBuilder
                        .newJob(Teste.class)
                        .setJobData(jobDataMap)
                        .withIdentity(String.valueOf(idatv), "grupo01")
                        .build();
                Trigger trigger = TriggerBuilder
                        .newTrigger()
                        .withIdentity(String.valueOf(idatv), "grupo01")
                        .withSchedule(CronScheduleBuilder.cronSchedule("0 " + horaAtv[1] + " " + hora + " * * ?"))
                        .build();

                Scheduler scheduler = new StdSchedulerFactory().getScheduler();
                scheduler.scheduleJob(job, trigger);
                scheduler.start();

            }


        } catch (SchedulerException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
@Override
    public void execute(JobExecutionContext context) {
        JobDataMap dataMap = context.getJobDetail().getJobDataMap();
        Atividades atividade = (Atividades) dataMap.get("atividade");
        System.out.println("Atividade " + atividade.getIdatv() + " - " + atividade.getDataInicialAtividade() + " " + atividade.getHoraInicialAtividade());
    }

Muito obrigado pela sua ajuda.
Abraços

1 curtida