0

Process_data is called via trigger. This code is working with the exception of when I do the actuall http callout I get the Please commit or rollback before callout out.

Based on similar post the issue seems to be saying that because I am doing a get_data within the callout (since it is doing a read aka select) it is the root cause of the error.

What I am trying to do is after the object is inserted or updated and handled on trigger to call the process data which is working as expected. I check to make sure what environment the code is executing in and set the named_credential I intend to use.

After this check I want to query (select) for the contact data columns I want to process in a for loop where I populate a data strucuture and then serialize it before doing my final endpoint settings and http callout where I encounter the error.

How can I change the code so it will still accomplish what I am trying to do and not get the error.

public class ws_mdm_contact
{    
    static string Environment = GLOBAL.getEnvironment();
    static string Named_Credential;
    static string EndPoint;
    static string JSON_Payload;
    static string outcomeMsg;
    static string thisClass = 'ws_mdm_contact';
    static List<Contact> lstContact;

    public static List<Contact> get_data(Set<ID> ids)
    {
        List<Contact> lstContact = Helper_MDM.get_Contact(ids);
        return lstContact;
    }

    @future(callout=true)    
    Public static void process_data(Set<ID> ids)
    {
        if (Environment == GLOBAL.ENVIRONMENT_PRODUCTION) 
        {
            Named_Credential = GLOBAL.namedCred_Prd;
        }
        else if (Environment == GLOBAL.ENVIRONMENT_TRAIN)
        {
            Named_Credential = GLOBAL.namedCred_Train;
        }
        else if (Environment == GLOBAL.ENVIRONMENT_STAGE)
        {
            Named_Credential = GLOBAL.namedCred_Stage;
        }
        else if (Environment == GLOBAL.ENVIRONMENT_DEV)
        {
            Named_Credential = GLOBAL.namedCred_Fake;
        }
        else
        {
            return;
        }

        lstContact = get_data(ids);

        for (Contact Contact_Row : lstContact)
        {
            if (Contact_Row.Recordtype.DeveloperName == GLOBAL.CONTACT_RECORDTYPE_CONTACT_MANAGEMENT) 
            {
                DataDef_MDM.Contact Contact_Record = New DataDef_MDM.Contact();

                Contact_Record.id = Contact_Row.Id;
                Contact_Record.firstName = Contact_Row.FirstName;

                JSON_Payload = JSON.serializepretty ( Contact_Record );

                EndPoint = Named_Credential;
                EndPoint += '/api/contact/';
                EndPoint += Contact_Row.Id;

                EmailManager.sendMail(GLOBAL.EMAIL_DARYN, thisClass + ' > Endpoint: ' + EndPoint + ' > JSON (MDM): ' , JSON_Payload);

                outcomeMsg = WS_HTTP.Callout(EndPoint, 'PUT', JSON_Payload);
                EmailManager.sendMail(GLOBAL.EMAIL_DARYN, thisClass + ' > outcome message', outcomeMsg);            
            }
            else
            {
                continue;
            }
         }
    }
}
Derek F
  • 61,401
  • 15
  • 50
  • 97
Daryn
  • 251
  • 1
  • 6
  • 16
  • can you post your sample code. – Santanu Boral Jul 24 '18 at 18:19
  • sorry about the code edit. Apparently I don't quite have the hang of posting code. – Daryn Jul 24 '18 at 19:09
  • @Daryn use the {} button, or press Ctrl/Cmd-K to format code. – sfdcfox Jul 24 '18 at 19:22
  • I did see that post prior to posting. I will take a deeper look to see if I can discern anything I did not see before. If not, I will try to include more code in what is going on. I was trying to keep it small and generic vs posting all of the actual code. – Daryn Jul 25 '18 at 01:59
  • 1
    So you have the callout in a loop. Try it doing it ONE time only. I think the problem may be the send email part of your code message and then the second callout in the next cycle of the for loop..... – Eric Jul 25 '18 at 13:24
  • 1
    @Eric Wow your intuition was right on. It was the EmailManager that was causing the issue. The code works fine once I made that adjustment. I never suspected it would be the cause. – Daryn Jul 25 '18 at 13:50
  • The error message is the same, but this is a different question than the one this is marked as a duplicate of (there is no explicit DML here). Voting to re-open. – Derek F Jul 25 '18 at 14:09

1 Answers1

1

The issue is that you are sending an email message after the callout and this whole process is within a for loop.

The first callout most likely succeeds but subsequent callouts will fail due to the Uncommitted work pending error.

You will need to refactor to send the emails after all callouts have been made

Eric
  • 54,152
  • 11
  • 100
  • 195