soap4r mapping problem when using google adwords api

P

Patrick Chanezon

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 =3D 'https://adwords.google.com/api/adwords/v2/CampaignService?WSDL'
wsdl =3D 'CampaignService.wsdl'

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

#the initial handler from the sample was wrong, it generated 2 level of tag=
s
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 ([email protected]) if you will get good/bad result in
# communicating with AdWords Server...
drv =3D 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 =3D STDOUT
#the file based logger works
drv.wiredump_file_base =3D "log"
drv.headerhandler << HeaderHandler.new('email', '(e-mail address removed)')
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 =3D 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=3D"http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd=3D"http://www.w3.org/2001/XMLSchema"
xmlns:xsi=3D"http://www.w3.org/2001/XMLSchema-instance"><soapenv:Header><re=
sponseTime
soapenv:actor=3D"http://schemas.xmlsoap.org/soap/actor/next"
soapenv:mustUnderstand=3D"0"
xmlns=3D"https://adwords.google.com/api/adwords/v2">23</responseTime><opera=
tions
soapenv:actor=3D"http://schemas.xmlsoap.org/soap/actor/next"
soapenv:mustUnderstand=3D"0"
xmlns=3D"https://adwords.google.com/api/adwords/v2">3</operations></soapenv=
:Header>
<soapenv:Body>
<getAllAdWordsCampaignsResponse
xmlns=3D"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</startD=
ate><endDate>2011-01-01T07:59:59.000Z</endDate><dailyBudget>1000000</dailyB=
udget><optInSearchNetwork>true</optInSearchNetwork><optInContentNetwork>tru=
e</optInContentNetwork><languageTargeting><languages>en</languages></langua=
geTargeting><geoTargeting
xsi:nil=3D"true"/></getAllAdWordsCampaignsReturn>
...
</getAllAdWordsCampaignsResponse></soapenv:Body></soapenv:Envelope>

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

Here is the rb file generated by wsdl2ruby
require 'xsd/qname'

# {https://adwords.google.com/api/adwords/v2}getCampaign
class GetCampaign
@@schema_type =3D "getCampaign"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["id", "SOAP::SOAPInt"]]

attr_accessor :id

def initialize(id =3D nil)
@id =3D id
end
end

# {https://adwords.google.com/api/adwords/v2}getCampaignResponse
class GetCampaignResponse
@@schema_type =3D "getCampaignResponse"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["getCampaignReturn", "Campaign"]]

attr_accessor :getCampaignReturn

def initialize(getCampaignReturn =3D nil)
@getCampaignReturn =3D getCampaignReturn
end
end

# {https://adwords.google.com/api/adwords/v2}getCampaignList
class GetCampaignList
@@schema_type =3D "getCampaignList"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["ids", "SOAP::SOAPInt[]"]]

attr_accessor :ids

def initialize(ids =3D [])
@ids =3D ids
end
end

# {https://adwords.google.com/api/adwords/v2}getCampaignListResponse
class GetCampaignListResponse
@@schema_type =3D "getCampaignListResponse"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["getCampaignListReturn", "Campaign[]"]]

attr_accessor :getCampaignListReturn

def initialize(getCampaignListReturn =3D [])
@getCampaignListReturn =3D getCampaignListReturn
end
end

# {https://adwords.google.com/api/adwords/v2}getAllAdWordsCampaigns
class GetAllAdWordsCampaigns
@@schema_type =3D "getAllAdWordsCampaigns"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["dummy", "SOAP::SOAPInt"]]

attr_accessor :dummy

def initialize(dummy =3D nil)
@dummy =3D dummy
end
end

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

attr_accessor :getAllAdWordsCampaignsReturn

def initialize(getAllAdWordsCampaignsReturn =3D [])
@getAllAdWordsCampaignsReturn =3D getAllAdWordsCampaignsReturn
end
end

# {https://adwords.google.com/api/adwords/v2}addCampaign
class AddCampaign
@@schema_type =3D "addCampaign"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["campaign", "Campaign"]]

attr_accessor :campaign

def initialize(campaign =3D nil)
@campaign =3D campaign
end
end

# {https://adwords.google.com/api/adwords/v2}addCampaignResponse
class AddCampaignResponse
@@schema_type =3D "addCampaignResponse"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["addCampaignReturn", "Campaign"]]

attr_accessor :addCampaignReturn

def initialize(addCampaignReturn =3D nil)
@addCampaignReturn =3D addCampaignReturn
end
end

# {https://adwords.google.com/api/adwords/v2}addCampaignList
class AddCampaignList
@@schema_type =3D "addCampaignList"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["campaigns", "Campaign[]"]]

attr_accessor :campaigns

def initialize(campaigns =3D [])
@campaigns =3D campaigns
end
end

# {https://adwords.google.com/api/adwords/v2}addCampaignListResponse
class AddCampaignListResponse
@@schema_type =3D "addCampaignListResponse"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["addCampaignListReturn", "Campaign[]"]]

