Welcome to the "trac"-ing site of soap4r!
[soap4r] [httpclient] [openpgp4u] [pkcs1] [logger] [csv] [vtr]

Ticket #123 (closed defect: fixed)

Opened 3 years ago

Last modified 3 years ago

soap4r mapping problem when using google adwords api

Reported by: nahi Assigned to: nahi
Priority: high Milestone: 1.5.5
Component: wsdl4r Version: 1.5
Keywords: Cc:

Description (Last modified by nahi)

The Google Adwords sample that Nahi included in the samples at
http://dev.ctor.org/soap4r/file/trunk/sample/wsdl/googleAdwords/client.rb
does not work.

In the course of fixing it I ran into a roadblock.
Here's my current fix. I highlight the problems I have fixed, and
areas where I'm not very happy with the fix I found.
---
#!/usr/local/bin/ruby

require 'soap/wsdlDriver'
require 'soap/header/simplehandler'

#wsdl = 'https://adwords.google.com/api/adwords/v2/CampaignService?WSDL'
wsdl = 'CampaignService.wsdl'

class HeaderHandler < SOAP::Header::SimpleHandler
  def initialize(tag, value)
    super(XSD::QName.new(nil, tag))
    @tag = tag
    @value = value
  end

#the initial handler from the sample was wrong, it generated 2 level of tags
  def on_simple_outbound
    @value
  end
end

#problem: wsdl2ruby does not pick up soap/property file, so yields a
certificate error when running against this https url
#run it on local file
# To generate deafult.rb, do like this;
# % wsdl2ruby.rb --wsdl
"https://adwords.google.com/api/adwords/v2/CampaignService?WSDL"
--classdef --force
require 'default'

