【问题标题】:Communicating to a SOAP webservice with constantly changing targetNamespace通过不断变化的 targetNamespace 与 SOAP Web 服务通信
【发布时间】:2015-06-21 18:28:13
【问题描述】:

所以有一个 SOAP 网络服务。 WSDL 中的targetNamespace 根据客户的可配置字符串动态变化。想一想

targetNamespace="http://myservice."+ [CouldBeAnyString] + "domain.com"

我有两个问题:

  1. 我的基础研究告诉我,这是开发 Web 服务的一种非常奇怪(不好?)的做法。想法?

  2. 如何为这样的网络服务编写客户端?我已经使用 jax-ws 存根进行了测试,当 targetNamespace 更改时它不兼容。还有其他建议吗?我一直在尝试了解基于 wsdl 的动态客户端生成。如果存在的话,会更喜欢一条更好的路径

更新: 我只是客户。服务由其他人提供。 同一客户有多个环境(例如测试、生产),其中服务托管在不同的目标命名空间下

【问题讨论】:

  • 您没有提供一些重要的上下文。您是服务提供商还是只是客户?为什么这个 WSDL 会发生变化? CouldBeAnyString 值是否会针对同一个客户端发生变化?这是区分调用者的一种方式吗?
  • 当然。用附加信息更新了问题
  • 每个环境的命名空间是一个奇怪的设置,至少对我来说这是我第一次看到这个。只是出于好奇,知道他们为什么选择这样做吗?服务商有解释吗?

标签: java web-services soap namespaces jax-ws


【解决方案1】:

如果 SOAPUI 调用在 targetNamespace 发生变化的情况下仍然有效,您可以使用名为 HTTPCLIENT 的轻量级 HTTP 库。

使用这个库,您不需要生成客户端,因为您将SOAP envelope 作为字符串发送,就像您通过 SOAPUI 所做的那样。

缺点是使用字符串。

【讨论】:

    【解决方案2】:

    理论上,创建这样一个Web Service客户端是可行的。 步骤:

    • 使用 JDK 的 wsimport.exe 创建基于 WSDL 的 Java 工件(参见:http://www.mkyong.com/webservices/jax-ws/jax-ws-wsimport-tool-example 作为参考)
    • 对于下面显示的代码,我使用了 Microsoft 提供的 Calculator WSDL
    • 通过 Eclipse J2EE 创建“动态 Web 项目”
    • 复制在第 1 步中创建的 Java 工件,在第 2 步中创建的项目的 src 文件夹下。
    • 创建一个包含主方法的新类。通常你会有类似的东西:
    String wsdlLocation = "127.0.0.1:8088";//Normally you should retrieve that value dynamically
    Url url = new URL(wsdlLocation + "?wsdl");// ?wsdl is actually needed
    String namespaceURI = "http://Example.org";//Normally you should retrieve that value dynamically
    String localPart = "CalculatorService";// as specified in WSDL file (see name attribute of service tag)
    QName qname = new QName(namespaceURI, localPart);
    CalculatorService service = new CalculatorService(url,qname);
    ICalculator iCalculator = service.getICalculator();
    int response = iCalculator.add(1, 2);
    System.out.println(response);
    

    现在是棘手的部分:

    • 如果您按照上述 WSDL 的示例进行操作,您现在应该有几个具有硬编码命名空间的带注释的类(例如,ICalculator 注释为:

      @WebResult(name = "result", targetNamespace = "..."))//其中...类似于http://example.org

    • 使用 Java 反射在运行时修改所有硬编码值(参见此处的示例:https://stackoverflow.com/a/14276270/2625635,了解如何修改注解)

    上述解决方案应该可以解决问题。

    【讨论】:

    • @mishal153:您可以选择使用Axis 客户端吗?如果是这样,请注意生成的类没有注释,因此您可以重构它们以便以动态方式检索命名空间。
    【解决方案3】:

    大多数客户端框架允许您创建一个接口来调用您的客户端(即它们创建一个合约接口)。它们还为该接口提供了一个实现,该实现具有特定的注释或扩展“SOAP 感知”类,而该接口没有此类细节。

    根据您发布的内容,我假设客户端具有相同的接口,只是实现命名空间不同?如果是,则编写您的应用程序以使用该接口,然后为每个环境的实现构建一个 jar。当您在测试服务器上部署时使用测试 jar 部署,而在生产部署时使用生产 jar(即根据环境为同一合约选择不同的实现)。

    即使您使用的框架没有为您创建接口,您也可以自己创建一个并将各种实现隐藏在某种adapter 后面。

    您也可以执行 edubriguenti 建议的操作,但我不会使用字符串。请改用SAAJ

    【讨论】:

      猜你喜欢
      • 2013-06-20
      • 1970-01-01
      • 2019-07-12
      • 1970-01-01
      • 2014-06-15
      • 2011-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多