I haver a scheduled job that runs every fifteen minutes. It runs fine for several months and then randomly it will stop running and doesn't reschedule for the next run. The apex jobs showed an "attempt to de-reference a null object error, but didn't give me a line number.
Here is the code I'm running:
global class OrderApprovalDeadlineScheduler implements Schedulable {
Boolean cacheLoaded = false;
private BusinessHours getDefaultBusinessHours() {
BusinessHours bh = new BusinessHours();
if(cacheLoaded) return bh;
bh = [SELECT Id FROM BusinessHours WHERE IsDefault=true];
cacheLoaded = true;
return bh;
}
global static String scheduleIt() {
datetime nextScheduleTime = system.now().addMinutes(15);
integer minute = nextScheduleTime.minute();
integer second = nextScheduleTime.second ();
integer hour = nextScheduleTime.hour();
integer year = nextScheduleTime.year();
integer month = nextScheduleTime.month();
integer day = nextScheduleTime.day();
string cronvalue = second + ' ' + minute + ' ' + hour + ' ' + day + ' ' + month + ' ? ' + year;
string jobName = 'Self Rescheduling Order Approval Deadline Scheduler ' + nextScheduleTime.format('hh:mm');
OrderApprovalDeadlineScheduler scheduler = new OrderApprovalDeadlineScheduler();
return system.schedule(jobName, cronvalue, scheduler);
}
global void execute(SchedulableContext sc) {
BusinessHours bh = getDefaultBusinessHours();
Map<Id, Order_Approvals__c> recordsToUpdate = new Map<Id, Order_Approvals__c>();
for(Order_Approvals__c oa : [select Approval_Deadline__c, Approval_Deadlines_Missed__c from Order_Approvals__c where Response__c = NULL]) {
if(system.now() >= oa.Approval_Deadline__c) {
oa.Approval_Deadline__c = BusinessHours.add(bh.Id, oa.Approval_Deadline__c, 32400000);
oa.Approval_Deadlines_Missed__c = oa.Approval_Deadlines_Missed__c + 1;
recordsToUpdate.put(oa.Id, oa);
}
}
if(!recordsToUpdate.isEmpty() && recordsToUpdate.size() > 0) {
List<Database.Saveresult> results = Database.update(recordsToUpdate.values(), false);
for(Database.SaveResult sr : results) {
if(!sr.isSuccess()) {
for(Database.Error err : sr.getErrors()) {
// process any errors here
system.debug(err.getMessage());
system.debug(err.getStatusCode());
}
}
}
}
try {
system.abortJob(sc.getTriggerId());
}
catch (exception e) {
system.debug('************ schedule job exception while aborting: ' + e);
}
system.debug('************* schedule job executing');
scheduleIt();
}
}
As I was looking over the code, I was looking for where the null error might be occurring. I could add a null check before referencing the Approval_Deadline__c field in the code right after the loop starts. Is there a way to capture the error when it occurs and email me with the error and line number so I can fix the issue. It has been hard to track down since it happens only randomly. Normally about every 6 months or so, the job will fail and not reschedule and I have to go back and run the ScheduleIt()
method in the anonymous window to get the job running again.