Цикл веб-сервиса с использованием Contract-First в Java - PullRequest
4 голосов
/ 07 февраля 2011

Я работаю над приложением с контрактными первыми веб-службами (wsimport и jaxws-maven-plugin).

Как мне писать файлы WSDL / XSD, чтобы иметь возможность обрабатывать циклы? Например, объект department со ссылкой на employees и employee со ссылкой на department (как в этой статье http://jaxb.java.net/guide/Mapping_cyclic_references_to_XML.html). В статье отмечается аннотация @XmlTransient, но, поскольку я использую контракт-сначала, я не могу каким-либо образом изменять сгенерированные классы.

Если я просто игнорирую эти циклы, то при первом запуске веб-службы я получаю сообщение об ошибке, например:

Caused by: com.sun.istack.SAXException2: 
A cycle is detected in the object graph. This will cause infinitely deep XML: 
Employee@18ac4d8 -> Department@aa35d5 -> Employee@18ac4d8

1 Ответ

3 голосов
/ 07 февраля 2011

Проблема в том, что контракты веб-сервисов (по крайней мере, те, которые соответствуют WS-I Basic Profile) не могут кодировать ссылки на другие объекты в сообщении. Таким образом, поле ссылочного типа всегда маршалируется путем маршалинга полей объекта, к которому он относится. Эта рекурсия безгранична, если граф объектов содержит цикл.

То есть, если у вас было:

class A {
    String name;
    A a;
}

и сделал:

A a = new A();
a.name = "hello";
a.a = a;
marshall(a);

XML будет выглядеть как

<a>
    <name>hello</name>
    <a>
        <name>hello</name>
        <a>
            <name>hello</name>
            <a>
                ...

Чтобы избежать этого, цикл необходимо разорвать. Типичные подходы включают в себя сделать ассоциацию доступной только в одном направлении, установить обратные ссылки на null перед маршалингом (поручить получателю восстановить их), переместить ассоциации в отдельные классы, как в

class A {
    String name;
}
class B {
    String adress;   
}

class AWithB {
    A a;
    B b;
}

и множество других опций.

...