0

I have a batch process that I am using to send SMS notifications. In the execute method, I am making the callout, creating a log record and then updating scope. When I try to update scope, the record is not updated and the log record fails. If I run without updating scope, log is created as desired. My problem is that I need the scope records to up date to show that a message was sent. I've tried various patterns, but here is the basic outline:

Global class Messagebatch implements Database.batchable<sObject>,
Database.stateful,Database.allowscallouts{

global Database.QueryLocator start(Database.BatchableContext bc) {
    return Database.getQueryLocator(
        'SELECT ID,firstname,lastname,cellphone__c,phone,needs_sms__c FROM Account WHERE needs_sms__c = true LIMIT 25');
}

global void execute(Database.BatchableContext BC, List<Account> scope){

 //list to hold logs to be inserted after loop
 list<messagelog__c>messagelist= new list<messagelog__c>();

     for (Account acc : scope) {
         acc.needs_sms__c=false;

     //class to send message here called here
     //after message sent, create a record
     messagelog__c log = new messagelog__c();

     //fill object with response data and add to list for insert
     messagelist.add(log);

    }//end of loop
    insert messagelist;
    update scope;

}//end of execute method

My problem is that when I update scope, the message logs are not created AND scope is not updated. When I remove the "update scope;" line, message records are created correctly. I tried to call another batch in the finish method to do the update, but was not successful with this approach. My end goal here is to simply uncheck the "needs_sms__c" check box to stop a duplicate message from being sent. The messages are sent successfully each time, but I need a way to update the record after a message has been sent. Any suggestions are appreciated. Thank you!

2
  • Do you have a lookup from your log object to Account?
    – Adrian Larson
    Jan 26, 2017 at 2:03
  • Yes, i have a lookup on the message log object looking at Account. I fill the value after the message is sent. "log.client__c = acc.id" and then added to the messagelist for insert.
    – JoshuaWS
    Jan 26, 2017 at 2:28

2 Answers 2

1

Go with following approach:

global void execute(Database.BatchableContext BC, List<Account> scope){

 //list to hold logs to be inserted after loop
 list<messagelog__c>messagelist= new list<messagelog__c>();

     for (Account acc : scope) {
         acc.needs_sms__c=false;

     //class to send message here called here
     //after message sent, create a record
     messagelog__c log = new messagelog__c();

     //fill object with response data and add to list for insert
     messagelist.add(log);

    }//end of loop
    try
    {
        insert messagelist;
    }
    catch(Exception ex {
         System.debug(' => messageList '+ex.getMessage());
    }

    try
    {
        update scope;
    }
    catch(Exception ex {
         System.debug(' => scope '+ex.getMessage());
    }
}//en

Try catch are added for investigation purpose if any of the system.debug is printed so, you have found the reason why you could n't update. My doubt is there is some issue in your DML statement.

1

One option here is to simply query for only Account records which have no child MessageLog__c.

public Database.QueryLocator start(Database.BatchableContext context)
{
    return Database.getQueryLocator([
        SELECT ... FROM Account WHERE Needs_SMS__c = true AND Id NOT IN (
            SELECT Client__c FROM MessageLog__c
        )
    ]);
}

You must log in to answer this question.

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