簡體   English   中英

方法可以在捕獲異常后再次調用自身嗎?

[英]Is it ok for a method to call itself again after catching an exception?

我正在運行后台作業,每天早晨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();
        }
    }

您的解決方案很好,但是很混亂。 我將重試和發送分開。

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

它的作用與代碼基本相同,但是提高了可讀性。

想想一種將兩件事分開的方法:執行方法的主要邏輯和發生故障時的行為。 如果可以編寫一個接口,則可以使用ExceptionHandler類型,在其中聲明方法handleFault (例如)。 然后,在您的主類中,您可以注入ExceptionHandler某些特定實現,您可以在其中確定發生故障時的處理方式。

這將使測試變得更加容易,因為您可以從一個簡單的測試對象中替換“實時”或“生產”或我們所謂的行為,在這里您只想檢查是否處理了錯誤的案例。

我認為,值得一提的是馬丁·福勒(Martin Fowler)在此處描述的電路斷路器模式https : //martinfowler.com/bliki/CircuitBreaker.html

您可以使用單獨的策略來處理錯誤,重試模板(重試次數,兩次重試之間的時間等)。

我想假設錯誤取決於時間。 由於它有時會發生,而有時卻不會。 考慮到這一點,我建議在count++之后將wait()放入循環中

像這樣:

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

其他答案中有一些有用的建議,但我認為問題的核心在於您永遠不會向服務器進行身份驗證。 除非您使用不需要身份驗證的本地服務器,否則我不知道它是如何工作的。

JavaMail常見問題解答中所述,將您的Transport.send調用替換為

Transport.send(msg, username, password);

用戶名和密碼是登錄到郵件服務器的憑據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM