[cl-soap-devel] ScheduleReportJob [was Re: CL-SOAP Progress]
Sven Van Caekenberghe
scaekenberghe at common-lisp.net
Thu Oct 6 12:02:54 UTC 2005
On 06 Oct 2005, at 01:17, Alain.Picard at memetrics.com wrote:
> Sven Van Caekenberghe writes:
>
>> It is very interesting that you are trying to use the
>> ReportService API...
>
> OK, I think I've found what I need to do to create a report job,
> but I don't know how to do it with CL-SOAP.
>
> Consider this function:
>
> (DEFUN SCHEDULE-REPORT-JOB (&KEY JOB)
> (WSDL-SOAP-CALL
> (WSDL-CACHE-GET "https://adwords.google.com/api/adwords/v2/
> ReportService?wsdl")
> "scheduleReportJob"
> :INPUT
> (LIST "scheduleReportJob"
> (LIST "job" JOB))
> :HEADERS
> (MAKE-GOOGLE-HEADERS)))
>
> Now, I found people having problems, with the same Java exception
> raised (missing constructor) as we have. Their solution was to
> send:
>
> <scheduleReportJob>
> <job xsi:type="CustomReportJob">
> ....
>
> Instead of just <job>.
>
> (I suspect this is in fact a bug in their implementation of the
> API, but don't know enough about this stuff to be 100% sure).
>
> Any ideas how to get CL-SOAP to issue something like this?
> I tried
>
> (DEFUN SCHEDULE-REPORT-JOB (&KEY JOB)
> (WSDL-SOAP-CALL
> (WSDL-CACHE-GET "https://adwords.google.com/api/adwords/v2/
> ReportService?wsdl")
> "scheduleReportJob"
> :INPUT
> (LIST "scheduleReportJob"
> (LIST "job xsi:type=\"UrlReportJob\" " JOB))
> :HEADERS
> (MAKE-GOOGLE-HEADERS)))
>
> But that fails because it cannot find a binding for job xsi=....
>
> We may need some extra syntax in there to dissociate the binding
> element from it's args. (Or maybe it's already in there and I
> didn't find it).
>
> Help?
OK, here is the deal:
ReportJob is like an abstract type with 4 concrete subtypes: [KeyWord|
AdText|Url|Custom]ReportJob.
As such this case was implemented (members are simply inherited from
super to sub types).
However, when binding input the operation signature only mentions
(and knows of) the abstract type.
There was no provision to specify a concrete subtype.
I managed to add a special case for this purpose without messing up
the code too much.
The following function (from test/test-xsd.lisp) show how to schedule
a report job:
(defun test-3 ()
(let* ((schema (get-xml-schema-definition
(wsdl-cache-get "https://adwords.google.com:443/
api/adwords/v2/ReportService?wsdl")))
(template (generate-xsd-template "scheduleReportJob" schema))
(binding `("scheduleReportJob"
("job"
(xsi:|type| "UrlReportJob"
"name" "test123"
"startDate" ,(ut)
"endDate" ,(ut)
"clientAccounts" (100 200)
"adWordsType" "SearchOnly"
"campaigns" (101 201))))))
(bind-xsd-template template
binding
schema
*google-adwords-ns*)))
The convention is that a special purpose member called xsi:|type|
whose value is the concrete subtype being used can be added where
needed (incidentally, XSI stands for XML Schema Instance). The above
code works as follows:
CL-SOAP 313 > (pprint (test-3))
((GOOGLE::|scheduleReportJob|
((GOOGLE::|job| XSI:|type| "UrlReportJob")
(GOOGLE::|name| "test123")
(GOOGLE::|startDate| "2005-10-06T00:00:00.000-01:00")
(GOOGLE::|endDate| "2005-10-06T00:00:00.000-01:00")
(GOOGLE::|clientAccounts| "100")
(GOOGLE::|clientAccounts| "200")
(GOOGLE::|adWordsType| "SearchOnly")
(GOOGLE::|campaigns| "101")
(GOOGLE::|campaigns| "201"))))
CL-SOAP 314 > (s-xml:print-xml (first (test-3)) :stream *standard-
output* :pretty t)
<google:scheduleReportJob>
<google:job xsi:type="UrlReportJob">
<google:name>test123</google:name>
<google:startDate>2005-10-06T00:00:00.000-01:00</google:startDate>
<google:endDate>2005-10-06T00:00:00.000-01:00</google:endDate>
<google:clientAccounts>100</google:clientAccounts>
<google:clientAccounts>200</google:clientAccounts>
<google:adWordsType>SearchOnly</google:adWordsType>
<google:campaigns>101</google:campaigns>
<google:campaigns>201</google:campaigns>
</google:job>
</google:scheduleReportJob>
Hopefully, this code will work in the actual call ;-)
Sven
More information about the cl-soap-devel
mailing list