attr_accessor :addCampaignListReturn

def initialize(addCampaignListReturn =3D [])
@addCampaignListReturn =3D addCampaignListReturn
end
end

# {https://adwords.google.com/api/adwords/v2}updateCampaign
class UpdateCampaign
@@schema_type =3D "updateCampaign"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["campaign", "Campaign"]]

attr_accessor :campaign

def initialize(campaign =3D nil)
@campaign =3D campaign
end
end

# {https://adwords.google.com/api/adwords/v2}updateCampaignResponse
class UpdateCampaignResponse
@@schema_type =3D "updateCampaignResponse"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D []

def initialize
end
end

# {https://adwords.google.com/api/adwords/v2}updateCampaignList
class UpdateCampaignList
@@schema_type =3D "updateCampaignList"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["campaigns", "Campaign[]"]]

attr_accessor :campaigns

def initialize(campaigns =3D [])
@campaigns =3D campaigns
end
end

# {https://adwords.google.com/api/adwords/v2}updateCampaignListResponse
class UpdateCampaignListResponse
@@schema_type =3D "updateCampaignListResponse"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D []

def initialize
end
end

# {https://adwords.google.com/api/adwords/v2}getOptimizeAdServing
class GetOptimizeAdServing
@@schema_type =3D "getOptimizeAdServing"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["campaignId", "SOAP::SOAPInt"]]

attr_accessor :campaignId

def initialize(campaignId =3D nil)
@campaignId =3D campaignId
end
end

# {https://adwords.google.com/api/adwords/v2}getOptimizeAdServingResponse
class GetOptimizeAdServingResponse
@@schema_type =3D "getOptimizeAdServingResponse"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["getOptimizeAdServingReturn", "SOAP::SOAPBoolean"]=
]

attr_accessor :getOptimizeAdServingReturn

def initialize(getOptimizeAdServingReturn =3D nil)
@getOptimizeAdServingReturn =3D getOptimizeAdServingReturn
end
end

# {https://adwords.google.com/api/adwords/v2}setOptimizeAdServing
class SetOptimizeAdServing
@@schema_type =3D "setOptimizeAdServing"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["campaignId", "SOAP::SOAPInt"], ["enable",
"SOAP::SOAPBoolean"]]

attr_accessor :campaignId
attr_accessor :enable

def initialize(campaignId =3D nil, enable =3D nil)
@campaignId =3D campaignId
@enable =3D enable
end
end

# {https://adwords.google.com/api/adwords/v2}setOptimizeAdServingResponse
class SetOptimizeAdServingResponse
@@schema_type =3D "setOptimizeAdServingResponse"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D []

def initialize
end
end

# {https://adwords.google.com/api/adwords/v2}getCampaignStats
class GetCampaignStats
@@schema_type =3D "getCampaignStats"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["campaignIds", "SOAP::SOAPInt[]"], ["start",
"SOAP::SOAPDateTime"], ["v_end", ["SOAP::SOAPDateTime",
XSD::QName.new(nil, "end")]]]

attr_accessor :campaignIds
attr_accessor :start

def end
@v_end
end

def end=3D(value)
@v_end =3D value
end

def initialize(campaignIds =3D [], start =3D nil, v_end =3D nil)
@campaignIds =3D campaignIds
@start =3D start
@v_end =3D v_end
end
end

# {https://adwords.google.com/api/adwords/v2}getCampaignStatsResponse
class GetCampaignStatsResponse
@@schema_type =3D "getCampaignStatsResponse"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["getCampaignStatsReturn", "StatsRecord[]"]]

attr_accessor :getCampaignStatsReturn

def initialize(getCampaignStatsReturn =3D [])
@getCampaignStatsReturn =3D getCampaignStatsReturn
end
end

# {https://adwords.google.com/api/adwords/v2}Keyword
class Keyword
@@schema_type =3D "Keyword"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["type", "KeywordType"], ["maxCpc",
"SOAP::SOAPLong"], ["adGroupId", "SOAP::SOAPInt"], ["language",
"SOAP::SOAPString"], ["status", "KeywordStatus"], ["negative",
"SOAP::SOAPBoolean"], ["destinationUrl", "SOAP::SOAPString"], ["text",
"SOAP::SOAPString"], ["id", "SOAP::SOAPInt"], ["exemptionRequest",
"SOAP::SOAPString"]]

attr_accessor :type
attr_accessor :maxCpc
attr_accessor :adGroupId
attr_accessor :language
attr_accessor :status
attr_accessor :negative
attr_accessor :destinationUrl
attr_accessor :text
attr_accessor :id
attr_accessor :exemptionRequest

