I have a relatively complex log4j.xml configuration file with many appenders. Some machines the application runs on need a separate log directory, which is actually a mapped network drive. To get around this, we embed a system property as part of the filename in order to specify the directory. Here is an example:
<appender name="JMX_HTTP_ACCESS_LOG_FILE" class="my.company.log4j.CustomAppender"> <param name="File" value="${user.dir}/log/jmxHttpAccess.log" /> <param name="MaxBackupIndex" value="14" /> <layout class="my.company.log4j.CustomPatternLayout"> <param name="ConversionPattern" value="%d %m%n" /> </layout> </appender>
The "${user.dir}" part is set as a system property on each system, and is normally set to the root directory of the application. On some systems, this location is not the root of the application.
The problem is that there is always one appender where this is not set, and the file appears not to write to the mapped drive. The rest of the appenders do write to the correct location per the system property. As a unit test, I set up our QA lab to hard-code the values for the appender above, and it worked: however, a different appender will then append to the wrong file. The mis-logged file is always the same for a given configuration: it is not a random file each time.
My best educated guess is that there is a HashMap somewhere containing these appenders, and for some reason, the first one retrieved from the map does not have the property set. Our application does have custom system properties loading: the main() method loads a properties file and calls into System.setProperties(). My first instinct was to check the static initialization order, and to ensure the controller class with the main method does not call into log4j (directly or indirectly) before setting the properties just in case this was interfering with log4j's own initialization. Even removing all vestiges of log4j from the initialization logic, this error condition still occurs.