-
Notifications
You must be signed in to change notification settings - Fork 39
Description
We have a few container types designed to wrap collections in the types
module. Upon closer inspection, the generated code for these containers has two methods:
T read(ReadContext ctx)
: which reads the context and creates the object of typeT
.void write(WriteContext ctx, T t)
: which reads the object of typeT
and marshall into the context.
The problem is that the write
method is always empty. Usually, this seems fine, but there are cases where this is a problem:
public class RangeQuery {
private final Map<String, ArrayList<Book>> books;
@ProtoFactory
public RangeQuery(Map<String, ArrayList<Book>> books) {
this.books = books;
}
@SuppressWarnings({"rawtypes", "unchecked"})
@ProtoField(number = 1, mapImplementation = HashMap.class)
public Map<String, ArrayList> getBooks() {
return (Map<String, ArrayList>) ((Object) books);
}
@ProtoSchema(
syntax = ProtoSyntax.PROTO3,
dependsOn = {
BookSchema.class,
CommonContainerTypes.class,
},
includeClasses = RangeQuery.class,
schemaFileName = "range-query.proto",
schemaFilePath = "proto/",
schemaPackageName = "queries"
)
public interface RangeQuerySchema extends GeneratedSchema { }
}
With test:
@Test
public void testRangeQuery() throws IOException {
ArrayList<Book> books = new ArrayList<>(
List.of(
new Book("Fellowship", "Tiny people and rings", 1954),
new Book("Towers", "Marsh with fun smell", 1954),
new Book("King", "Big mountain and eagles", 1955)
)
);
var query = new RangeQuery(Map.of("tolkien", books));
var bytes = ProtobufUtil.toWrappedByteArray(context, query, 512);
System.out.println(Arrays.toString(bytes));
var copy = ProtobufUtil.fromWrappedByteArray(context, bytes);
System.out.println(copy);
}
Will fail to marshall the object. It returns the following byte array:
bytes = [-126, 1, 18, 113, 117, 101, 114, 105, 101, 115, 46, 82, 97, 110, 103, 101, 81, 117, 101, 114, 121, -118, 1, 13, 10, 11, 10, 7, 116, 111, 108, 107, 105, 101, 110, 18, 0]
Which contains only the name of the type, the field number, and the "tolkien" key. Everything else inside the map is ignored because the write method in the generated container is empty.
When invoking the method to unmarshall, it will fail because the parameters for the value are interpreted as nulls because they weren't marshalled:
java.lang.NullPointerException: Cannot invoke "java.lang.Integer.intValue()" because "__v$sizeParam" is null
at org.infinispan.protostream.types.java.collections.ArrayListAdapter$___Marshaller_644b926b0d3f3b832ca16b720ed12a15fdedccbf32741bf201b2c4bb4245d40c.read(ArrayListAdapter$___Marshaller_644b926b0d3f3b832ca16b720ed12a15fdedccbf32741bf201b2c4bb4245d40c.java:38)
at org.infinispan.protostream.types.java.collections.ArrayListAdapter$___Marshaller_644b926b0d3f3b832ca16b720ed12a15fdedccbf32741bf201b2c4bb4245d40c.read(ArrayListAdapter$___Marshaller_644b926b0d3f3b832ca16b720ed12a15fdedccbf32741bf201b2c4bb4245d40c.java:13)
at org.infinispan.protostream.impl.ProtobufTagMarshallerDelegate.unmarshall(ProtobufTagMarshallerDelegate.java:32)
at org.infinispan.protostream.annotations.impl.GeneratedMarshallerBase.readMessage(GeneratedMarshallerBase.java:25)
at org.infinispan.protostream.types.java.RangeQuery$___Marshaller_dac22d3300a708d417ab87b73fde2e08e9e21c43dae8e85e158495c972f749a5.read(RangeQuery$___Marshaller_dac22d3300a708d417ab87b73fde2e08e9e21c43dae8e85e158495c972f749a5.java:54)
at org.infinispan.protostream.types.java.RangeQuery$___Marshaller_dac22d3300a708d417ab87b73fde2e08e9e21c43dae8e85e158495c972f749a5.read(RangeQuery$___Marshaller_dac22d3300a708d417ab87b73fde2e08e9e21c43dae8e85e158495c972f749a5.java:13)
at org.infinispan.protostream.impl.ProtobufTagMarshallerDelegate.unmarshall(ProtobufTagMarshallerDelegate.java:32)
at org.infinispan.protostream.WrappedMessage.readCustomObject(WrappedMessage.java:588)
at org.infinispan.protostream.WrappedMessage.readMessage(WrappedMessage.java:411)
at org.infinispan.protostream.WrappedMessage.read(WrappedMessage.java:401)
at org.infinispan.protostream.ProtobufUtil.fromWrappedByteArray(ProtobufUtil.java:132)
at org.infinispan.protostream.ProtobufUtil.fromWrappedByteArray(ProtobufUtil.java:128)
at org.infinispan.protostream.types.java.TypesMarshallingTest.testRangeQuery(TypesMarshallingTest.java:103)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)
Serializing just the list with the books objects works fine. The problem seems to be with these nested containers. I also believe it needs a map in the mix.