解组ONVIF

时间:2018-04-20 14:37:14

标签: java web-services soap cxf onvif

我目前正在开发一个在嵌入式设备上运行的Java应用程序,并提供各种功能来通过Web界面配置和控制设备。该设备还具有摄像头,因此即将推出的软件版本的要求之一是实现Profile S规范的一些功能(ONVIF),以支持集成到兼容的视频管理系统。由于兼容设备的初始检测是通过WS-Discovery(SOAP over UDP)完成的,我们正在尝试使用Apache CXF(版本3.2.4)实现第一种方法,这似乎有用 - 的现成。

现在,如果我正确地阅读了ONVIF Core Specification(第7.2章)中的相应部分,那么可发现的设备也应该监听并响应探测和解析消息,而这已经是它有点棘手的地方,因为我们遇到了以下问题:

我们网络上的其他一些设备(我不确定哪些设备)会定期以下列格式发送探测消息:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsd="http://schemas.xmlsoap.org/ws/2005/04/discovery" xmlns:wsdp="http://schemas.xmlsoap.org/ws/2006/02/devprof">
    <soap:Header>
        <wsa:To>urn:schemas-xmlsoap-org:ws:2005:04:discovery</wsa:To>
        <wsa:Action>http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</wsa:Action>
        <wsa:MessageID>urn:uuid:a9a24485-7fbd-48bb-bcfc-cce7d98add73</wsa:MessageID>
    </soap:Header>
    <soap:Body>
        <wsd:Probe>
            <wsd:Types>wsdp:Device</wsd:Types>
        </wsd:Probe>
    </soap:Body>
</soap:Envelope>

如您所见,SOAP消息的正文部分包含一个部分<wsd:Types>wsdp:Device</wsd:Types>,根据OASIS WS-Discovery Specification(第5.2章)中的相应部分,它应该是正确的格式。但是,当CXF尝试使用JAXB解组并验证此消息时,我们会收到以下错误:

DefaultValidationEventHandler: [ERROR]: prefix wsdp is not bound to a namespace 
     Location:  node: [wsd:Types: null]
javax.xml.bind.UnmarshalException: prefix wsdp is not bound to a namespace
 - with linked exception:
[java.lang.IllegalArgumentException: prefix wsdp is not bound to a namespace]
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:726)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleError(UnmarshallingContext.java:753)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleError(UnmarshallingContext.java:749)
    at com.sun.xml.internal.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$24.parse(RuntimeBuiltinLeafInfoImpl.java:807)
    at com.sun.xml.internal.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$24.parse(RuntimeBuiltinLeafInfoImpl.java:802)
    at com.sun.xml.internal.bind.v2.runtime.reflect.ListTransducedAccessorImpl.processValue(ListTransducedAccessorImpl.java:125)
    at com.sun.xml.internal.bind.v2.runtime.reflect.ListTransducedAccessorImpl.parse(ListTransducedAccessorImpl.java:140)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.LeafPropertyLoader.text(LeafPropertyLoader.java:50)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.text(UnmarshallingContext.java:572)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.InterningXmlVisitor.text(InterningXmlVisitor.java:78)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.processText(SAXConnector.java:198)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.endElement(SAXConnector.java:161)
    at com.sun.xml.internal.bind.unmarshaller.DOMScanner.visit(DOMScanner.java:240)
    at com.sun.xml.internal.bind.unmarshaller.DOMScanner.visit(DOMScanner.java:266)
    at com.sun.xml.internal.bind.unmarshaller.DOMScanner.visit(DOMScanner.java:235)
    at com.sun.xml.internal.bind.unmarshaller.DOMScanner.scan(DOMScanner.java:112)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:354)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:337)
    at org.apache.cxf.common.jaxb.JAXBUtils.unmarshall(JAXBUtils.java:195)
    at org.apache.cxf.ws.discovery.internal.WSDiscoveryServiceImpl$WSDiscoveryProvider.invoke(WSDiscoveryServiceImpl.java:512)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:179)
    at org.apache.cxf.jaxws.JAXWSMethodInvoker.performInvocation(JAXWSMethodInvoker.java:66)
    at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96)
    at org.apache.cxf.jaxws.AbstractJAXWSMethodInvoker.invoke(AbstractJAXWSMethodInvoker.java:232)
    at org.apache.cxf.jaxws.JAXWSMethodInvoker.invoke(JAXWSMethodInvoker.java:85)
    at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:74)
    at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:59)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at org.apache.cxf.interceptor.ServiceInvokerInterceptor$2.run(ServiceInvokerInterceptor.java:126)
    at org.apache.cxf.workqueue.SynchronousExecutor.execute(SynchronousExecutor.java:37)
    at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:131)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
    at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
    at org.apache.cxf.transport.udp.UDPDestination$MCastListener$2.run(UDPDestination.java:114)
    at org.apache.cxf.workqueue.AutomaticWorkQueueImpl$3.run(AutomaticWorkQueueImpl.java:421)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.cxf.workqueue.AutomaticWorkQueueImpl$AWQThreadFactory$1.run(AutomaticWorkQueueImpl.java:346)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalArgumentException: prefix wsdp is not bound to a namespace
    at com.sun.xml.internal.bind.DatatypeConverterImpl._parseQName(DatatypeConverterImpl.java:355)
    at com.sun.xml.internal.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$24.parse(RuntimeBuiltinLeafInfoImpl.java:805)
    ... 40 more

由于此错误,未调用相应的Web服务端点,并且未正确处理/回答Probe消息。但是imho(以及同事的)也应该正确地验证Probe消息,因为所需的命名空间存在于消息的SOAP信封中。

有没有人遇到类似CXF的问题,并且知道我要解决这个问题的提示?是否可能是CXF中导致此问题的错误?

到目前为止,我还没有在网上找到非常具体的问题,除了this question,其中提出的答案是转向WS-Discovery ...但这不是一个选项对我们来说,因为我们实际上想要使用这个功能。

我也尝试disable the schema validation of CXF或实施own ValidationEventHandler for JAXB,但这些方法似乎对我们没有用(或者没有任何反应)。因此,如果有人有关于如何正确实现其中一个的更多信息(但请不要使用像Spring这样的其他框架,所以只需基于注释或使用现有的CXF / JAXB功能进行编程),我也很感激。

其他信息:

我们使用Weld作为CDI框架,我们的网络服务器是Untertow。但是,Web服务端点的部署(目前仍然)是通过javax.xml.ws.Endpoint.publish(...)完成的,稍后也应该在某些时候将其集成到Undertow中。

提前感谢任何建议!

0 个答案:

没有答案