2010-10-21 89 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);