function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Brodie LawtonBrodie Lawton 

Attempt to dereference a null object when calling class

Hi, Hope someone can help!

When I am calling a method from an instance of a class, I am getting the attempt to dereference a null object when calling a class error. I have tried building in validation to stop null values from being allowed to pass through but to no avail.

My code is below:
// department_Field_Population - Written by Brodie Lawton 10/01/2019
    // Class takes the current Case(s) and iterates through them. If the Department__c field is a triage department
    // and the owner is not a triage queue, then set Department__c to the appropriate department for the running user
    // 
    public Case[] department_Field_Population(List<Case> caseRecords){ 
        List<Case> toUpdate = new List<Case>();
        for (Case c : caseRecords){
            if (!(string.valueOf(c.Owner.Name).Contains('Triage')) && (c.Department__c.Contains('Triage'))){ //If the owner name contains triage, and the department does not
                if (UserInfo.getUserRoleId() == '00E0Y000000XzuUUAS'){ //If the user belongs to 2nd line support, change department__c to 2nd line
                    Case toAdd = new Case(Id = c.Id, Department__c = '2nd Line Support'); //Creates temp case to put into toUpdate list
                    toUpdate.add(toAdd);// Adds temp case to the toUpdate list
                }
                if (UserInfo.getUserRoleId() == '00E0Y000000x6oPUAQ'){ //If the user belongs to 1nd line support, change department__c to 1nd line
                    Case toAdd= new Case(Id = c.Id, Department__c = '1st Line Support'); //Creates temp case to put into toUpdate list
                    toUpdate.add(toAdd);// Adds temp case to the toUpdate list
                }
                if (UserInfo.getUserRoleId() == '00E1v000001ZGaMEAW' || UserInfo.getUserRoleId() == '00E1v000001ZGaHEAW'){ //If the user is a Salesforce user, change department to Dev team
                    Case toAdd = new Case(Id = c.Id, Department__c = 'Development Team');
                    toUpdate.add(toAdd);
                }
                if (UserInfo.getUserRoleId() == '00E1v000001ZGaCEAW'){ //If the user is a Salesforce user, change department to Dev team
                    Case toAdd = new Case(Id = c.Id, Department__c = 'Informatics Team');
                    toUpdate.add(toAdd);
                }
            }
        }
        return toUpdate;
    }
It's quite simple code (explanation included in comments), and I have always been able to get past this error before.

Hope someone can help me out!

Thanks.
 
Best Answer chosen by Brodie Lawton
doughauck-corpdoughauck-corp
Brodie - 

See what not paying attention gets you?  Sorry, I was so focused on your method that I missed the calling context.  I know what your problem is.

When an object (or set of objects) is passed via the trigger.old or trigger.new input parameters, all of the value fields will be set, but the reference fields will all be null.  This is to avoid that whole exponential tree-of-objects thing I mentioned earlier.  If you plan to use values from the reference fields, you will need to do your own SOQL query inside the trigger method.

Try the following and tell me if it works:
 
trigger testTriggerCase on Case (before update, after insert, after update) {
    Case_Class caseclass = new Case_Class();

    if (trigger.isAfter) {
        update caseclass.populateMilestoneDate(trigger.old, trigger.new);
        
        Set<Id> triggerNewCaseIDs = new Set<id>();
        for(Case c : trigger.new)
            triggerNewCaseIDs.add(c.Id);
        
        Case[] triggerNewCases = [SELECT Department__c, Owner.Name FROM Case WHERE Id IN :triggerNewCaseIDs];

        Case[] departmentCases = caseclass.department_Field_Population(triggerNewCases);
        if (departmentCases != null) {
            update departmentCases;
        }
    }

    if (trigger.isBefore) {
        caseclass.Change_Owner_When_Solution_Provided(trigger.new);        
    }    
}

Basically, I pulled the IDs out of the Cases stored in trigger.new[ ] and put them into a Set named triggerNewCaseIDs.  (Yes, I know you're only passing one Case, but it works the same either way, and this way you're prepared if that changes.)  Then I used that Set in my SOQL query to get the Case objects that have IDs in that Set (again, only one for now) and put them in a List<Case> named triggerNewCases.  It is that list that I then pass to the department_Field_Population() method.

