Bug 53536 - RollingFileAppender with TimeBasedRolling policy doesn't create parent-path if FileNamePattern contains date pattern as directory
RollingFileAppender with TimeBasedRolling policy doesn't create parent-path i...
Product: Log4j
Classification: Unclassified
Component: Companions
PC All
: P2 major
: ---
Assigned To: log4j-dev
Depends on:
  Show dependency tree
Reported: 2012-07-11 11:48 UTC by Daniel Stankiewicz
Modified: 2013-05-16 09:41 UTC (History)
1 user (show)

Log4j XML configuration (784 bytes, text/xml)
2012-07-11 11:48 UTC, Daniel Stankiewicz
Proposed patch (2.32 KB, patch)
2012-07-11 12:40 UTC, Daniel Stankiewicz
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Daniel Stankiewicz 2012-07-11 11:48:09 UTC
Created attachment 29048 [details]
Log4j XML configuration

I'm using org.apache.log4j.rolling.RollingFileAppender together with org.apache.log4j.rolling.TimeBasedRollingPolicy to rotate log files periodically. I need log files to be placed in directories based on date pattern.

Unfortunately, the first log file is created properly, while after rollover RollingFileAppender doesn't check if for newly calculated log file path the whole directory path exists and tries to create FileOutputStream directly, which causes FileNotFoundException:

log4j:WARN Exception during rollover, rollover deferred.
java.io.FileNotFoundException: c:\ssr\log\20120711_1336\ssr.log (The system cannot find the path specified)
	at java.io.FileOutputStream.open(Native Method)
	at java.io.FileOutputStream.<init>(FileOutputStream.java:194)
	at java.io.FileOutputStream.<init>(FileOutputStream.java:116)
	at org.apache.log4j.rolling.RollingFileAppender.rollover(RollingFileAppender.java:286)
	at org.apache.log4j.rolling.RollingFileAppender.subAppend(RollingFileAppender.java:353)
	at org.apache.log4j.WriterAppender.append(WriterAppender.java:162)
	at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:251)
	at org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:66)
	at org.apache.log4j.Category.callAppenders(Category.java:206)
	at org.apache.log4j.Category.forcedLog(Category.java:391)
	at org.apache.log4j.Category.info(Category.java:666)
	at asseco.ssr.common.Log4jTests.main(Log4jTests.java:21)

The similar bug 9150 was filled for base Log4J FileAppender class and it is now fixed. That's why first log file is created successfully. But during rollover() in RollingFileAppender new FileOutputStream is created without creating a new parent directory, which results in the above exception and the file is not rolled.
Comment 1 Daniel Stankiewicz 2012-07-11 12:04:38 UTC
org.apache.log4j.FileAppender contains the following code for creating FileOutputStream, which should be incorporated also to org.apache.log4j.rolling.RollingFileAppender:

    FileOutputStream ostream = null;
    try {
          //   attempt to create file
          ostream = new FileOutputStream(fileName, append);
    } catch(FileNotFoundException ex) {
          //   if parent directory does not exist then
          //      attempt to create it and try to create file
          //      see bug 9150
          String parentName = new File(fileName).getParent();
          if (parentName != null) {
             File parentDir = new File(parentName);
             if(!parentDir.exists() && parentDir.mkdirs()) {
                ostream = new FileOutputStream(fileName, append);
             } else {
                throw ex;
          } else {
             throw ex;
Comment 2 Daniel Stankiewicz 2012-07-11 12:40:15 UTC
Created attachment 29049 [details]
Proposed patch

The code of proposed patch is copied from org.apache.log4j.FileAppender.setFile(String, boolean, boolean, int) method.

It would be best to extract this functionality in FileAppender to another protected method so that derived classes (like org.apache.log4j.rolling.RollingFileAppender) could use the method and the code wouldn't be duplicated.
Comment 3 grobmeier 2013-05-16 09:41:46 UTC
Thanks for the patch! 

I used the duplicated method. You are right, it should be refactored. But with log4j 2 arriving to stable soon, we are minimizing our efforts to log4j 1