Ошибка чтения аргументов метода службы WSDL в ColdFusion - PullRequest
1 голос
/ 05 февраля 2009

Я разрабатываю скрипт вызова службы, который выглядит следующим образом:

<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. Извините за мой английский - не мой родной язык. Пожалуйста, спросите, не написал ли я что-нибудь недостаточно ясное.

EDIT:

Чтобы уточнить. Проблема не в доступе к сервису. Я являюсь его владельцем, и я точно знаю все аргументы и их типы для каждого метода.

Проблема только в чтении сообщения об ошибке при создании запроса - заполнение контейнера аргументов метода.

Например, метод получил 10 аргументов, и я случайно добавил 9 - локальный экземпляр ошибки CF, который не может быть найден, и показывает необработанный список (см. Выше) полей, которые я передал. И мне нужно сравнить их один за другим с аргументами метода, чтобы найти то, что я пропустил.

Действительно, это проблема удобства и простоты использования.

Ответы [ 3 ]

2 голосов
/ 05 февраля 2009

Действительно, это проблема удобства и простоты использования.

Хорошо, поэтому, если я вас правильно понимаю, вам нужен способ «отладки», чтобы сравнить то, что у вас есть, с тем, что вам нужно.

Предположим, у вас есть структура "вот как это должно быть":

<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>
0 голосов
/ 09 февраля 2009

Наконец я закончил с написанием дополнительного кода, чтобы помочь мне протестировать мой сервис. Кроме того, мне нужно было предоставить своим пользователям API примеры на CFML и объединить эти задачи.

Хотите поделиться примерами кода, может быть, кто-то еще найдет их полезными.

Я использовал метод проверки структур (но немного упростил его, удалив регулярные выражения из-за их накладных расходов в моем случае - служба проверяет входящие аргументы и сообщает об ошибках). Основная идея заключалась в том, чтобы вытащить WSDL и построить структуру-шаблон для сравнения с данными тестирования. Также добавлен простой скрипт с интерфейсом для тестирования различных методов, он помогает мне быстрее тестировать изменения в сервисе.

Итак, вот UDF для выборки WSDL и сравнения структур (мой XPath-фу может быть не идеальным :), а вот базовый код тестирования .

Надеюсь, что такой способ публикации кода не является нарушением правил. Подумал, что не стоит публиковать все прямо здесь.

Отдельное спасибо Томалак за его идеи.

0 голосов
/ 05 февраля 2009

Ваша головная боль возникает из-за того, что вы просто принимаете значения, которые передаются в ваш метод, без проверки правильности ввода. это легко исправить, добавив проверку и перегрузку в ваш метод.

...