The SOQL query allows me (well, you actually) to control which fields of the Case objects are populated.  I have populated the Department__c and Owner.Name fields, because those are the only two you use in your method (besides Id, and Id is always populated no matter what).

Of course, every one of the fields of both Case and Case.Owner that you didn't specifically populate is going to be null on the result objects, but you don't care because you only use those two.  If you find you need more fields values in the future (e.g. Account.Name) then add them to your SELECT statement.

Because I don't actually have a Case_Class class or Case.Department__c field, I couldn't test this on my end, but I'm pretty confident it should solve your problem.  Leave the debug statements in there the first time, though, so we can see what happened if it doesn't work.

Best,
Doug
 

All Answers

doughauck-corpdoughauck-corp
Brodie - 

Any chance you could jump into the log from one of your runs and pull some more info about this error? 

You're right - it's simple code and not many places for null objects.  I see five possibles:
  1. The object that contains this  department_Field_Population() method, natch;
  2. The caseRecords[] parameter to the method;
  3. An individual Case item in caseRecords[];
  4. The Case.Owner field of index variable c (when you try to ref its Name field - I don't think Name itself can be null);
  5. The Case.Department__c field of index variable c (when you try to call its Contains() method);
The log is what's going to tell us which of these is the problem.  Either look at the line number where the error occurs, or add some system.debug() statements for the possible null objects right after your for() statement: 
  • system.debug(c);
  • system.debug(c.Owner);
  • system.debug(c.Department__c );
Then you can see which of the values prints "null" for its debug output. If you get the error without getting any output from your debug statements, then you know the problem is with 1 or 2.

Best,
Doug
Raj VakatiRaj Vakati
Remove your hard-coded Id valued and they because the record id are different from the instance to instance

Those lines causing an issue
 
// department_Field_Population - Written by Brodie Lawton 10/01/2019
    // Class takes the current Case(s) and iterates through them. If the Department__c field is a triage department
    // and the owner is not a triage queue, then set Department__c to the appropriate department for the running user
    // 
    public Case[] department_Field_Population(List<Case> caseRecords){ 
        List<Case> toUpdate = new List<Case>();
        for (Case c : caseRecords){
            if (!(string.valueOf(c.Owner.Name).Contains('Triage')) && (c.Department__c.Contains('Triage'))){ //If the owner name contains triage, and the department does not
                if (UserInfo.getUserRoleId() == '00E0Y000000XzuUUAS'){ //If the user belongs to 2nd line support, change department__c to 2nd line
                    Case toAdd = new Case(Id = c.Id, Department__c = '2nd Line Support'); //Creates temp case to put into toUpdate list
                    toUpdate.add(toAdd);// Adds temp case to the toUpdate list
                }
                if (UserInfo.getUserRoleId() == '00E0Y000000x6oPUAQ'){ //If the user belongs to 1nd line support, change department__c to 1nd line
                    Case toAdd= new Case(Id = c.Id, Department__c = '1st Line Support'); //Creates temp case to put into toUpdate list
                    toUpdate.add(toAdd);// Adds temp case to the toUpdate list
                }
                if (UserInfo.getUserRoleId() == '00E1v000001ZGaMEAW' || UserInfo.getUserRoleId() == '00E1v000001ZGaHEAW'){ //If the user is a Salesforce user, change department to Dev team
                    Case toAdd = new Case(Id = c.Id, Department__c = 'Development Team');
                    toUpdate.add(toAdd);
                }
                if (UserInfo.getUserRoleId() == '00E1v000001ZGaCEAW'){ //If the user is a Salesforce user, change department to Dev team
                    Case toAdd = new Case(Id = c.Id, Department__c = 'Informatics Team');
                    toUpdate.add(toAdd);
                }
            }
        }
        return toUpdate;
    }


 
Brodie LawtonBrodie Lawton
Hi,

I have replaced the hard-coded IDs with a formula field that populates to what the Department__c field needs to be depending on the running user. I am however still getting the same null pointer exception. I have included a new snippet of the code, as well as the code from the trigger where the method is called. The log files are also included. I have run tests and found that Cases are being passed through by the trigger, but are not being passed into the for loop, as system.debug(c) returns nothing.

Thanks for your help,
Brodie.
Updated Method:
// department_Field_Population - Written by Brodie Lawton 10/01/2019
    // Class takes the current Case(s) and iterates through them. If the Department__c field is a triage department
    // and the owner is not a triage queue, then set Department__c to the appropriate department for the running user
    // 
    public Case[] department_Field_Population(List<Case> caseRecords){ 
        List<Case> toUpdate = new List<Case>();
        for (Case c : caseRecords){
            if ((c.Department__c.Contains('Triage')) && (!c.Owner.Name.ContainsIgnoreCase('Triage'))){
                system.debug(c);
            	Case updateCase = New Case(Id = c.Id, Department__c = c.Default_Department__c);
            	toUpdate.add(updateCase);
            }
        }
        return toUpdate;
        
    }

Trigger:
trigger caseTrigger on Case (before update, after insert, after update) {
    Case_Class caseclass = new Case_Class();

    if (trigger.isAfter){
        update caseclass.populateMilestoneDate(trigger.old, trigger.new);
        Case[] departmentCases = caseclass.department_Field_Population(trigger.new);
        if (departmentCases != null){
            update departmentCases;
        }
    }
    if (trigger.isBefore){
        caseclass.Change_Owner_When_Solution_Provided(trigger.new);        
    }
        
    

}

Log File:
13:24:09.507 (507481878)|CODE_UNIT_STARTED|[EXTERNAL]|01q1l0000008VDM|caseTrigger on Case trigger event AfterInsert|__sfdc_trigger/caseTrigger
13:24:09.507 (507554772)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:8
13:24:09.507 (534417111)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:8
13:24:09.507 (534443729)|VARIABLE_SCOPE_BEGIN|[1]|this|caseTrigger|true|false
13:24:09.507 (534500781)|VARIABLE_ASSIGNMENT|[1]|this|{}|0x533e88ce
13:24:09.507 (534563939)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:8
13:24:09.507 (534612495)|VARIABLE_SCOPE_BEGIN|[1]|this|caseTrigger|true|false
13:24:09.507 (534628330)|VARIABLE_ASSIGNMENT|[1]|this|{}|0x533e88ce
13:24:09.507 (534637830)|STATEMENT_EXECUTE|[1]
13:24:09.507 (534640695)|STATEMENT_EXECUTE|[2]
13:24:09.507 (534651024)|HEAP_ALLOCATE|[2]|Bytes:8
13:24:09.507 (534659627)|HEAP_ALLOCATE|[2]|Bytes:2
13:24:09.507 (534684958)|METHOD_ENTRY|[1]|01p1l0000009S0D|Case_Class.Case_Class()
13:24:09.507 (534692468)|STATEMENT_EXECUTE|[1]
13:24:09.507 (534697014)|STATEMENT_EXECUTE|[1]
13:24:09.507 (535269521)|SYSTEM_MODE_ENTER|false
13:24:09.507 (535292424)|HEAP_ALLOCATE|[2]|Bytes:5
13:24:09.507 (535303816)|SYSTEM_MODE_EXIT|false
13:24:09.507 (535317704)|METHOD_EXIT|[1]|Case_Class
13:24:09.507 (535337928)|HEAP_ALLOCATE|[2]|Bytes:8
13:24:09.507 (535360199)|CONSTRUCTOR_ENTRY|[2]|01p1l0000009S0D|<init>()|Case_Class
13:24:09.507 (535394133)|VARIABLE_SCOPE_BEGIN|[1]|this|Case_Class|true|false
13:24:09.507 (535424140)|VARIABLE_ASSIGNMENT|[1]|this|{}|0x518e8c55
13:24:09.507 (535437137)|SYSTEM_MODE_ENTER|false
13:24:09.507 (535442152)|HEAP_ALLOCATE|[4]|Bytes:5
13:24:09.507 (535479798)|SYSTEM_MODE_EXIT|false
13:24:09.507 (535485970)|STATEMENT_EXECUTE|[1]
13:24:09.507 (535489956)|SYSTEM_MODE_ENTER|false
13:24:09.507 (535495556)|HEAP_ALLOCATE|[4]|Bytes:5
13:24:09.507 (535498776)|STATEMENT_EXECUTE|[4]
13:24:09.507 (535505484)|HEAP_ALLOCATE|[4]|Bytes:5
13:24:09.507 (535521415)|VARIABLE_ASSIGNMENT|[4]|this.dataLoading|false|0x518e8c55
13:24:09.507 (535528476)|SYSTEM_MODE_EXIT|false
13:24:09.507 (535536428)|CONSTRUCTOR_EXIT|[2]|01p1l0000009S0D|<init>()|Case_Class
13:24:09.507 (535561445)|VARIABLE_ASSIGNMENT|[2]|this.caseclass|0x518e8c55|0x533e88ce
13:24:09.507 (535574459)|STATEMENT_EXECUTE|[4]
13:24:09.507 (535576549)|STATEMENT_EXECUTE|[5]
13:24:09.507 (535652611)|METHOD_ENTRY|[5]|01p1l0000009S0D|Case_Class.populateMilestoneDate(List<Case>, List<Case>)
13:24:09.507 (535675084)|VARIABLE_SCOPE_BEGIN|[47]|this|Case_Class|true|false
13:24:09.507 (535696964)|VARIABLE_ASSIGNMENT|[47]|this|{"dataLoading":false}|0x518e8c55
13:24:09.507 (535706161)|VARIABLE_SCOPE_BEGIN|[47]|oldRecords|List<Case>|true|false
13:24:09.507 (535717554)|VARIABLE_ASSIGNMENT|[47]|oldRecords|null|
13:24:09.507 (535725152)|VARIABLE_SCOPE_BEGIN|[47]|newRecords|List<Case>|true|false
13:24:09.507 (549307651)|VARIABLE_ASSIGNMENT|[47]|newRecords|[{"Origin":"Phone","LastModifiedDate":"2019-01-10T13:24:09.000Z","Default_Department__c":"Development Team","Process_CaseId__c":"5001l000001Fjf5","IsClosed":false,"Reason":"Issue Resolved","BusinessHoursId":"01m0Y000000YLDOQA4","CreatedById":"0050Y000004ObsQQAS","OwnerId":"0050Y000004ObsQQAS","Owned_by_Queue__c":false,"csmrgp__Subject_Conversation__c":"test record","RecordTypeId":"0120Y000000KYFEQA4","IsClosedOnCreate":false,"CaseNumber":"00001403","Thread_ID__c":"ref:_00D1l8bzY._5001 (10 more) ...","Status":"New","IsDeleted":false,"Priority":"Priority Three","Case_Flag_Text__c":"Blue","Subject":"test record","SystemModstamp":"2019-01-10T13:24:09.000Z","IsStopped":false,"Case_Flag__c":"_IM1_/resource/15417 (32 more) ...","IsEscalated":false,"CreatedDate":"2019-01-10T13:24:09.000Z","Id":"5001l000001Fjf5AAC","LastModifiedById":"0050Y000004ObsQQAS"}]|0xb83019f
13:24:09.507 (549842242)|SYSTEM_MODE_ENTER|false
13:24:09.507 (549869636)|HEAP_ALLOCATE|[48]|Bytes:5
13:24:09.507 (549882792)|STATEMENT_EXECUTE|[47]
13:24:09.507 (549885850)|STATEMENT_EXECUTE|[48]
13:24:09.507 (549912679)|HEAP_ALLOCATE|[48]|Bytes:4
13:24:09.507 (549933070)|SYSTEM_CONSTRUCTOR_ENTRY|[48]|<init>()
13:24:09.507 (550000928)|SYSTEM_CONSTRUCTOR_EXIT|[48]|<init>()
13:24:09.507 (550012331)|VARIABLE_SCOPE_BEGIN|[48]|toUpdate|List<Case>|true|false
13:24:09.507 (550034669)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:4
13:24:09.507 (550053898)|VARIABLE_ASSIGNMENT|[48]|toUpdate|[]|0x1b48ac4d
13:24:09.507 (550078849)|STATEMENT_EXECUTE|[49]
13:24:09.507 (550082304)|STATEMENT_EXECUTE|[50]
13:24:09.507 (550092791)|HEAP_ALLOCATE|[50]|Bytes:98
13:24:09.507 (550121896)|HEAP_ALLOCATE|[50]|Bytes:4
13:24:09.507 (550189082)|HEAP_ALLOCATE|[50]|Bytes:7
13:24:09.507 (550195592)|HEAP_ALLOCATE|[50]|Bytes:45
13:24:09.507 (550204355)|HEAP_ALLOCATE|[50]|Bytes:4
13:24:09.507 (550475717)|SOQL_EXECUTE_BEGIN|[50]|Aggregations:0|SELECT Id FROM Case WHERE Case_Topic__c != ''
13:24:09.507 (568659872)|SOQL_EXECUTE_END|[50]|Rows:5
13:24:09.507 (568698136)|HEAP_ALLOCATE|[50]|Bytes:24
13:24:09.507 (568730569)|HEAP_ALLOCATE|[50]|Bytes:145
13:24:09.507 (568785639)|HEAP_ALLOCATE|[50]|Bytes:24
13:24:09.507 (570396050)|SOQL_EXECUTE_BEGIN|[50]|Aggregations:0|SELECT Id, TargetDate, CaseId FROM CaseMilestone WHERE (CaseId IN :tmpVar1 AND CaseID IN :tmpVar2)
13:24:09.507 (574430210)|SOQL_EXECUTE_END|[50]|Rows:0
13:24:09.507 (574470862)|HEAP_ALLOCATE|[50]|Bytes:4
13:24:09.507 (574486587)|HEAP_ALLOCATE|[50]|Bytes:0
13:24:09.507 (574577955)|HEAP_ALLOCATE|[50]|Bytes:4
13:24:09.507 (574600380)|VARIABLE_SCOPE_BEGIN|[50]|caseMilestone|List<CaseMilestone>|true|false
13:24:09.507 (574628996)|VARIABLE_ASSIGNMENT|[50]|caseMilestone|[]|0x1a6015c2
13:24:09.507 (574687846)|SYSTEM_METHOD_ENTRY|[51]|List<CaseMilestone>.size()
13:24:09.507 (574723148)|SYSTEM_METHOD_EXIT|[51]|List<CaseMilestone>.size()
13:24:09.507 (574737369)|STATEMENT_EXECUTE|[51]
13:24:09.507 (574741605)|STATEMENT_EXECUTE|[62]
13:24:09.507 (574748868)|SYSTEM_MODE_EXIT|false
13:24:09.507 (574767691)|METHOD_EXIT|[5]|01p1l0000009S0D|Case_Class.populateMilestoneDate(List<Case>, List<Case>)
13:24:09.507 (574855674)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:4
13:24:09.507 (574879989)|STATEMENT_EXECUTE|[6]
13:24:09.507 (574884074)|STATEMENT_EXECUTE|[7]
13:24:09.507 (574921132)|METHOD_ENTRY|[7]|01p1l0000009S0D|Case_Class.department_Field_Population(List<Case>)
13:24:09.507 (574943215)|VARIABLE_SCOPE_BEGIN|[29]|this|Case_Class|true|false
13:24:09.507 (574980028)|VARIABLE_ASSIGNMENT|[29]|this|{"dataLoading":false}|0x518e8c55
13:24:09.507 (574989644)|VARIABLE_SCOPE_BEGIN|[29]|caseRecords|List<Case>|true|false
13:24:09.507 (575518892)|VARIABLE_ASSIGNMENT|[29]|caseRecords|[{"Origin":"Phone","LastModifiedDate":"2019-01-10T13:24:09.000Z","Default_Department__c":"Development Team","Process_CaseId__c":"5001l000001Fjf5","IsClosed":false,"Reason":"Issue Resolved","BusinessHoursId":"01m0Y000000YLDOQA4","CreatedById":"0050Y000004ObsQQAS","OwnerId":"0050Y000004ObsQQAS","Owned_by_Queue__c":false,"csmrgp__Subject_Conversation__c":"test record","RecordTypeId":"0120Y000000KYFEQA4","IsClosedOnCreate":false,"CaseNumber":"00001403","Thread_ID__c":"ref:_00D1l8bzY._5001 (10 more) ...","Status":"New","IsDeleted":false,"Priority":"Priority Three","Case_Flag_Text__c":"Blue","Subject":"test record","SystemModstamp":"2019-01-10T13:24:09.000Z","IsStopped":false,"Case_Flag__c":"_IM1_/resource/15417 (32 more) ...","IsEscalated":false,"CreatedDate":"2019-01-10T13:24:09.000Z","Id":"5001l000001Fjf5AAC","LastModifiedById":"0050Y000004ObsQQAS"}]|0xb83019f
13:24:09.507 (575555578)|SYSTEM_MODE_ENTER|false
13:24:09.507 (575569458)|HEAP_ALLOCATE|[30]|Bytes:5
13:24:09.507 (575577514)|STATEMENT_EXECUTE|[29]
13:24:09.507 (575580426)|STATEMENT_EXECUTE|[30]
13:24:09.507 (575595491)|HEAP_ALLOCATE|[30]|Bytes:4
13:24:09.507 (575608610)|SYSTEM_CONSTRUCTOR_ENTRY|[30]|<init>()
13:24:09.507 (575630297)|SYSTEM_CONSTRUCTOR_EXIT|[30]|<init>()
13:24:09.507 (575635599)|VARIABLE_SCOPE_BEGIN|[30]|toUpdate|List<Case>|true|false
13:24:09.507 (575649515)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:4
13:24:09.507 (575659087)|VARIABLE_ASSIGNMENT|[30]|toUpdate|[]|0x56abde02
13:24:09.507 (575673346)|SYSTEM_METHOD_ENTRY|[31]|List<Case>.iterator()
13:24:09.507 (575693903)|SYSTEM_METHOD_EXIT|[31]|List<Case>.iterator()
13:24:09.507 (575707360)|SYSTEM_METHOD_ENTRY|[31]|system.ListIterator.hasNext()
13:24:09.507 (575716970)|HEAP_ALLOCATE|[31]|Bytes:5
13:24:09.507 (575725462)|SYSTEM_METHOD_EXIT|[31]|system.ListIterator.hasNext()
13:24:09.507 (575746379)|VARIABLE_SCOPE_BEGIN|[31]|c|Case|true|false
13:24:09.507 (576141671)|VARIABLE_ASSIGNMENT|[31]|c|{"Origin":"Phone","LastModifiedDate":"2019-01-10T13:24:09.000Z","Default_Department__c":"Development Team","Process_CaseId__c":"5001l000001Fjf5","IsClosed":false,"Reason":"Issue Resolved","BusinessHoursId":"01m0Y000000YLDOQA4","CreatedById":"0050Y000004ObsQQAS","OwnerId":"0050Y000004ObsQQAS","Owned_by_Queue__c":false,"csmrgp__Subject_Conversation__c":"test record","RecordTypeId":"0120Y000000KYFEQA4","IsClosedOnCreate":false,"CaseNumber":"00001403","Thread_ID__c":"ref:_00D1l8bzY._5001 (10 more) ...","Status":"New","IsDeleted":false,"Priority":"Priority Three","Case_Flag_Text__c":"Blue","Subject":"test record","SystemModstamp":"2019-01-10T13:24:09.000Z","IsStopped":false,"Case_Flag__c":"_IM1_/resource/15417 (32 more) ...","IsEscalated":false,"CreatedDate":"2019-01-10T13:24:09.000Z","Id":"5001l000001Fjf5AAC","LastModifiedById":"0050Y000004ObsQQAS"}|0x4cff0f10
13:24:09.507 (576168994)|STATEMENT_EXECUTE|[31]
13:24:09.507 (576184202)|HEAP_ALLOCATE|[32]|Bytes:6
13:24:09.507 (576223942)|SYSTEM_METHOD_ENTRY|[32]|String.contains(String)
13:24:09.507 (576289764)|HEAP_ALLOCATE|[32]|Bytes:41
13:24:09.507 (576302483)|SYSTEM_METHOD_EXIT|[32]|String.contains(String)
13:24:09.507 (576314135)|SYSTEM_MODE_EXIT|false
13:24:09.507 (576325565)|METHOD_EXIT|[7]|01p1l0000009S0D|Case_Class.department_Field_Population(List<Case>)
13:24:09.507 (576486987)|FATAL_ERROR|System.NullPointerException: Attempt to de-reference a null object

Class.Case_Class.department_Field_Population: line 32, column 1
Trigger.caseTrigger: line 7, column 1
13:24:09.507 (576498763)|FATAL_ERROR|System.NullPointerException: Attempt to de-reference a null object

Class.Case_Class.department_Field_Population: line 32, column 1
Trigger.caseTrigger: line 7, column 1
13:24:09.576 (576547193)|CUMULATIVE_LIMIT_USAGE
13:24:09.576 (576547193)|LIMIT_USAGE_FOR_NS|(default)|
  Number of SOQL queries: 2 out of 100
  Number of query rows: 5 out of 50000
  Number of SOSL queries: 0 out of 20
  Number of DML statements: 0 out of 150
  Number of DML rows: 0 out of 10000
  Maximum CPU time: 183 out of 10000
  Maximum heap size: 0 out of 6000000
  Number of callouts: 0 out of 100
  Number of Email Invocations: 0 out of 10
  Number of future calls: 0 out of 50
  Number of queueable jobs added to the queue: 0 out of 50
  Number of Mobile Apex push calls: 0 out of 10

13:24:09.576 (576547193)|LIMIT_USAGE_FOR_NS|csmrgp|
  Number of SOQL queries: 4 out of 100
  Number of query rows: 4 out of 50000
  Number of SOSL queries: 0 out of 20
  Number of DML statements: 0 out of 150
  Number of DML rows: 0 out of 10000
  Maximum CPU time: 0 out of 10000
  Maximum heap size: 0 out of 6000000
  Number of callouts: 0 out of 100
  Number of Email Invocations: 0 out of 10
  Number of future calls: 0 out of 50
  Number of queueable jobs added to the queue: 0 out of 50
  Number of Mobile Apex push calls: 0 out of 10

13:24:09.576 (576547193)|CUMULATIVE_LIMIT_USAGE_END
doughauck-corpdoughauck-corp
Hi, Brodie - 

So if you look in your log, line #118 (as you have it listed here) you will see that the problem is in Line [32] of your actual code (not the same as line numbers here, obviously).  I can see from the assignment of your method input parameter (caseRecords) in log line #87, that the start of the method is at your actual code line [29].  Counting up (29..30..31..32) means that the problem line is:
if ((c.Department__c.Contains('Triage')) && (!c.Owner.Name.ContainsIgnoreCase('Triage'))) {
That means you never even make it to your system.debug(c) statement, which is why you never see its output. 

I'm presuming that the problem is that one of the two fields checked in that if() statement is null.  But to find out which, you will need to put your system.debug() statements BEFORE the if() that is causing the error:
  • system.debug(c);
  • system.debug(c.Department__c);
  • system.debug(c.Owner);
  • system.debug(c.Owner.Name);
Don't skip out on any of these, keep them in this order, and put them right after the for() statement.  Note that when viewing your log in the Developer Console, there is a checkbox for Debug Only, which will hide everything but these 4 lines, and save you some search time.  If you click on a line to highlight it, then uncheck the Debug Only box, that line will stay as the active line when everything else appears, so you can see where it fits in the grand scheme.

I'm betting the problem is with the SOQL statement you used to get your Case records.  Remember that any field you want to be in your Apex variable has to be called out in your SOQL, including reference fields like Owner and Owner.Name.  If you want to reference c.Department__c and c.Owner.Name from then your Select has to be something like:
SELECT Department__c, Owner.Name, ... FROM Case WHERE ...
You can't just have Owner by itself (w/o Name) in the Select clause, because only its Id field will be populated.  Whatever the problem is, though, those debug statements should point it out. 

And you didn't need to get rid of those hard-coded ID values, at least, not for this issue.  (Though hard-coding is generally frowned upon - if sometimes unavoidable - because problems can crop up if somebody deletes that record 10 years from now.  Is there another way you could reference those user role records?  If not, then not, but just think about it.)

Let me know how this works out for you.

Best,
Doug
Brodie LawtonBrodie Lawton
I've had a look and the Owner field seems to be null. As every record in Salesforce needs to have a record owner, I am unsure as to how this field could be blank?

Brodie.
doughauck-corpdoughauck-corp
As I said, if it's not in your SOQL query, it won't be in your Apex variable. 

Can you post the text of the query you are using to get the Case records you're passing into department_Field_Population(caseRecords)?  Then we can have a look and hopefully see what's going on here.
doughauck-corpdoughauck-corp
Some context while you're looking:

Every Case variable in your Apex method costs memory, right?  If your query returns 100 Cases, that's 100 Case variables that are sitting in memory now.  And once you start bringing in parent object references, one object (e.g. Case) can have multiple objects associated with it (Owner, Account, etc.)  So now for each Case returned by your query, there is a whole tree of associated objects sitting in that memory.  

But let's say that for each Case, I only want to know the date it was started - why would SFDC populate that whole tree for every Case object it returned, just so I can pull one stupid piece of information from it and throw the rest away?  That's why SFDC makes you specify the fields you want in your query statemen.  If you don't, those fields will exist on the Case object, but their values will be set to null.  (Except for ID, which is always returned whether you ask for it or not.)

Capisce?
Brodie LawtonBrodie Lawton
Hi Doug,

This class is called by a trigger (the code for which is above) and there are not SOQL queries involved. Sorry if I was not more clear on that. It was my understanding that a trigger would pass in a full record?

Thanks,
Brodie.
doughauck-corpdoughauck-corp
Brodie - 

See what not paying attention gets you?  Sorry, I was so focused on your method that I missed the calling context.  I know what your problem is.

When an object (or set of objects) is passed via the trigger.old or trigger.new input parameters, all of the value fields will be set, but the reference fields will all be null.  This is to avoid that whole exponential tree-of-objects thing I mentioned earlier.  If you plan to use values from the reference fields, you will need to do your own SOQL query inside the trigger method.

Try the following and tell me if it works:
 
trigger testTriggerCase on Case (before update, after insert, after update) {
    Case_Class caseclass = new Case_Class();

    if (trigger.isAfter) {
        update caseclass.populateMilestoneDate(trigger.old, trigger.new);
        
        Set<Id> triggerNewCaseIDs = new Set<id>();
        for(Case c : trigger.new)
            triggerNewCaseIDs.add(c.Id);
        
        Case[] triggerNewCases = [SELECT Department__c, Owner.Name FROM Case WHERE Id IN :triggerNewCaseIDs];

        Case[] departmentCases = caseclass.department_Field_Population(triggerNewCases);
        if (departmentCases != null) {
            update departmentCases;
        }
    }

    if (trigger.isBefore) {
        caseclass.Change_Owner_When_Solution_Provided(trigger.new);        
    }    
}

Basically, I pulled the IDs out of the Cases stored in trigger.new[ ] and put them into a Set named triggerNewCaseIDs.  (Yes, I know you're only passing one Case, but it works the same either way, and this way you're prepared if that changes.)  Then I used that Set in my SOQL query to get the Case objects that have IDs in that Set (again, only one for now) and put them in a List<Case> named triggerNewCases.  It is that list that I then pass to the department_Field_Population() method.

The SOQL query allows me (well, you actually) to control which fields of the Case objects are populated.  I have populated the Department__c and Owner.Name fields, because those are the only two you use in your method (besides Id, and Id is always populated no matter what).

Of course, every one of the fields of both Case and Case.Owner that you didn't specifically populate is going to be null on the result objects, but you don't care because you only use those two.  If you find you need more fields values in the future (e.g. Account.Name) then add them to your SELECT statement.

Because I don't actually have a Case_Class class or Case.Department__c field, I couldn't test this on my end, but I'm pretty confident it should solve your problem.  Leave the debug statements in there the first time, though, so we can see what happened if it doesn't work.

Best,
Doug
 
This was selected as the best answer
doughauck-corpdoughauck-corp
One minor mistake - I accidentally left the trigger name as testTriggerCase instead of your name of caseTrigger.  So don't copy that over when you copy my code.
Brodie LawtonBrodie Lawton
Hi Doug,

That worked great... Thank you!

Brodie.
doughauck-corpdoughauck-corp
Great!  Can you do me a favor and mark it as the answer then?  That will copy that response to the top of the stack and mark it as a working answer, which will save other people the time of digging through all of our back-and-forth.