Hello,
I am attempting to serialize and deserialize an Object that contains a list of sub Objects with the same type.
For example, I have an Object called Pojo that contains a List of sub Pojo's.
Writing a snapshot seems to work fine, but reading in the snapshot results in an IndexOutOfBoundsException.
Here is my code:
// Pojo object
private class Pojo {
private String name;
private List<Pojo> subPojos;
public Pojo(String name) {
this.subPojos = new ArrayList<Pojo>();
}
public Pojo(String name, List<Pojo> subPojos) {
this.subPojos = subPojos;
}
public String getName() {
return name;
}
public List<Pojo> getSubPojos() {
return subPojos;
}
}
// Serializer
private class PojoSerializer extends NFTypeSerializer<Pojo>{
public PojoSerializer(String name) {
super(name);
}
@Override
protected void doSerialize(Pojo value, NFSerializationRecord rec) {
serializePrimitive(rec, "name", value.getName());
serializeObject(rec, "subPojos", value.getSubPojos());
}
@Override
protected Pojo doDeserialize(NFDeserializationRecord rec) {
return new Pojo(deserializePrimitiveString(rec, "name"), deserializeObject(rec, "subPojos"));
}
@Override
protected FastBlobSchema createSchema() {
return schema(
field("name", FieldType.STRING),
field("subPojos", "ListOfPojos")
);
}
@Override
public Collection<NFTypeSerializer<?>> requiredSubSerializers() {
return serializers(new ListSerializer<Pojo>("ListOfPojos", new PojoSerializer("SubPojo")));
}
}
// Writing the snapshot
Pojo pojo = new Pojo("Pojo", Lists.newArrayList(new Pojo("SubPojo")));
Pojo pojo2 = new Pojo("Pojo2", Lists.newArrayList(new Pojo("SubPojo", Lists.newArrayList(new Pojo("SubSubPojo")))));
FastBlobStateEngine engine1 = new FastBlobStateEngine(new SerializerFactory() {
@Override
public NFTypeSerializer<?>[] createSerializers() {
return new NFTypeSerializer<?>[] {new PojoSerializer("Pojo")};
}
});
FastBlobWriter writer = new FastBlobWriter(engine1);
engine1.prepareForNextCycle();
engine1.add("Pojo", pojo);
engine1.add("Pojo", pojo2);
engine1.prepareForWrite();
try (DataOutputStream outputStream = new DataOutputStream(new FileOutputStream(new File("./pojos")))) {
writer.writeSnapshot(outputStream);
}
// Reading the snapshot
final FastBlobStateEngine engine2 = new FastBlobStateEngine(new SerializerFactory() {
@Override
public NFTypeSerializer<?>[] createSerializers() {
return new NFTypeSerializer<?>[] {new PojoSerializer("Pojo")};
}
});
final FastBlobReader reader = new FastBlobReader(engine2);
try (DataInputStream inputStream = new DataInputStream(new FileInputStream(new File("./pojos")))) {
reader.readSnapshot(inputStream);
}
The IndexOutOfBoundsException is thrown upon calling reader.readSnapshot(...)
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:653)
at java.util.ArrayList.get(ArrayList.java:429)
at com.netflix.zeno.fastblob.state.FastBlobTypeDeserializationState.get(FastBlobTypeDeserializationState.java:66)
at com.netflix.zeno.fastblob.FastBlobFrameworkDeserializer.deserializeObject(FastBlobFrameworkDeserializer.java:308)
at com.netflix.zeno.fastblob.FastBlobFrameworkDeserializer.deserializeObject(FastBlobFrameworkDeserializer.java:281)
at com.netflix.zeno.fastblob.FastBlobFrameworkDeserializer.deserializeObject(FastBlobFrameworkDeserializer.java:48)
at com.netflix.zeno.serializer.NFTypeSerializer.deserializeObject(NFTypeSerializer.java:107)
at zeno.test.NestedPojoTest$PojoSerializer.doDeserialize(NestedPojoTest.java:70)
at zeno.test.NestedPojoTest$PojoSerializer.doDeserialize(NestedPojoTest.java:1)
at com.netflix.zeno.serializer.NFTypeSerializer.deserialize(NFTypeSerializer.java:61)
at com.netflix.zeno.fastblob.state.FastBlobTypeDeserializationState.add(FastBlobTypeDeserializationState.java:71)
at com.netflix.zeno.fastblob.io.FastBlobReader.readTypeStateObjects(FastBlobReader.java:200)
at com.netflix.zeno.fastblob.io.FastBlobReader.readSnapshotTypes(FastBlobReader.java:93)
at com.netflix.zeno.fastblob.io.FastBlobReader.readSnapshot(FastBlobReader.java:73)
at zeno.test.NestedPojoTest.test(NestedPojoTest.java:126)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
The only solution I have come up with is to pre-instantiate sub serializers with unique names:
return serializers(new ListSerializer<Pojo>("ListOfPojos1", new PojoSerializer("SubPojo1")));
return serializers(new ListSerializer<Pojo>("ListOfPojos2", new PojoSerializer("SubPojo2")));
return serializers(new ListSerializer<Pojo>("ListOfPojos3", new PojoSerializer("SubPojo3")));
...
The only issue with this is that I am limited to a fixed number of nested objects.
Is there another way around this that I am overlooking?