Tricky SOAP input problem; need help with cfinvokesyntax

Ask a Question related to Coldfusion - Advanced Techniques, Design and Development.

  1. #1

    Default Re: Tricky SOAP input problem; need help with cfinvokesyntax

    Notes on Interfacing CFMX to External Web Services Requiring
    Complex-Within-Complex XML Documents as Input Authors: Doug James
    (jamesd@musc.edu) Larry Afrin, MD (afrinl@musc.edu) Hollings Cancer Center
    Medical University of South Carolina March 31, 2005 <cfacknowledgement> The
    authors would like to acknowledge Macromedia's Tom Jordahl (who we understand
    is sort of the principal developer and 'guru' of ColdFusion's web services
    functionality) both for his assistance in helping them understand how
    ColdFusion handles certain complex web service interactions and for his
    critical review of the following document. </cfacknowledgement>
    <cfdisclaimer> While the authors have tried to ensure the accuracy and utility
    of the information below, they offer the following information with no
    warranties whatsoever and hereby explicitly state that their employer has had
    absolutely nothing to do with the development of this document and therefore
    also bears no liabilities with regard to how the information presented here may
    be used. The authors are also quite sure that despite Tom Jordahl's review of
    this document, Macromedia takes no responsibility for this information, either.
    By their posting of this information, the authors are not offering themselves
    as support resources for other developers wrestling with the problems addressed
    herein. Requests for assistance in this area that are communicated to the
    authors may or may not be acknowledged or answered, solely at the authors'
    whim. After all, we do have to attend first to our day jobs (which often spill
    over into our night jobs, too.) ;-) </cfdisclaimer>
    ================================================== ===== CFMX is able to
    communicate with web services hosted in arbitrary computing environments as
    long as the SOAP standards are followed. The SOAP standards require that all
    input arguments to a web service be passed as XML documents. The expected
    format of the XML document for any given input argument is defined either
    directly in the service's WSDL (Web Services Description Language) document, or
    by reference in that WSDL document to another data element definition document.
    Before proceeding further to discuss how CFMX handles 'complex'-type web
    service input arguments, it is helpful to review how CFMX handles a <cfinvoke>
    (or equivalent) request in general. CFMX first retrieves the target service's
    WSDL, then runs this WSDL through the WSDL2Java tool (see below for more
    information), which outputs Java code defining Java-based classes equivalent to
    the XML data structures defined in the WSDL. This Java code is then compiled.
    The input arguments provided to <cfinvoke> are then mapped to the Java types
    generated by the compilation, and finally the Java stub functions for those
    types are called. In this fashion, CFMX *automatically* converts input values
    referenced in <cfinvoke> or <cfinvokeargument> tags to XML documents of the
    appropriate formats based on input argument format information provided in the
    service's WSDL. The burden on the coder, of course, is to ensure the input
    values are structured in accordance with what CFMX expects to find based on the
    translation by WSDL2Java from an XML-based data structure to a Java-based data
    structure. A similar process is followed to handle the service's return value
    and other output arguments. This process is quite straightforward for 'simple'
    type input arguments, such as simple strings or numeric values. Because
    ColdFusion variables, strictly speaking, are untyped, CFMX automatically
    converts simple input ColdFusion variables to the equivalent string-based
    simple XML structures. However, some web service input arguments are XML
    documents of 'complex' type. As briefly described in the ColdFusion MX 7
    documentation at:
    [url]http://livedocs.macromedia.com/coldfusion/7/htmldocs/00001554.htm[/url] for
    complex-type arguments, CFMX expects to find a ColdFusion structure provided as
    the value for the input argument. Unfortunately, the ColdFusion MX
    documentation only provides clear examples of how to compose a ColdFusion
    structure that corresponds merely to a relatively simple form of a 'complex'
    XML document in which the child elements of an outer 'complex' parent element
    are simple scalar values, as illustrated in Example 1: ---------Example
    1:------------------------------------ WSDL snippet: <s:complexType
    name='Employee'> <s:sequence> <s:element minOccurs='1' maxOccurs='1'
    name='fname' type='s:string' /> <s:element minOccurs='1' maxOccurs='1'
    name='lname' type='s:string' /> <s:element minOccurs='1' maxOccurs='1'
    name='age' type='s:int' /> </s:sequence> </s:complexType> Sample XML
    document: <Employee> <fname>John</fname> <lname>Smith</fname>
    <age>25</age> </Employee> CFML snippet: <!--- Create a structure using
    CFScript, then call the web service. ---> <cfscript> stUser = structNew();
    stUser.fname = 'John'; stUser.lname = 'Smith'; stUser.age = 23; ws =
    createObject('webservice', 'http://somehost/echosimple.asmx?wsdl');
    ws.echoStruct(stUser); </cfscript>
    ------------------------------------------------------- While the above is
    helpful for 'simple' complex-type input arguments, the ColdFusion MX
    documentation provides no examples of how to compose a ColdFusion structure
    that corresponds to a more complex form of a complex-type XML document in which
    the child elements of an outer 'complex' parent element are themselves
    'complex' parent elements (so-called 'complex-within-complex' XML documents),
    as illustrated in Example 2: ---------Example
    2:------------------------------------ WSDL snippet: <s:complexType
    name='Employee'> <s:sequence> <s:element minOccurs='1' maxOccurs='1'
    name='fname' type='s:string' /> <s:element minOccurs='1' maxOccurs='1'
    name='lname' type='s:string' /> <s:element minOccurs='0'
    maxOccurs='unbounded' name='nickname' type='s:nickname' /> <s:element
    minOccurs='1' maxOccurs='1' name='age' type='s:int' /> <s:element
    ref='s:address' minOccurs='0' maxOccurs='unbounded' name='address' />
    </s:sequence> <xsd:attribute name='employeeGender' type='string'
    use='required'/> </s:complexType> <s:complexType name='nickname'>
    <s:simpleContent> <s:extension base='string' /> </s:simpleContent>
    </s:complexType> <s:complexType name='address'> <s:sequence>
    <s:element minOccurs='1' maxOccurs='1' name='street' type='s:string' />
    <s:element minOccurs='1' maxOccurs='1' name='street' type='s:string' />
    <s:element minOccurs='1' maxOccurs='1' name='state' type='s:state' />
    <s:element minOccurs='1' maxOccurs='1' name='zip' type='s:zip' />
    </s:sequence> <xsd:attribute name='addressType' type='string'
    use='required'/> </s:complexType> Sample XML document: <Employee
    employeeGender='Male'> <fname>John</fname> <lname>Smith</fname>
    <nickname>Jack</nickname> <nickname>Johnny</nickname> <age>25</age>
    <address addressType='Home'> <street>25 Main Street</street>
    <city>Townville</street> <state>Anystate</state> <zip>99999</zip>
    </address> </Employee> CFML snippet: <!--- Create a structure using
    CFScript, then call the web service. ---> <cfscript> stUser = structNew();
    stUser.fname = 'John'; stUser.lname = 'Smith'; stUser.age = 23; <!---
    If .x corresponds to *element* <x>, then what syntax is used to specify an
    *attribute*? How should employeeGender get set up in this struct?
    Read on to find out. ---> <!--- And what about the *two*
    nicknames? stUser.nickname = ... clearly won't work. Read on to find
    out how this is handled. --->
    <!--- And what about <address>? Does that get coded simply as stUser.address =
    structNew(), stUser.address.street = '25 Main Street', etc. etc.?????
    The answer is 'No.' Read on to find out more.
    ---> ws = createObject('webservice',
    'http://somehost/echosimple.asmx?wsdl'); ws.echoStruct(stUser); </cfscript>
    ------------------------------------------------------- There are just a few
    key (pardon the pun) principles you need to understand in order to determine
    how to compose a CF structure that CFMX will map to the properly formatted XML
    document needed as an input argument to an arbitrary web service: (1)
    Principle #1: Any given key in a CF structure will be mapped by CFMX into
    *either* an element name *or* an attribute name depending on what role the WSDL
    says that particular name should play at that level in the document. In other
    words, you do not need to differentiate between attributes and elements in the
    CFML structure you create; ColdFusion will automatically handle for you the
    proper mapping of each key into either an attribute or element as required by
    the WSDL. Following along with Example 2 above, then, stUser.age will get
    translated into an <age> child *element* within the <Employee> parent element,
    and stUser.employeeGender will get translated as the employeeGender *attribute*
    within the <Employee> element. (2) Elements in a WSDL that can occur more than
    once (cf. the 'address' element in Example 2 above) are represented in the CF
    struct as an array. OK, but an array of what? Well, it depends on how the
    WSDL defines the subelements. Again, following along with Example 2 above,
    <address> would be coded into the stUser structure as follows:
    stUser.address = arrayNew(1); stUser.address[1] = structNew();
    stUser.address[1].street = '25 Main Street'; stUser.address[1].city =
    'Townville'; stUser.address[1].state = 'Anystate'; stUser.address[1].zip
    = '99999'; stUser.address[1].addressType = 'Home'; and the nicknames would
    be coded a
    afrinl Guest

  2. Similar Questions and Discussions

    1. A tricky query problem
      what i am trying to do is 1. let a user decide which language they want 2. pull the apropriate information fom a few different tables project...
    2. Tricky problem with WebControl vs. Panel
      I have built a class derived from WebControl, and added somespecific functionality to it..Then I built a set of web controlsbased on that...
    3. Tricky problem with classes!
      Problem: I try to store data in a objects field and read it out again. Sounds easy, yeah. But its a bit tricky here.... ;-) This is the class...
    4. tricky disable button problem
      Ok, I need to know a little actionscript and hope you will be able to help - I have always found replies here. I have my main movie with home,...
    5. Problem of using apache soap to consume WSE 2.0 soap attachment
      I developed a web service at .NET with WSE 2.0 attachming soap attachment with soap response, and I can write a .NET client app to consume it. ...
  3. #2

    Default Re: Tricky SOAP input problem; need help with cfinvoke syntax

    This is great stuff and we plan on publishing a tech note with this
    information as well.

    Thanks for Larry and Doug for putting this document together.

    --
    Tom Jordahl
    Macromedia Server Development


    Tom Jordahl Guest

  4. #3

    Default Re: Tricky SOAP input problem; need help with cfinvokesyntax

    Unfortunately, a good bit of the original formatting of the answer I posted was
    not preserved upon posting here in the forum. An alternative view with
    improved formatting is available here:
    [url]http://hcc.musc.edu/research/shared_resources/xml_complex_types_to_cf_structure_[/url]
    notes.cfm I hope this helps. -- LBA

    afrinl Guest

  5. #4

    Default Re: Tricky SOAP input problem; need help with cfinvokesyntax

    Excellent post. Thanks for the info.
    Mike Greider Guest

Posting Permissions

  • You may not post new threads
  • You may post replies
  • You may not post attachments
  • You may not edit your posts

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139