+ Start a Discussion
JayChenJayChen 

Apex Batch Job Error

Hi there:
Let me start by saying I'm not a developer and very new to development. I'm trying to update a field in on all leads where the business logic results to true, I want the logic to run every 65 minutes. I've written my batch schedule class and schedule class. My batch schedule class works and I can save it in my apex class. However, my schedule class does not work outside of the developer console - everytime I save it as a apex class - it gives me an error message "unexpected token: 'MQLEscalationBatch' at line 1 column 0". Any assistance would be greatly appreciated.

 Batch Class:

global class MQLEscalationBatch implements Database.Batchable<sObject> {
    
    global Database.QueryLocator start(Database.BatchableContext BC)    {
      String query= 'SELECT Id, Company, OwnerId, Escalation_Calculation__c,Status, Inside_Sales_Representative__c 
FROM Lead WHERE Escalation_Calculation__c > 7.50 AND Escalation_Calculation__c < 19.00 AND Inside_Sales_Representative__c != NULL AND IsConverted = FALSE AND Sales_Initial_Last_Modification__c = NULL AND LastActivityDate = NUll ';

        //return Database.QueryLocator(query);

        return Database.getQueryLocator(query);

    }
     
    global void execute(Database.BatchableContext bc, List<Lead> scope)

    {
        for(Lead l: scope)
        {
            l.MQL_Alert__c = TRUE;
            system.debug(l);
        }
        update scope;
        }
        
    global void finish(Database.BatchableContext bc){
        
    }
}


Schedule Class: it gives me an error message "unexpected token: 'MQLEscalationBatch' at line 1 column 0

MQLEscalationBatch b = new MQLEscalationBatch();
database.executeBatch(b);
String sch = '0 05 * * * ?';
String jobID = database.executeBatch(b);
Best Answer chosen by JayChen
DeveloperSudDeveloperSud
Hi Jing,

Yes this job will trigger in every 65 minutes, which will automatically help to run the associated batch job.If it runs at 2017-03-16 20:05:00 once next it will run at 2017-03-16 21:05:00 .
Please mark this as solved when you feel this meet your requirement. :)

 

All Answers

DeveloperSudDeveloperSud
Hi Jing,

Please refer the below link .This will hep you to check your schedulable class.
https://success.salesforce.com/answers?id=90630000000h3YKAAY
JayChenJayChen
Hi Sudipto: Thank you for your response. I’ve read the thread that you mentioned and have already tried executing the following code in the developer console, but no jobs have been scheduled which makes me think that my code isn’t correct. Thoughts on what I could be doing wrong? MQLEscalationBatch b = new MQLEscalationBatch(); database.executeBatch(b); String sch = '0 05 * * * ?'; String jobID = database.executeBatch(b, 200);
AjazAjaz
Hi Jing,

After looking at your code, it looked very fine for me, so i tried saving the code in my org and was able to save it successfully. Below is the code snippet that i saved.. Can you try saving it at your end and let me know feedback.

global class MQLEscalationBatch implements Database.Batchable<sObject> {
    
    global Database.QueryLocator start(Database.BatchableContext BC)    {
      String query= 'SELECT Id, Company, OwnerId, Escalation_Calculation__c,Status, Inside_Sales_Representative__c FROM Lead WHERE Escalation_Calculation__c > 7.50 AND Escalation_Calculation__c < 19.00 AND Inside_Sales_Representative__c != NULL AND IsConverted = FALSE AND Sales_Initial_Last_Modification__c = NULL AND LastActivityDate = NUll ';
        return Database.getQueryLocator(query);

    }
     
    global void execute(Database.BatchableContext bc, List<Lead> scope)

    {
    
    }
    
    global void finish(Database.BatchableContext bc){
        
    }
    }
JayChenJayChen
HI Ajaz: Thank you for you response, my batch class is okay. But I can’t get my schedule class job to execute: I need it to run every 65 minutes (see code below). I thought I did it correctly, but every time I execute it, the jobs are not scheduled in my Apex Jobs. MQLEscalationBatch b = new MQLEscalationBatch(); database.executeBatch(b); String sch = '0 05 * * * ?'; String jobID = database.executeBatch(b,200);
DeveloperSudDeveloperSud
Hi Jing,

Please follow the steps 

1.Create a schedule class for your batch class like below
 
global class YourClassName implements Schedulable
{
    global void execute(SchedulableContext sc)
    {
        // Implement any logic to be scheduled
       
        // We now call the batch class to be scheduled
        MQLEscalationBatch b = new MQLEscalationBatch ();
       
        //Parameters of ExecuteBatch(context,BatchSize)
        database.executebatch(b,200);
    }
   
}

2. Execute the below code in Anonymous window of developer console
 
