infinispan / protostream

ProtoStream is a serialization library based on Protocol Buffers
Apache License 2.0
39 stars 36 forks source link

@Proto does not fully work on classes that extend other classes #304

Open omasseau opened 3 months ago

omasseau commented 3 months ago

Hello,

I'm using the @Proto annotations on classes I want to marshall in an infinispan cache, as described here : https://quarkus.io/guides/infinispan-client-reference#annotation-based-serialization

But I cannot find how to make it work on classes that extends other classes.

Here is an example :

public class Parent {
    public String id;

    public Parent() {
        this.id = UUID.randomUUID().toString();
    }
}

@Proto
public class Person extends Parent {
    public String name;

    public Person(){
    }

    public Person(String name) {
        super();
        this.name = name;

    }
}

@ProtoSchema(includeClasses = {Person.class })
interface Schema extends GeneratedSchema {
}

But the id field from the Parent class is not included in the result :

image

I then tried to add the annotation @Proto on the Parent class and declare the class in @ProtoSchema :

@Proto
public class Parent {
    public String id;

    public Parent() {
        this.id = UUID.randomUUID().toString();
    }
}

@Proto
public class Person extends Parent {
    public String name;

    public Person(){
    }

    public Person(String name) {
        super();
        this.name = name;

    }
}

@ProtoSchema(includeClasses = {Parent.class, Person.class })
interface Schema extends GeneratedSchema {
}

But I then get this error :

C:\dev\git\quarkus-test\src\main\java\com\test\Person.java:22 java: org.infinispan.protostream.annotations.ProtoSchemaBuilderException: Duplicate field number definition. Found two field definitions with number 1: in name and in id, while processing com.test.Schema

So is this a bug or a current limitation with inherited classes ? Do I have to explicitely define a custom proto schema instead on relying on annotations ?

Note: Using Protostream 5.0.5.Final (dependency coming with Quarkus 3.12.2)

tristantarrant commented 2 months ago

Since Protocol Buffers don't support inheritance natively (composition is the recommended approach), we'd need to determine how we want to represent these internally, as well as ensuring that all the compatibility checks, to avoid field name/number/type conflicts, extend to the entire class hierarchy. I think the best approach would be for children to have a synthetic _super field, with a fixed id (1?) so that any changes to the superclass won't overlap with the child classes.

tristantarrant commented 2 months ago

For completeness, I'm quoting the last paragraph from https://protobuf.dev/getting-started/javatutorial/#protocol-format

Don’t go looking for facilities similar to class inheritance, though – protocol buffers don’t do that