2010-10-21 86 views
3

歷史背景:這個問題最終並不是我認爲的那樣。原因和解決方案如下,但原始發佈留作參考。log4j Appender被捕捉的異常關閉

我正在開發一個簡單的框架,用於定期輪詢.properties文件的目錄,然後執行SQL查詢並根據它們的配置發送電子郵件。由於每個.properties文件具有相同的操作範圍,因此它們都由相同的Task類進行解釋。但是由於它們每個都代表不同的邏輯操作,它們每個都會得到不同的日誌文件

這是通過共享log4j RollingFileAppender的一個實例並根據.properties文件中的值動態更改其輸出文件來實現的。由於這是一個單線程應用程序,因此這可以正常工作。

但是,我注意到在某些情況下,這個RollingFileAppender將會關閉,並且應用程序會不經意地繼續,除非現在沒有記錄發生。由於控制檯輸出的原因,我只能設法在動作中捕捉到這一點,因爲通常此服務在Linux服務器上作爲後臺進程運行。發生了什麼事:

1)StartScheduler是主類,每分鐘創建一個TaskPoller的新實例。

2)TaskPoller掃描目錄,從每個.properties文件加載一些信息,並確定它是否應該運行。它也有自己獨立的RollingFileAppender,它通過Logger.getLogger(TaskPoller.class)獲取它。如果應該運行一個任務,那麼它會實例化一個Task對象,傳入要運行的特定.properties文件。 3)任務獲取其RollingFileAppender,然後調用fileAppender.setFile(「newtaskname.log」)和fileAppender.activateOptions()更改輸出文件的位置。然後,在其執行過程中,這樣的事情發生了:

[TaskPoller] 
... 
task = new Task(fileName); //Points RollingFileAppender to the right place 
if (!task.Execute()) 
    logger.warn(fileName + " returned with an error code."); //Succeeds 
[Task.Execute] 
... 
try { 
    dbDAO.Connect(); 
} catch (Exception e) { 
    logger.fatal{"Database connection error.", e}; //Different RFA; Fails 
    return false; 
} 
[DBDAO.Connect throws SQLException, ClassNotFoundException] 
... 
try { 
    Class.forName(dbDriver); //Dynamically loaded jdbc driver class name 
    connection = DriverManager.getConnection(urlString, userName, password); 
} catch (SQLException e) { 
    if (connection != null) 
     try { connection.close(); } catch (Exception e2) { ; } 
    throw e; 
} 

發生的事情是,DBDAO.Connect()時,有時我會得到一個com.mysql.jdbc.exceptions.jdbc4.CommunicationsException(或其他一些從任何jdbc類加載意外的異常)。這不會被Connect()捕獲,但會被Execute()捕獲。

不知何故,這個過程導致Task的RollingFileAppender關閉。對於這種情況,我認爲唯一的事情就是特殊的,而不是它的一致和穩定的正常操作,因爲拋出的異常沒有被Connect()拋出。但我不認爲這會導致log4j Appender關閉。

所以我的問題是,什麼可能導致這個appender意外關閉在與其配置無關的方法?

- 編輯 - 它看起來像我一直誤導完全;問題出在Quartz之間的交互中,我正在使用它來讓TaskPoller每分鐘觸發一次,而log4j。我還沒有完全理解它的原因,但[這個解決方案] [1]似乎解決了這個問題。它直到現在才表現爲觀察到的問題,所以我認爲它與最近發生的事情有關。

+1

+1的研究和共享解決方案的意願。我的建議是:把大膽的標題放在頂部,表示問題已經解決,解決方案在底部;保持原樣,並在底部追加解決方案。那樣,我們就不會失去這個問題的歷史以及它是如何演變的。 – Isaac 2010-10-22 01:07:35

+0

其實,你應該把這篇文章的答案部分放到實際的答案中,這樣它可以被提高,並且你可以接受它。這顯示在「未答覆」選項卡上,實際上不應該。 – 2010-10-25 18:48:52

回答

0

這個問題的真正原因是Quartz調度器和我使用log4j的方式之間的交互。事實證明,如果您通過調用fileAppender.setFile(fileName)和fileAppender.activateOptions())來修改log4j的屬性(即通過調用Quartz工作線程)(即使Quartz配置爲一次只運行一個線程),事情崩潰了。這是通過使用它之前重裝的工作線程的每個新實例log4j屬性,這是我完成的,像這樣固定的:

[Task() Constructor] 
Properties props = new Properties(); 
URL url = ClassLoader.getSystemResource("log4j.properties"); 
try { 
    props.load(url.openStream()); 
    PropertyConfigurator.configure(props); 
} catch (Exception e) { 
    //The logger that never got renamed never stopped working. 
    Logger.getLogger(TaskPoller.class).error("Diagnostics!"); 
} 
logger = Logger.getLogger(Task.class);