Избегайте дублирования пространств имен при сортировке сообщений SOAP - PullRequest
0 голосов
/ 29 мая 2018

В настоящее время я работаю над реализацией спецификации WS-Discovery для устройства, которое должно обнаруживаться клиентами, совместимыми с ONVIF (например, системами управления видео).Для маршалинга объектов Java и помещения их в конверт SOAP я использую подход, описанный в в этом примере .Как вы можете видеть, в этом примере объект Java маршалируется в документ с использованием реализации маршаллера JAXB, добавляется к части тела объекта SOAPMessage, а затем SOAPMessage записывается в ByteArrayOutputStream.

При таком подходеВ настоящее время я создаю сообщения в следующей форме (например, ответ ProbeMatches на запросы Probe):

<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://www.w3.org/2005/08/addressing">
    <env:Header>
        <wsa:Action env:mustUnderstand="true">http://docs.oasis-open.org/ws-dd/ns/discovery/2009/01/ProbeMatches</wsa:Action>
        <wsa:MessageID>urn:uuid:9a7e8bc4-d4aa-4269-bbd6-2414084f47fe</wsa:MessageID>
        <wsa:To env:mustUnderstand="true">http://www.w3.org/2005/08/addressing/anonymous</wsa:To>
       <wsa:RelatesTo>urn:uuid:f3e33900-6284-11e8-80b1-add204fec0a3</wsa:RelatesTo>
    </env:Header>
    <env:Body>
        <ns2:ProbeMatches xmlns:ns2="http://docs.oasis-open.org/ws-dd/ns/discovery/2009/01" xmlns="http://www.w3.org/2005/08/addressing">
             <ns2:ProbeMatch>
                 <EndpointReference>
                     <Address>urn:uuid:09edc0f4-d65c-3545-aba5-a59f86348521</Address>
                     <ReferenceParameters />
                 </EndpointReference>
                 <ns2:Types xmlns:dn="http://www.onvif.org/ver10/network/wsdl">dn:NetworkVideoTransmitter</ns2:Types>
                 <ns2:Scopes>onvif://www.onvif.org/name/MyDevice onvif://www.onvif.org/hardware/MyHardware onvif://www.onvif.org/location onvif://www.onvif.org/Profile/Streaming</ns2:Scopes>
                 <ns2:XAddrs>http://192.168.0.10:8080/onvif/device_service</ns2:XAddrs>
                 <ns2:MetadataVersion>1</ns2:MetadataVersion>
             </ns2:ProbeMatch>
        </ns2:ProbeMatches>
    </env:Body>
</env:Envelope>

Как вы можете видеть, объявление пространства имен для WS-Addressing присутствует дважды, один раз в конверте и один раз втег ProbeMatches.Также я хотел бы переместить объявление пространства имен из тега ProbeMatches в конверт.Итак, чего я на самом деле хочу достичь, так это:

<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:wsd="http://docs.oasis-open.org/ws-dd/ns/discovery/2009/01">
    <env:Header>
        <wsa:Action env:mustUnderstand="true">http://docs.oasis-open.org/ws-dd/ns/discovery/2009/01/ProbeMatches</wsa:Action>
        <wsa:MessageID>urn:uuid:9a7e8bc4-d4aa-4269-bbd6-2414084f47fe</wsa:MessageID>
        <wsa:To env:mustUnderstand="true">http://www.w3.org/2005/08/addressing/anonymous</wsa:To>
       <wsa:RelatesTo>urn:uuid:f3e33900-6284-11e8-80b1-add204fec0a3</wsa:RelatesTo>
    </env:Header>
    <env:Body>
        <wsd:ProbeMatches>
             <wsd:ProbeMatch>
                 <wsa:EndpointReference>
                     <wsa:Address>urn:uuid:09edc0f4-d65c-3545-aba5-a59f86348521</wsa:Address>
                     <wsa:ReferenceParameters />
                 </wsa:EndpointReference>
                 <wsd:Types xmlns:dn="http://www.onvif.org/ver10/network/wsdl">dn:NetworkVideoTransmitter</wsd:Types>
                 <wsd:Scopes>onvif://www.onvif.org/name/MyDevice onvif://www.onvif.org/hardware/MyHardware onvif://www.onvif.org/location onvif://www.onvif.org/Profile/Streaming</wsd:Scopes>
                 <wsd:XAddrs>http://192.168.0.10:8080/onvif/device_service</wsd:XAddrs>
                 <wsd:MetadataVersion>1</wsd:MetadataVersion>
             </wsd:ProbeMatch>
        </wsd:ProbeMatches>
    </env:Body>
</env:Envelope>

Как я могу добиться этого с JAXB и в отношении упомянутого примера с использованием SOAPMessage?Проблема в том, что SOAPMassege, похоже, не распознает объявления пространства имен, которые уже присутствуют в маршалированной части тела.Я также открыт для совершенно другого подхода к маршаллингу.

В качестве дополнительной информации приведена структура классов ProbeMatchesType и ProbeMatchType, которые маршалируются (я вручную добавил аннотацию @XmlRootElement в ProbeMatchesType,остальное было сгенерировано из официальных файлов ONVIF WSDL):

@XmlRootElement(name = "ProbeMatches")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ProbeMatchesType", propOrder = {
    "probeMatch",
    "any"
})
public class ProbeMatchesType {

    @XmlElement(name = "ProbeMatch")
    protected List<ProbeMatchType> probeMatch;
    @XmlAnyElement(lax = true)
    protected List<Object> any;
    @XmlAnyAttribute
    private Map<QName, String> otherAttributes = new HashMap<QName, String>();

    ...
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ProbeMatchType", propOrder = {
    "endpointReference",
    "types",
    "scopes",
    "xAddrs",
    "metadataVersion",
    "any"
})
public class ProbeMatchType {

    @XmlElement(name = "EndpointReference", namespace = "http://www.w3.org/2005/08/addressing", required = true)
    protected W3CEndpointReference endpointReference;
    @XmlList
    @XmlElement(name = "Types")
    protected List<QName> types;
    @XmlElement(name = "Scopes")
    protected ScopesType scopes;
    @XmlList
    @XmlElement(name = "XAddrs")
    protected List<String> xAddrs;
    @XmlElement(name = "MetadataVersion")
    @XmlSchemaType(name = "unsignedInt")
    protected long metadataVersion;
    @XmlAnyElement(lax = true)
    protected List<Object> any;
    @XmlAnyAttribute
    private Map<QName, String> otherAttributes = new HashMap<QName, String>();

    ...
}

Заранее благодарен за любую помощь!

Обновление

В моем текущемподход, когда я удаляю @XmlRootElement из класса ProbeMatchesType, я получаю следующее исключение:

com.sun.istack.internal.SAXException2: unable to marshal type "org.xmlsoap.schemas.ws._2005._04.discovery.ProbeMatchesType" as an element because it is missing an @XmlRootElement annotation
    at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:234)
    at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:323)
    at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:479)
    at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:308)

Это происходит, потому что в настоящее время объект ProbeMatchesType действительно является корневым объектом для маршалинга XML.Позднее маршалированный объект документа добавляется к части тела объекта SOAPMessage, который упаковывает все в конверт SOAP, когда он наконец записывается в ByteArrayOutputStream (как вы можете видеть в примере , который я ужесвязаны в начале моего вопроса).

1 Ответ

0 голосов
/ 06 июня 2018

Попробуйте удалить @XmlRootElement (name = "ProbeMatches") из класса ProbeMatchesType.

@ XmlRootElement следует использовать для класса верхнего уровня, в вашем случае классом верхнего уровня является Envelope.

...