YourClassName batchSch=new YourClassName();
String sch='0 5 * * * ?';
//System.schedule(String jobName, String cronExp, APEX_OBJECT schedulable);
System.schedule('Batch Schedule ', sch , batchSch);


 
JayChenJayChen
Hi Sudipto: I executed the code and received this error: The System.AsyncException: trigger must be associated with a job detail on step 2 (in the developer console) I followed your example exactly: Step 1: global class MQLEscalationUpdate implements Schedulable { global void execute(SchedulableContext sc) { // Implement any logic to be scheduled // We now call the batch class to be scheduled MQLEscalationBatch b = new MQLEscalationBatch (); //Parameters of ExecuteBatch(context,BatchSize) database.executebatch(b,200); } } Step 2: Error Message: System.AsyncException: trigger must be associated with a job detail MQLEscalationUpdate batchSch=new MQLEscalationUpdate(); String sch='0 5 * * * ?'; //System.schedule(String jobName, String cronExp, APEX_OBJECT schedulable); System.schedule('Batch Schedule ', sch , batchSch);
DeveloperSudDeveloperSud
Hi Jing,

Try Running this.
MQLEscalationUpdate batchSch=new MQLEscalationUpdate(); 
String sch='0 5 * * * ?'; 
//System.schedule(String jobName, String cronExp, APEX_OBJECT schedulable);
 System.schedule('BatchJob', sch , batchSch);

 
JayChenJayChen
Thank you for your help so far. The latest code worked, but it only scheduled one job, the String sch='0 5 * * * ?'; should schedule 1 job every 65 minutes, correct?

User-added image
DeveloperSudDeveloperSud
Hi Jing,

Yes this job will trigger in every 65 minutes, which will automatically help to run the associated batch job.If it runs at 2017-03-16 20:05:00 once next it will run at 2017-03-16 21:05:00 .
Please mark this as solved when you feel this meet your requirement. :)

 
This was selected as the best answer
JayChenJayChen
Thank you, Sudipto!
JayChenJayChen
Hi Sudipto, 

I'm working on the test class now and was wondering if you could assist as well. I keep getting an error message on the codes below. I tried debuggind, but that doesn't seem to be working at all and I've been stucked for a few hours now.

System.AssertException: Assertion Failed: all there: Expected: 200, Actual: 0

@isTest
public class mqlEscalationAlert2Test {
    public static String CRON_EXP = '0 0 0 15 3 ? 2022';
static testmethod void testBatchJob2() {

List<Lead> lds = new List<Lead>();
    for (Integer i=0; i<200; i++){
        Lead l = new Lead( FirstName = 'Lead ' + i,LastName='LastName'+i,Company ='demo'+i, RecordTypeId='01270000000E9G6', Inside_Sales_Representative__c='005390000059ObT', Status='Open', LeadSource='Cold Call/Telemarketing');
lds.add(l); 
    }
    insert lds;
    
    Map<Id, Lead> ledMap = new Map<Id, Lead>(lds);
    List<Id> ledIds = new List<Id>(ledMap.keySet());
Test.startTest();
String jobId = System.schedule('Batchjob',CRON_EXP, new mqlEscalationAlertBatch2());
List<Lead> lt = [SELECT Id, Company, OwnerId, Escalation_Calculation__c, Status, Inside_Sales_Representative__c FROM Lead WHERE Escalation_Calculation__c >= 16.00 AND Escalation_Calculation__c <= 17.10 AND Inside_Sales_Representative__c != NULL AND IsConverted = FALSE AND Sales_Initial_Last_Modification__c = NULL AND Lead_Lost_Reason__c = NULL AND MQL_Second_Alert__c = FALSE and id in :ledIds];
    System.assertEquals(200,lt.size(),'all there');
Test.stopTest();
lt = [SELECT Id, Company, OwnerId, Escalation_Calculation__c, Status, Inside_Sales_Representative__c FROM Lead WHERE Escalation_Calculation__c >= 16.00 AND Escalation_Calculation__c <= 17.10 AND Inside_Sales_Representative__c != NULL AND IsConverted = FALSE AND Sales_Initial_Last_Modification__c = NULL AND Lead_Lost_Reason__c = NULL AND MQL_Second_Alert__c = FALSE and id in :ledIds];
 System.assertEquals(200,lt.size(),'all done');
}
    
}
 
DeveloperSudDeveloperSud
Hi Jing,

The approach looks not good to me.First write a test class for the batch class you have written earlier and then wrtie the test class for the schedule class separately.You can write something like below for your test class for the schedule apex you have written earlier .
@isTest
public class  yourTestClassName{
    
    public static String CRON_EXP = '0 5 * * * ?';

    static testMethod void unitTest1(){
        test.startTest();
        // create a instance of you schedule apex class
        MQLEscalationUpdate sp=new MQLEscalationUpdate();
        //schedule the test job
        String jobid=system.schedule('testscheduleApex',CRON_EXP ,sp);
        // get the job details 
        CronTrigger ct = [Select id , CronExpression from CronTrigger where id = :jobId];
       // step to verify
        System.assertEquals(CRON_EXP,ct.CronExpression);
        test.stopTest();

    }

}

If you need help on writing the test class for your batch apex then please follow the link below.For any further problem feel free to create a new post.
https://trailhead.salesforce.com/modules/asynchronous_apex/units/async_apex_batch