def initialize(type =3D nil, maxCpc =3D nil, adGroupId =3D nil, language =
=3D
nil, status =3D nil, negative =3D nil, destinationUrl =3D nil, text =3D nil=
,
id =3D nil, exemptionRequest =3D nil)
@type =3D type
@maxCpc =3D maxCpc
@adGroupId =3D adGroupId
@language =3D language
@status =3D status
@negative =3D negative
@destinationUrl =3D destinationUrl
@text =3D text
@id =3D id
@exemptionRequest =3D exemptionRequest
end
end

# {https://adwords.google.com/api/adwords/v2}LanguageTarget
class LanguageTarget < ::Array
@@schema_type =3D "string"
@@schema_ns =3D "http://www.w3.org/2001/XMLSchema"
end

# {https://adwords.google.com/api/adwords/v2}GeoTarget
class GeoTarget
@@schema_type =3D "GeoTarget"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["countries", "SOAP::SOAPString[]"], ["regions",
"SOAP::SOAPString[]"], ["metros", "SOAP::SOAPString[]"], ["cities",
"SOAP::SOAPString[]"]]

attr_accessor :countries
attr_accessor :regions
attr_accessor :metros
attr_accessor :cities

def initialize(countries =3D [], regions =3D [], metros =3D [], cities =
=3D [])
@countries =3D countries
@regions =3D regions
@metros =3D metros
@cities =3D cities
end
end

# {https://adwords.google.com/api/adwords/v2}Campaign
class Campaign
@@schema_type =3D "Campaign"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["id", "SOAP::SOAPInt"], ["name",
"SOAP::SOAPString"], ["status", "CampaignStatus"], ["startDate",
"SOAP::SOAPDateTime"], ["endDate", "SOAP::SOAPDateTime"],
["dailyBudget", "SOAP::SOAPLong"], ["optInSearchNetwork",
"SOAP::SOAPBoolean"], ["optInContentNetwork", "SOAP::SOAPBoolean"],
["campaignNegativeKeywords", "Keyword[]"], ["languageTargeting",
"LanguageTarget"], ["geoTargeting", "GeoTarget"]]

attr_accessor :id
attr_accessor :name
attr_accessor :status
attr_accessor :startDate
attr_accessor :endDate
attr_accessor :dailyBudget
attr_accessor :eek:ptInSearchNetwork
attr_accessor :eek:ptInContentNetwork
attr_accessor :campaignNegativeKeywords
attr_accessor :languageTargeting
attr_accessor :geoTargeting

def initialize(id =3D nil, name =3D nil, status =3D nil, startDate =3D ni=
l,
endDate =3D nil, dailyBudget =3D nil, optInSearchNetwork =3D nil,
optInContentNetwork =3D nil, campaignNegativeKeywords =3D [],
languageTargeting =3D nil, geoTargeting =3D nil)
@id =3D id
@name =3D name
@status =3D status
@startDate =3D startDate
@endDate =3D endDate
@dailyBudget =3D dailyBudget
@optInSearchNetwork =3D optInSearchNetwork
@optInContentNetwork =3D optInContentNetwork
@campaignNegativeKeywords =3D campaignNegativeKeywords
@languageTargeting =3D languageTargeting
@geoTargeting =3D geoTargeting
end
end

# {https://adwords.google.com/api/adwords/v2}ApiException
class ApiException
@@schema_type =3D "ApiException"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["code", "SOAP::SOAPInt"], ["internal",
"SOAP::SOAPBoolean"], ["message", "SOAP::SOAPString"], ["trigger",
"SOAP::SOAPString"], ["violations", "SOAP::SOAPString"]]

attr_accessor :code
attr_accessor :internal
attr_accessor :message
attr_accessor :trigger
attr_accessor :violations

def initialize(code =3D nil, internal =3D nil, message =3D nil, trigger =
=3D
nil, violations =3D nil)
@code =3D code
@internal =3D internal
@message =3D message
@trigger =3D trigger
@violations =3D violations
end
end

# {https://adwords.google.com/api/adwords/v2}StatsRecord
class StatsRecord
@@schema_type =3D "StatsRecord"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["averagePosition", "SOAP::SOAPDouble"],
["clicks", "SOAP::SOAPLong"], ["conversionRate", "SOAP::SOAPDouble"],
["conversions", "SOAP::SOAPLong"], ["cost", "SOAP::SOAPLong"], ["id",
"SOAP::SOAPLong"], ["impressions", "SOAP::SOAPLong"]]

attr_accessor :averagePosition
attr_accessor :clicks
attr_accessor :conversionRate
attr_accessor :conversions
attr_accessor :cost
attr_accessor :id
attr_accessor :impressions

def initialize(averagePosition =3D nil, clicks =3D nil, conversionRate =
=3D
nil, conversions =3D nil, cost =3D nil, id =3D nil, impressions =3D nil)
@averagePosition =3D averagePosition
@clicks =3D clicks
@conversionRate =3D conversionRate
@conversions =3D conversions
@cost =3D cost
@id =3D id
@impressions =3D impressions
end
end

