Creating request object for complicated SOAP request

137 views
Skip to first unread message

crir...@multiservice.com

unread,
Dec 2, 2015, 10:56:01 AM12/2/15
to Savon
I'm completely new to Savon, fairly new to Ruby and my SOAP skills and knowledge are only moderate. So, I admit that I am laboring under a significant learning curve. Your help would be much appreciated.

Here's my problem. I have to write a client to a SOAP service operation that has a very verbose request object. I'm finding that the Savon documentation for creating requests provides examples for very simple requests only. 

My background is mostly Java. I'm used to having SOAP development frameworks where classes for request objects are generated for you from the WSDL. It then becomes a simple matter to instantiate such classes and invoke the corresponding operations. I'm not finding anything like this in Savon. My attempts to create the request messages by hand has not been successful. I pass the requests to the service and it just hangs.

A request object that does work and is  generated by SOAPUI from the WSDL is shown below. I'm also attaching the WSDL file. I know it's a lot to ask but I am struggling now for a couple of days. Would someone be good enough to give me whatever help they can in using Savon to create a request object corresponding to my WSDL? 

Thanks, Chuck

Working request object generated by SOAPUI:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ows="http://www.wfscorp.com/v1/OWS">
   <soapenv:Header/>
   <soapenv:Body>
      <ows:request>
         <ows:Caller-Application>?</ows:Caller-Application>
         <ows:Caller-User>?</ows:Caller-User>
         <ows:Fail-Fast>?</ows:Fail-Fast>
         <ows:Entities>
            <!--Optional:-->
            <ows:Customer-Contact>
               <ows:EntityId>?</ows:EntityId>
               <ows:LastName>?</ows:LastName>
               <ows:FirstName>?</ows:FirstName>
               <!--Optional:-->
               <ows:City>?</ows:City>
               <!--Optional:-->
               <ows:Country>?</ows:Country>
               <!--Optional:-->
               <ows:PhoneAreaCode>?</ows:PhoneAreaCode>
               <ows:CustomerId>?</ows:CustomerId>
               <ows:CustomerSiteId>?</ows:CustomerSiteId>
            </ows:Customer-Contact>
            <!--Optional:-->
            <ows:Supplier-Contact>
               <ows:EntityId>?</ows:EntityId>
               <ows:LastName>?</ows:LastName>
               <!--Optional:-->
               <ows:MiddleName>?</ows:MiddleName>
               <ows:FirstName>?</ows:FirstName>
               <!--Optional:-->
               <ows:City>?</ows:City>
               <!--Optional:-->
               <ows:Country>?</ows:Country>
               <!--Optional:-->
               <ows:SiteAreaCode>?</ows:SiteAreaCode>
               <!--Optional:-->
               <ows:SiteFaxAreaCode>?</ows:SiteFaxAreaCode>
               <!--Optional:-->
               <ows:ContactAreaCode>?</ows:ContactAreaCode>
               <!--Optional:-->
               <ows:ContactAltAreaCode>?</ows:ContactAltAreaCode>
               <!--Optional:-->
               <ows:ContactFaxAreaCode>?</ows:ContactFaxAreaCode>
               <ows:VendorId>?</ows:VendorId>
               <ows:VendorSiteId>?</ows:VendorSiteId>
            </ows:Supplier-Contact>
            <!--Optional:-->
            <ows:Customer>
               <ows:EntityId>?</ows:EntityId>
               <!--Optional:-->
               <ows:EntityName>VNESHECONOMBANK</ows:EntityName>
               <ows:Country>?</ows:Country>
               <!--Optional:-->
               <ows:CustomerId>?</ows:CustomerId>
               <!--Optional:-->
               <ows:CustomerSiteUseId>?</ows:CustomerSiteUseId>
               <!--Optional:-->
               <ows:OperatingUnit>?</ows:OperatingUnit>
            </ows:Customer>
            <!--Optional:-->
            <ows:CustomerSite>
               <ows:EntityId>?</ows:EntityId>
               <ows:EntityName>?</ows:EntityName>
               <!--Optional:-->
               <ows:City>?</ows:City>
               <!--Optional:-->
               <ows:Country>?</ows:Country>
               <ows:OperatingUnit>?</ows:OperatingUnit>
               <!--Optional:-->
               <ows:CustomerId>?</ows:CustomerId>
               <!--Optional:-->
               <ows:CustomerSiteUseId>?</ows:CustomerSiteUseId>
            </ows:CustomerSite>
            <!--Optional:-->
            <ows:Supplier>
               <ows:EntityId>?</ows:EntityId>
               <ows:EntityName>?</ows:EntityName>
               <ows:Country>?</ows:Country>
               <!--Optional:-->
               <ows:AreaCode>?</ows:AreaCode>
               <!--Optional:-->
               <ows:VendorSiteId>?</ows:VendorSiteId>
            </ows:Supplier>
            <!--Optional:-->
            <ows:SupplierSite>
               <ows:EntityId>?</ows:EntityId>
               <ows:EntityName>?</ows:EntityName>
               <!--Optional:-->
               <ows:City>?</ows:City>
               <ows:Country>?</ows:Country>
            </ows:SupplierSite>
            <!--Optional:-->
            <ows:Customer-Bank>
               <ows:EntityId>?</ows:EntityId>
               <ows:EntityName>?</ows:EntityName>
               <ows:Country>?</ows:Country>
               <!--Optional:-->
               <ows:AreaCode>?</ows:AreaCode>
               <!--Optional:-->
               <ows:ContactAreaCode>?</ows:ContactAreaCode>
               <!--Optional:-->
               <ows:CustomerSiteUseId>?</ows:CustomerSiteUseId>
            </ows:Customer-Bank>
            <!--Optional:-->
            <ows:Supplier-Bank>
               <ows:EntityId>?</ows:EntityId>
               <ows:EntityName>?</ows:EntityName>
               <ows:Country>?</ows:Country>
               <!--Optional:-->
               <ows:AreaCode>?</ows:AreaCode>
               <!--Optional:-->
               <ows:ContactAreaCode>?</ows:ContactAreaCode>
               <!--Optional:-->
               <ows:VendorSiteId>?</ows:VendorSiteId>
            </ows:Supplier-Bank>
            <!--Optional:-->
            <ows:FBO>
               <ows:EntityId>?</ows:EntityId>
               <!--Optional:-->
               <ows:EntityName>?</ows:EntityName>
               <ows:Country>?</ows:Country>
            </ows:FBO>
            <!--Optional:-->
            <ows:Vessel>
               <ows:EntityId>?</ows:EntityId>
               <!--Optional:-->
               <ows:EntityName>?</ows:EntityName>
               <!--Optional:-->
               <ows:Country>?</ows:Country>
               <!--Optional:-->
               <ows:IMO>?</ows:IMO>
            </ows:Vessel>
            <!--Optional:-->
            <ows:Tail-Number>
               <ows:EntityId>?</ows:EntityId>
               <!--Optional:-->
               <ows:EntityName>?</ows:EntityName>
               <ows:Country>?</ows:Country>
            </ows:Tail-Number>
            <!--Optional:-->
            <ows:Port>
               <ows:EntityId>?</ows:EntityId>
               <!--Optional:-->
               <ows:EntityName>?</ows:EntityName>
               <ows:Country>?</ows:Country>
            </ows:Port>
            <!--Optional:-->
            <ows:Employee>
               <ows:EntityId>?</ows:EntityId>
               <!--Optional:-->
               <ows:LastName>?</ows:LastName>
               <!--Optional:-->
               <ows:FirstName>?</ows:FirstName>
            </ows:Employee>
         </ows:Entities>
      </ows:request>
   </soapenv:Body>
