[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