BingAds / BingAds-Java-SDK

Other
42 stars 47 forks source link

CampaignPerformanceReportRequest namespace not recognized on ReportingService requests #143

Closed wruoting closed 1 year ago

wruoting commented 1 year ago

We've found that creating a request hitting the https://reporting.api.bingads.microsoft.com/Api/Advertiser/Reporting/v13/ReportingService.svc endpoint results in this request body:

    <S:Body xmlns="https://bingads.microsoft.com/Reporting/v13"
            xmlns:ns3="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
        <SubmitGenerateReportRequest xmlns="https://bingads.microsoft.com/Reporting/v13">
            <ReportRequest xmlns="http://www.w3.org/2001/XMLSchema-instance"
                           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                           type="CampaignPerformanceReportRequest">
            </ReportRequest>
        </SubmitGenerateReportRequest>
    </S:Body>

While CampaignPerformanceReportRequest extends ReportRequest, the endpoint does not recognize type="CampaignPerformanceReportRequest" as a valid attribute assignment.

Updating the namespace of the ReportRequest entity from:

@XmlType(name = "ReportRequest", propOrder = {
    "excludeColumnHeaders",
    "excludeReportFooter",
    "excludeReportHeader",
    "format",
    "formatVersion",
    "reportName",
    "returnOnlyCompleteData"
})

to

@XmlType(name = "ReportRequest", propOrder = {
    "excludeColumnHeaders",
    "excludeReportFooter",
    "excludeReportHeader",
    "format",
    "formatVersion",
    "reportName",
    "returnOnlyCompleteData"
}, namespace = "http://www.w3.org/2001/XMLSchema-instance")

Results in

  <S:Body xmlns="https://bingads.microsoft.com/Reporting/v13"
            xmlns:ns1="http://schemas.microsoft.com/2003/10/Serialization/Arrays"
            xmlns:ns3="http://www.w3.org/2001/XMLSchema-instance">
        <SubmitGenerateReportRequest xmlns="https://bingads.microsoft.com/Reporting/v13">
            <ReportRequest ns3:type="CampaignPerformanceReportRequest">
             ...
            </ReportRequest>
        </SubmitGenerateReportRequest>
    </S:Body>

Which allows that type to be recognized.

I'm unsure as to whether this fix is the correct pattern for this particular repo, or whether we were doing something wrong in the first place. Happy to open a PR if this is the valid way to solve this issue.

qitia commented 1 year ago

hi @wruoting, we have some samples on how to create ReportRequest in file ReportRequests.java. Are you following that to compose your request?

wruoting commented 1 year ago

Yes, I am forming the requests using this SDK with the same pattern as linked by setting a ReportRequest's parameters. The only difference is that we are building a CampaignPerformanceReportRequest, which inherits ReportRequest and results in the first XML block from above. We are also utilizing ReportingServiceManager.downloadFileAsync(ReportingDownloadParameters parameters, AsyncCallback<File> callback) to send this request without any custom marshalling.

If it wouldn't be too much trouble, could you post a custom working CampaignPerformanceReportRequest implementation and SOAP request object for reference? Thank you!

qitia commented 1 year ago

Hi, I did not repro this issue. my code to generate CampaignPerformanceReportRequest is:

    private static CampaignPerformanceReportRequest getCampaignPerformanceReportRequest(
            java.lang.Long accountId,
            ReportAggregation aggregation,
            java.lang.Boolean excludeColumnHeaders,
            java.lang.Boolean excludeReportFooter,
            java.lang.Boolean excludeReportHeader,
            ReportFormat format,
            java.lang.Boolean returnOnlyCompleteData,
            ReportTime time)
    {
        CampaignPerformanceReportRequest reportRequest = new CampaignPerformanceReportRequest();

        reportRequest.setAggregation(aggregation);
        reportRequest.setExcludeColumnHeaders(excludeColumnHeaders);
        reportRequest.setExcludeReportFooter(excludeReportFooter);
        reportRequest.setExcludeReportHeader(excludeReportHeader);
        reportRequest.setFormat(format);
        reportRequest.setReturnOnlyCompleteData(returnOnlyCompleteData);
        reportRequest.setTime(time);
        reportRequest.setReportName("My Campaign Performance Report");
        ArrayOflong accountIds = new ArrayOflong();
        accountIds.getLongs().add(accountId);
        reportRequest.setScope(new AccountThroughCampaignReportScope());
        reportRequest.getScope().setAccountIds(accountIds);
        reportRequest.getScope().setCampaigns(null);
        CampaignPerformanceReportFilter filter = new CampaignPerformanceReportFilter();
        reportRequest.setFilter(filter);
        ArrayOfCampaignPerformanceReportColumn adPerformanceReportColumns = new ArrayOfCampaignPerformanceReportColumn(); 
        adPerformanceReportColumns.getCampaignPerformanceReportColumns().add(CampaignPerformanceReportColumn.ACCOUNT_NAME);
        adPerformanceReportColumns.getCampaignPerformanceReportColumns().add(CampaignPerformanceReportColumn.ACCOUNT_NUMBER);
        adPerformanceReportColumns.getCampaignPerformanceReportColumns().add(CampaignPerformanceReportColumn.IMPRESSIONS);
        adPerformanceReportColumns.getCampaignPerformanceReportColumns().add(CampaignPerformanceReportColumn.CLICKS);
        adPerformanceReportColumns.getCampaignPerformanceReportColumns().add(CampaignPerformanceReportColumn.CTR);
        adPerformanceReportColumns.getCampaignPerformanceReportColumns().add(CampaignPerformanceReportColumn.AVERAGE_CPC);
        reportRequest.setColumns(adPerformanceReportColumns);

        return reportRequest;
    }

