Subject: | Yahoo/Marketing/DateTimeAccessor.pm causes invalid dateTime fields (E1021) |
Date: | Wed, 5 Nov 2008 10:32:22 -0800 |
To: | bug-Yahoo-Marketing-APT [...] rt.cpan.org |
From: | "Noel Burton-Krahn" <noel [...] burton-krahn.com> |
I called getHistoricalDataForKeywords, and kept getting an E1021 error. I
tracked the problem down to DateTimeAccessor, and fixed it by
converting DateTime objects to formatted strings. My fix and example
code are below.
Regards,
Noel Burton-Krahn
noel@burton-krahn.com
software versions:
This is perl, v5.8.8 built for i486-linux-gnu-thread-multi
Yahoo::Marketing 4.30
SOAP::Lite 0.710.08
The old Yahoo/Marketing/DateTimeAccessor.pm. Converting to DateTime and
calling set_formatter results in invalid dateTime structs in XML.
sub _force_datetime_object {
my ( $self, $value ) = @_;
if( defined $value ){
unless( ref $value ){ # not a date time object
$value = DateTime::Format::ISO8601->new->parse_datetime( $value );
}
# let's hope it looks like a duck... er, DateTime object
$value->set_formatter( DateTime::Format::W3CDTF->new );
}
return $value;
}
The fixed Yahoo/Marketing/DateTimeAccessor.pm.
sub _force_datetime_object {
my ( $self, $value ) = @_;
if( defined $value ){
unless( ref $value ){ # not a date time object
$value = DateTime::Format::ISO8601->new->parse_datetime( $value );
}
# NBK - 2008-11-05 - convert the value to a string like
# YYYY-mm-ddTHH:MM:SS+zz:zz. If it's left as a DateTime
# object, SOAP::Lite encode it as an unparseable DateTime
# struct in XML.
$value = DateTime::Format::W3CDTF->new->format_datetime($value);
}
return $value;
}
Sample code to reproduce:
use SOAP::Lite;
SOAP::Lite->import(+trace => 'all');
my $endDate = DateTime->now->subtract(days => 1);
my $startDate = DateTime->now->subtract(months => 3);
my $service = $self->config_service(Yahoo::Marketing::ForecastService->new);
my $result = $service->getHistoricalDataForKeywords(
keywords => [
Yahoo::Marketing::HistoricalKeyword->new
->keyword($keyword)
],
historicalRequestData => Yahoo::Marketing::HistoricalRequestData->new
->accountID($cfg->{ews_account_id})
->matchTypes([qw(AdvancedMatch)])
->marketID($marketID)
->startDate($startDate)
->endDate($endDate)
);
XML sent to Yahoo. The startDate and endDate structs are not valid
dateTimes:
SOAP::Transport::HTTP::Client::send_receive: POST
https://ews11.marketing.ews.yahooapis.com:443/services/V4/ForecastService
HTTP/1.1
Accept: text/xml
Accept: multipart/*
Accept: application/soap
Content-Length: 1752
Content-Type: text/xml; charset=utf-8
SOAPAction:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:namesp1="http://namespaces.soaplite.com/perl"
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ysm="http://marketing.ews.yahooapis.com/V4"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Header>
<wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext">
<wsse:UsernameToken soapenc:arrayType="xsd:string[2]"
xsi:type="soapenc:Array">
<wsse:Username xsi:type="xsd:string">USERNAME</wsse:Username>
<wsse:Password xsi:type="xsd:string">PASSWORD</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
<license xmlns="http://marketing.ews.yahooapis.com/V4"
xsi:type="xsd:string">06E1D3B637E57AEF</license>
<masterAccountID xmlns="http://marketing.ews.yahooapis.com/V4"
xsi:type="xsd:string">1121899</masterAccountID>
</soap:Header>
<soap:Body>
<getHistoricalDataForKeywords
xmlns="http://marketing.ews.yahooapis.com/V4">
<keywords xsi:type="tns:ArrayOfHistoricalKeyword">
<HistoricalKeyword>
<keyword xsi:type="xsd:string">gadgets</keyword>
</HistoricalKeyword>
</keywords>
<historicalRequestData xsi:type="tns:HistoricalRequestData">
<accountID xsi:type="xsd:string">9857894300</accountID>
<endDate href="#ref-2008" xsi:type="xsd:dateTime" />
<marketID xsi:type="xsd:string">US</marketID>
<matchTypes xsi:type="tns:ArrayOfKeywordForecastMatchType">
<KeywordForecastMatchType
xsi:type="xsd:string">AdvancedMatch</KeywordForecastMatchType>
</matchTypes>
<startDate href="#ref-2008" xsi:type="xsd:dateTime" />
</historicalRequestData>
</getHistoricalDataForKeywords>
<DateTime xsi:type="namesp1:DateTime" id="ref-2008">
<local_rd_secs xsi:type="xsd:int">64197</local_rd_secs>
<local_rd_days xsi:type="xsd:int">733259</local_rd_days>
<locale href="#ref-142707740"
xsi:type="namesp1:DateTime__Locale__en_US" />
<rd_nanosecs xsi:type="xsd:int">0</rd_nanosecs>
<utc_rd_secs xsi:type="xsd:int">64197</utc_rd_secs>
<local_c href="#ref-178882332" />
<formatter href="#ref-178882476"
xsi:type="namesp1:DateTime__Format__W3CDTF" />
<utc_year xsi:type="xsd:int">2009</utc_year>
<tz href="#ref-178882524" xsi:type="namesp1:DateTime__TimeZone__UTC" />
<offset_modifier xsi:type="xsd:int">0</offset_modifier>
<utc_rd_days xsi:type="xsd:int">733259</utc_rd_days>
</DateTime>
<DateTime__Locale__en_US
xsi:type="namesp1:DateTime__Locale__en_US" id="ref-142707740">
<default_time_format_length
xsi:type="xsd:string">medium</default_time_format_length>
<native_territory xsi:type="xsd:string">United States</native_territory>
<native_language xsi:type="xsd:string">English</native_language>
<native_complete_name xsi:type="xsd:string">English United
States</native_complete_name>
<en_language xsi:type="xsd:string">English</en_language>
<id xsi:type="xsd:string">en_US</id>
<default_date_format_length
xsi:type="xsd:string">medium</default_date_format_length>
<en_complete_name xsi:type="xsd:string">English United
States</en_complete_name>
<en_territory xsi:type="xsd:string">United States</en_territory>
</DateTime__Locale__en_US>
</soap:Body>
</soap:Envelope>
XML fault returned from Yahoo
SOAP::Transport::HTTP::Client::send_receive: HTTP/1.1 500 Internal Server Error
Connection: close
Date: Wed, 05 Nov 2008 17:49:53 GMT
Content-Type: text/xml;charset=UTF-8
Client-Date: Wed, 05 Nov 2008 17:49:58 GMT
Client-Peer: 72.30.33.57:443
Client-Response-Num: 1
Client-SSL-Cert-Issuer: /C=US/O=Equifax/OU=Equifax Secure Certificate Authority
Client-SSL-Cert-Subject: /C=US/ST=California/L=Santa Clara/O=Yahoo!
Inc./OU=Yahoo/CN=*.marketing.ews.yahooapis.com
Client-SSL-Cipher: DHE-RSA-AES256-SHA
Client-SSL-Warning: Peer certificate not verified
Client-Transfer-Encoding: chunked
P3P: policyref="http://p3p.yahoo.com/w3c/p3p.xml", CP="CAO DSP COR
CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi
UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE
GOV"
X-Powered-By: Servlet 2.4; JBoss-4.0.2 (build: CVSTag=JBoss_4_0_2
date=200505022023)/Tomcat-5.5
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Header>
<yns:sid xmlns:yns="http://marketing.ews.yahooapis.com/V4">sk1-1adsrvcs-003.ysm.sk1.yahoo.com</yns:sid>
<yns:stime xmlns:yns="http://marketing.ews.yahooapis.com/V4">Wed
Nov 05 09:49:53 PST 2008</yns:stime>
</soap:Header>
<soap:Body>
<soap:Fault>
<faultcode>soap:Client</faultcode>
<faultstring>Invalid parameter.</faultstring>
<detail>
<yns:ApiFault xmlns:yns="http://marketing.ews.yahooapis.com/V4">
<yns:code xmlns:yns="http://marketing.ews.yahooapis.com/V4">E1021</yns:code>
<yns:message
xmlns:yns="http://marketing.ews.yahooapis.com/V4">Invalid
parameter.</yns:message>
</yns:ApiFault>
</detail>
</soap:Fault>
</soap:Body>
</soap:Envelope>
SOAP::Deserializer::deserialize: ()
SOAP::Parser::decode: ()
SOAP::SOM::new: ()
SOAP::SOM::DESTROY: ()
error calling module: SOAP FAULT!
fixed XML sent to Yahoo with fix:
SOAP::Transport::HTTP::Client::send_receive: POST
https://ews11.marketing.ews.yahooapis.com:443/services/V4/ForecastService
HTTP/1.1
Accept: text/xml
Accept: multipart/*
Accept: application/soap
Content-Length: 1752
Content-Type: text/xml; charset=utf-8
SOAPAction:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:namesp1="http://namespaces.soaplite.com/perl"
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ysm="http://marketing.ews.yahooapis.com/V4"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Header>
<wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext">
<wsse:UsernameToken soapenc:arrayType="xsd:string[2]"
xsi:type="soapenc:Array">
<wsse:Username xsi:type="xsd:string">USERNAME</wsse:Username>
<wsse:Password xsi:type="xsd:string">PASSWORD</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
<license xmlns="http://marketing.ews.yahooapis.com/V4"
xsi:type="xsd:string">06E1D3B637E57AEF</license>
<masterAccountID xmlns="http://marketing.ews.yahooapis.com/V4"
xsi:type="xsd:string">1121899</masterAccountID>
</soap:Header>
<soap:Body>
<getHistoricalDataForKeywords
xmlns="http://marketing.ews.yahooapis.com/V4">
<keywords xsi:type="tns:ArrayOfHistoricalKeyword">
<HistoricalKeyword>
<keyword xsi:type="xsd:string">gadgets</keyword>
</HistoricalKeyword>
</keywords>
<historicalRequestData xsi:type="tns:HistoricalRequestData">
<accountID xsi:type="xsd:string">9857894300</accountID>
<endDate xsi:type="xsd:dateTime">2008-11-04T18:11:20Z</endDate>
<marketID xsi:type="xsd:string">US</marketID>
<matchTypes xsi:type="tns:ArrayOfKeywordForecastMatchType">
<KeywordForecastMatchType
xsi:type="xsd:string">AdvancedMatch</KeywordForecastMatchType>
</matchTypes>
<startDate xsi:type="xsd:dateTime">2008-08-05T18:11:20Z</startDate>
</historicalRequestData>
</getHistoricalDataForKeywords>
</soap:Body>
</soap:Envelope>