0

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);
  • 2
    Can you point the line which is causing, it would help us debug. – Pranay Jaiswal May 11 '18 at 16:00
  • 2
    You're going to want to check your debug logs (Your Name/⚙ > Developer Console > Logs); it should show you which line/class caused the error. – sfdcfox May 11 '18 at 16:08
  • Thanks for the dope slap, people! I kept staring at new code, and didn't follow the trail into the class the new code was calling... I generally create custom log objects rather than trace debug logs, and nothing in execute() runs if there's an issue like this one so those custom logging objects were never created. Now, if I can just get my morning back ... – Duncan Stewart May 11 '18 at 17:46
0

As @Pranay Jaswal & @sfdcfox suggested, System.debug was the way to go. I had inserted custom logging code in the execute() method, but no logging occurred while there was a null reference in the code that I was calling from the queueable class.

Thankfully, the System log wasn't truncated before it got to the line in question; once I resolved the issue there, the design worked fine! phew!

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.