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!

1 Answer 1

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);

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .