在ColdFusion中获取可读的WSDL服务方法参数错误

时间:2009-02-05 14:23:33

标签: web-services coldfusion error-handling wsdl

我正在开发一个服务调用脚本,如下所示:

<cfinvoke webservice="#ServiceURL#" method="AddCustomer" returnvariable="ResponseData" argumentcollection="#stAguments#">
    <cfinvokeargument name="api_key" value="#ServiceKey#" />
</cfinvoke>
显然,在此调用之前填充

stAguments 结构。 想象一下,你忘了在这个容器中添加一个参数或者使用了错误的参数类型,比如创建了无效的请求。 ColdFusion抛出可以捕获的异常,但不能(不是字面上)读取:

*Web service operation AddCustomer with parameters {postcode={12345},org_name={Terms test 7.79661762856},fax={},html={1},addr1={address1},firstname={sergey},city={Austin},country={},taxable={},notify={1},lastname={galashyn},addr2={},ssn={},api_key={8FE9AD0BCF2382D92A1080DB3AA62DB9},taxrate={0},terms={Net 15},active={},state={},salutation={Mr.},password={123},account_manager={1}} cannot be found.*

它一个接一个地手动检查所有这些参数。这就是问题所在。

也许有人会使用某种技术来使这更容易。

我甚至考虑过某种解析器来自动进行比较。

会欣赏任何想法和想法。

谢谢。

P.S。抱歉我的英语 - 不是我的母语。请问我是否写了一些不够清楚的东西。

修改

澄清。问题不在于访问服务。我是它的拥有者,我肯定知道每个方法的所有参数和类型。

问题仅在于在创建请求时读取错误消息 - 填充方法参数容器。

例如,方法得到了10个参数,并且意外地我添加了9 - CF的本地实例抛出了无法找到方法的错误,并显示了我传递的字段的原始列表(上面的em')。我需要将它们与方法参数逐一进行比较,以找到我错过的内容。

真的,这是一个可用性和节省时间的问题。

3 个答案:

答案 0 :(得分:2)

  

真的,这是一个可用性和节省时间的问题。

好的,所以如果我理解正确的话,你需要一种“调试”方式来比较你所拥有的东西。

让我们假设你有一个“这是它应该如何”--struct:

<cfset WSargs = StructNew()>
<cfset WSargs.AddCustomer = StructNew()>
<cfset WSargs.AddCustomer.postcode  = "\d{5}">
<cfset WSargs.AddCustomer.org_name  = ".+">
<cfset WSargs.AddCustomer.fax       = ".*">
<cfset WSargs.AddCustomer.html      = "^[01]$">
<cfset WSargs.AddCustomer.addr1     = ".*">
<cfset WSargs.AddCustomer.firstname = ".*">
<cfset WSargs.AddCustomer.city      = ".*">
<cfset WSargs.AddCustomer.country   = ".*">
<cfset WSargs.AddCustomer.taxable   = ".*">
<cfset WSargs.AddCustomer.notify    = "^[01]$">
<cfset WSargs.AddCustomer.lastname  = ".*">
<cfset WSargs.AddCustomer.addr2     = ".*">
<cfset WSargs.AddCustomer.ssn       = ".*">
<cfset WSargs.AddCustomer.taxrate   = "^\d*$">
<cfset WSargs.AddCustomer.terms     = ".*">
<cfset WSargs.AddCustomer.active    = ".*">
<cfset WSargs.AddCustomer.state     = ".*">  
<cfset WSargs.AddCustomer.salutation= ".*">
<cfset WSargs.AddCustomer.password  = ".+">
<cfset WSargs.AddCustomer.account_manager = "^[01]$">

并且您想要一个将argumentcollection与此进行比较的函数。

<cffunction name="CompareStructs" returntype="array" output="no">
  <cfargument name="template" type="struct" required="yes">
  <cfargument name="data"     type="struct" required="yes">

  <cfset var errors = ArrayNew(1)>
  <cfset var key = "">

  <cfloop collection="#template#" item="key">
    <cfif StructKeyExists(data, key)>
      <cfif REFind(template[key], ToString(data[key])) eq 0> 
        <cfset ArrayAppend(errors, "Field '#key#' has an invalid value.")>
      </cfif>
    <cfelse>
      <cfset ArrayAppend(errors, "Field '#key#' is missing.")>
    </cfif>
  </cfloop>

  <cfloop collection="#data#" item="key">
    <cfif not StructKeyExists(template, key)>
      <cfset ArrayAppend(errors, "Field '#key#' is not allowed.")>
    </cfif>
  </cfloop>

  <cfreturn errors>
</cffunction>

这样称呼:

<cfset errors = CompareStructs(WSargs.AddCustomer, stAguments)>

<cfif ArrayLen(errors) eq 0>
  <cfinvoke 
    webservice="#ServiceURL#" 
    method="AddCustomer" 
    returnvariable="ResponseData" 
    argumentcollection="#stAguments#"
  >
    <cfinvokeargument name="api_key" value="#ServiceKey#" />
  </cfinvoke>
<cfelse>
  <cfdump var="#errors#" label="Errors calling AddCustomer()">
  <cfabort>
  <!--- or whatever --->
</cfif>

答案 1 :(得分:0)

您的头痛源于仅接受传递到您的方法中的值而不验证输入。通过在方法中添加验证和重载可以轻松解决这个问题。

答案 2 :(得分:0)

最后,我完成了编写其他代码以帮助我测试我的服务。此外,我需要为我的API用户提供CFML中的示例并组合这些任务。

想分享代码示例,也许别人会觉得它们很有用。

我已经使用了验证结构方法(但是通过删除正则表达式来简化它,因为它们在我的情况下是开销 - 服务验证传入的参数并报告错误)。主要思想是提取WSDL并构建结构模板以与测试数据进行比较。此外,添加了带有界面的简单脚本来测试不同的方法,它可以帮助我更快地测试服务中的变化。

所以,这里是UDFs for fetching WSDL and comparing structures(我的XPath-fu可能不是完美:),这里是base testing code

希望这种发布代码的方式不违反规则。认为在这里发布它不是一个好主意。

特别感谢Tomalak的想法。