代码之家  ›  专栏  ›  技术社区  ›  Sergey Galashyn

使用来自不同子域的Web服务时,相同WSDL命名空间的“重复文件名”

  •  1
  • Sergey Galashyn  · 技术社区  · 15 年前

    序言

    我们为客户提供我们的服务API。

    每个客户都有自己的子域(例如sergii.ourwebsite.com)和自己的WSDL URL,看起来像 http://sergii.ourwebsite.com/api/bsapi.cfc?wsdl

    此外,所有的网站(当然包括API)都使用相同的代码库。


    问题

    例如,同一个CF服务器上有两个应用程序。这很容易发生,因为有些客户网站托管在我们的服务器上。

    两者都试图使用自己的API WSDL,比如:

    http://sergii.ourwebsite.com/api/bsapi.cfc?wsdl
    http://galashyn.ourwebsite.com/api/bsapi.cfc?wsdl
    

    问题来了。

    当第二个网站尝试注册Web服务时,CF会抛出一个错误:

    姓名: https://galashyn.ourwebsite.com/api/bsapi.cfc?wsdl . WSDL: https://galashyn.ourwebsite.com/api/bsapi.cfc?WSDL . org.apache.axis.wsdl.tojava.duplicateFileException: 重复文件名: /opt/coldfusion8/stubs/ws1985941973/api/bsapi.java。 提示:您可能已经映射了两个 具有相同元素的命名空间 名称与包名称相同。它是 建议您使用Web浏览器 检索和检查请求的 WSDL文档以确保它是正确的。 如果请求的WSDL文档不能 被检索或是动态的 生成,很可能 目标Web服务有编程 错误。

    问题是,它们都使用相同的WSDL命名空间,该命名空间是从cfc路径构建的:

    <wsdl:definitions targetNamespace="http://api">
    


    当前解决方案

    我们唯一的工作解决方案是使用cfc别名,例如:

    http://galashyn.ourwebsite.com/api/v1n1/bsapi.cfc?wsdl
    http://galashyn.ourwebsite.com/api/v1n1/bsapi.cfc?wsdl
    

    每个cfc都像这样扩展父级:

    <cfcomponent output="false" extends="api.bsapi">
    <!--- this component used to extend base api version 1.x --->
    </cfcomponent>
    

    它们产生不同的名称空间,可以毫无问题地使用——每个应用程序都有自己的名称空间:

    <wsdl:definitions targetNamespace="http://v1n1.api">
    <wsdl:definitions targetNamespace="http://v1n2.api">
    


    这是一个相当愚蠢的解决方法,但目前它仍然有效。


    另一种解决方案是使用单一的API子域,并通过一些键来识别客户(我们已经将其用于安全目的),但由于一些遗留代码,它对我们来说存在严重的负面问题。


    请注意,我不知道Java,所以很多具体的建议对我来说不太清楚。

    谷歌显示这个问题存在多年,但我找不到明智的解决方案。

    也许在这里?

    4 回复  |  直到 14 年前
        1
  •  2
  •   Adam Tuttle    15 年前

    我现在不能“将WSDL放在所有客户的公共URL上”,我已经解释了原因:因为我必须使用子域。如果您知道如何将WSDL放在一个URL上并向另一个URL发出服务请求,请告诉我。

    WSDL只是描述Web服务的XML文档。您可以使用cfml编写(定制)它。例如:

    http://subdomain.domain.com/api/wsdl.cfm?api=bsapi&customer=subdomain

    然后复制由CF生成的WSDL,并将其用作自定义WSDL页面的模板。替换WSDL中特定于子域的部分,并返回XML文档。留心空白(也许看 CFSilent , CFSetting )并考虑使用 CFHeader 将mime类型设置为“text/xml”。

        2
  •  1
  •   John Saunders    15 年前

    所有客户都使用相同的WSDL吗?然后将WSDL放在所有客户的公共URL上。

    我还认为您需要确切地了解错误消息的含义。我看不出它与正在使用的URL有什么关系。如果它提到了另一个客户的URL,我会理解的。


    部分原因可能是我对CF的工作方式缺乏了解。尤其是,当两个客户这样做时,触发问题的“注册Web服务”是什么?

    您是否意识到 <soap:address/> WSDL中的元素只是一个提示?在许多客户机中,它可以被重写。在.NET客户端中,只需设置代理类的URL属性。这应该允许您在一个位置拥有一个WSDL,并且让您的客户每个都引用适当的子域,假设有某种方法可以将这些信息传递给他们。例如,如果有一种方法可以让您知道哪个客户正在打电话,那么您可能会在一个URL上接收到呼叫,然后重定向到正确的URL,或者使用SOAP路由基础结构来路由到正确的URL。

    我希望您不要将名称空间从一个客户更改为另一个客户。名称空间与URL无关,即使它们恰好看起来像URL。

        3
  •  0
  •   Ben Doom    15 年前

    cfcomponent标记有一个名称空间属性。您应该能够使用这个,以及cgi.host_name(?我在家,没有文档)指定一个与正在查询的子域匹配的命名空间。

    类似:

    <cfcomponent namespace="http://#cgi.host_name#/api/v1n1/bsapi.cfc">
    
        4
  •  0
  •   Rodion Bykov    14 年前

    当试图通过位于同一本地主机(但位于不同文件夹)上的测试脚本从本地主机cfinvoke WebService时,捕获到此错误消息。对我来说,听起来很糟糕。