1

I am trying to populate the SymbolTable for a specific class (currentClass) by following this question's solution Trying to get SymbolTable of an Apex class and get null

Here's what I have so far

public class testController {

    public JsonTest containerResponse {get;set;}
    public JsonTest classMemberJson {get;set;}
    public JsonTest containerAsyncJson {get;set;}
    public Boolean pollClassMember {get;set;}
    JsonGET currentClass {get;set;}

    public testController(){

        System.Debug('****************************** Constructor initialized!');
        containerResponse = new JsonTest();

        //pre-Step 1
        pollCurrentClass();

        //Step 1 - Create MetadataContainer
        containerResponse = createMetadataContainer();

        //Step 2 - Create ApexClassMember
        createApexClassMember();

        //Step 3 - Create ContainerAsyncRequest
        createContainerAsyncRequest();

    }

    public void pollCurrentClass(){

        //Request
        HttpRequest apexClassRequest = new HttpRequest();
        apexClassRequest.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionID());
        apexClassRequest.setHeader('Content-Type', 'application/json');
        apexClassRequest.setEndpoint('https://instance.salesforce.com/services/data/v36.0/tooling/sobjects/ApexClass/{currentClassId}');
        apexClassRequest.setMethod('GET');

        //Response
        Http httpResponse = new Http();
        HttpResponse apexClassResponse = httpResponse.send(apexClassRequest);
        System.Debug('**************************** ApexClass Poll Response: ' + apexClassResponse.getBody());
        currentClass = new JsonGET();
        currentClass = (JsonGET)JSON.Deserialize(apexClassResponse.getBody(),JsonGET.class);
        System.Debug('**************************** Body of the class: ' + currentClass.body);
    }

    public JsonTest createMetadataContainer(){

        //Request
        HttpRequest containerRequest = buildHttpRequest('https://instance.salesforce.com/services/data/v36.0/tooling/sobjects/MetadataContainer/', 'POST');
        containerRequest.setBody('{"Name":"TestContainer"}');

        //Response
        HttpResponse containerResponse = buildHttpResponse(containerRequest);

        System.Debug('**************************** Metadata Container Response: ' + containerResponse.getBody());
        return (JsonTest)JSON.Deserialize(containerResponse.getBody(), JsonTest.class);
    }

    public void createApexClassMember(){
        //Request
        HttpRequest apexClassRequest = buildHttpRequest('https://instance.salesforce.com/services/data/v36.0/tooling/sobjects/ApexClassMember/', 'POST');
        apexClassRequest.setBody('{"ContentEntityId": "{currentClassId}", "MetadataContainerId": "'+ containerResponse.id +'", "Body" : "' + currentClass.body + '"}');

        //Response
        HttpResponse apexClassResponse = buildHttpResponse(apexClassRequest);

        System.Debug('**************************** ApexClassMember Response: ' + apexClassResponse.getBody());
    }

    public void createContainerAsyncRequest(){
        //Request
        HttpRequest containerAsyncRequest = buildHttpRequest('https://instance.salesforce.com/services/data/v36.0/tooling/sobjects/ContainerAsyncRequest/', 'POST');
        containerAsyncRequest.setBody('{"IsCheckOnly": true, "MetadataContainerId": "'+ containerResponse.id +'"}');

        //Response
        HttpResponse containerAsyncResponse = buildHttpResponse(containerAsyncRequest);

        System.Debug('**************************** ContainerAsync Response: ' + containerAsyncResponse.getBody());
        containerAsyncJson = (JsonTest)JSON.Deserialize(containerAsyncResponse.getBody(), JsonTest.class);
    }

    //Used as Step - 4
    public void pollContainerAsyncRequest(){
        //Request
        HttpRequest pollAsyncRequest = buildHttpRequest('https://instance.salesforce.com/services/data/v36.0/tooling/sobjects/ContainerAsyncRequest/' + containerAsyncJson.id, 'GET');

        //Response
        HttpResponse pollAsyncResponse = buildHttpResponse(pollAsyncRequest);

        System.Debug('**************************** ContainerAsyncRequest Response: ' + pollAsyncResponse.getBody());
    }

    //Used as Step - 5
    public void pollApexClassMember(){
        //Build Request
        HttpRequest apexClassMemberRequest = buildHttpRequest('https://instance.salesforce.com/services/data/v36.0/tooling/sobjects/ApexClassMember/' + classMemberJson.id, 'GET');

        //Response
        HttpResponse apexClassMemberResponse = buildHttpResponse(apexClassMemberRequest);

        System.Debug('**************************** ApexClassMember Response: ' + apexClassMemberResponse.getBody());
    }

    public HttpRequest buildHttpRequest(String endpoint, String method){
        HttpRequest request = new HttpRequest();
        request.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionID());
        request.setHeader('Content-Type', 'application/json');
        request.setEndpoint(endpoint);
        request.setMethod(method);
        return request;
    }

    public HttpResponse buildHttpResponse(HttpRequest sendRequest){
        Http poll = new Http();
        HttpResponse pollResponse = poll.send(sendRequest);
        return pollResponse;
    }

    public class JsonTest{
        Public String Id{get;set;}
    }

    Public class JsonGET {
        public String body {get;set;}
    }
}

Within "createApexClassMember" if I use

apexClassRequest.setBody('{"ContentEntityId": "{currentClassId}", "MetadataContainerId": "'+ containerResponse.id +'", "Body" : "' + currentClass.body + '"}');

I'm getting the following error in the Debug Log:

DEBUG|**************************** ApexClassMember Response: [{"message":"Cannot deserialize instance of textarea from VALUE_STRING value at [line:1, column:199]","errorCode":"JSON_PARSER_ERROR"}]

However, if I use

apexClassRequest.setBody('{"ContentEntityId": "{currentClassId}", "MetadataContainerId": "'+ containerResponse.id +'", "Body" : "' + JSON.serialize(currentClass.body) + '"}');

I'm getting the following error in the Debug Log:

DEBUG|**************************** ApexClassMember Response: [{"message":"Unexpected character ('/' (code 47)): maybe a (non-standard) comment? (not recognized as one since Feature 'ALLOW_COMMENTS' not enabled for parser) at [line:1, column:100]","errorCode":"JSON_PARSER_ERROR"}]

Any help/pointers would be greatly appreciated.

Thank you!

3

You shouldn't be hand-building your JSON. Doing so is asking for all sorts of trouble (as you've noticed). Instead, allow the system to build it for you:

Map<String, Object> payload = new Map<String, Object> {
'ContentEntityId' => '{currentClassId}',
'MetadataContainerId' => containerResponse.id,
'Body' => currentClass.Body
};
String jsonBody = JSON.serialize(payload);

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.