简体   繁体   English

ONVIF WSDL 基于 JAX-WS SOAP Web 服务 - 客户端为 SOAP 1.2 但服务器为 SOAP 1.1

[英]ONVIF WSDL Based JAX-WS SOAP Web Services - Client is SOAP 1.2 but Server is SOAP 1.1

Issue:问题:

I have created ONVIF WSDL Based Java Client and Server using JAX-WS.我使用 JAX-WS 创建了基于ONVIF WSDL Java 的客户端和服务器。

The problem is that the automatically generated Client is using SOAP 1.2 with HTTP "Content-Type: application:/xml+soap" while the Server is exposing SOAP 1.1 with HTTP "Content-Type: text/xml"问题是自动生成的客户端使用 SOAP 1.2 和 HTTP "Content-Type: application:/xml+soap" 而服务器暴露 SOAP 1.1 和 HTTP "Content-Type: text/xml"

The result is that client fails with media type exception and server throws "Unsupported Content-Type" exception:结果是客户端因媒体类型异常而失败,服务器抛出“Unsupported Content-Type”异常:

Jan. 03, 2023 3:42:55 PM com.sun.xml.ws.transport.http.HttpAdapter$HttpToolkit handle
SEVERE: Unsupported Content-Type: application/soap+xml; charset=utf-8;action="http://www.onvif.org/ver10/device/wsdl/GetDeviceInformation" Supported ones are: [text/xml]
com.sun.xml.ws.server.UnsupportedMediaException: Unsupported Content-Type: application/soap+xml; charset=utf-8;action="http://www.onvif.org/ver10/device/wsdl/GetDeviceInformation" Supported ones are: [text/xml]

I have confirmed this by doing direct SOAP invocations via curl.我已经通过 curl 直接调用 SOAP 来确认这一点。

This is successful when "Content-Type: text/xml":当“Content-Type: text/xml”时,这是成功的:

