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!

  • Do you have a lookup from your log object to Account? – Adrian Larson Jan 26 '17 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 '17 at 2:28
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.

| improve this answer | |
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
        )
    ]);
}
| improve this answer | |

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.