function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Swamy P R NSwamy P R N 

how to seperate transactions for " callouts " and " DMl's "

Hello Everyone,

While doing callout getting the error :: 
System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out .

Actually i am sending request to 3rd party system based on the response iam upserting records in salesforce.
When i was doing with 1 record, it is working fine. But when i tried with bulkified manner getting the above error.

So while research i got an idea that i need to seperate the transactions for both the Callout's and DML's.
Is there any function or method that callout has been done, with that i can seperate both the transactions for DML's in salesforce and Callouts

How can i avoid this particular error??  Please suggest me !!!
Thiyagarajan Selvaraj (SFDC Developer)Thiyagarajan Selvaraj (SFDC Developer)
Hi Swamy,

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. Use dml in the future methods. 
Surya KiranSurya Kiran
Hi Swamy,

We can avoid it in two different approches.
1. First do that callout, then perform the DML 
2. As Selvaraj said do the DML and use the @futue method to perform the callout
Swamy P R NSwamy P R N
Hello Thiyagarajan Selvaraj, Surya Kiran
Thanks for your updates!!

With your suggestion used @future infront of the DML operations method. like::

After sending the callout below method we are using for parsing.
@future
public static void parseTest(){
        DOM.Document doc = new DOM.Document();      
          try {
          System.debug('&&&&='+resbody);
            doc.load(resbody);    -->> In resbody, getting the response
            DOM.XMLNode root = doc.getRootElement();
            parseNodes(root);
            //System.debug('!!after parse='+newData);
          } catch (System.XMLException e) {  // invalid XML
            System.debug('!!eroor='+e.getMessage());
          }
          //return null;
    } 
@future
    public static void parseNodes(DOM.XMLNode node) {
    
           string result = '\n';
          //System.debug('node type='+node.getNodeType());
          if (node.getNodeType() == DOM.XMLNodeType.COMMENT) {
            return 'Comment (' +  node.getText() + ')';
          }
in this method DML's are there
etc.........................

Now iam facing the error  unsupported parameter type dom.xmlnode. How can i pass this variable???
Thiyagarajan Selvaraj (SFDC Developer)Thiyagarajan Selvaraj (SFDC Developer)
Hi Swamy,

In future methods,  parameters must be primitive data types, arrays of primitive data types, or collections of primitive data types. Covert your xml to apex class structure and pass it to a future method as a string. 

Try this approach : https://developer.salesforce.com/blogs/developer-relations/2013/06/passing-objects-to-future-annotated-methods.html

 
prithvi kumarprithvi kumar
You can make callout and dml different transactions

public static testmethod void getTest() {

Test.setMock(HttpCalloutMock.class, new MockHttpResponseGeneratorApiTest());
system.runAs(usr1)
{
Test.startTest();
ProductOff.getTesting1('docId');
Test.stopTest();
}
}

--------------------------------------------------------------------------------------------------------------------------
public static testmethod void getTest() {

Test.setMock(HttpCalloutMock.class, new MockHttpResponseGeneratorApiTest());
system.runAs(usr1)
{
Test.startTest();
ProductOff.getTesting2('docId');
Test.stopTest();
}
}


This should resolve your issue.

Thanks