2

After reading the information around the issue Call error: System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out I tryed everything, like moving my WriteLog funcion outside the main function and it didn't worked.

I'm doing the next logical steps:

  • Create List
  • Save the response into ApiLogs__c using WriteLog
  • Call from my Main class the next method with is ImportSubscribers, which uses the ID that CreateList returned
  • Import subscribers also needs to save the HTTP Response to my ApiLogs__c

I asume that the last step, as the Doc says cannot be performed, since I cannot do an insert after a HTTP Callout.

Which is the workaround for this? Since I moved the ApiLogs__c DML insert out to another Method and it didn't worked.

public String createList(String listName){

    HttpRequest request = new HttpRequest();
    HttpResponse response = null;
    Http http = new Http();

    // Set the endpoint
    request.setEndpoint(DopplerServiceUtil.urlBuilder('createList'));
    request.setHeader('Authorization', 'token ' + DopplerServiceUtil.apiKeyBuilder());
    request.setHeader('content-type', 'application/json; charset=utf-8;');
    request.setMethod('POST');
    request.setTimeout(60000);
    request.setCompressed(false);

    // Calling Serializer to get createList JSON for setBody
    String listNameJSON = DopplerJSONSerializer.createListJSON(listName);

    // Set the httpRequest body
    request.setBody(listNameJSON); // The listId comes @response as 'createdResourceId'

    try {
        // Debugging all the requested data
        System.debug('Request is: ' + request);

        // Fireing the HttpRequest
        response = http.send(request);
        if(response != null) {
            System.debug('Response is: ' + response.getBody());
            System.debug('Connection statusCode: ' + response.getStatusCode() + ' - Connection status: ' +
                    response.getStatus());

            //DopplerJSON2Apex dopplerJSON2Apex = new DopplerJSON2Apex();
            if (String.valueOf(response.getStatusCode()).startsWith('2')) {
                DopplerJSON2Apex jsonparser = DopplerJSON2Apex.parse(response.getBody());
                createdListId = jsonparser.createdResourceId;
                messageResponse = jsonparser.message;

                LogCreatedList(createdListId,messageResponse,null,null,request.getMethod(),
                        request.getEndpoint(),request.getBody(),response.getBody(),response.getStatusCode());

                return createdListId;

            } else if (String.valueOf(response.getStatusCode()).startsWith('4')) {
                DopplerJSON2Apex jsonparser = DopplerJSON2Apex.parse(response.getBody());
                titleResponse = jsonparser.title;
                detailResponse = jsonparser.detail;

                LogCreatedList(null,null,titleResponse,detailResponse,request.getMethod(),
                        request.getEndpoint(),request.getBody(),response.getBody(),response.getStatusCode());

                return 'list-404';
            }
        }

    } catch (System.CalloutException e) {
        System.debug('Call error: ' + e);
        return 'list-error';
    }
    return 'list-error';
}
@future
public static void LogCreatedList(String logCreatedListId,String logMessageResponse, String logTitleResponse,
                                  String logDetailResponse, String logReqMethod, String logReqGetEndpoing,
                                  String logReqGetBody, String logResGetBody, Integer logResGetStatusCode){
    // ApiLog is outside the try-catch to avoid DML uncommited error on Callout.
    // Successful Status Code 200/201/202/404
    if(logCreatedListId != null && logTitleResponse == null) {
        // **** ApiLog__c ****
        DopplerApiLogs.WriteLog(logReqMethod, logReqGetEndpoing, 'Create List', logMessageResponse,
                logCreatedListId, logReqGetBody, logResGetBody, logResGetStatusCode);
        // *** End of ApiLog__c **
        // Error Status Code 400/401/402
    } else if (logCreatedListId == null && logTitleResponse != null){
        String JSONErrorStatus = logTitleResponse + ' - ' + logDetailResponse;
        // **** ApiLog__c ****
        DopplerApiLogs.WriteLog(logReqMethod, logReqGetEndpoing, 'Create List',
                JSONErrorStatus,'', logReqGetBody, logResGetBody, logResGetStatusCode);
        // *** End of ApiLog__c **
    }
}

