You need to sign in to do that
Don't have an account?
Brodie 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:
Hope someone can help me out!
Thanks.
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.
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:
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
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:
- The object that contains this department_Field_Population() method, natch;
- The caseRecords[] parameter to the method;
- An individual Case item in caseRecords[];
- 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);
- 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
Those lines causing an issue
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:
Trigger:
Log File:
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: 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: 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.
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.
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?
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.
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:
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
That worked great... Thank you!
Brodie.