I have two queueable classes for handing off trigger-like processing; one Case-specific, one generic. The first implementation of the generic version also involves Cases, and editing a Case works in one, fails in the other; Case trigger calls them sequentially.
The one difference that I can see is that in one, I pass the entire context to a separate class to process; in the second, I only pass certain attributes, but I've validated in the trigger that those attributes are populated, and I don't know how else to determine where the null is, or where it's coming from.
This first one runs fine:
public class FieldHistory_queueable implements Queueable {
private triggerContext triggerCon;
public FieldHistory_queueable(triggerContext currContext){
this.triggerCon = currContext;
}
public void execute(QueueableContext context) {
// Pass in a list of SObjects & the trigger state,
// call processes formerly called directly from TriggerDispatcher as part of the
// immediate execution of the trigger, and save them off as a queueable to be
// handled as resources allow.
FieldHistory fh = new FieldHistory();
fh.MainEntry(this.triggerCon.triggerType,
this.triggerCon.isBefore, this.triggerCon.isDelete,
this.triggerCon.isAfter, this.triggerCon.isInsert,
this.triggerCon.isUpdate, this.triggerCon.isExecuting,
this.triggerCon.newList, this.triggerCon.newMap,
this.triggerCon.oldList, this.triggerCon.oldMap);
}
public class triggerContext {
public String triggerType {get; private set;}
public Boolean isBefore {get; private set;}
public Boolean isDelete {get; private set;}
public Boolean isAfter {get; private set;}
public Boolean isInsert {get; private set;}
public Boolean isUpdate {get; private set;}
public Boolean isExecuting {get; private set;}
public List<SObject> newList {get; private set;}
public Map<Id, SObject> newMap {get; private set;}
public List<SObject> oldList {get; private set;}
public Map<Id, SObject> oldMap {get; private set;}
public triggerContext(String triggerType, Boolean isBefore, Boolean isDelete, Boolean isAfter,
Boolean isInsert, Boolean isUpdate, Boolean isExecuting,
List<SObject> newList, Map<Id, SObject> newMap, List<SObject> oldList, Map<Id, SObject> oldMap)
{
this.triggerType = triggerType;
this.isBefore = isBefore;
this.isDelete = isDelete;
this.isAfter = isAfter;
this.isInsert = isInsert;
this.isUpdate = isUpdate;
this.isExecuting = false;
this.newList = newList;
this.newMap = newMap;
this.oldList = oldList;
this.oldMap = oldMap;
}
}
}
Classname is rather specific, so I'm working on a generic version, and I'm hitting our friend 'de-reference a null' and can't see the cause.
public class TriggerProcess_queueable implements Queueable {
private trigContext myContext;
public TriggerProcess_queueable(trigContext currContext){
this.myContext = currContext;
Utils.debug('Hello', 'Case', 'TP_queueable1');
}
public void execute(QueueableContext context) {
if(this.myContext <> null && this.myContext.triggerType == 'Case') {
Case[] cases = (Case[]) this.myContext.newList;
Map<Id, Case> newMap = (Map<Id, Case>) this.myContext.newMap;
Map<Id, Case> oldMap = (Map<Id, Case>) this.myContext.oldMap;
NxSwapReplacementNotification nxSwap = new NxSwapReplacementNotification(
cases, newMap, oldMap, this.myContext.isUpdate);
}
}
public class trigContext {
public String triggerType {get; private set;}
public Boolean isBefore {get; private set;}
public Boolean isDelete {get; private set;}
public Boolean isAfter {get; private set;}
public Boolean isInsert {get; private set;}
public Boolean isUpdate {get; private set;}
public Boolean isExecuting {get; private set;}
public List<SObject> newList {get; private set;}
public Map<Id, SObject> newMap {get; private set;}
public List<SObject> oldList {get; private set;}
public Map<Id, SObject> oldMap {get; private set;}
public trigContext(String triggerType, Boolean isBefore, Boolean isDelete, Boolean isAfter,
Boolean isInsert, Boolean isUpdate, Boolean isExecuting,
List<SObject> newList, Map<Id, SObject> newMap, List<SObject> oldList, Map<Id, SObject> oldMap)
{
this.triggerType = triggerType;
this.isBefore = isBefore;
this.isDelete = isDelete;
this.isAfter = isAfter;
this.isInsert = isInsert;
this.isUpdate = isUpdate;
this.isExecuting = false;
this.newList = newList;
this.newMap = newMap;
this.oldList = oldList;
this.oldMap = oldMap;
}
}
}
Both are called from the Case trigger the same way, but inside the execute() method, the generic one dies.
FieldHistory_queueable.triggerContext context = new FieldHistory_queueable.triggerContext(
'Case',
trigger.isBefore, trigger.isDelete, trigger.isAfter, trigger.isInsert,
trigger.isUpdate, trigger.isExecuting, trigger.new, trigger.newMap,
trigger.old, trigger.oldMap);
FieldHistory_queueable fieldHistory_queue = new FieldHistory_queueable(context);
Id jobId = System.enqueueJob(fieldHistory_queue);
vs.
TriggerProcess_queueable.trigContext tContext = new TriggerProcess_queueable.trigContext(
'Case',
trigger.isBefore, Trigger.isDelete, trigger.isAfter, Trigger.isInsert,
trigger.isUpdate, trigger.isExecuting, trigger.new, trigger.newMap,
trigger.old, trigger.oldMap);
TriggerProcess_queueable caseQueue = new TriggerProcess_queueable(tContext);
Id jobId = System.enqueueJob(caseQueue);