jackson-databind
jackson-databind copied to clipboard
Sporadic failures on deserialization of cyclic object graph
When deserializing a cyclic object graph, sometimes an exception will be thrown
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot resolve ObjectId forward reference using property 'propertyName' (of type someType): Bean not yet resolved
Iv'e prepared a reproduction example: https://github.com/nlisker/JacksonRepoExample
The project contains:
- 2 (interface) types,
LandPlot
andStructure
, which hold references to each other. Implementation1 of these interfaces is serialized and then deserialized into implementation2. TheBuildPlan
POJOs hold the data that is serialized and deserialized into. -
StateGenerator
creates an exampleBuildPlan
for serialization. -
SerializationTools
contains the methods for serializing and deserializing. -
SerializationToolsTest
is a JUnit test that creates aBuildPlan
and then tries to serialize and deserialize it with the classes above. - JSOG ID generator dependency. I don't think this is where the problem is coming from, but I could be wrong.
After setting up the project, execute serializeCycle
several times (you might need 20). Sometimes it will work, sometimes it will throw:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot resolve ObjectId forward reference using property 'landPlot' (of type impls2.StructureImpl2): Bean not yet resolved
with a very long stack trace.
The method testSerializeCycle
runs serializeCycle
in a loop, but you will notice that either all attempts fail or all succeed. This tells me that the thing that causes the difference is not in the process of creating a POJO, serializing it, and then deserializing it. Instead, that difference happens each time the JVM is started. I suspect that there is a dependence on the order of values returned from a map, which is randomized on each JVM startup since Java 9. The order of the values in the JSON is different, and sometimes it will fail and sometimes not depending on this order.
If in interfaces.Structure
you comment out the block:
int getOwner();
Status getStatus();
StructureType getType();
int getDefaultRate();
int getRate();
int getTimeToBuild();
then the error does not occur (at least after many attempts). These properties are unrelated to the cyclic dependency of LandPlot
and Structure
, which is further evidence that the deserialization process is doing something wrong.