0

我有一个来自现有服务的 WSDL,我正在为此开发一个客户端和一个模拟器(在上线之前测试界面的两侧)。我使用 glassfish JAXWS 库来生成代码,并使用 glassfish 3.1.2.2 作为服务器。我们正在运行 Java 1.6。

在原始 WSDL 中,多个返回类型被定义为多个部分,并且自动生成的代码创建 Holder 条目来保存它们。也就是说,WSDL 中的示例返回消息如下所示:

 <message name="returnTypeMessage">
    <part name="outDoc" element="tns:myResponseType"/>
    <part name="XMLAttach" element="xsd:string"/>
 </message>
 ...
<operation name="...">
  <wsdlsoap:operation soapAction="" soapActionRequired="false"/>
  <input ... />
  <output name="...response">
    <mime:multipartRelated>
      <mime:part>
        <wsdlsoap:body parts="outDoc" use="literal" />
      </mime:part>
      <mime:part>
        <mime:content part="XMLAttach" type="text/xml" />
      </mime:part>
    </mime:multipartRelated>
  </output>
</operation>

端口接口中生成的签名如下所示:

@WebMethod
public void methodName(@WebParam(name="...") inParameter,
  @WebParam(name="myResponseType", partName="outDoc") Holder<myResponseType> outDoc,
  @WebParam(name="moreData", partName="moreData") Holder<String> moreData);

到目前为止,一切都很好。现在,当我从此接口创建服务端点类并将其部署到 GlassFish 3.1.2.x,然后我转到 WSDL 时,WSDL 反而显示:

 <message name="returnTypeMessage">
    <part name="parameters" element="tns:someNewResponseType" />
 </message>
...
<operation name="...">
  <soap:operation soapAction=""/>
  <input>
    <soap:body use="literal"/>
  </input>
  <output>
    <soap:body use="literal"/>
  </output>
</operation>

端口签名如下所示:

@WebMethod
@WebResult(name="someNewResponseType", partName="parameters")
public someNewResponseType methodName(...);

因此,它将其从在其自己的 Holder 中具有多个返回类型转换为在其中包含多个元素的单个返回参数(类)。

真正的问题是,然后尝试使用以前的签名针对此部署的服务运行客户端,失败并显示“IllegalStateException:阅读器必须在 START_ELEMENT 事件上,而不是 8 事件上”。

我觉得这种行为很烦人,并且真的很想很好地解释为什么我可以从 WSDL 生成端口,部署它的实现,然后它会广播与针对该初始端口定义生成的客户端不兼容的 WSDL。

4

1 回答 1

0

结果证明这是一个不太理想的 WSDL(我无法更改)和参数格式的组合。解决方案有两个要求。

首先,在生成的端口文件中,将 SOAPBinding 从 SOAPBinding.ParameterStyle.BARE 更改为 WRAPPED:

@SOAPBinding(parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)

在使用 wsimport 生成代码后,我使用 ant replace 任务完成了该操作。enableWrapperStyle 的 wsimport 自定义选项不起作用(我相信因为有一个警告,如果它不能完全标记包装的 wsdl,它将恢复为裸露)。

其次,在服务实现类中,@WebService 注释中,必须添加 endpointInterface=".​​.." 属性。没有它,它会在通话期间失败。我还补充说:

@WebService(..., endpointInterface="...")
@BindingType(value=SOAPBinding.SOAP12HTTP_BINDING)

给定这三个项目(WRAPPED、endpointInterface、BindingType)后,它就适用于从 WSDL 生成的服务和客户端。任何其他组合都会导致某种错误(现在似乎与其他问题有关,但最终是红鲱鱼)。

请注意,生成的 WSDL 仍然不正确,但客户端可以正常工作,这才是最重要的。

于 2013-09-23T15:53:06.773 回答