apache / logging-log4j2

Apache Log4j 2 is a versatile, feature-rich, efficient logging API and backend for Java.
https://logging.apache.org/log4j/2.x/
Apache License 2.0
3.39k stars 1.62k forks source link

log4j-spring-boot gives error #2384

Closed JyotiSathe closed 7 months ago

JyotiSathe commented 7 months ago

Description

I have spring boot project, recently upgraded to version 3.2.2 from 3.1.0. We are using dependency "org.apache.logging.log4j:log4j-spring-boot" in our project.

After upgrading to 3.2.2 we are getting below exception when started the the application.

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory at org.springframework.boot.SpringApplication.(SpringApplication.java:202)

On analyzing found that spring-boot-3.1.0 imports dependency log4j-spring-boot with version 2.20.0 and spring-boot-3.2.2 imports dependency log4j-spring-boot with version 2.21.1

If I use version 2.20.0 explicitly for log4j-spring-boot with spring-boot 3.2.2, application works as expected with warning in logs "Standard Commons Logging discovery in action with spring-jcl: please remove commons-logging.jar from classpath in order to avoid potential conflicts".

As per initial observation it seems 2.21.1 version of log4j-spring-boot have some issue which throws NoClassDefFoundError.

Configuration

Version: 2.21.1

JDK: JDK-17

ppkarwasz commented 7 months ago

@JyotiSathe,

Which Spring Boot 3.x artifact depends on org.apache.logging.log4j:log4j-spring-boot?

The functionality of log4j-spring-boot is embedded into Spring Boot 3.x (cf. spring-projects/spring-boot#32578), so there is no need for an additional artifact.

The log4j-spring-boot artifact only supports Spring Boot 2.x.

ppkarwasz commented 7 months ago

@JyotiSathe,

The stack trace you deleted seems like a problem with Spring Boot's version of our lookup. Unlike our version it fails if there is no environment.

Such an occurrence is pretty natural. If you use a log4j2.xml configuration file it will be used twice: before an environment is available and after the environment is available. You can work around the problem by renaming the file to log4j2-spring.xml or using a Spring arbiter.

Edit: For posterity's sake, this is the stack trace in question. Since it does not contain any of your classes I assume you don't have anything against keeping it:

ERROR StatusConsoleListener Resolver failed to lookup spring:[spring.application.name](http://spring.application.name/)
java.lang.IllegalStateException: Unable to obtain Spring Environment from LoggerContext
at org.springframework.util.Assert.state(Assert.java:76)
at org.springframework.boot.logging.log4j2.SpringEnvironmentLookup.lookup(SpringEnvironmentLookup.java:46)
at org.apache.logging.log4j.core.lookup.StrLookup.evaluate(StrLookup.java:108)
at org.apache.logging.log4j.core.lookup.Interpolator.evaluate(Interpolator.java:199)
at org.apache.logging.log4j.core.lookup.StrSubstitutor.resolveVariable(StrSubstitutor.java:1183)
at org.apache.logging.log4j.core.lookup.StrSubstitutor.substitute(StrSubstitutor.java:1098)
at org.apache.logging.log4j.core.lookup.StrSubstitutor.substitute(StrSubstitutor.java:974)
at org.apache.logging.log4j.core.lookup.StrSubstitutor.replace(StrSubstitutor.java:488)
at org.apache.logging.log4j.core.config.plugins.visitors.PluginBuilderAttributeVisitor.visit(PluginBuilderAttributeVisitor.java:47)
at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.injectFields(PluginBuilder.java:186)
at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.build(PluginBuilder.java:122)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createPluginObject(AbstractConfiguration.java:1138)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:1063)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:1055)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:1055)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:1055)
at org.apache.logging.log4j.core.config.AbstractConfiguration.doConfigure(AbstractConfiguration.java:664)
at org.apache.logging.log4j.core.config.AbstractConfiguration.initialize(AbstractConfiguration.java:258)
at org.apache.logging.log4j.core.config.AbstractConfiguration.start(AbstractConfiguration.java:304)
at org.apache.logging.log4j.core.LoggerContext.setConfiguration(LoggerContext.java:621)
at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:694)
at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:711)
at org.apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:253)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:155)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:47)
at org.apache.logging.log4j.LogManager.getContext(LogManager.java:196)
at org.apache.commons.logging.LogAdapter$Log4jLog.(LogAdapter.java:146)
at org.apache.commons.logging.LogAdapter$Log4jAdapter.createLog(LogAdapter.java:113)
at org.apache.commons.logging.LogAdapter.createLog(LogAdapter.java:95)
at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:67)
at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:59)
at org.springframework.boot.SpringApplication.(SpringApplication.java:202)
JyotiSathe commented 7 months ago

Yes after removing log4j-spring-boot and renaming log4j-spring.xml issue is resolved. Thanks for the help.

9you commented 7 months ago

Spring Boot should remove log4j-spring-boot from their declaration. It will cause errors to be reported immediately when upgrading the Spring Boot version from 2.x to 3.x.

ppkarwasz commented 7 months ago

@9you,

Does any Spring Boot 3.x artifact or starter depend on log4j-spring-boot? If you know such an example, you should probably submit an issue report to Spring Boot.

Remark: since Maven doesn't have a notion of "conflicting dependencies", it is impossible for Spring Boot to automatically remove log4j-spring-boot dependencies that users have in their POM files, although the "Migrate to Spring Boot 3.0" OpenRewrite recipe could do it.

9you commented 7 months ago

In Spring 2.x, we use the following declaration (without specifying the version): `

org.apache.logging.log4j
 <artifactId>log4j-spring-boot</artifactId>

So, I believe Spring Boot has defined it in their` section. And if they remove it in version 3.x, Maven will raise an error when it tries to resolve dependencies.

But you are right, I just checked, and I found that they don't include the individual log4j-spring-boot but rather the whole log4j-bom. So, I think they didn't do anything wrong.

ppkarwasz commented 7 months ago

So, I believe Spring Boot has defined it in their <dependencyManagement> section. And if they remove it in version 3.x, Maven will raise an error when it tries to resolve dependencies.

But you are right, I just checked, and I found that they don't include the individual log4j-spring-boot but rather the whole log4j-bom. So, I think they didn't do anything wrong.

Yes, and we also can not remove log4j-spring-boot from the BOM, because it has many other users beyond Spring Boot 3.x (e.g. Spring Boot 2.x :wink:)