jackson-databind icon indicating copy to clipboard operation
jackson-databind copied to clipboard

Sporadic failures on deserialization of cyclic object graph

Open nlisker opened this issue 5 years ago • 12 comments

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 and Structure, which hold references to each other. Implementation1 of these interfaces is serialized and then deserialized into implementation2. The BuildPlan POJOs hold the data that is serialized and deserialized into.
  • StateGenerator creates an example BuildPlan for serialization.
  • SerializationTools contains the methods for serializing and deserializing.
  • SerializationToolsTest is a JUnit test that creates a BuildPlan 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.

nlisker avatar Oct 07 '18 17:10 nlisker