log4j2 configuration file not found with java 9

2019-02-18 15:01发布

问题:

I had a Java 8 project and my configuration file was in resource folder and everything worked fine. Now I switched to Java 9, added requirement for log4j.api, and configuration file cannot be found anymore.

Do I need to add something else in my module-info file for the logger to find it's config?

For now, it's like this

module project.main {
    requires jdk.incubator.httpclient;
    requires jackson.databind;
    requires jackson.core;
    requires jackson.annotations;
    requires log4j.api;
}

The Project structure is as:

The build.gradle file is as:

回答1:

The log4j~faq suggests using at least log4j-api-2.x and log4j-core-2.x. Preferably add these to your build.gradle file:

compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.9.0'
compile group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: '2.9.0'
compile group: 'org.apache.logging.log4j', name: 'log4j-1.2-api', version: '2.9.0'

And make sure conflicting dependencies are excluded


In the module-info.java further you shall update(this is what I did in a custom maven project)

requires log4j; // not log4j.api

It should work for you then with the same directory structure as well.


Hint: This is where I started debugging it from. Why do I see a warning about "No appenders found for logger" and "Please configure log4j properly"?

This occurs when the default configuration files log4j.properties and log4j.xml can not be found and the application performs no explicit configuration. log4j uses Thread.getContextClassLoader().getResource() to locate the default configuration files and does not directly check the file system...

Placed a debug point in the ClassLoader#getResource method and just keep an eye of resources looked for by the library.


Also to bring up the point over resources like resources/foo/bar/log4j.properties as stated in the release notes in JDK-8142968

  • JDK internal resources, other than class files, in the standard and JDK modules can no longer be located with the ClassLoader.getResourceXXXAPIs. This may impact code that relies on using these APIs to get at JDK internal properties files or other resources.

and seconded by the java-doc of ClassLoader#getResource as well:

  • Resources in named modules are subject to the encapsulation rules specified by Module.getResourceAsStream. Additionally, and except for the special case where the resource has a name ending with ".class", this method will only find resources in packages of named modules when the package is opened unconditionally (even if the caller of this method is in the same module as the resource).