Почему protostuff повреждает объекты при использовании дженериков в сочетании с циклическими ссылками?

Я использую двоичный файл protostuff с циклическими ссылками и дженериками. В качестве очень упрощенного сценария у меня есть следующие классы:

    public class A {

    private String name;
    private B b;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public B getB() {
        return b;
    }

    public void setB(B b) {
        this.b = b;
        this.b.setA(this);
    }
}

///////////////////////////////////////////////////////////////////////////////

public class B {

    private String name;
    private A a;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public A getA() {
        return a;
    }

    public void setA(A a) {
        this.a = a;
    }
}

///////////////////////////////////////////////////////////////////////////////

public class Container<E> {
    private E element;
    private String name;

    public Container() {
    }

    public Container(E e, String name) {
        super();
        this.element = e;
        this.name = name;
    }

    public E getElement() {
        return element;
    }

    public void setElement(E e) {
        this.element = e;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Когда я запускаю следующий модульный тест, чтобы проверить правильность выполнения сериализации/десериализации туда и обратно, я получаю очень странный результат. последнее утверждение не работает:

public class CircularRefTest {

    @Test
    public void testCircularReferences() {

        A a = new A();
        a.setName("a");
        B b = new B();
        b.setName("b");
        a.setB(b);
        Container<A> container = new Container<A>(a, "container");

        Schema<Container> schema = RuntimeSchema.getSchema(Container.class);
        LinkedBuffer buffer = LinkedBuffer.allocate(256);
        byte[] data = GraphIOUtil.toByteArray(container, schema, buffer);

        Container<A> copy = new Container<A>();
        GraphIOUtil.mergeFrom(data, copy, schema);

        assertEquals(container.getName(), copy.getName());
        assertEquals(container.getElement().getName(), copy.getElement().getName());
        assertEquals(container.getElement().getB().getName(), copy.getElement().getB().getName());

        // something weird happens here with the circular references here
        System.out.println(copy.getElement().getB().getA().getClass());
        assertTrue(copy.getElement().getB().getA() instanceof A); // fails
    }
}

Protostuff повреждает циклические ссылки от дочернего класса к родительскому. Последнее утверждение должно пройти, но по какой-то причине класс имеет тип Container.

Что я делаю неправильно ?

Если я изменю класс контейнера для использования строго типизированных объектов, тогда модульный тест пройдет. Это баг??

Артефакт maven, который я использую:

<dependency>
        <groupId>com.dyuproject.protostuff</groupId>
        <artifactId>protostuff-api</artifactId>
        <version>1.0.4</version>
    </dependency>

person user1011782    schedule 01.02.2012    source источник
comment
Я не знаю насчет буферов протоколов, но при сериализации WCF обязательно специально задавать атрибут IsReference, чтобы ссылки на родительские объекты устанавливались корректно (иначе у вас было бы ParentInstanceA -> ChildInstanceA -> ParentInstanceB вместо дочернего, указывающего обратно на родительский объект). правильный родитель). Возможно, есть что-то подобное с буферами протоколов.   -  person Eric J.    schedule 01.02.2012
comment
Я не нашел никаких ссылок на это в документации Protostuff code.google.com/p/protostuff /wiki/Сериализация ObjectGraphs   -  person user1011782    schedule 01.02.2012
comment
@Eric поддержка дженериков и циклических ссылок не является частью спецификации Google; protobuf-net и protostuff, по сути, обманывают с расширениями (которые соответствуют спецификации Wire); Я понятия не имею, похожи ли подходы, принятые для этих двух, хотя бы отдаленно.   -  person Marc Gravell    schedule 01.02.2012


Ответы (1)


Я очень внимательно просмотрел полный список зависимостей в моем проекте и нашел следующее:

protostuff-api: 1.0.4
protostuff-collectionsschema: 1.0.2
protostuff-runtime: 1.0.2
protostuff-core: 1.0.2

У меня банки 1.0.2 выглядели странно. Затем я удалил все зависимости.

Затем я добавил следующие зависимости:

 <dependency>
      <groupId>com.dyuproject.protostuff</groupId>
      <artifactId>protostuff-runtime</artifactId>
      <version>1.0.4</version>
    </dependency>
    <dependency>
      <groupId>com.dyuproject.protostuff</groupId>
      <artifactId>protostuff-core</artifactId>
      <version>1.0.4</version>
    </dependency>

Это потянуло в следующие банки:

protostuff-api: 1.0.4
protostuff-collectionsschema: 1.0.4
protostuff-runtime: 1.0.4
protostuff-core: 1.0.4

Затем я повторно запустил модульный тест, и все заработало!

Просто для двойной проверки я запустил модульный тест со всеми банками на основе версии 1.0.2, тест не прошел. Похоже, эта проблема была исправлена ​​в версии 1.0.4.

person user1011782    schedule 02.02.2012