Problem in scheduling for email notifications Spring and JavaMailSender

0

Good morning,

I'm using spring with Scheduled, before using the quartz but as I uploaded the spring version I decided to abandon the quartz since the first option was enough to meet my need.

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

@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 a notification that is generated in a pending table, that every 1 hour the pending notifications are sent, the problem is right there, the method analyze () is working correctly, ), it is sending the same notification 2 times (there are not two lines of the same record in my bank). During the tests I did in eclipse, only once was it sent, but there on the tomcat server I have this problem.

Below the base query method

@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 everyone

    
asked by anonymous 02.01.2019 / 14:09

1 answer

1

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

Some considerations:

  • If you configure your application through XML and annotations, it may be that an instance is created through annotations and consequently a new instance created after the XML is considered by the context, as discussed in bug SPR-10830
  • Your application context is loading twice
  • Duplicate Deploy on Server
  • In any case, try to run your Scheduler outside of the configuration class, for example:

    @Configuration
    @EnableScheduling
    public class JobSchedulerConfig {}
    

    Annotation @EnableScheduling does the following:

      

    This enables detection of annotated annotations on any Spring-managed bean in the container.

    This way you can have your job settings outside 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 found, you can include the annotation @ComponentScan(basePackages="meu.pacote.scheduler") to indicate Spring where to find them.

    Reference related to job configuration can be found at Spring documentation , some of the points I mentioned can also be found in this StackOverflow thread

        
    02.01.2019 / 17:08