我将Log4J2的JSON layout logging用于基于Spring Boot(2.1.6)的Web应用程序。
我在Converter
s中验证请求的传入参数。
如果参数无效,则抛出IllegalArgumentException
。那个包裹在ConversionFailedException
中,而包裹又包裹在MethodArgumentTypeMismatchException
中。
现在,当尝试使用JSON记录器记录此异常时,Jackson序列化会遇到无限循环:
ERROR StatusLogger com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Direct self-reference leading to cycle (through reference chain: org.apache.logging.log4j.core.impl.Log4jLogEvent["message"]->java.util.LinkedHashMap["exception"]->org.springframework.web.method.annotation.MethodArgumentTypeMismatchException["cause"]->org.springframework.core.convert.ConversionFailedException["sourceType"]->org.springframework.core.convert.TypeDescriptor["resolvableType"]->org.springframework.core.ResolvableType["componentType"]->org.springframework.core.ResolvableType["componentType"])
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Direct self-reference leading to cycle (through reference chain: org.apache.logging.log4j.core.impl.Log4jLogEvent["message"]->java.util.LinkedHashMap["exception"]->org.springframework.web.method.annotation.MethodArgumentTypeMismatchException["cause"]->org.springframework.core.convert.ConversionFailedException["sourceType"]->org.springframework.core.convert.TypeDescriptor["resolvableType"]->org.springframework.core.ResolvableType["componentType"]->org.springframework.core.ResolvableType["componentType"])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1191)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter._handleSelfReference(BeanPropertyWriter.java:944)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:721)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
...
该错误似乎归结为TypeDescriptor
中的ConversionFailedException
不能序列化为JSON的事实。
要复制:
val illegalArgumentException = java.lang.IllegalArgumentException("your value is bad")
val conversionFailedException = org.springframework.core.convert.ConversionFailedException(TypeDescriptor.valueOf(String.javaClass), TypeDescriptor.valueOf(String.javaClass), "some bad value", illegalArgumentException)
val mapper = com.fasterxml.jackson.databind.ObjectMapper()
mapper.writeValueAsString(conversionFailedException)
或者,如果您想将问题缩小到最小的单位:
com.fasterxml.jackson.databind.ObjectMapper().writeValueAsString(org.springframework.core.convert.TypeDescriptor.valueOf(String.javaClass))
解决此问题的最佳方法是什么?
答案 0 :(得分:0)
您收到的错误是因为org.springframework.core.ResolvableType
具有对自身的引用:componentType
会创建无限循环。
避免这种情况的一种方法是在全局范围内将org.springframework.core.ResolvableType
从JSON序列化/反序列化中排除。您可以通过使用Jackson的mixins来做到这一点:
@JsonIgnoreType
public class MyMixInForIgnoreType {}
现在,在配置类中创建一个自定义对象映射器:
@Bean
@Primary
public ObjectMapper objectMapper () {
ObjectMapper mapper = new Log4jJsonObjectMapper();
mapper.addMixIn(org.springframework.core.ResolvableType.class, MyMixInForIgnoreType.class);
return mapper;
}