Search code examples
javajakarta-eeconfigurationlog4j2slf4j

External Log4J2 configuration in Java EE application


I'm working on a Java EE project which had configuration files in resources folder. The web project is assembled into a war file using Maven and deployed to Tomcat.

Then I started doing some maintainance and tried to externalize the configurations which had been successful to some extent.

In case you wonder how it was on production before I edited the code, here it goes:

// x stands for `application.conf` or  `en.properties` depending on where in the code the file is being 
getClass().getClassLoader().getResourceAsStream(x)

I've moved every single file under resources to /CATALINA_BASE/conf/myProject and I'm reading from these paths in the code. (doesn't look like a good practice to me)

And here is my version:

// x stands for `application.conf` or  `en.properties` depending on where in the code the file is being read
new File(System.getProperty("catalina.base") + "/conf/myProject/x")

This works fine obviously but the project also has a log4j2.properties file which was automatically read from the classpath before and since I've externalized the configuration I'm not able to read from it.

What I tried was setting a parameter inside web.xml like below(not sure if it is right thing to do)

<web-app>
...
    <context-param>
<!--        also tried with log4jConfigLocation-->
        <param-name>log4Configuration</param-name>
        <param-value>file:${catalina.base}/conf/myProject/log42.properties</param-value>
    </context-param>
...
</web-app>

The error output during application startup:

ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console. Set system property 'org.apache.logging.log4j.simplelog.StatusLogger.level' to TRACE to show Log4j2 internal initialization logging.

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".

SLF4J: Defaulting to no-operation (NOP) logger implementation

Any suggestions would be appreciated.

UPDATE: The tomcat running on the server is serving several other applications so setting VM arguments is not an option for me since other projects might have their log4j configurations in their classpath and VM arguments may break those configurations.


Solution

  • In case anyone faces this issue, I've found a solution.

    After digging down into the source files of org.apache.logging.log4j:log4j-core:2.8.2 I saw that the ConfigurationFactory class calls PropertiesUtil.getProperties() which has a line as follows:

    private static final PropertiesUtil LOG4J_PROPERTIES = new PropertiesUtil("log4j2.component.properties");
    

    Therefore I created a log4j2.component.properties file under src/main/resources/ which has only one line of property:

    log4j.configurationFile=myCustomPath/log4j2.properties
    

    Since we cannot use logging.config property to set configuration path in Java EE applications unlike a Spring project, adding this specific file solved my problem with externalizing Log4j configuration.

    Hope this answer helps others too.