Issue
I was working on upgrading log4j1.x to log4j2.x. For that I replace log4j1.x with log4j2.17.1(get both log4j-core and api) and my pom file has commons-logging with version 1.2. I had replaces log4j.properties with log4j2.properties file. After deploying changes, in EC2 instance i am getting below error.
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: org.apache.commons.logging.LogConfigurationException: User-specified log class 'org.apache.commons.logging.impl.Log4JLogger' cannot be found or is not useable.
at org.apache.commons.logging.impl.LogFactoryImpl.discoverLogImplementation(LogFactoryImpl.java:804)
at org.apache.commons.logging.impl.LogFactoryImpl.newInstance(LogFactoryImpl.java:541)
at org.apache.commons.logging.impl.LogFactoryImpl.getInstance(LogFactoryImpl.java:292)
at org.apache.commons.logging.impl.LogFactoryImpl.getInstance(LogFactoryImpl.java:269)
at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:655)
Pom file:
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.1</version>
</dependency>
I do have commons-logging.properties file which has code below.
org.apache.commons.logging.Log = org.apache.commons.logging.impl.Log4JLogger
In my project, they have used logger as mentioned below:
A.java
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class A{
public static Log logger = LogFactory.get(A.class);
}
Can someone please help me out with this.
Solution
You explicitly configured Jakarta Commons Logging to use Log4j 1.x. Since you don't have it on the classpath an error is generated.
Remark that Log4j 1.x and Log4j 2.x are not compatible. To bind JCL to Log4j 2.x you need to:
remove/comment the entry in
commons-logging.properties
that forces JCL to use Log4j 1.x,add the appropriate Log4j 2.x binding:
<dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-jcl</artifactId> <version>2.17.1</version> <scope>runtime</scope> </dependency>
Edit: Regarding your comment: since log4j-jcl
has a transitive dependency on commons-logging
, you could remove the latter from the POM file (and use the default compile
scope for log4j-jcl
).
However the common practice is to add as compile
dependencies all the artifacts that you use directly in your code (cf. Maven's dependency:analyze goal) and don't rely on transitive dependencies (which can change). Therefore you should have both commons-logging
in the compile
scope and log4j-jcl
in the runtime
scope.
You can also consider switching from JCL to the Log4j 2.x API, which is more easy to use (cf. documentation). In such a case you should remove commons-logging
from your dependencies, but keep log4j-jcl
to allow your other dependencies to use JCL.
Answered By - Piotr P. Karwasz
Answer Checked By - David Goodson (JavaFixing Volunteer)