4685

Get readable WSDL service method arguments error in ColdFusion

Question:

I'm developing a service invoking script that looks like:

<cfinvoke webservice="#ServiceURL#" method="AddCustomer" returnvariable="ResponseData" argumentcollection="#stAguments#"> <cfinvokeargument name="api_key" value="#ServiceKey#" /> </cfinvoke>

<strong>stAguments</strong> structure filled before this call, obviously. Imagine you've forgot to add one of arguments into this container or used wrong argument type, say created invalid request. ColdFusion throws exception that can be catched, but can not (not literally) be read:

*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.*

It breaks my head checking all these arguments manually one by one. This is the problem.

Maybe anyone uses some technique to make this easier.

I've even thought about some kind of parser to automate this comparison.

Will appreciate any thought and ideas.

Thank you.

P.S. Sorry for my English -- not my native language. Please ask if I've wrote anything not clear enough.

<strong>EDIT:</strong>

To clarify. Problem is not in accessing service. I am owner of it and I am definitely know all arguments and their types of each method.

Problem is only in reading error message when creating request -- filling method arguments container.

For example, method got 10 arguments and accidentally I've added 9 -- local instance of CF throws error that method can't be found and shows raw list (em'ed above) of fields I've passed. And I need to compare them one by one with method arguments to find what I've missed.

Really, it's an usability and time saving problem.

Answer1:

<blockquote>

Really, it's an usability and time saving problem.

</blockquote>

Okay, so if I understand you correctly, you need a "debugging" way to compare what you have to what you need.

Let's assume you have a "this is how it should be"-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]$">

And you want a function that compares the argumentcollection to this.

<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>

Called like this:

<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>

Answer2:

your headache is stemming from just accepting the values that are passed into your method without validating that the input. this is easily fixed by adding validation and overloading into your method.

Answer3:

Finally I've finished with writing additional code to help me testing my service. Also, I needed to provide my API users with examples in CFML and combined these tasks.

Would like to share code samples, maybe someone else will find them useful.

I've used validating structures method (but a bit simplified it by removing regex'es because of they are overhead in my case -- service validates incoming arguments and reports errors). Main idea was to pull WSDL and build structure-template to compare with testing data. Also, added simple script with interface to test different methods, it helps me to test changes in service faster.

So, here is <a href="http://galashyn.com/assets/code/udflib.cfm.txt" rel="nofollow">UDFs for fetching WSDL and comparing structures</a> (my XPath-fu can be not a perfect :) and here is <a href="http://galashyn.com/assets/code/invoke.cfm.txt" rel="nofollow">base testing code</a>.

<em>Hope this way of publishing code is not a rules violation.</em> Thought it's not a good idea to post it all right here.

Special thanks to <a href="https://stackoverflow.com/users/18771/tomalak" rel="nofollow">Tomalak</a> for his ideas.

Recommend

  • respondsToSelector - not working
  • Can I disable IE compatibility mode only for content within a ?
  • Why is new Number(8) not exactly equal to 8?
  • Exception handling as per java coding standards
  • Broadcast advanced indexing numpy
  • What is the difference between Socket.Send and Stream.Write? (in relation to tcp ip connections)
  • Selection Sort, For Java
  • Storing a copy of a document embedded in another document in MongoDB via Mongoose
  • Concise regex extract function in XSLT 2.0
  • Gforce min not supported for character in data.table
  • Whats the right place for testhelper-classes? (phpunit/best practise)
  • Custom locale in Android
  • Javascript unload page condition
  • How to resolve dependencies from one gradle project to another gradle project in my Eclipse workspac
  • CFBundleDevelopmentRegion not works as expected
  • force json_encode to create strings
  • SQL query to group by maximal sets of a column having inner consecutive distances below a threshold
  • Specifying virtual keyboard type for EditText in XML
  • What causes the runtime difference in this trivial fortran code?
  • Tell Git to stop prompting me for conflicts when none really exist?
  • Azure table store snapshot/backup capability
  • JPA flush vs commit
  • How do I display a dialog that asks the user multi-choice questıon using tkInter?
  • How to detect interior vertices in groups of 2d polygons? (E.g. ZIP Codes to determine a territory)
  • how does System.Web.HttpRequest::PathInfo work?
  • Calling Worksheet functions from vba in foreign language versions of Excel
  • What and where is mdimport
  • Does it make sense to call System.gc() and Thread.sleep() when working on Bitmaps?
  • Test if a set exists before trying to drop it
  • Jquery UI tool tip close icon
  • Chrome doesn't support silverlight anymore? How to solve this?
  • Exchange data b/w iOS devices using Bluetooth 4.0
  • Display issues when we change from one jquery mobile page to another in firefox
  • Get object from AWS S3 as a stream
  • Join two tables and save into third-sql
  • How to model a transition system with SPIN
  • ORA-29908: missing primary invocation for ancillary operator
  • How to get Windows thread pool to call class member function?
  • How to Embed XSL into XML
  • Converting MP3 duration time