2015-07-20 9 views
3

У меня проблема с JavaMailSender, которая отправляет двойные или тройные сообщения.Почтовый отправитель Java отправляет повторяющиеся письма

В контроллере:

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("[email protected]"); 

    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; 
} 

Я просто предполагаю, что это проблема в моей электронной почте отправка класса, но, возможно, вызов апи слишком медленно, что выполнение метода занимает слишком много времени и отправляет повторяющиеся сообщения? Иногда, когда я отправляю только несколько писем (например, 3), это нормально, и он не отправляет дубликаты. Когда я хочу отправить, как 20 или 30, все занимает около 15 минут, и я получаю дубликаты (я не могу контролировать время отклика API, иногда это быстрее, чем когда-либо его супер медленно). Есть ли способ отлаживать его и видеть, какой метод вызывается, когда и почему я получаю эти дубликаты?

Edit: Вот мой itemRepository реализации:

@Repository 
@Qualifier(value = "itemRepository") 
@Transactional 
public interface itemRepository extends CrudRepository<Item, Long> { 

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

Ваш код контроллера запускается несколько раз в одно и то же время? возможно, запрос отправляется в бэкэнд несколько раз в одно и то же время? add synchronized – andy

+0

Я не был знаком с синхронизированным, исследуя его сейчас. поэтому, используя мой метод контроллера, выполните следующие действия: общедоступные синхронизированные идентификаторы SendAtems ModelAndView (размер @PathVariable ("size") int) выбрасывает исключение {должно быть? – Damian

+0

попробуйте, и как вы называете ваш контроллер, из пользовательского интерфейса? – andy

ответ

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();, прежде чем у нее появилась возможность обновить запись.

Вместо этого вы должны запросить у своего репозитория список неотправленных писем, соответствующих некоторым критериям, а затем выполнить цикл в этом возвращенном списке, чтобы отправить электронное письмо, а затем обновить запись в репозитории.

+0

Извините, моя ошибка, я забыл скопировать этот декремент (он всегда был в моем коде). Обновлен мой вопрос. Я использовал запрос к БД для списка предметов, которые мне нужно отправить, а затем foop на resoultset. Время от времени я получал дубликаты – Damian