Можно ли вызывать метод снова после перехвата исключения? - PullRequest
0 голосов
/ 26 апреля 2019

У меня работает фоновая работа, и каждое утро в 7:00 я вызываю метод, чтобы отправить электронное письмо на определенный адрес, для этого я использую Java-почту. Я спрашиваю об этом потому, что иногда посылает MessagingException (всегда это исключение, когда это происходит). Это ошибка:

nested exception is:
    class javax.mail.MessagingException: 530 5.7.1 Client was not authenticated

Как я уже сказал, это происходит только время от времени; но это немного раздражает, так как я должен удостовериться, что отправляю почту вручную в случае неудачи. Я не нашел причину для этого, я попытался найти это, и некоторые ответы предполагают, что это проблема с сервером; к сожалению, я не могу это контролировать. Когда я выполняю процедуру вручную, иногда требуется до 5 или 7 попыток, пока письмо не будет отправлено.

Итак, я пытаюсь вызвать тот же метод в секции catch, также я бы поставил счетчик для контроля количества попыток в случае, если исключение перехватывается больше, чем, скажем, 5 раз.

Вы бы предложили этот подход? Я ценю вашу помощь и ответы.

Вот код для метода, который я пытаюсь вызывать каждый раз при возникновении исключения MessagingException:

  public void sendMail(String msj, String dest, String asunto, File attachmentSource, int count) {
        String to = dest;
        String from = "some.user@vw.com.mx";
        String host = "someserver.xx.xx.xx";
        boolean debug = true;
        Properties props = new Properties();
        props.put("mail.smtp.host", host);
        if (debug) {
            props.put("mail.debug", "");
        }
        Session session = Session.getInstance(props, null);
        session.setDebug(debug);
        try {
            MimeMessage msg = new MimeMessage(session);
            msg.setFrom(new InternetAddress(from));
            InternetAddress[] address = {new InternetAddress(to)};
            msg.setRecipients(Message.RecipientType.TO, address);
            msg.setSubject("Reporte");
            msg.setSentDate(new Date());
            msg.setText(msj);
            MimeBodyPart messageBodyPart = new MimeBodyPart();
            messageBodyPart.setDataHandler(new DataHandler(new FileDataSource(attachmentSource)));
            messageBodyPart.setFileName(attachmentSource.getName());
            Multipart multipart = new MimeMultipart();
            multipart.addBodyPart(messageBodyPart);
            msg.setContent(multipart);

            Transport.send(msg);
        } catch (MessagingException mex) {
            Logger.getLogger(SendMSG.class.getName()).log(Level.SEVERE, ("ERROR EN ENVÍO!!!! " + mex.getMessage()));
            //THIS IS a TEST TO TRY UNTIL THE MSG IS SENT
            count++;
            if (count <= 5) {
                Logger.getLogger(SendMSG.class.getName()).log(Level.INFO, ("Intento No:  " + count + " de 5" + mex.getMessage()));
                sendMail(msj, dest, asunto, attachmentSource, count);                
            } else {
                Logger.getLogger(SendMSG.class.getName()).log(Level.SEVERE, ("No. de Intentos excedido " + count + " SALIR DE MÉTODO" + mex.getMessage()));
            }
            mex.printStackTrace();
        }
    }

Ответы [ 4 ]

3 голосов
/ 26 апреля 2019

Ваше решение в порядке, но довольно грязное.Я бы разделял повторные попытки и отправку.

public boolean sendMail(String msj, String dest, String asunto, File attachmentSource, int retries) {
    for (int i = 0; i< retries; i++){
        if (sendMail(msj, dest, asunto, attachmentSource)){
            return true;
        }
    }
    return false;
}

public boolean sendMail(String msj, String dest, String asunto, File attachmentSource) {
    try {
        ...
        return true;
    } catch (Exception ex) {
        return false;
    }
}

Это в основном то же самое, что и ваш код, но улучшает читабельность.

0 голосов
/ 26 апреля 2019

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

Как объяснено в JavaMail FAQ , замените ваш вызов Transport.sendс

Transport.send(msg, username, password);

Где имя пользователя и пароль - учетные данные для входа на ваш почтовый сервер.

0 голосов
/ 26 апреля 2019

Я хотел бы предположить, что ошибка зависит от времени.Так как это иногда случается, а иногда нет.Имея это в виду, я предлагаю поместить wait () в цикл после count++

следующим образом:

synchronized (this) 
        {
        this.wait(count*1000);//delay after each error
        }

0 голосов
/ 26 апреля 2019

Придумайте способ разделения двух вещей: выполнение основной логики вашего метода и поведение в случае сбоя. Если бы вы могли написать интерфейс, типа ExceptionHandler, где вы объявляете метод handleFault (например). Затем в своем основном классе вы можете внедрить некоторую конкретную реализацию ExceptionHandler, где вы решаете, что делать в случае сбоя.

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

Я думаю, что действительно стоит взглянуть на схему автоматического выключателя , описанную здесь Мартином Фаулером: https://martinfowler.com/bliki/CircuitBreaker.html

Вы можете иметь отдельные стратегии для обработки ошибок, шаблонов повторов (сколько повторов, время между ними и т. Д.).

...