1

I'm attempting to update the tooling api project (https://github.com/afawcett/apex-toolingapi) with a SOAP variant in addition to the REST api. The issue I'm currently having is supporting all the objects that extend / inherit the sObject_x object.

I first came across the following blog http://mauriciodesiderio.blogspot.com/2014/02/salesforce-wsdl2apex-and-class.html and went full steam ahead with modifying the WSDL2Apex code to support this. I've been able generated the ToolingAPIWSDL and Metadata classes based on the blog above, by duplicating the fields across the sObject and its subclasses, like ApexCodeCoverageAggregate.

Now, when I try to issue a simple query, I am getting the following message:

System.TypeException: Invalid conversion from runtime type timesheet.ToolingAPIWSDL.sObject_x to timesheet.ToolingAPIWSDL.ApexCodeCoverageAggregate

Here's an example of the ApexCodeCoverageAggregate class:

public class ApexCodeCoverageAggregate extends sObject_x {
    public ToolingAPIWSDL.Name ApexClassOrTrigger;
    public String ApexClassOrTriggerId;
    public ToolingAPIWSDL.Coverage Coverage;
    public DateTime CoverageLastModifiedDate;
    public ToolingAPIWSDL.User_x CreatedBy;
    public String CreatedById;
    public DateTime CreatedDate;
    public Boolean IsDeleted;
    public ToolingAPIWSDL.User_x LastModifiedBy;
    public String LastModifiedById;
    public DateTime LastModifiedDate;
    public Integer NumLinesCovered;
    public Integer NumLinesUncovered;
    public DateTime SystemModstamp;
    public String[] fieldsToNull;
    public String Id;
    private String[] ApexClassOrTrigger_type_info = new String[]{'ApexClassOrTrigger','urn:tooling.soap.sforce.com',null,'0','1','true'};
    private String[] ApexClassOrTriggerId_type_info = new String[]{'ApexClassOrTriggerId','urn:tooling.soap.sforce.com',null,'0','1','true'};
    private String[] Coverage_type_info = new String[]{'Coverage','urn:tooling.soap.sforce.com',null,'0','1','true'};
    private String[] CoverageLastModifiedDate_type_info = new String[]{'CoverageLastModifiedDate','urn:tooling.soap.sforce.com',null,'0','1','true'};
    private String[] CreatedBy_type_info = new String[]{'CreatedBy','urn:tooling.soap.sforce.com',null,'0','1','true'};
    private String[] CreatedById_type_info = new String[]{'CreatedById','urn:tooling.soap.sforce.com',null,'0','1','true'};
    private String[] CreatedDate_type_info = new String[]{'CreatedDate','urn:tooling.soap.sforce.com',null,'0','1','true'};
    private String[] IsDeleted_type_info = new String[]{'IsDeleted','urn:tooling.soap.sforce.com',null,'0','1','true'};
    private String[] LastModifiedBy_type_info = new String[]{'LastModifiedBy','urn:tooling.soap.sforce.com',null,'0','1','true'};
    private String[] LastModifiedById_type_info = new String[]{'LastModifiedById','urn:tooling.soap.sforce.com',null,'0','1','true'};
    private String[] LastModifiedDate_type_info = new String[]{'LastModifiedDate','urn:tooling.soap.sforce.com',null,'0','1','true'};
    private String[] NumLinesCovered_type_info = new String[]{'NumLinesCovered','urn:tooling.soap.sforce.com',null,'0','1','true'};
    private String[] NumLinesUncovered_type_info = new String[]{'NumLinesUncovered','urn:tooling.soap.sforce.com',null,'0','1','true'};
    private String[] SystemModstamp_type_info = new String[]{'SystemModstamp','urn:tooling.soap.sforce.com',null,'0','1','true'};
    private String[] fieldsToNull_type_info = new String[]{'fieldsToNull','urn:tooling.soap.sforce.com',null,'0','-1','true'};
    private String[] Id_type_info = new String[]{'Id','urn:tooling.soap.sforce.com',null,'1','1','true'};
    private String[] apex_schema_type_info = new String[]{'urn:tooling.soap.sforce.com','true','false'};
    private String[] field_order_type_info = new String[]{'ApexClassOrTrigger','ApexClassOrTriggerId','Coverage','CoverageLastModifiedDate','CreatedBy','CreatedById','CreatedDate','IsDeleted','LastModifiedBy','LastModifiedById','LastModifiedDate','NumLinesCovered','NumLinesUncovered','SystemModstamp','fieldsToNull','Id'};
}

Here's a snippet from the sobject_x class:

public virtual class sObject_x {
    public String[] fieldsToNull;
    public String Id;
    ...}

(Note that the sObject_x class has declared all of the variables in ApexCodeCoverageAggregate, in addition to several other member variables)

Lastly, here's an example of where the exception happens:

    ToolingAPIWSDL.QueryResult qr = toolingApi.query('Select ApexClassOrTriggerId,NumLinesCovered,NumLinesUncovered From ApexCodeCoverageAggregate Order By NumLinesUncovered Desc');


    Map<Id,CodeCoverageWrapper> wrapperMap = new Map<Id,CodeCoverageWrapper>();
    for(ToolingAPIWSDL.sObject_x ags : qr.records){
        //Exception happens at the line below.
        ToolingAPIWSDL.ApexCodeCoverageAggregate ag = (ToolingAPIWSDL.ApexCodeCoverageAggregate)ags;
        coveredLines += (ag.numLinesCovered != null) ? ag.numLinesCovered : 0;
        uncoveredLines += (ag.numLinesUncovered !=  null) ? ag.numLinesUncovered : 0;
        CodeCoverageWrapper w = new CodeCoverageWrapper(ag);
        wrapperMap.put(ag.ApexClassOrTriggerId,w);
        this.coverageList.add(w);
    }

Question is, how would I adjust the structure above to properly support inheritance, and make it work nicely with the Webservice.invoke callout that's part of the WSDL2Apex functionality?

1

The WebService.invoke instantiates the virtual class instead of the concrete class. Hence, it cannot be cast to the concrete class without some JSON serialization magic. Here is how I did it, although it's pricey:

public ToolingAPIWSDL.QueryResult query(String queryString,String className) {
    ToolingAPIWSDL.QueryResult result = service.query(queryString);
    result.records = (List<ToolingAPIWSDL.sObject_x>)Json.deserialize(JSON.serialize(result.records),Type.forName(className));
    return result;
}
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.