I have a @RestController
@RequestBody
that Jackson should be able
to deserialize, but it can't because I made an error in my
serialization setup. All I get in my application's logs is
org.springframework.web.server.UnsupportedMediaTypeStatusException: 415 UNSUPPORTED_MEDIA_TYPE "Content type 'application/json' not supported for bodyType=CLASS_NAME"
Meanwhile there's a very helpful IllegalArgumentException
from within
Jackson that gets swallowed. Jackson actually propagates the exception
all the way up to ObjectMapper#canDeserialize(JavaType)
, where it
sees that you haven't asked for that exception and swallows it. If we
instead called
ObjectMapper#canSerialize(Class<T>, AtomicReference<Throwable>)
,
the consumer could do something with the exception. And the same is
true of ObjectMapper#canDeserialize
.
This changes Jackson2Encoder and Jackson2Decoder to call the canSerialize/canDeserialize methods that propagate the Throwable. It adds a hook where users can receive that Throwable and act on it if they want.
Comment From: Anusien
If you're interested in this, I'd love to get it marked hacktoberfest_accepted
.
Comment From: rstoyanchev
It seems we have a similar mechanism for HttpMessageConverter
so we should make the two consistent.
Comment From: Anusien
I was concerned about the overhead of creating a new AtomicReference
each time, but I wasn't confident enough about the way this thing was called to try and reuse an instance variable.
My understanding, which is admittedly limited, is that Jackson will only throw an exception if it thinks it should be able to deserialize and it can't. I'd want to log this at a higher level than DEBUG
because it likely presents an actual problem. But I'll implement it this way.
One question though: why do we check for logger.isDebugEnabled()
before deciding whether to log the actual exception (versus just using string concatenation)? CC @jhoeller who made this commit;
Comment From: jhoeller
That special debug level check for a warn statement is a pattern that we're using in a few places. The goal is to only log a single line in case of just warn level, while a full stacktrace is being added to the warn level log statement if debug level is active as well. It's a compromise to not log an extra debug log statement with the full stacktrace, and to keep the plain warn log as concise as possible.
Comment From: rstoyanchev
I've added similar logic to the Jackson Encoder/Decoder but mainly enabled as long as the DEBUG level is on. This saves us from creating and using an AtomicReference
at runtime for what is essentially a debugging feature.