Java邮件发送器发送重复邮件

3

我有一个与JavaMailSender有关的问题,它会发送两到三条重复的信息。

在控制器中:

while(size > 0) //# of emails I want to send, for example 5
{
    Item item= itemRepository.findFirstBySentFalseAndValidTrue(); //getting only emails that are not sent!
    item.getData(); // API call that adds some info to the item, takes between 5-15 seconds per item    
    if(item.isValid())
    {

            item.setHeaderName(dataService.setHeader(item.getStore(), LocaleContextHolder.getLocale()));
            item.setAddress(dataService.getAddress(item.getStore(), LocaleContextHolder.getLocale()) + item.getId());

            String email = dataService.getEmail(item.getStore());
            String footer = dataService.getFooter(item.getStore(), LocaleContextHolder.getLocale());

            if(!item.isSent()) //I check if sent here but still get double messages!
            {
                if(mailSenderService.sendEmail(item, "emails/templates/item", email, footer))
                {
                    item.setSent(true);
                }
            }

    itemRepository.save(item);
    size--;
    }
}

在我的电子邮件发送服务类中:
    final MimeMessage mimeMessage = this.mailSender.createMimeMessage();
    final MimeMessageHelper message = new MimeMessageHelper(mimeMessage,true, "UTF-8");

    Context ctx =  new Context(LocaleContextHolder.getLocale());
    message.setFrom(email);
    message.setTo("test@gmail.com");

    ResourceBundle labels = ResourceBundle.getBundle("messages", LocaleContextHolder.getLocale());
    mimeMessage.setHeader("Content-Type", encodingOptions);
    mimeMessage.setSubject(labels.getString("email.itme.title"), "UTF-8");


    ctx.setVariable("data", item);
    ctx.setVariable("footer", footer);

    try{        
        String processedTemplate =  templateEngine.process(template, ctx);
        mimeMessage.setContent(processedTemplate, encodingOptions);
        this.mailSender.send(mimeMessage);

    } catch(Exception e){
      e.printStackTrace();
    }

    return true;
}

我猜这可能是我的邮件发送类的问题,但也有可能是API调用太慢,导致方法执行时间过长,从而发送了重复的消息?有时候,当我只发送几封邮件(比如3封)时,一切都很好,不会发送重复的邮件。但是,当我想要发送20或30封邮件时,所有的东西都需要约15分钟,然后我就会收到重复的邮件(我不能控制API的响应时间,有时它会快一些,有时则会非常缓慢)。我能否以某种方式进行调试,并查看哪个方法在何时被调用,为什么会出现这些重复数据呢?
编辑: 这是我的itemRepository实现:
 @Repository
 @Qualifier(value = "itemRepository")
 @Transactional
 public interface itemRepository extends CrudRepository<Item, Long> {

 public Item save(Item item);
 public Item findFirstBySentFalseAndValidTrue();
 }

我之前不熟悉synchronized,现在正在探索它。所以我将我的控制器方法更改为: public synchronized ModelAndView sendItems(@PathVariable("size") int size) throws Exception { 这样可以吗? - Damian
你可以试一下,你是如何从UI中调用你的控制器的? - andy
不,控制器方法是从crontab调用的,或者只是通过URL在浏览器中进行测试。 - Damian
itemRepository.save(item) 是如何实现的?也许是在 save 操作未持久化之前,findFirstBySentFalseAndValidTrue() 获取了过期数据,导致了某种竞态条件? - Dirk Lachowski
Dirk Lachowski,你熟悉锁注释吗?在我的保存方法上放置@Lock(LockModeType.PESSIMISTIC_READ)是否有意义,以阻止下一个循环迭代中对存储库的脏读取? - Damian
显示剩余2条评论
1个回答

0

这部分:

while(size > 0) //# of emails I want to send, for example 5
{
    Item item= itemRepository.findFirstBySentFalseAndValidTrue(); //getting only emails that are not sent!

这没有任何意义。您正在指定要发送的静态电子邮件数量,然后从未减少此值,然后从尚未发送的存储库中调用一个电子邮件,并对其进行某些操作。这是糟糕的设计。您可能会收到重复项,因为没有防止程序在更新记录之前多次检索相同记录的内容: Item item = itemRepository.findFirstBySentFalseAndValidTrue();

相反,您应该查询存储库以获取与某些条件匹配的未发送电子邮件列表,然后对返回的列表执行循环以发送电子邮件,然后在存储库中更新记录。


抱歉,我的错误,我忘记复制那个递减语句了(它一直在我的代码中)。我更新了我的问题。 我曾经查询数据库以获取我需要发送的项目列表,然后在结果集上进行操作。有时也会出现重复。 - Damian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接