</soapenv:Envelope>




wf_ofac.wsdl

Steffen Roller

unread,
Dec 2, 2015, 2:40:49 PM12/2/15
to sav...@googlegroups.com
What I usually do is to make sure the call works from SoapUI.
In the second step I'm writing the savon client which creates the same output structure.
Then I'm done. :-)

You can use the following structures when creating your client for debugging:

require 'savon'

c = Savon.client(
    endpoint: "http://....",
    namespace: "http://.....",
    log: true,
    log_level: :debug,
    pretty_print_xml: true)

c.call(:<your_action_here>,
        message: {
            request: {
                    ...
                entities: {
                    ...
                }
            }
        }
    


--
You received this message because you are subscribed to the Google Groups "Savon" group.
To unsubscribe from this group and stop receiving emails from it, send an email to savonrb+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

crir...@multiservice.com

unread,
Dec 2, 2015, 3:22:21 PM12/2/15
to Savon
Hi Steffan,

Actually, I have been trying to do as you suggested - making sure that the request was working via SOAPUI and then trying to duplicate the request using Savon. So far, I'm not successful in getting the generated request to look like the SOAPUI request. And, when I call the service, it basically hangs.

The code I have so far is:

***************** My client code **************************
require 'savon'
require 'pry'
binding.pry
wsdl_path =

client = Savon.client(
  wsdl: wsdl_path,
  log: true,
  log_level: :debug,
  pretty_print_xml: true,
  namespace: namespace)

message = {
  request: {
    entities: {
      customer: {
        entity_name: "VNESHECONOMBANK"}}}}
                              
response = client.call(:process, message: message)

details = response.body

*********************************************

The SOAP UI request looks like:

***************************** SOAPUI Request ********************

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ows="http://www.wfscorp.com/v1/OWS">
   <soapenv:Header/>
   <soapenv:Body>
      <ows:request>
         <ows:Caller-Application>?</ows:Caller-Application>
         <ows:Caller-User>?</ows:Caller-User>
         <ows:Fail-Fast>?</ows:Fail-Fast>
         <ows:Entities>
            <ows:Customer>
               <ows:EntityId>?</ows:EntityId>
               <!--Optional:-->
               <ows:EntityName>VNESHECONOMBANK</ows:EntityName>
               <ows:Country>?</ows:Country>
               <!--Optional:-->
               <ows:CustomerId>?</ows:CustomerId>
               <!--Optional:-->
               <ows:CustomerSiteUseId>?</ows:CustomerSiteUseId>
               <!--Optional:-->
               <ows:OperatingUnit>?</ows:OperatingUnit>
            </ows:Customer>
                ...

**************** end of SOAP UI Request ***************

The request that Savon generates is:

****************** Savon generated request ******************

<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns1="http://www.wfscorp.com/v1/OWS" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">

  <env:Body>

    <ns1:request>

      <request>

        <entities>

          <customer>

            <entityName>VNESHECONOMBANK</entityName>

          </customer>

        </entities>

      </request>

    </ns1:request>

  </env:Body>

</env:Envelope>


******************** end of savon generated request *********************


From the top, notice the things that I have highlighted in yellow:


1. I specify a wsdl file, while your example specifies an endpoint. Should I use and endpoint instead? I'm not sure what my endpoint should be unfortunately.

2. Notice that SOAP inserts the ows namespace prefix while Savon does not. Is that a problem, do you think?

2. When generating the request, Savon inserts and extra "request" element. Should I remove the "request" entry from my hashmap?


Thanks for your help!!

crir...@multiservice.com

unread,
Dec 2, 2015, 4:44:55 PM12/2/15
to Savon
Hi Steffan,

I did manage to get things working. The main problem was that Savon wasn't prepending the namespace to XML elements of the child request. I worked around this by using hardcoded strings in my message hashmap, e.g. "prefix:foo" => "foo". I'm going to see if I can find a way to get Savon to do this for me automatically.

Thanks very, very much for reaching out.

Chuck


On Wednesday, December 2, 2015 at 1:40:49 PM UTC-6, Steffen Roller wrote:

Steffen Roller

unread,
Dec 2, 2015, 11:35:40 PM12/2/15
to sav...@googlegroups.com
Hi Chuck,

I re-read the documentation for v2 (http://savonrb.com/version2/globals.html)
You might want to look into

    env_namespace
    namespace_identifier
    element_form_default

I'd play around with those parameters and see whether it makes a difference in your case.

As you have already noticed I used a syntax without a WSDL. I personally prefer that variant, because I believe it give me more wiggle room for the client, avoid the WSDL interpretation of Savon (which is a bit sketchy to be polite) and I also believe it is faster.
If the interface doesn't change then I don't think you need a WSDL. I also think Savon doesn't perform many check against the WSDL making a call.

Good luck with all of this.

-st
Reply all
Reply to author
Forward
0 new messages