Scheduling problem for sending notices by e-mail Spring and Javamailsender

Asked

Viewed 101 times

0

Good morning,

I am using spring with Scheduled, before I used Quartz but as I uploaded the version of spring I decided to abandon Quartz since the first option was enough to meet my need.

In short, I have a task that sends emails, this below is the event.

@Configuration
@EnableScheduling
public class NotificacaoScheduler {
    Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private NotificacaoService notificacao;
    @Scheduled(fixedRate = 3600000)//1800000
    public void scheduleFixedRateTask() {
        notificacao.analisar();
        logger.debug("Fixed rate task - " + LocalDateTime.now());
        notificacao.enviarPendentes();
        logger.debug("Send ok - " + LocalDateTime.now());
    }
}

Below the service,

@Service
public class NotificacaoService {
    Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired 
    private JavaMailSender mailSender;
    @Autowired
    private Notificacoes notificacao;
    @Autowired
    private NotificacoesEnvios envios;
    @Transactional
    public void analisar() {
        List<Notificacao> result = notificacao.buscarHoje();
        List<NotificacaoEnvio> notEnvios = new ArrayList<>();
        for(Notificacao n : result) {
            if(!notificacao.verSeExiste(n)) {
                NotificacaoEnvio ne = new NotificacaoEnvio();
                ne.setNotificacao(n);
                ne.setStatus(false);
                notEnvios.add(ne);
            }
        }
        if(!notEnvios.isEmpty()) envios.saveAll(notEnvios);
    }
    @Transactional
    public void enviarPendentes() {
        List<NotificacaoEnvio> ne = notificacao.notificacoesPendentes();
        List<NotificacaoEnvio> nList = new ArrayList<>();
        for (NotificacaoEnvio n : ne) {
            try {
                MimeMessage mail = mailSender.createMimeMessage();
                MimeMessageHelper helper = new MimeMessageHelper(mail);
                helper.setTo(n.getNotificacao().getPara().replace(" ", "").split(";"));
                if(!n.getNotificacao().getCc().trim().equals(""))
                    helper.setCc(n.getNotificacao().getCc().replace(" ", "").split(";"));
                if(!n.getNotificacao().getCo().trim().equals(""))
                    helper.setBcc(n.getNotificacao().getCo().replace(" ", "").split(";"));
                helper.setSubject(n.getNotificacao().getAssunto());
                helper.setText(n.getNotificacao().getModelo().getTexto(),true);
                helper.setFrom(n.getNotificacao().getDe(),n.getNotificacao().getAutor());
                mailSender.send(mail);
                n.setDataEnvio(Calendar.getInstance());
                n.setStatus(true);
                nList.add(n);
            } catch (NullPointerException | MailException | MessagingException | UnsupportedEncodingException e) {
                logger.error(e.getMessage());
            }
        }
        if(!nList.isEmpty()) envios.saveAll(nList);
    }
}

What happens, that I have notification that is generated in a table of pendencias, that every 1 hour is sent the pending notifications, the problem is just there, the method analyze() working correctly, but send the method(), is sending the same notification 2 times (there are no two lines of the same record in my bank). During the tests I did in the eclipse, only once was sent, but there on the Tomcat server I have this problem.

Below the method of consultation the base

@Override
public List<NotificacaoEnvio> notificacoesPendentes(){
    Criteria criteria = manager.unwrap(Session.class).createCriteria(NotificacaoEnvio.class);
    criteria.add(Restrictions.eq("data", Calendar.getInstance()));
    criteria.add(Restrictions.eq("status", false));
     return criteria.list();
}

Hugs and Happy New Year to all

2 answers

1

Probably your problem is in multiple instances of your Scheduler being executed at the same time.

Some considerations:

  1. If you configure your application through XML and Annotations, it may be that an instance is created through the Annotations and consequently a new instance created after XML is considered by the context, as discussed in bug SPR-10830
  2. Your application context is being loaded twice
  3. Duplicate deploy on the server

Anyway, try also to run your Scheduler outside the configuration class, for example:

@Configuration
@EnableScheduling
public class JobSchedulerConfig {}

The Annotation @EnableScheduling does the following:

This Enables Detection of @Scheduled Annotations on any Spring-Managed bean in the container.

This way you can have your Jobs settings out of the configuration class.

And your notification job:

@Component
public class NotificacaoJob {

    Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private NotificacaoService notificacao;

    @Scheduled(fixedRate = 3600000)
    public void doSchedule() {
        notificacao.analisar();
        logger.debug("Fixed rate task - " + LocalDateTime.now());
        notificacao.enviarPendentes();
        logger.debug("Send ok - " + LocalDateTime.now());
    }

}

If your job is not located, you can include the Annotation @ComponentScan(basePackages="meu.pacote.scheduler") to indicate the Spring where to find them.

The reference related to the job configuration can be found in spring documentation, some of the points I mentioned can also be found on this Stackoverflow thread

  • Thanks for the tips, I’ll try the method you suggested, just to be included configured only by Annotations. I just don’t understand why it runs twice. Even so I will test the project and give a feedback. Thank you very much

  • I tried to do as mentioned, but it didn’t work, still keep sending 2 times. if it doesn’t work I will use Quartz

0

Good afternoon, finally managed to solve, I did not understand the problem, but changing the annotation @Scheduled(fixedRate = 3600000) by cron no longer gave problem.

@Component
@EnableScheduling
public class NotificacaoJob{
    Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private NotificacaoService notificacao;
    @Autowired 
    private JavaMailSender mailSender;
    @Scheduled(cron="0 0 * * * *")
    public void execute() {
    //restante do codigo aqui
    }
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.