# I don't have an account of AdWords so the following code is not tested.
# Please tell me (nahi@ruby-lang.org) if you will get good/bad result in
# communicating with AdWords Server...
drv = SOAP::WSDLDriverFactory.new(wsdl).create_rpc_driver
#problem: http protocol properties set in soap/property from rubyhome
are not picked up
drv.loadproperty('soap/property')
#print drv.options["client"]["ssl_config"].inspect
#problem: wiredump_dev does not output anything when running in SSL mode
drv.wiredump_dev = STDOUT
#the file based logger works
drv.wiredump_file_base = "log"
drv.headerhandler << HeaderHandler.new('email', 'patlist@chanezon.com')
drv.headerhandler << HeaderHandler.new('password', 'your_password_here')
drv.headerhandler << HeaderHandler.new('useragent', 'P@ playing with
the API from ruby')
drv.headerhandler << HeaderHandler.new('token', 'your_token_here')
camplist = drv.call("getAllAdWordsCampaigns", GetAllAdWordsCampaigns.new(123))
print camplist
---

When I run that with a valid adwords developer account, the call is
made and the correct repsonse is sent back, as seen in the filke log.
However the mapper barfs.

I incldue the relevant data.
Any idea of where to look for next is welcome.
I run soap4r soap4r-1_5_4, which seem to have fixed a few things
regarding doc/literal encoding style.

stack trace
/usr/lib/ruby/1.8/soap/mapping/wsdlliteralregistry.rb:73: warning:
Object#type is deprecated; use Object#class
/usr/lib/ruby/1.8/soap/mapping/wsdlliteralregistry.rb:73:in
`soap2obj': cannot map SOAP::SOAPElement to Ruby object
(SOAP::Mapping::MappingError)
        from /usr/lib/ruby/1.8/soap/mapping/mapping.rb:126:in `_soap2obj'
        from /usr/lib/ruby/1.8/soap/mapping/mapping.rb:49:in `soap2obj'
        from /usr/lib/ruby/1.8/soap/rpc/proxy.rb:417:in `response_doc_lit'
        from /usr/lib/ruby/1.8/soap/rpc/proxy.rb:416:in `collect'
        from /usr/lib/ruby/1.8/soap/rpc/proxy.rb:416:in `each'
        from /usr/lib/ruby/1.8/soap/baseData.rb:473:in `each'
        from /usr/lib/ruby/1.8/soap/baseData.rb:473:in `each'
        from /usr/lib/ruby/1.8/soap/rpc/proxy.rb:416:in `collect'
        from /usr/lib/ruby/1.8/soap/rpc/proxy.rb:416:in `response_doc_lit'
        from /usr/lib/ruby/1.8/soap/rpc/proxy.rb:382:in `response_doc'
        from /usr/lib/ruby/1.8/soap/rpc/proxy.rb:289:in `response_obj'
        from /usr/lib/ruby/1.8/soap/rpc/proxy.rb:129:in `call'
        from /usr/lib/ruby/1.8/soap/rpc/driver.rb:177:in `call'
        from ./client.rb:44
in soap2obj #<SOAP::SOAPElement:0x369636
{https://adwords.google.com/api/adwords/v2}getAllAdWordsCampaignsResponse>

the trace in soap2obj is a print node.inspect

here is the response log
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Header><responseTime
soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next"
soapenv:mustUnderstand="0"
xmlns="https://adwords.google.com/api/adwords/v2">23</responseTime><operations
soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next"
soapenv:mustUnderstand="0"
xmlns="https://adwords.google.com/api/adwords/v2">3</operations></soapenv:Header>
<soapenv:Body>
<getAllAdWordsCampaignsResponse
xmlns="https://adwords.google.com/api/adwords/v2">
<getAllAdWordsCampaignsReturn><id>6000213</id><name>Campaign
#1</name><status>Active</status><startDate>2005-04-16T21:27:50.000Z</startDate><endDate>2011-01-01T07:59:59.000Z</endDate><dailyBudget>1000000</dailyBudget><optInSearchNetwork>true</optInSearchNetwork><optInContentNetwork>true</optInContentNetwork><languageTargeting><languages>en</languages></languageTargeting><geoTargeting
xsi:nil="true"/></getAllAdWordsCampaignsReturn>
...
</getAllAdWordsCampaignsResponse></soapenv:Body></soapenv:Envelope>

It seems to barf on <getAllAdWordsCampaignsResponse
xmlns="https://adwords.google.com/api/adwords/v2">

Here is the rb file generated by wsdl2ruby

[...]

The error happens in soap/mapping/wsdlliteralregistry.rb

  # node should be a SOAPElement
  def soap2obj(node, obj_class = nil)
          print "in soap2obj #{node.inspect}"
    unless obj_class.nil?
      raise MappingError.new("must not reach here")
    end
    begin
      return any2obj(node)
    rescue MappingError
    end
    if @excn_handler_soap2obj
      begin
        return @excn_handler_soap2obj.call(node) { |yield_node|
            Mapping._soap2obj(yield_node, self)
          }
      rescue Exception
      end
    end
    raise MappingError.new("cannot map #{node.type.name} to Ruby object")
  end

I guess the problem must lie in the fact that the class
GetAllAdWordsCampaignsResponse is not known to the registry, to be
applied to the response element
{https://adwords.google.com/api/adwords/v2}getAllAdWordsCampaignsResponse>

# {https://adwords.google.com/api/adwords/v2}getAllAdWordsCampaignsResponse
class GetAllAdWordsCampaignsResponse
  @@schema_type = "getAllAdWordsCampaignsResponse"
  @@schema_ns = "https://adwords.google.com/api/adwords/v2"
  @@schema_element = [["getAllAdWordsCampaignsReturn", "Campaign[]"]]

How is this registry informed about the classes that must be used for
mapping when using the wsdl files?
Is there a message to be sent to drv in order to let it know about
default.rb classes?

Thanks in advance for any hints.

P@

Change History

07/13/05 21:31:14 changed by nahi

  • description changed.

07/14/05 21:37:26 changed by nahi

  • status changed from new to closed.
  • resolution set to fixed.

(In [1572]) SOAP Data which is defined as a simpletype was not mapped correctly to Ruby obj when wsdl2ruby.rb generated classdef file. closes #123.

05/29/06 20:06:59 changed by kkkkoaaa

Keep a good job up! http://quick-adult-links.com