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

时间:2009-07-13 14:19:23

标签: coldfusion wsdl stub

前言

我们正在为客户提供我们的服务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

这就是问题所在。

当第二个网站尝试注册网络服务时,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 个答案:

答案 0 :(得分:2)

  
    

我现在不能“将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文档。请注意空格(可能请参阅CFSilentCFSetting),并考虑使用CFHeader将mime类型设置为“text / xml”。

答案 1 :(得分:1)

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

我还认为你需要找出错误信息的确切含义。我没有看到它与使用的URL有什么关系。如果它提到了另一个客户的URL,我就明白了。


部分原因可能是由于我对CF的运作方式缺乏了解。特别是,当两个客户这样做时,这个“注册Web服务”会引发什么问题?

您是否意识到WSDL中<soap:address/>元素中的URL只是一个提示?在许多客户中,它可以被覆盖。在.NET客户端中,只需设置代理类的Url属性即可。这应该允许您在单个位置拥有单个WSDL,并且让您的客户各自引用正确的子域,假设有某种方式将信息传达给他们。例如,如果您有办法知道哪个客户正在进行呼叫,那么您可能会在一个URL上接收呼叫,然后重定向到正确的URL,或者使用SOAP路由基础设施路由到正确的URL。

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

答案 2 :(得分:0)

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

类似的东西:

<cfcomponent namespace="http://#cgi.host_name#/api/v1n1/bsapi.cfc">

答案 3 :(得分:0)

尝试通过位于同一localhost(但位于不同文件夹中)的测试脚本从localhost CFINVOKE webservice时捕获到此错误消息。对我来说听起来很“烦躁”。