Java 相同的 SOAP Web 服务需要不同的参数类型?

Java different parameter type needed for identical SOAP Web Service?

我有一个 Web 服务客户端,用于 2 个相同的 SOAP Web 服务,分别称为 Company1Service 和 Company2Service。这两个 Web 服务都具有完全相同的 PurchaseOrder class.

但是,当我想从每个 Web 服务调用 m1ProcessPurchaseOrder() 方法和 m2ProcessPurchaseOrder() 方法时,它们需要不同的 Po 对象参数类型。然而,两种服务的 PurchaseOrder class 是相同的。

我正在使用 NetBeans 和生成的源 (jax-ws)。

public boolean m1ProcessPurchaseOrder(ab.service.company1.PurchaseOrder Po) 
{
    ab.service.company1.Company1Service port = service1.getComapny1ServicePort();
    return port.processPurchaseOrder(po);
}

public boolean m2ProcessPurchaseOrder(ab.service.company2.PurchaseOrder Po) 
{
    ab.service.company2.Company2Service port = service2.getComapny2ServicePort();
    return port.processPurchaseOrder(po);
}

我想做的是让 ab.service.company1.PurchaseOrder 成为 Company1Service 和 Company2Service 的参数类型。

如果我尝试将 m2ProcessPurchaseOrder() 参数类型更改为 ab.service.company1.PurchaseOrder:

,这是我的错误

method processPurchaseOrder in interface Company2Service cannot be applied to given types;

Required: ab.service.Company2.PurchaseOrder

Found: ab.service.Company1.PurchaseOrder

Reason: actual argument ab.service.Company1.PurchaseOrder cannot be converted to ab.service.Company2.PurchaseOrder by method invocation conversion

取决于您使用的 JAX-WS 实现——有几个:CXFRI/Metro, Axis2, JBossWS, Spring-WS等等——您可能需要调用不同的工具来生成您的工件(XSD 模式或 WSDL's),即 RI 的 wsimport,或特定的 JAX-WS 实现工具,如 *Axis*2 或 CXF's WSDL2Java, or JBossWS' wsprovide.

此外,根据您为项目设置的构建 script/tool,可能有一个任务、目标或目标可用于自动调用这些工具。然而,当涉及到 XML-to-Java 绑定时,您可以利用 JAXB 绑定文档来操作生成的 Java classes 包括对其生成位置(包)的操作。这是通过 jaxb:bindings 完成的(jaxb 只是一个名称空间前缀)。对于 WSDL 工件,即服务,您可以将映射指令放在 jaxws:bindings 中(此处相同jaxws 只是一个 XML 命名空间)。请注意,这两个是两个单独的绑定 (XML) 文档,可以将其提供给上述工具之一,即 CXF' s WSDL2Javawsimport.

对于 JAXB 绑定,您可以创建类似 (Company1Binding.xml):

的绑定文档
<?xml version="1.0" encoding="UTF-8" ?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" version="2.1">

  <jaxb:bindings schemaLocation="PurchaseOrder.xsd">
    <jaxb:schemaBindings>
      <jaxb:package name="ab.service.common" />
    </jaxb:schemaBindings>
  </jaxb:bindings>

  <!-- more binding related to Company1Service -->

</jaxb:bindings>

Company2Binding.xml 的 JAXB 绑定:

<?xml version="1.0" encoding="UTF-8" ?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" version="2.1">

  <jaxb:bindings schemaLocation="PurchaseOrder.xsd">
    <jaxb:schemaBindings>
      <jaxb:package name="ab.service.common" />
    </jaxb:schemaBindings>
  </jaxb:bindings>

  <!-- more binding related to Company2Service -->

</jaxb:bindings>

这会将生成的 PurchaseOrder.java class 放入 ab.service.common 包中,因此您可以在 ab.service.company1.* 和 [=] 中引用此 class 的实例20=] 来自这首单曲 class (ab.service.common.PurchaseOrder.java).

请注意,我在 Company1 和 Company2 中都放置了这样的绑定,以防您在某个时候对 PurchaseOrder.xsd 进行更改,并且仅生成绑定其中一项服务,即 Company1 的。在这种情况下,为两者重新生成 PurchaseOrder.java,因为只有一个为它生成 class (ab.service.common.PurchaseOrder.java)。

您可以对 WSDL 工件执行相​​同的操作,例如对于 Comapny1Service.wsdl,您可以创建一个新的绑定文档,例如 (Company1ServiceBinding.xml):

<?xml version="1.0" encoding="UTF-8"?>
<jaxws:bindings xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    version="2.1" xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
    wsdlLocation="Company1Service.wsdl">

    <jaxws:bindings node="wsdl:definitions">
        <jaxws:package
            name="ab.service.company1" />
    </jaxws:bindings>

    <jaxws:bindings
        node="wsdl:definitions/wsdl:portType/wsdl:operation/wsdl:fault[@name='fault']">
        <jaxws:class
            name="ab.service.common.ServiceException" />
    </jaxws:bindings>

</jaxws:bindings>

这会将服务 classes(如接口、客户端代理,以及您在 WSDL 中为操作指定的 Soap Fault 类型)放在 ab.service.Company1 包中。请注意每个绑定文档中命名空间之间的差异(jaxb:bindingsjaxws:bindings)。最后,您可以将这些绑定信息传递给实际工具,即 CXFWSDL2Java(在本例中,一个片段来自 Ant 构建文件的代码):

<java classname="org.apache.cxf.tools.wsdlto.WSDLToJava" fork="true">
    <arg value="-d"/>
    <arg value="${path.to.generated.code}"/>
    <arg value="-b"/>
    <arg value="${path.to.artifacts}/Company1Binding.xml"/>
    <arg value="-b"/>
    <arg value="${path.to.artifacts}/Company1ServiceBinding.xml"/>
    <arg value="${path.to.artifacts}/Company1Service.wsdl"/>
    <classpath>
        <path refid="${jaxws.impl.library.path}"/>
    </classpath>
</java>

(注意:您应该为 Company2Service 设置类似的目标)

如您所见,此特定工具通过 -b 接受绑定文档(JAXBJAX-WS)旗帜。事实上,这些工具(如 WSDL2Java 最终调用的 Binding Compiler (xjc) 确实通过 -b 选项接受绑定文档(请注意 link 会将您带到 参考 Implementation/Metor 版本的 xjc,但是 CXF's and others' 应该接近)。事实上,您可以直接调用 WSDL2Java 本身:

/path/to/wsdltojava -d /path/to/where/you/want/to/generate -b /path/to/wsdl/artifacts/CompanyBinding.xml -b /path/to/wsdl/artifacts/Company1ServiceBinding.xml /path/to/wsdl/artifacts/Company1Service.wsdl

使用 JAXB 的映射需要让自己熟悉一些细节,但您可以 read more about it here which is JAX-WS RI/Metro's. For CXF's, you can refer to here, and some examples for Maven's plugin 用于 CXF's WSDL2Java。同样,每个 JAX-WS 实现都有自己的一套工具,但是当涉及到与 JAXB 相关的底层 mapping/binding 时,概念是相同的.