+ Start a Discussion
RDSSRDSS 

Batch class for sending SMSs is failing at insert operation

Hi,
I have written a batch class for sending SMSs using SMS Magic.
Everything seems fine but it is failing while insertion.
Please help.
Below is the batch class.

Global class BatchSmsAfterSevenDaysOFDisburmentEFS implements Database.Batchable<sObject>
{
    Public date varDate = date.today();
    Public string str = 'Disbursed';
    list<smagicinteract__smsMagic__c> lstSmsMagic = new list<smagicinteract__smsMagic__c>();
    smagicinteract__smsMagic__c objSmsMagic = new smagicinteract__smsMagic__c();
    string Query = 'Select Id, Client_Name_EFS__c, Actual_Disbursement_date__c,(Select id, Account.phone, Account.Name from opportunities__r) from Application__c where Application_Status__c =\'' + str + '\'';
    global Database.QueryLocator start(Database.batchableContext bc)
    {
        system.debug('inside start');
        return database.getQueryLocator(Query);
    }
    
    global void execute(Database.batchableContext bc, list<Application__c> scope)
    {    
        system.debug('inside Execute start' + scope);
        for(Application__c ObjApplication : scope)
        {
            system.debug('@@@@@@@@@@@ inside application for loop');
            //objSmsMagic.smagicinteract__Name__c = ObjApplication.Client_Name_EFS__c;
            if(ObjApplication.Actual_Disbursement_date__c.daysbetween(varDate) == 7)
            {
                system.debug('@@@@@@@@ date checking');
                for(opportunity objOpp : ObjApplication.opportunities__r )
                {
                    system.debug('@@@@@@@@ inside opportunity for loop');
                      If(objOpp.Account.Phone.length() == 10 || objOpp.Account.Phone.isNumeric())
                      {
                        System.Debug('^^^^^Inside IFF^^^^^ ');
                        objSmsMagic.smagicinteract__Name__c = objOpp.Account.Name;
                        objSmsMagic.smagicinteract__PhoneNumber__c=objOpp.Account.Phone;
                        objSmsMagic.smagicinteract__SenderId__c='Transactional';
                        objSmsMagic.smagicinteract__external_field__c = smagicinteract.ApexAPI.generateUniqueKey();
                        objSmsMagic.smagicinteract__SMSText__c= LoanMessageBasedOnApplicationStatus.AfterSevenDaysofDisbursmentMessage;
                        lstSmsMagic.add(objSmsMagic);
                        system.debug('>>> >>> Inside for Second loop ' + lstSmsMagic);
                      }     
                }  
            }    
        }
        try
        {    
            if(lstSmsMagic.size()> 0)
            {
                system.debug('@@@@@@@@ before sending' + lstSmsMagic.size() + ' and  ' + lstSmsMagic);
                Database.insert(lstSmsMagic, false);
                system.debug('@@@@@@@@ after sending');
            }
        }
        catch(DmlException e)
        {
             system.debug('********++++++++++*******'+e.getMessage());            
        }
    }
    
    
    global void finish(Database.batchableContext bc)
    {
    }
}


 
Alain CabonAlain Cabon
Hello,

"failing while insertion" with what error?  

Alain
RDSSRDSS
Hi Alain,

There is no error. but in debug logs, i have checked that number of insert statement execution is 0. Also the "system.debug('@@@@@@@@ after sending');" is not printing in the debug log. Before database.insert statement, everything is captured in debug logs.

Thanks
Raman
Alain CabonAlain Cabon

Could you replace this part:
 
try
        {    
            if(lstSmsMagic.size()> 0)
            {
                system.debug('@@@@@@@@ before sending' + lstSmsMagic.size() + ' and  ' + lstSmsMagic);
                Database.insert(lstSmsMagic, false);
                system.debug('@@@@@@@@ after sending');
            }
        }
        catch(DmlException e)
        {
             system.debug('********++++++++++*******'+e.getMessage());            
        }

by this one:
 
if(lstSmsMagic.size()> 0) {
  system.debug('@@@@@@@@ before sending' + lstSmsMagic.size() + ' and  ' + lstSmsMagic);
  Database.SaveResult[] srList = Database.insert(lstSmsMagic, false);
  system.debug('@@@@@@@@ after sending');
// Iterate through each returned result
  for (Database.SaveResult sr : srList) {
    if (!sr.isSuccess()) {
        // Operation failed, so get all errors                
        for(Database.Error err : sr.getErrors()) {
            System.debug('The following error has occurred.');                    
            System.debug(err.getStatusCode() + ': ' + err.getMessage());
            System.debug('Fields that affected this error: ' + err.getFields());
        }
     }
  }
}

Database class methods can either do so or allow partial success for record processing. In the latter case of partial processing, Database class methods don’t throw exceptions. Instead, they return a list of errors for any errors that occurred on failed records.

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_dml_database_error.htm

It is just a try. Logically, we will not see  system.debug('@@@@@@@@ after sending');  if it is the same probem.

Alain
 
RDSSRDSS
Hi Alain,

I removed the try catch, got the below error.

Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, smagicinteract.SendSMSTrigger: execution of AfterInsert caused by: System.AsyncException: Future method cannot be called from a future or batch method: smagicinteract.SMSUtility.callSMSAPI(String) Class.smagicinteract.SMSUtility.sendSMS: line 438, column 1 Trigger.smagicinteract.SendSMSTrigger: line 2, column 1: []

Thanks
Raman
Alain CabonAlain Cabon
Hi Ramandeep,

Ok many people can help you now.

During the insert, the trigger smagicinteract.SendSMSis activated.
You have called a code with the @future annotation from your batch: http://www.screen-magic.com/pushsmscallout/
You have a commercial tool for sending your SMS

The reason of the error: Future method cannot be called from a future or batch method.

You have to prevent the call to the @future method from the trigger using a condtion: !system.isBatch()

And send the SMS directly from your batch as explained in the link above (use also Database.AllowsCallouts )

 2. When we do not call from a trigger its a direct callout.
  http://www.screen-magic.com/pushsmscallout/

Alain




 
RDSSRDSS
Hi Alain,

I donot have any trigger. I am sending SMS straightaway from the batch class and later on i will schedule this batch class. And according to above link we need to set smagicinteract__disableSMSOnTrigger__c =1, which means that it will create the entry of the SMS in the salesforce but SMS will not be sent. I am stuck at this error.

Raman