public String upsertSubscribers (Id subscribersListId, String dopplerListId) {

    HttpRequest request = new HttpRequest();
    HttpResponse response = null;
    Http http = new Http();

    // Get subscribersList using the SF subscribersListId
    DopplerServiceUtil SubsList = new DopplerServiceUtil();
    List<DopplerServiceUtil.SubsInfo> subscribersList =  SubsList.getSubscribers(subscribersListId);
    System.debug('subscribersList: ' + subscribersList);

    // Set the endpoint url
    request.setEndpoint(DopplerServiceUtil.urlBuilder('upsertSubscribers',dopplerListId));
    request.setHeader('Authorization', 'token ' + DopplerServiceUtil.apiKeyBuilder());
    request.setHeader('content-type', 'application/json; charset=utf-8;');
    request.setMethod('POST');
    request.setCompressed(false);
    request.setTimeout(60000);
    // Calling Serializer to get createList JSON for setBody
    String suscWrapperJSON = DopplerJSONSerializer.upsertSubscribersJSON(subscribersList,DopplerServiceUtil.urlBuilder('apiCallback'));
    // Set the httpRequest body
    request.setBody(suscWrapperJSON); // The created or inserted comes @response as 'createdResourceId'

    try {
        // Debugging all the requested data
        System.debug('Request is: ' + request);

        // Fireing the HttpRequest
        response = http.send(request);
        if(response != null) {
            System.debug('Response is: ' + response.getBody());

            System.debug('Connection status: ' + response.getStatus());
            System.debug('Connection statusCode: ' + response.getStatusCode());

            if(String.valueOf(response.getStatusCode()).startsWith('2')){
                DopplerJSON2Apex jsonparser = DopplerJSON2Apex.parse(response.getBody());

                createdImportId = jsonparser.createdResourceId;
                messageResponse = jsonparser.message;


                LogImportSubscribers(createdImportId,messageResponse,null,null,request.getMethod(),
                        request.getEndpoint(),request.getBody(),response.getBody(),response.getStatusCode());

                return createdImportId;

            } else if(String.valueOf(response.getStatusCode()).startsWith('4')) {
                DopplerJSON2Apex jsonparser = DopplerJSON2Apex.parse(response.getBody());

                titleResponse = jsonparser.title;
                detailResponse = jsonparser.detail;

                LogImportSubscribers(null,null,titleResponse,detailResponse,request.getMethod(),
                        request.getEndpoint(),request.getBody(),response.getBody(),response.getStatusCode());

                return 'import-404';
            }
        }

    } catch (System.CalloutException e) {
        System.debug('Call error: ' + e);
    }

    return 'import-error';
}


@future
public static void LogImportSubscribers(String logCreatedImportId,String logMessageResponse, String logTitleResponse,
                                  String logDetailResponse, String logReqMethod, String logReqGetEndpoing,
                                  String logReqGetBody, String logResGetBody, Integer logResGetStatusCode){
    // ApiLog is outside the try-catch to avoid DML uncommited error on Callout.
    // Successful Status Code 200/201/202/404
    if(logCreatedImportId != null && logTitleResponse == null) {
        // **** ApiLog__c ****
        DopplerApiLogs.WriteLog(logReqMethod, logReqGetEndpoing, 'Import Subscribers', logMessageResponse,
                logCreatedImportId, logReqGetBody, logResGetBody, logResGetStatusCode);
        // *** End of ApiLog__c **
        // Error Status Code 400/401/402
    } else if (logCreatedImportId == null && logTitleResponse != null){
        String JSONErrorStatus = logTitleResponse + ' - ' + logDetailResponse;
        // **** ApiLog__c ****
        DopplerApiLogs.WriteLog(logReqMethod, logReqGetEndpoing, 'Import Subscribers',
                JSONErrorStatus,'', logReqGetBody, logResGetBody, logResGetStatusCode);
        // *** End of ApiLog__c **
    }
}

And I'm calling this Methods from:

    public class DopplerApiService {

    private static String dopplerListId {get;set;}
    private static String dopplerImportId {get;set;}

    public static String SendList(Id ListId) {

        ApiInterface AI;
        AI = new DopplerService();

        // Get the listName using the received ListId
        String listName = DopplerServiceUtil.getListName(ListId);

        // Call the createList method with the retreived listName;
        try {
            System.debug('listName: ' + listName);
            if(listName != null) {
                dopplerListId = AI.createList(listName);
                System.debug('dopplerListId: ' + dopplerListId);

                //if(dopplerListId != null && dopplerListId != 'list-404' && dopplerListId != 'list-error') {
                    PopulateList(ListId, dopplerListId);
                //}
            } else {
                dopplerListId = null;
                System.debug('dopplerListId: ' + dopplerListId);
            }
        } catch (System.CalloutException e) {
            System.debug('Call error: ' + e);
        }

        return null;
    }
    // @Future annotation is not working here since I get CPU Apex limits error
    public static void PopulateList(Id ListId, String DopplerListName){

        ApiInterface AI;
        AI = new DopplerService();
        // Call the createList method with the retreived listName;
        try {
            if(ListId != null && DopplerListName != null) {
                dopplerImportId = AI.upsertSubscribers(ListId, DopplerListName);
                System.debug('dopplerImportId: ' + dopplerImportId);
            } else {
                dopplerImportId = null;
                System.debug('dopplerImportId: ' + dopplerImportId);
            }

        } catch (System.CalloutException e) {
            System.debug('Call error: ' + e);
        }
    }
}

It executes the CreateList, saves CreateList log, gets the createList id return, fires the upsertSubscriber function, but inside it, it hangs on the HTTP response = http.send(request);

2

Your assumption:

I asume that the last step, as the Doc says cannot be performed, since I cannot do an insert after a HTTP Callout.

is not correct

You can do a dml after the callout just not before.

So after your callout it is perfectly fine to perform DML. If you are making several callouts, store the results in a collection and write them after all callouts are made.

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.