22

I have same exception can please Click Here The previous post issue is resolved.

Exception: :System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out

Visualforce Page

<apex:page controller="Controller" action="{!init}" showHeader="false" sidebar="false">
    <center>
        <apex:pageBlock title="Request Listener"></apex:pageBlock>          
    </center>
</apex:page>

Controller :

PUBLIC with sharing class Controller
{   
    PUBLIC String fromNumber      = ApexPages.currentPage().getParameters().get('From');
    PUBLIC String toNumber        = ApexPages.currentPage().getParameters().get('To');
    PUBLIC String body            = ApexPages.currentPage().getParameters().get('Body');   
    PUBLIC PageReference init()
    {           
        System.debug('From Phone Number :' +fromNumber);
        System.debug('To phone NUmber :' + toNumber);
        System.debug('Message Body :' + body);

        TwilioRestClient Client = TwilioAPI.getDefaultClient();                                                   
            SYSTEM.DEBUG('FROM AND To  Number is NOT NULL');         
            String formattedNumber='+919876543210';    
            IF(body != NULL)
                body = body;
            ELSE
                body = '';
            Case c = NEW Case (Subject = formattedNumber,Description = body,Origin = 'Phone');
            INSERT c;                 

            Map<String,String> params1 = new Map<String,String>
            {
               'To'   => fromNumber,
               'From' => '+1908280****',
               'Body' => 'Conformation to customer'
            };
            TwilioMessage message = client.getAccount().getMessages().create(params1); /* Valid conformation SMS sent to the Customer.*/                                   
        return null ;
    }
}

While loin as admin then click preview on visualforce page executed but case is not created.I have checked the the debug log it throw the exception.

2
  • 1
    Before making a callout ensure you do not have any insert/update/delete DML statements. Try to make the callout in a separate context say @future.
    – Bforce
    Jun 24, 2014 at 16:06
  • I have added the code above where I should add the @future annotation in my code Jun 25, 2014 at 5:21

2 Answers 2

20

You're trying to insert a new case record and then make the call out — the case is your uncommitted work in this instance.

You should insert the case, and then call a new method which contains the rest of the code for the callout, and mark that with the @future annotation, something like this:

public PageReference init()
{           
    System.debug('From Phone Number :' +fromNumber);
    System.debug('To phone NUmber :' + toNumber);
    System.debug('Message Body :' + body);                                              
    System.debug('FROM AND To  Number is NOT NULL');

    String formattedNumber='+919876543210';    
    if(body != NULL)
        body = body;
    else
        body = '';
    Case c = NEW Case (Subject = formattedNumber,Description = body,Origin = 'Phone');
    insert c;                 

    Map<String,String> params1 = new Map<String,String>
    {
       'To'   => fromNumber,
       'From' => '+1908280****',
       'Body' => 'Conformation to customer'
    };

    DoCallout(params);

    return null ;
}

@future(callout=true)
private static void DoCallout(Map<String, String> params)
{
    TwilioRestClient Client = TwilioAPI.getDefaultClient();

    TwilioMessage message = Client.getAccount().getMessages().create(params);
    // Valid conformation SMS sent to the Customer.                                   
}

Also, you're doing all of this from the page init method — you really shouldn't do DML operations on page load as that's open to abuse and would fail security review if you were submitting this to the AppExchange. It's much better to have the user confirm they want to perform the action using a button on the page or similar.

4
  • aren't future methods supposed to be static? I mean the DoCallOut Method should be static.
    – sfdcFanBoy
    Oct 6, 2015 at 2:48
  • 1
    And also, is should be @future(callout=true)
    – sfdcFanBoy
    Oct 6, 2015 at 3:03
  • @sfdcFanBoy Good catch!
    – Matt Lacey
    Oct 6, 2015 at 3:36
  • One note for future readers, if also doing this from a page level action, you can also redirect the page prior to making the call out, not by returning null but creating a new page reference and redirect=true. Doing so will tell the db to commit changes made - even if the new page reference redirects to the same page with some new parameters in the url.
    – Ronnie
    Sep 12, 2017 at 2:09
8

One of the main reason of this exception is that you are doing some CRUD operation (create,read,update,delete) in your code in same context of running code, means you are doing some DML operation and then doing call out in single run.

You have to break thread with @future annotation.

1
  • Hi,@regalforce I added my code can please tell me where I should I add the @future annotation. Jun 25, 2014 at 5:45

You must log in to answer this question.

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