# {https://adwords.google.com/api/adwords/v2}KeywordStatus
module KeywordStatus
Deleted =3D "Deleted"
Disabled =3D "Disabled"
Disapproved =3D "Disapproved"
InTrial =3D "InTrial"
Normal =3D "Normal"
OnHold =3D "OnHold"
end

# {https://adwords.google.com/api/adwords/v2}KeywordType
module KeywordType
Broad =3D "Broad"
Exact =3D "Exact"
Phrase =3D "Phrase"
end

# {https://adwords.google.com/api/adwords/v2}CampaignStatus
module CampaignStatus
Active =3D "Active"
Deleted =3D "Deleted"
Ended =3D "Ended"
Paused =3D "Paused"
Pending =3D "Pending"
Suspended =3D "Suspended"
end

The error happens in soap/mapping/wsdlliteralregistry.rb

# node should be a SOAPElement
def soap2obj(node, obj_class =3D 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 =3D "getAllAdWordsCampaignsResponse"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["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?

A few hours later after finding this other sample
I now generate the client driver myself using wsdl2ruby
wsdl2ruby.rb --wsdl CampaignService.wsdl --type client

Now I understand where the mapping is defined.
Still the new program yields the same error

---
#!/usr/local/bin/ruby

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

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

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

#the initial handler from the sample was wrong, it generated 2 level of tag=
s
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 ([email protected]) if you will get good/bad result in
# communicating with AdWords Server...
#drv =3D SOAP::WSDLDriverFactory.new(wsdl).create_rpc_driver

require 'defaultDriver.rb'
require 'yaml'

prefs =3D YAML::load( File.open('adwords.yaml', 'r'))
headers =3D prefs['headers']

drv =3D CampaignService.new()

#problem: http protocol properties set in soap/property from rubyhome
are not picked up
drv.loadproperty('soap/property')
#problem: wiredump_dev does not output anything when running in SSL mode
#drv.wiredump_dev =3D STDOUT
#the file based logger works
drv.wiredump_file_base =3D "log"

headers.each {|key, value| drv.headerhandler << HeaderHandler.new(key, valu=
e)}

puts drv.getAllAdWordsCampaigns(GetAllAdWordsCampaigns.new(123))
---

/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 /usr/lib/ruby/1.8/soap/rpc/driver.rb:231:in
`getAllAdWordsCampaigns'
from /usr/lib/ruby/1.8/soap/rpc/driver.rb:226:in
`getAllAdWordsCampaigns'
from ./client.rb:39
in soap2obj #<SOAP::SOAPElement:0x36be68
{https://adwords.google.com/api/adwords/v2}getAllAdWordsCampaignsResponse>

It is as if the mapping defined in CampaignService is not used.

Thanks in advance for any hints.

P@
 
P

Patrick Chanezon

adding some debug in proxy.rb
def response_doc_lit(body, mapping_registry)
puts "in proxy mapping =3D #{mapping_registry.inspect}"
body.collect { |key, value|
Mapping.soap2obj(value, mapping_registry)
}
end

shows that the mapping does not contain any information about the adwords t=
ypes
in proxy mapping =3D #<SOAP::Mapping::WSDLLiteralRegistry:0x6eea34
@excn_handler_obj2soap=3Dnil,
@schema_element_cache=3D{GetAllAdWordsCampaigns=3D>[{"dummy"=3D>"SOAP::SOAP=
Int"},
[]]}, @schema_attribute_cache=3D{GetAllAdWordsCampaigns=3D>nil},
@definedtypes=3D#<XSD::NamedElements:0x2a56fc
@cache=3D{#<XSD::QName:0x3706ca {}dummy>=3D>nil, #<XSD::QName:0x3766b0
{https://adwords.google.com/api/adwords/v2}getAllAdWordsCampaigns>=3D>nil},
@elements=3D[]>, @definedelements=3D#<XSD::NamedElements:0x2a56fc
@cache=3D{#<XSD::QName:0x3706ca {}dummy>=3D>nil, #<XSD::QName:0x3766b0
{https://adwords.google.com/api/adwords/v2}getAllAdWordsCampaigns>=3D>nil},
@elements=3D[]>, @excn_handler_soap2obj=3Dnil>

Is the init generated by wsdl2ruby correct?
if RUBY_VERSION > "1.7.0"
def add_method_interface(name, param_count)
::SOAP::Mapping.define_singleton_method(self, name) do |*arg|
unless arg.size =3D=3D param_count
raise ArgumentError.new(
"wrong number of arguments (#{arg.size} for #{param_count})")
end
call(name, *arg)
end
self.method(name)
end

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.
=20
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
=20
require 'soap/wsdlDriver'
require 'soap/header/simplehandler'
=20
#wsdl =3D 'https://adwords.google.com/api/adwords/v2/CampaignService?WSDL= '
wsdl =3D 'CampaignService.wsdl'
=20
class HeaderHandler < SOAP::Header::SimpleHandler
def initialize(tag, value)
super(XSD::QName.new(nil, tag))
@tag =3D tag
@value =3D value
end
=20
#the initial handler from the sample was wrong, it generated 2 level of t= ags
def on_simple_outbound
@value
end
end
=20
#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'
=20
# I don't have an account of AdWords so the following code is not tested.
# Please tell me ([email protected]) if you will get good/bad result in
# communicating with AdWords Server...
drv =3D 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 =3D STDOUT
#the file based logger works
drv.wiredump_file_base =3D "log"
drv.headerhandler << HeaderHandler.new('email', '(e-mail address removed)')
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 =3D drv.call("getAllAdWordsCampaigns", GetAllAdWordsCampaigns.ne= w(123))
print camplist
---
=20
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.
=20
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.
=20
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=

=20
the trace in soap2obj is a print node.inspect
=20
here is the response log
<soapenv:Envelope
xmlns:soapenv=3D"http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd=3D"http://www.w3.org/2001/XMLSchema"
xmlns:xsi=3D"http://www.w3.org/2001/XMLSchema-instance"><soapenv:Header><= responseTime
soapenv:actor=3D"http://schemas.xmlsoap.org/soap/actor/next"
soapenv:mustUnderstand=3D"0"
xmlns=3D"https://adwords.google.com/api/adwords/v2">23</responseTime><ope= rations
soapenv:actor=3D"http://schemas.xmlsoap.org/soap/actor/next"
soapenv:mustUnderstand=3D"0"
xmlns=3D"https://adwords.google.com/api/adwords/v2">3</operations></soape=
nv:Header>
<soapenv:Body>
<getAllAdWordsCampaignsResponse
xmlns=3D"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</star=
tDate><endDate>2011-01-01T07:59:59.000Z</endDate><dailyBudget>1000000</dail=
yBudget><optInSearchNetwork>true</optInSearchNetwork><optInContentNetwork>t=
rue said:
xsi:nil=3D"true"/></getAllAdWordsCampaignsReturn>
...
</getAllAdWordsCampaignsResponse></soapenv:Body></soapenv:Envelope>
=20
It seems to barf on <getAllAdWordsCampaignsResponse
xmlns=3D"https://adwords.google.com/api/adwords/v2">
=20
Here is the rb file generated by wsdl2ruby
require 'xsd/qname'
=20
# {https://adwords.google.com/api/adwords/v2}getCampaign
class GetCampaign
@@schema_type =3D "getCampaign"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["id", "SOAP::SOAPInt"]]
=20
attr_accessor :id
=20
def initialize(id =3D nil)
@id =3D id
end
end
=20
# {https://adwords.google.com/api/adwords/v2}getCampaignResponse
class GetCampaignResponse
@@schema_type =3D "getCampaignResponse"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["getCampaignReturn", "Campaign"]]
=20
attr_accessor :getCampaignReturn
=20
def initialize(getCampaignReturn =3D nil)
@getCampaignReturn =3D getCampaignReturn
end
end
=20
# {https://adwords.google.com/api/adwords/v2}getCampaignList
class GetCampaignList
@@schema_type =3D "getCampaignList"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["ids", "SOAP::SOAPInt[]"]]
=20
attr_accessor :ids
=20
def initialize(ids =3D [])
@ids =3D ids
end
end
=20
# {https://adwords.google.com/api/adwords/v2}getCampaignListResponse
class GetCampaignListResponse
@@schema_type =3D "getCampaignListResponse"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["getCampaignListReturn", "Campaign[]"]]
=20
attr_accessor :getCampaignListReturn
=20
def initialize(getCampaignListReturn =3D [])
@getCampaignListReturn =3D getCampaignListReturn
end
end
=20
# {https://adwords.google.com/api/adwords/v2}getAllAdWordsCampaigns
class GetAllAdWordsCampaigns
@@schema_type =3D "getAllAdWordsCampaigns"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["dummy", "SOAP::SOAPInt"]]
=20
attr_accessor :dummy
=20
def initialize(dummy =3D nil)
@dummy =3D dummy
end
end
=20
# {https://adwords.google.com/api/adwords/v2}getAllAdWordsCampaignsRespon= se
class GetAllAdWordsCampaignsResponse
@@schema_type =3D "getAllAdWordsCampaignsResponse"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["getAllAdWordsCampaignsReturn", "Campaign[]"]]
=20
attr_accessor :getAllAdWordsCampaignsReturn
=20
def initialize(getAllAdWordsCampaignsReturn =3D [])
@getAllAdWordsCampaignsReturn =3D getAllAdWordsCampaignsReturn
end
end
=20
# {https://adwords.google.com/api/adwords/v2}addCampaign
class AddCampaign
@@schema_type =3D "addCampaign"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["campaign", "Campaign"]]
=20
attr_accessor :campaign
=20
def initialize(campaign =3D nil)
@campaign =3D campaign
end
end
=20
# {https://adwords.google.com/api/adwords/v2}addCampaignResponse
class AddCampaignResponse
@@schema_type =3D "addCampaignResponse"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["addCampaignReturn", "Campaign"]]
=20
attr_accessor :addCampaignReturn
=20
def initialize(addCampaignReturn =3D nil)
@addCampaignReturn =3D addCampaignReturn
end
end
=20
# {https://adwords.google.com/api/adwords/v2}addCampaignList
class AddCampaignList
@@schema_type =3D "addCampaignList"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["campaigns", "Campaign[]"]]
=20
attr_accessor :campaigns
=20
def initialize(campaigns =3D [])
@campaigns =3D campaigns
end
end
=20
# {https://adwords.google.com/api/adwords/v2}addCampaignListResponse
class AddCampaignListResponse
@@schema_type =3D "addCampaignListResponse"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["addCampaignListReturn", "Campaign[]"]]
=20
attr_accessor :addCampaignListReturn
=20
def initialize(addCampaignListReturn =3D [])
@addCampaignListReturn =3D addCampaignListReturn
end
end
=20
# {https://adwords.google.com/api/adwords/v2}updateCampaign
class UpdateCampaign
@@schema_type =3D "updateCampaign"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["campaign", "Campaign"]]
=20
attr_accessor :campaign
=20
def initialize(campaign =3D nil)
@campaign =3D campaign
end
end
=20
# {https://adwords.google.com/api/adwords/v2}updateCampaignResponse
class UpdateCampaignResponse
@@schema_type =3D "updateCampaignResponse"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D []
=20
def initialize
end
end
=20
# {https://adwords.google.com/api/adwords/v2}updateCampaignList
class UpdateCampaignList
@@schema_type =3D "updateCampaignList"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["campaigns", "Campaign[]"]]
=20
attr_accessor :campaigns
=20
def initialize(campaigns =3D [])
@campaigns =3D campaigns
end
end
=20
# {https://adwords.google.com/api/adwords/v2}updateCampaignListResponse
class UpdateCampaignListResponse
@@schema_type =3D "updateCampaignListResponse"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D []
=20
def initialize
end
end
=20
# {https://adwords.google.com/api/adwords/v2}getOptimizeAdServing
class GetOptimizeAdServing
@@schema_type =3D "getOptimizeAdServing"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["campaignId", "SOAP::SOAPInt"]]
=20
attr_accessor :campaignId
=20
def initialize(campaignId =3D nil)
@campaignId =3D campaignId
end
end
=20
# {https://adwords.google.com/api/adwords/v2}getOptimizeAdServingResponse
class GetOptimizeAdServingResponse
@@schema_type =3D "getOptimizeAdServingResponse"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["getOptimizeAdServingReturn", "SOAP::SOAPBoolean= "]]
=20
attr_accessor :getOptimizeAdServingReturn
=20
def initialize(getOptimizeAdServingReturn =3D nil)
@getOptimizeAdServingReturn =3D getOptimizeAdServingReturn
end
end
=20
# {https://adwords.google.com/api/adwords/v2}setOptimizeAdServing
class SetOptimizeAdServing
@@schema_type =3D "setOptimizeAdServing"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["campaignId", "SOAP::SOAPInt"], ["enable",
"SOAP::SOAPBoolean"]]
=20
attr_accessor :campaignId
attr_accessor :enable
=20
def initialize(campaignId =3D nil, enable =3D nil)
@campaignId =3D campaignId
@enable =3D enable
end
end
=20
# {https://adwords.google.com/api/adwords/v2}setOptimizeAdServingResponse
class SetOptimizeAdServingResponse
@@schema_type =3D "setOptimizeAdServingResponse"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D []
=20
def initialize
end
end
=20
# {https://adwords.google.com/api/adwords/v2}getCampaignStats
class GetCampaignStats
@@schema_type =3D "getCampaignStats"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["campaignIds", "SOAP::SOAPInt[]"], ["start",
"SOAP::SOAPDateTime"], ["v_end", ["SOAP::SOAPDateTime",
XSD::QName.new(nil, "end")]]]
=20
attr_accessor :campaignIds
attr_accessor :start
=20
def end
@v_end
end
=20
def end=3D(value)
@v_end =3D value
end
=20
def initialize(campaignIds =3D [], start =3D nil, v_end =3D nil)
@campaignIds =3D campaignIds
@start =3D start
@v_end =3D v_end
end
end
=20
# {https://adwords.google.com/api/adwords/v2}getCampaignStatsResponse
class GetCampaignStatsResponse
@@schema_type =3D "getCampaignStatsResponse"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["getCampaignStatsReturn", "StatsRecord[]"]]
=20
attr_accessor :getCampaignStatsReturn
=20
def initialize(getCampaignStatsReturn =3D [])
@getCampaignStatsReturn =3D getCampaignStatsReturn
end
end
=20
# {https://adwords.google.com/api/adwords/v2}Keyword
class Keyword
@@schema_type =3D "Keyword"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["type", "KeywordType"], ["maxCpc",
"SOAP::SOAPLong"], ["adGroupId", "SOAP::SOAPInt"], ["language",
"SOAP::SOAPString"], ["status", "KeywordStatus"], ["negative",
"SOAP::SOAPBoolean"], ["destinationUrl", "SOAP::SOAPString"], ["text",
"SOAP::SOAPString"], ["id", "SOAP::SOAPInt"], ["exemptionRequest",
"SOAP::SOAPString"]]
=20
attr_accessor :type
attr_accessor :maxCpc
attr_accessor :adGroupId
attr_accessor :language
attr_accessor :status
attr_accessor :negative
attr_accessor :destinationUrl
attr_accessor :text
attr_accessor :id
attr_accessor :exemptionRequest
=20
def initialize(type =3D nil, maxCpc =3D nil, adGroupId =3D nil, languag= e =3D
nil, status =3D nil, negative =3D nil, destinationUrl =3D nil, text =3D n= il,
id =3D nil, exemptionRequest =3D nil)
@type =3D type
@maxCpc =3D maxCpc
@adGroupId =3D adGroupId
@language =3D language
@status =3D status
@negative =3D negative
@destinationUrl =3D destinationUrl
@text =3D text
@id =3D id
@exemptionRequest =3D exemptionRequest
end
end
=20
# {https://adwords.google.com/api/adwords/v2}LanguageTarget
class LanguageTarget < ::Array
@@schema_type =3D "string"
@@schema_ns =3D "http://www.w3.org/2001/XMLSchema"
end
=20
# {https://adwords.google.com/api/adwords/v2}GeoTarget
class GeoTarget
@@schema_type =3D "GeoTarget"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["countries", "SOAP::SOAPString[]"], ["regions",
"SOAP::SOAPString[]"], ["metros", "SOAP::SOAPString[]"], ["cities",
"SOAP::SOAPString[]"]]
=20
attr_accessor :countries
attr_accessor :regions
attr_accessor :metros
attr_accessor :cities
=20
def initialize(countries =3D [], regions =3D [], metros =3D [], cities = =3D [])
@countries =3D countries
@regions =3D regions
@metros =3D metros
@cities =3D cities
end
end
=20
# {https://adwords.google.com/api/adwords/v2}Campaign
class Campaign
@@schema_type =3D "Campaign"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["id", "SOAP::SOAPInt"], ["name",
"SOAP::SOAPString"], ["status", "CampaignStatus"], ["startDate",
"SOAP::SOAPDateTime"], ["endDate", "SOAP::SOAPDateTime"],
["dailyBudget", "SOAP::SOAPLong"], ["optInSearchNetwork",
"SOAP::SOAPBoolean"], ["optInContentNetwork", "SOAP::SOAPBoolean"],
["campaignNegativeKeywords", "Keyword[]"], ["languageTargeting",
"LanguageTarget"], ["geoTargeting", "GeoTarget"]]
=20
attr_accessor :id
attr_accessor :name
attr_accessor :status
attr_accessor :startDate
attr_accessor :endDate
attr_accessor :dailyBudget
attr_accessor :eek:ptInSearchNetwork
attr_accessor :eek:ptInContentNetwork
attr_accessor :campaignNegativeKeywords
attr_accessor :languageTargeting
attr_accessor :geoTargeting
=20
def initialize(id =3D nil, name =3D nil, status =3D nil, startDate =3D = nil,
endDate =3D nil, dailyBudget =3D nil, optInSearchNetwork =3D nil,
optInContentNetwork =3D nil, campaignNegativeKeywords =3D [],
languageTargeting =3D nil, geoTargeting =3D nil)
@id =3D id
@name =3D name
@status =3D status
@startDate =3D startDate
@endDate =3D endDate
@dailyBudget =3D dailyBudget
@optInSearchNetwork =3D optInSearchNetwork
@optInContentNetwork =3D optInContentNetwork
@campaignNegativeKeywords =3D campaignNegativeKeywords
@languageTargeting =3D languageTargeting
@geoTargeting =3D geoTargeting
end
end
=20
# {https://adwords.google.com/api/adwords/v2}ApiException
class ApiException
@@schema_type =3D "ApiException"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["code", "SOAP::SOAPInt"], ["internal",
"SOAP::SOAPBoolean"], ["message", "SOAP::SOAPString"], ["trigger",
"SOAP::SOAPString"], ["violations", "SOAP::SOAPString"]]
=20
attr_accessor :code
attr_accessor :internal
attr_accessor :message
attr_accessor :trigger
attr_accessor :violations
=20
def initialize(code =3D nil, internal =3D nil, message =3D nil, trigger= =3D
nil, violations =3D nil)
@code =3D code
@internal =3D internal
@message =3D message
@trigger =3D trigger
@violations =3D violations
end
end
=20
# {https://adwords.google.com/api/adwords/v2}StatsRecord
class StatsRecord
@@schema_type =3D "StatsRecord"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["averagePosition", "SOAP::SOAPDouble"],
["clicks", "SOAP::SOAPLong"], ["conversionRate", "SOAP::SOAPDouble"],
["conversions", "SOAP::SOAPLong"], ["cost", "SOAP::SOAPLong"], ["id",
"SOAP::SOAPLong"], ["impressions", "SOAP::SOAPLong"]]
=20
attr_accessor :averagePosition
attr_accessor :clicks
attr_accessor :conversionRate
attr_accessor :conversions
attr_accessor :cost
attr_accessor :id
attr_accessor :impressions
=20
def initialize(averagePosition =3D nil, clicks =3D nil, conversionRate = =3D
nil, conversions =3D nil, cost =3D nil, id =3D nil, impressions =3D nil)
@averagePosition =3D averagePosition
@clicks =3D clicks
@conversionRate =3D conversionRate
@conversions =3D conversions
@cost =3D cost
@id =3D id
@impressions =3D impressions
end
end
=20
# {https://adwords.google.com/api/adwords/v2}KeywordStatus
module KeywordStatus
Deleted =3D "Deleted"
Disabled =3D "Disabled"
Disapproved =3D "Disapproved"
InTrial =3D "InTrial"
Normal =3D "Normal"
OnHold =3D "OnHold"
end
=20
# {https://adwords.google.com/api/adwords/v2}KeywordType
module KeywordType
Broad =3D "Broad"
Exact =3D "Exact"
Phrase =3D "Phrase"
end
=20
# {https://adwords.google.com/api/adwords/v2}CampaignStatus
module CampaignStatus
Active =3D "Active"
Deleted =3D "Deleted"
Ended =3D "Ended"
Paused =3D "Paused"
Pending =3D "Pending"
Suspended =3D "Suspended"
end
=20
The error happens in soap/mapping/wsdlliteralregistry.rb
=20
# node should be a SOAPElement
def soap2obj(node, obj_class =3D 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
=20
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=

=20
# {https://adwords.google.com/api/adwords/v2}getAllAdWordsCampaignsRespon= se
class GetAllAdWordsCampaignsResponse
@@schema_type =3D "getAllAdWordsCampaignsResponse"
@@schema_ns =3D "https://adwords.google.com/api/adwords/v2"
@@schema_element =3D [["getAllAdWordsCampaignsReturn", "Campaign[]"]]
=20
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?
=20
A few hours later after finding this other sample
I now generate the client driver myself using wsdl2ruby
wsdl2ruby.rb --wsdl CampaignService.wsdl --type client
=20
Now I understand where the mapping is defined.
Still the new program yields the same error
=20
---
#!/usr/local/bin/ruby
=20
require 'soap/wsdlDriver'
require 'soap/header/simplehandler'
=20
wsdl =3D 'https://adwords.google.com/api/adwords/v2/CampaignService?WSDL'
=20
class HeaderHandler < SOAP::Header::SimpleHandler
def initialize(tag, value)
super(XSD::QName.new(nil, tag))
@tag =3D tag
@value =3D value
end
=20
#the initial handler from the sample was wrong, it generated 2 level of t= ags
def on_simple_outbound
@value
end
end
=20
#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'
=20
# I don't have an account of AdWords so the following code is not tested.
# Please tell me ([email protected]) if you will get good/bad result in
# communicating with AdWords Server...
#drv =3D SOAP::WSDLDriverFactory.new(wsdl).create_rpc_driver
=20
require 'defaultDriver.rb'
require 'yaml'
=20
prefs =3D YAML::load( File.open('adwords.yaml', 'r'))
headers =3D prefs['headers']
=20
drv =3D CampaignService.new()
=20
#problem: http protocol properties set in soap/property from rubyhome
are not picked up
drv.loadproperty('soap/property')
#problem: wiredump_dev does not output anything when running in SSL mode
#drv.wiredump_dev =3D STDOUT
#the file based logger works
drv.wiredump_file_base =3D "log"
=20
headers.each {|key, value| drv.headerhandler << HeaderHandler.new(key, va= lue)}
=20
puts drv.getAllAdWordsCampaigns(GetAllAdWordsCampaigns.new(123))
---
=20
/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 /usr/lib/ruby/1.8/soap/rpc/driver.rb:231:in
`getAllAdWordsCampaigns'
from /usr/lib/ruby/1.8/soap/rpc/driver.rb:226:in
`getAllAdWordsCampaigns'
from ./client.rb:39
in soap2obj #<SOAP::SOAPElement:0x36be68
{https://adwords.google.com/api/adwords/v2}getAllAdWordsCampaignsResponse=

=20
It is as if the mapping defined in CampaignService is not used.
=20
Thanks in advance for any hints.
=20
P@
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top