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@