and the generated soap body is

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header/>
   <S:Body xmlns="https://bingads.microsoft.com/Reporting/v13" xmlns:ns2="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns:ns3="https://adapi.microsoft.com" xmlns:ns4="http://schemas.microsoft.com/2003/10/Serialization/">
       <SubmitGenerateReportRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
           <ReportRequest xsi:type="CampaignPerformanceReportRequest">
               <ExcludeColumnHeaders>false</ExcludeColumnHeaders>
               <ExcludeReportFooter>false</ExcludeReportFooter>
               <ExcludeReportHeader>false</ExcludeReportHeader>
               <Format>Csv</Format>
               <FormatVersion xsi:nil="true"/>
               <ReportName>My Campaign Performance Report</ReportName>
               <ReturnOnlyCompleteData>false</ReturnOnlyCompleteData>
               <Aggregation>Daily</Aggregation>
               <Columns>
                   <CampaignPerformanceReportColumn>AccountName</CampaignPerformanceReportColumn>
                   <CampaignPerformanceReportColumn>AccountNumber</CampaignPerformanceReportColumn>
                   <CampaignPerformanceReportColumn>Impressions</CampaignPerformanceReportColumn>
                   <CampaignPerformanceReportColumn>Clicks</CampaignPerformanceReportColumn>
                   <CampaignPerformanceReportColumn>Ctr</CampaignPerformanceReportColumn>
                   <CampaignPerformanceReportColumn>AverageCpc</CampaignPerformanceReportColumn>
               </Columns>
               <Filter>
                   <AccountStatus xsi:nil="true"/>
                   <AdDistribution xsi:nil="true"/>
                   <DeviceOS xsi:nil="true"/>
                   <DeviceType xsi:nil="true"/>
                   <Status xsi:nil="true"/>
               </Filter>
               <Scope>
                   <AccountIds>
                       <ns2:long>{accountId}</ns2:long>
                   </AccountIds>
                   <Campaigns xsi:nil="true"/>
               </Scope>
               <Time>
                   <CustomDateRangeEnd xsi:nil="true"/>
                   <CustomDateRangeStart xsi:nil="true"/>
                   <PredefinedTime>Yesterday</PredefinedTime>
                   <ReportTimeZone>PacificTimeUSCanadaTijuana</ReportTimeZone>
               </Time>
           </ReportRequest>
       </SubmitGenerateReportRequest>
   </S:Body>
</S:Envelope>

CampaignPerformanceReportRequest, KeywordPerformanceReportRequest, AdPerformanceReportRequest are all inherited from ReportRequest, it is interesting that you only see issue with CampaignPerformanceReportRequest. Do not seems like proxy issue to me.

wruoting commented 1 year ago

@qitia Thanks for your prompt response. Are you also passing your object to the the ReportingServiceManager.downloadFileAsync((ReportingDownloadParameters parameters, AsyncCallback<File> callback) API to generate this SOAP request? It shouldn't technically make a difference to how the object is created, but I want to make sure the pathway we are using is the same. Thanks!

wruoting commented 1 year ago

Also I want to note that we are building this object in Kotlin, not Java, which should be compatible but if you've dealt with this in the past, information would be very helpful.

qitia commented 1 year ago

As the sample shows, it is using ReportingServiceManager.downloadReportAsync, but this method internally uses downloadFileAsync acutally. I do not think it should make differences.

I did not test in Kotlin.

qitia commented 1 year ago

@wruoting, is your issue reolved?

wruoting commented 1 year ago

This is a Kotlin specific issue that we have found to seemingly exist in JUnit tests running in a Kotlin environment, and therefore not related to this codebase. Thanks for your help!