spring-boot-starter-log4j2
using log4j'sConsoleJSONAppender
can cause following error if org.springframework.boot.autoconfigure.logging
log level is set to DEBUG
.
2021-04-19 16:07:17,180 main ERROR com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportMessage and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.apache.logging.log4j.core.impl.Log4jLogEvent["message"]) com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportMessage and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.apache.logging.log4j.core.impl.Log4jLogEvent["message"])
Setting org.springframework.boot.autoconfigure.logging: INFO
removes the error message.
(Relatively minified) steps to reproduce
pom.xml
snippet
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- not sure why this is needed, removing this causes error to go away -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
</dependencies>
```
application.yml
logging.level.org.springframework.boot.autoconfigure.logging: DEBUG
log4j2-spring.xml
<Loggers>
<Root level="INFO">
<AppenderRef ref="ConsoleJSONAppender"/>
</Root>
</Loggers>
Java application
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication public class MainApp { public static void main(String[] args) { SpringApplication.run(MainApp.class, args); } } ```
Comment From: wilkinsona
Thanks for the report.
As configured, Log4j2 is assuming that everything that's logged can be serialised to JSON using Jackson in its default configuration. This assumption does not hold true for ConditionEvaluationReportMessage
. This appears to be a known issue with Log4j2 (see LOG4J2-2670 and LOG4J2-2034) where other classes have caused similar problems.
We could address the problem with ConditionEvaluationReportMessage
by calling toString()
ourselves before passing it into the logger. This would be a point fix for a potentially much broader problem so I'm not sure that it's worth it. I think you'd be better leaving objectMessageAsJsonObject
set to false
so that Log4j2 doesn't attempt to treat every object that's passed into a logging call as something that can be serialised to json. Beyond that, I think you'll need to customize the ObjectMapper
that Log4j2 is using (assuming that this is possible before LOG4J2-2670 has been addressed).