$ curl --verbose  http://127.0.0.1:9080/onvif/device_service -H "Content-Type: text/xml" --data '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><getDeviceInformation xmlns="http://www.onvif.org/ver10"></getDeviceInformation></s:Body></s:Envelope>' | xmllint --format -
*   Trying 127.0.0.1:9080...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* Connected to 127.0.0.1 (127.0.0.1) port 9080 (#0)
> POST /onvif/device_service HTTP/1.1
> Host: 127.0.0.1:9080
> User-Agent: curl/7.81.0
> Accept: */*
> Content-Type: text/xml
> Content-Length: 273
> 
} [273 bytes data]
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Mon, 02 Jan 2023 06:14:40 GMT
< Content-Type: text/xml;charset=utf-8
< Transfer-Encoding: chunked
< Server: Jetty(10.0.12)
< 
{ [114 bytes data]
100  1037    0   764  100   273  31538  11269 --:--:-- --:--:-- --:--:-- 45086
* Connection #0 to host 127.0.0.1 left intact
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
  <S:Body>
    <ns3:getDeviceInformationResponse xmlns:ns3="http://www.onvif.org/ver10" xmlns:ns4="http://www.onvif.org/ver10/schema" xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:ns6="http://docs.oasis-open.org/wsn/b-2" xmlns:ns7="http://www.w3.org/2005/08/addressing" xmlns:ns8="http://docs.oasis-open.org/wsrf/bf-2" xmlns:ns9="http://docs.oasis-open.org/wsn/t-1" xmlns:ns10="http://www.w3.org/2004/08/xop/include" xmlns:ns11="http://www.onvif.org/ver10/device/wsdl" xmlns:ns12="http://www.w3.org/2003/05/soap-envelope">
      <arg0>john</arg0>
      <arg1>beta</arg1>
      <arg2>0.0.1</arg2>
      <arg3>1</arg3>
      <arg4>hw1</arg4>
    </ns3:getDeviceInformationResponse>
  </S:Body>
</S:Envelope>

And fails when "Content-Type: application/xml+soap":当“Content-Type: application/xml+soap”时失败:

$ curl --verbose  http://127.0.0.1:9080/onvif/device_service -H "Content-Type: application/xml+soap" --data '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><getDeviceInformation xmlns="http://www.onvif.org/ver10"></getDeviceInformation></s:Body></s:Envelope>' | xmllint --format -
*   Trying 127.0.0.1:9080...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* Connected to 127.0.0.1 (127.0.0.1) port 9080 (#0)
> POST /onvif/device_service HTTP/1.1
> Host: 127.0.0.1:9080
> User-Agent: curl/7.81.0
> Accept: */*
> Content-Type: application/xml+soap
> Content-Length: 273
> 
} [273 bytes data]
* Mark bundle as not supporting multiuse
< HTTP/1.1 415 Unsupported Media Type
< Date: Mon, 02 Jan 2023 06:19:50 GMT
< Transfer-Encoding: chunked
< Server: Jetty(10.0.12)
< 
{ [5 bytes data]
100   273    0     0  100   273      0   5812 --:--:-- --:--:-- --:--:--  5934
* Connection #0 to host 127.0.0.1 left intact
-:1: parser error : Document is empty

^

Environment is:环境是:

  • Ubuntu 22.04 Ubuntu 22.04
  • OpenJDK 11 OpenJDK 11
  • Embedded Jetty Version 10 for javax.* generated code用于 javax.* 生成代码的嵌入式 Jetty 版本 10
  • Embedded Jetty Version 11 for jakarta.* generated code用于 jakarta.* 的嵌入式 Jetty 版本 11 生成的代码
  • Maven JAX-WS Plugin: com.sun.xml.ws: jaxws-maven-plugin: 2.3.5 & 3.0.2 Maven JAX-WS 插件:com.sun.xml.ws:jaxws-maven-plugin:2.3.5 & 3.0.2

JAX-WS Version: JAX-WS 版本:

I have tested with both Java EE & Jakarta EE and they both show the same SOAP 1.1/1.2 Asymmetry for client and server我已经对 Java EE 和 Jakarta EE 进行了测试,它们都显示了相同的 SOAP 1.1/1.2 客户端和服务器的不对称性

Here is server code which just boiler plate using the generated code where这是服务器代码,它只是使用生成的代码的样板

JaxDeviceImpl device = new JaxDeviceImpl();

Is derived from WSDL JAX-WS generated "Device" Server Interface class (WSDL below):源自 WSDL JAX-WS 生成的“设备”服务器接口 class(下面的 WSDL):

/**
@what Embedded Jetty JAVAX JAX-WS Device Simulator 
@note: See Eclipse Jetty: Programming Guide
*/


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import org.eclipse.jetty.server.Server;

import javax.xml.ws.Endpoint;

import onvif_relay.service.JaxDeviceImpl;
import fence.util.ConfigurationData;

public class EmbeddedJettyJaxDevice {
    
  public static void main(String[] args) throws Exception {
    ConfigurationData confData = new ConfigurationData(args);

    String srvPort = confData.getItem("onvif-device", "port");
    String port = confData.getItem("onvif-device", "device-port");
    String request = confData.getItem("onvif-device", "request");
    
    try {
        
      System.out.println("Starting the Jetty server on port: " + srvPort + " onvif mgt on: " + port);
        
      Server server = new Server(Integer.parseInt(srvPort));
      
      JaxDeviceImpl device = new JaxDeviceImpl();
      
      // System.setProperty("com.sun.net.httpserver.HttpServerProvider", "org.eclipse.jetty.http.spi.JettyHttpServerProvider");
      // System.setProperty("jakarta.xml.ws.spi.Provider", "org.eclipse.jetty.http.spi.JettyHttpServerProvider");
      // System.setProperty("javax.xml.ws.spi.Provider", "org.eclipse.jetty.http.spi.JettyHttpServerProvider");
     
      String uri = "http://127.0.0.1:" + port + request;
      // Endpoint ep = Endpoint.create(uri, device);
      Endpoint ep = Endpoint.publish(uri, device);
      
      server.start();
      
      // consoleLoop(DevManager);
      
      server.join();
      System.out.println("Stopped the simple server...");
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }

Service WSDL:客服WSDL:

<?xml version="1.0" encoding="utf-8" ?>
<wsdl:definitions name="onvif_device"
 xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap12/"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:tds="http://www.onvif.org/ver10/device/wsdl"
 xmlns:trt="http://www.onvif.org/ver10/media/wsdl"
 targetNamespace="http://www.onvif.org/ver10">

 <wsdl:import namespace="http://www.onvif.org/ver10/device/wsdl"
              location="../ver10/device/wsdl/devicemgmt.wsdl"/>
 <wsdl:import namespace="http://www.onvif.org/ver10/media/wsdl"
              location="../ver10/media/wsdl/media.wsdl"/>

 <wsdl:service name="DeviceService">
  <wsdl:documentation>ONVIF - Device</wsdl:documentation>
   <!-- wsdl:port name="Device" binding="tns:DeviceBinding" -->
   <wsdl:port name="DevicePort" binding="tds:DeviceBinding">
    <soap:address location="http://127.0.0.1/onvif/device_service"/>
   </wsdl:port>
 </wsdl:service>

 <!-- wsdl:service name="MediaService">
     <wsdl:documentation>ONVIF - Media</wsdl:documentation>
   <!- wsdl:port name="Device" binding="tns:MediaBinding" ->
   <wsdl:port name="MediaPort" binding="trt:MediaBinding">
    <soap:address location="http://127.0.0.1/onvif/device_service"/>
   </wsdl:port>
 </wsdl:service -->
</wsdl:definitions>

Full code set for both test client and server is posted via github测试客户端和服务器的完整代码集通过github发布

Expectation:期待:

Expectation is that automatically generated JAX-WS code would work transparently between Client / Server.期望自动生成的 JAX-WS 代码将在客户端/服务器之间透明地工作。

NOTE: The current Jakarta XML Web Services specification (Version 3.0) appears to be ambiguous on SOAP 1.1/1.2 support:注意:当前Jakarta XML Web 服务规范(版本 3.0)似乎对 SOAP 1.1/1.2 支持不明确:

  • "Goals - SOAP 1.2 - Whilst SOAP 1.1 is still widely deployed, it's expected that services will migrate to SOAP 1.2[3][4] now that it is a W3C Recommendation. Jakarta XML Web Services will add support for SOAP 1.2 whilst requiring continued support for SOAP 1.1." “目标 - SOAP 1.2 - 虽然 SOAP 1.1 仍在广泛部署,但预计服务将迁移到 SOAP 1.2[3][4],因为它是 W3C 推荐标准。雅加达 XML Web 服务将继续支持 SOAP 1.2[3][4]支持 SOAP 1.1。”
  • "Non Goals - SOAP Encoding Support - Use of the SOAP encoding is essentially deprecated in the web services community, eg, the WS-I Basic Profile[8] excludes SOAP encoding. Instead, literal usage is preferred, either in the RPC or document style. SOAP 1.1 encoding is supported in JAX-RPC 1.0 and Jakarta XML RPC but its support in Jakarta XML Web Services runs counter to the goal of delegation of data binding to Jakarta XML Binding. Therefore Jakarta XML Web Services will make support for SOAP 1.1 encoding optional and defer description of it to Jakarta XML RPC. Support for the SOAP 1.2 Encoding[4] is optional in SOAP 1.2 and Jakarta XML Web Services will not add support for SOAP 1.2 encoding. “非目标 - SOAP 编码支持 - 在 web 服务社区中基本上不推荐使用 SOAP 编码,例如,WS-I 基本配置文件 [8] 不包括 SOAP 编码。相反,在 RPC 或文档中首选文字使用style. SOAP 1.1 encoding is supported in JAX-RPC 1.0 and Jakarta XML RPC but its support in Jakarta XML Web Services runs counter to the goal of delegation of data binding to Jakarta XML Binding. Therefore Jakarta XML Web Services will make support for SOAP 1.1 encoding optional and defer description of it to Jakarta XML RPC. Support for the SOAP 1.2 Encoding[4] is optional in SOAP 1.2 and Jakarta XML Web Services will not add support for 88201591.058 encoding.

What I tried:我尝试了什么:

Tried using:尝试使用:

  1. full Jakarta EE toolset完整的 Jakarta EE 工具集
  2. transitional Java EE toolset过渡 Java EE 工具集

Testing with generated Client / Server and via direct curl invocation.使用生成的客户端/服务器并通过直接 curl 调用进行测试。

Always get the same result of client (SOAP 1.2) and Server (SOAP 1.1).始终获得客户端 (SOAP 1.2) 和服务器 (SOAP 1.1) 相同的结果。

NOTE #1: as the underlying WSDL is from ONVIF I do not have option of changing WSDL,注意#1:由于基础 WSDL 来自 ONVIF,我没有更改 WSDL 的选项,

Questions:问题:

  1. Can I change client behavior to always request via SOAP 1.1?我可以将客户端行为更改为始终通过 SOAP 1.1 请求吗?
  2. Is the problem with Jetty Embedded Server and SOAP 1.2 support? Jetty Embedded Server 和 SOAP 1.2 支持有问题吗?
  3. Is the problem with Jakarta Reference Implementation? Jakarta Reference Implementation 有问题吗?

sDoing further investigation on this I found that the ONVIF SOAP Binding URL: http://schemas.xmlsoap.org/soap/http get redirected to dead end.对此进行进一步调查,我发现 ONVIF SOAP Binding URL: http://schemas.xmlsoap.org/soap/http被重定向到死胡同。

Here is snippet from devicemgmt.wsdl这是来自 devicemgmt.wsdl 的片段

<wsdl:binding name="DeviceBinding" type="tds:Device">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="GetServices">
                <soap:operation soapAction="http://www.onvif.org/ver10/device/wsdl/GetServices"/>
                <wsdl:input>
                        <soap:body use="literal"/>
                </wsdl:input>
                <wsdl:output>
                        <soap:body use="literal"/>
                </wsdl:output>
        </wsdl:operation>

I am not sure if this is root cause of problem, but found that I could work around it by changing the server EndPoint create/publish code to it explicitly used SOAP 1.2 / HTTP binding:我不确定这是否是问题的根本原因,但发现我可以通过将服务器 EndPoint 创建/发布代码更改为明确使用 SOAP 1.2 / HTTP 绑定来解决它:

  String soapver = SOAPBinding.SOAP11HTTP_BINDING;
  if (ver.equals("12"))
    soapver = SOAPBinding.SOAP12HTTP_BINDING;
  
  String uri = "http://127.0.0.1:" + port + request;
  Endpoint ep = Endpoint.create(soapver, device);
  ep.publish(uri);

I have committed update to example and confirmed that ONVIF Device Simulator is now serving SOAP 1.2/HTTP as per ONVIF Specification.我已承诺更新示例并确认 ONVIF 设备模拟器现在根据 ONVIF 规范提供 SOAP 1.2/HTTP 服务。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 ONVIF WSDL JAX-WS wsimport 不支持大写名称的操作 Java 代码生成 - ONVIF WSDL Operations with upper case names not being honoured by JAX-WS wsimport Java Code Generation Bean 验证和 JAX-WS - Bean Validation and JAX-WS 如何使用数组或列表作为参数创建 Java Web 服务 (jax-ws) - How can I create Java web service (jax-ws) with array or List as a parameter 如果我使用 Widfly 26.1.1、JDK 11 和 JEE 8,我应该向 POM 添加哪些依赖项来创建和使用 SOAP Web 服务? - What dependencies to create and use SOAP Web Services should I add to the POM if I am working with Widfly 26.1.1, JDK 11 and JEE 8? Java WS:如何将直接 XML 作为 SOAP 请求的一部分发送 - Java WS: How do I send direct XML as part of a SOAP request 以编程方式获取 JAX-WS WebService 实现的 Servlet 实例? - Programmatically obtain a Servlet instance for a JAX-WS WebService implementation? JAX-WS:javax.xml.bind.UnmarshalException - JAX-WS: javax.xml.bind.UnmarshalException Java + SOAP:两次执行相同的 SOAP 服务时出现意外的 IndexOutOfBoundsException - Java + SOAP: Unexpected IndexOutOfBoundsException when executing the same SOAP service twice 访问 JAX-WS 服务时 org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:272) 处的 java.lang.NullPointerException - java.lang.NullPointerException at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:272) while accessing JAX-WS services 在没有 EJB 的情况下拦截 SOAP RPC 方法响应 - Intercept SOAP RPC method response without EJB
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM