+ Start a Discussion
John AthitakisJohn Athitakis 

Help: System.NullPointerException: Attempt to de-reference a null object:

Hello, I'm hoping someone can help me out! 

So this code is pretty basic in idea. A custom object is created or edited. It has numerous lookups to the user table (each representing a different type of relationship, for example: Field Rep).

The user table as number fields that this code is meant to decrement or increment.

The issue is this; when i made an adjustment to the user table, if i set a static value--its fine, example:

 

u.Sales_Area_Field_Rep__c=10;

But if I do something like the following, I get the de-reference error
u.Sales_Area_Field_Rep__c++;
u.Sales_Area_Field_Rep__c+=1;
u.Sales_Area_Field_Rep__c=u.Sales_Area_Field_Rep__c+1;

Here is a big snippet of the code. Any help would be REALLY appreciated. 

 

trigger UpdateSalesAreaToUserCount on Sales_Area__c (before insert, before update) {
    
String prefix = User.sObjectType.getDescribe().keyPrefix;
   
list <User> usersToUpdate= new List <User>{};
    if(Trigger.IsUpdate){
       for (Sales_Area__c co : Trigger.new) { 
  		 Sales_Area__c coOld = Trigger.oldMap.get(co.Id);
         
          //Begin Field Rep
 		   	if(coOld.Field_Rep__c != co.Field_Rep__c){
			if(!String.isBlank(coOld.Field_Rep__c))
            {
                User u = new User(Id = coOld.Field_Rep__c, Sales_Area_Field_Rep__c=coOld.Field_Rep__r.Sales_Area_Field_Rep__c);
                u.Sales_Area_Field_Rep__c++;
                usersToUpdate.add(u);           
            }
            if(!String.isBlank(co.Field_Rep__c))
            {
                User u = new User(Id = co.Field_Rep__c, Sales_Area_Field_Rep__c=co.Field_Rep__r.Sales_Area_Field_Rep__c);
                u.Sales_Area_Field_Rep__c=10;
                usersToUpdate.add(u);              
            }
Best Answer chosen by John Athitakis
Margaret FleischakerMargaret Fleischaker
Sorry about that! cosChanged should hold all of the Sales Areas that have a change in field rep. So it should be defined and populated in the first for loop.
if(Trigger.isUpdate){
	Set<Id> fieldRepIds = new Set<Id>();
	List<Sales_Area__c> cosChanged = new List<Sales_Area__c>();

	//filter for Sales Areas that have had a change in Field Rep
	for(Sales_Area__c co : Trigger.new){
		Sales_Area__c coOld = Trigger.oldMap.get(co.Id);
		if(coOld.Field_Rep__c != co.Field_Rep__c){
			fieldRepIds.add(coOld.Field_Rep__c);
			fieldRepIds.add(co.Field_Rep__c);
			cosChanged.add(co);
		}
	}

And just to reiterate what I said in my first post - before testing, please make sure there is a value in the the Sales_Area_Field_Rep__c field on the user. Or add in null checks like the below:
 
//decrement Sales Area Field Rep for the old field rep value
			if(!String.isBlank(coOld.Field_Rep__c)){
				User u = fieldReps.get(coOld.Field_Rep__c);
				if(u.Sales_Area_Field_Rep__c == null){
					u.Sales_Area_Field_Rep__c = 0;
				} else {
					u.Sales_Area_Field_Rep__c --;
				}
			}

			//increment Sales Area Field rep for the new field rep value
			if(!String.isBlank(co.Field_Rep__c)){
				User u = fieldReps.get(co.Field_Rep__c);
				if(u.Sales_Area_Field_Rep__c == null){
					u.Sales_Area_Field_Rep__c = 0;
				}
				u.Sales_Area_Field_Rep__c ++;
			}

 

All Answers

Margaret FleischakerMargaret Fleischaker
If the fields are blank/null on the user records, you won't be able to use ++ or += without running into the null pointer exception. In your code, I would recommend checking first for a null, and if it is null, setting it to zero before incrementing.
 
if(u.Sales_Area_Field_Rep__c == null){
    u.Sales_Area_Field_Rep__c = 0;
}
u.Sales_Area_Field_Rep__c ++;

 
Margaret FleischakerMargaret Fleischaker
I just took a closer look at the larger snippet of code - my previous suggestion won't work in this case, because you aren't querying for the user and don't know the value of Sales_Area_Field_Rep__c. If you want to avoid querying, just make sure that the field on all user records is not blank (will require a data migration, and preferably a default value of 0 on new users).
John AthitakisJohn Athitakis

Actually looking back at your answer, I'm confused on two things. You say...

"If you want to avoid querying, just make sure that the field on all user records is not blank (will require a data migration, and preferably a default value of 0 on new users"

But we want to increment/decrement, so we need to know the value. 

As to the rest..I'm also confused. 

This code words (assignign a static value)

User u = new User(Id = co.Field_Rep__c, Sales_Area_Field_Rep__c=co.Field_Rep__r.Sales_Area_Field_Rep__c);
                u.Sales_Area_Field_Rep__c=10;
                usersToUpdate.add(u);
So I created a user, i assigned it the same ID as the 'newmap' (this also works for the old map mind you). And I was able to assign Sales_Area_Field_Rep a value of 10. Clearly I was able to 'know' the id of the the user id from my map.

So then what is wrong with this?
 
User u = new User(Id = coOld.Field_Rep__c, Sales_Area_Field_Rep__c=coOld.Field_Rep__r.Sales_Area_Field_Rep__c);
                u.Sales_Area_Field_Rep__c++;
                usersToUpdate.add(u);


I'm  assigning the Sales Area at create from the map (with new or old map mind you). Can you use references in a map? It's not throwing any errors when I try to do that? 

 

Whats strange is this causes no error:

u.Sales_Area_Field_Rep__c=u.Sales_Area_Field_Rep__c;

But this does
 
u.Sales_Area_Field_Rep__c=u.Sales_Area_Field_Rep__c+1;

 
Margaret FleischakerMargaret Fleischaker
The only fields available in Trigger.newMap and Trigger.oldMap are the Sales_Area__c fields - you won't have access to the Field_Rep__r.Sales_Area_Field_Rep__c field. This is why when you try to increment, you get a null pointer exception.

I think something like this would do the trick:
if(Trigger.isUpdate){
    List<Sales_Area__c> cos = [SELECT Field_Rep__c, Field_Rep__r.Sales_Area_Field_Rep__c FROM     Sales_Area__c WHERE Id in: Trigger.old];

    for(Sales_Area__c co : cos){

            .....checking if field_rep__c has changed...

           User u = new User(Id = coOld.Field_Rep__c, Sales_Area_Field_Rep__c = coOld.Field_Rep__r.Sales_Area_Field_Rep__c);
           u.Sales_Area_Field_Rep__c ++;
           usersToUpdate.add(u);


}
If you wanted to increment the Sales_Area_Field_Rep__c on the user that is newly assigned to the Sales_Area__c, you would want the soql query statement to say WHERE Id in : Trigger.new, but I used Trigger.old since it looked like you were taking the value of the old Field Rep.
John AthitakisJohn Athitakis

Tried the above. No errors but--it's not doing anything anymore (specifically to the old values). Even if I assign a explicit value like u.Sales_Area_Field_Rep__c = 10 it now does nothing. 

 

What the code looks like. Basically what you posted. Im....wondering if with how you have the for loop if its breaking the check 'if changed' condition? 

 

trigger UpdateSalesAreaToUserCount on Sales_Area__c (before insert, before update) {
list <User> usersToUpdate= new List <User>{};
    if(Trigger.IsUpdate){
       List<Sales_Area__c> cos = [SELECT Field_Rep__c, Field_Rep__r.Sales_Area_Field_Rep__c FROM Sales_Area__c WHERE Id in: Trigger.old];
       for (Sales_Area__c co : cos) { 
  		 Sales_Area__c coOld = Trigger.oldMap.get(co.Id);
         
          //Begin Field Rep
 		   	if(coOld.Field_Rep__c != co.Field_Rep__c){
			if(!String.isBlank(coOld.Field_Rep__c))
            {
                User u = new User(Id = coOld.Field_Rep__c, Sales_Area_Field_Rep__c=coOld.Field_Rep__r.Sales_Area_Field_Rep__c);
                u.Sales_Area_Field_Rep__c--;
                usersToUpdate.add(u);           
            }
         
       		 									} 
         
 
					}
  	  }

      try{
            update usersToUpdate;  
        }
    catch (DMLException ex){}
						
    
}
 


 

Margaret FleischakerMargaret Fleischaker
You're totally right - it's breaking the 'if changed' condition. Give this a shot -  it's checking to see if there is a field rep change. If so, it builds a map of user id to user and includes the value for the sales area field rep, and then updates those users based on if they were assigned or unassigned from the sales area.
 
if(Trigger.isUpdate){
	Set<Id> fieldRepIds = new Set<Id>();

	//filter for Sales Areas that have had a change in Field Rep
	for(Sales_Area__c co : Trigger.new){
		Sales_Area__c coOld = Trigger.oldMap.get(co.Id);
		if(coOld.Field_Rep__c != co.Field_Rep__c){
			fieldRepIds.add(coOld.Field_Rep__c);
			fieldRepIds.add(co.Field_Rep__c);
		}
	}

	if(!fieldRepIds.isEmpty()){

		//get the user records for the field reps, including the Sales Area Field Rep Total
		Map<Id,User> fieldReps = new Map<Id,User>([SELECT Sales_Area_Field_Rep__c FROM User WHERE Id in: fieldRepIds]);

		for(Sales_Area__c co : cosChanged){
			Sales_Area__c coOld = Trigger.oldMap.get(co.Id);

			//decrement Sales Area Field Rep for the old field rep value
			if(!String.isBlank(coOld.Field_Rep__c)){
				User u = fieldReps.get(coOld.Field_Rep__c);
				u.Sales_Area_Field_Rep__c --;
			}

			//increment Sales Area Field rep for the new field rep value
			if(!String.isBlank(co.Field_Rep__c)){
				User u = fieldReps.get(co.Field_Rep__c);
				u.Sales_Area_Field_Rep__c ++;
			}
		}

		update fieldReps.values();
	}
}

 
John AthitakisJohn Athitakis

Where are your defining "cosChanged" from line 18?

I assume something like...

 

List<Sales_Area__c> cosChanged = [SELECT Field_Rep__c, Field_Rep__r.Sales_Area_Field_Rep__c FROM Sales_Area__c WHERE Id in: Trigger.new];
 

?

 

John AthitakisJohn Athitakis
Trying the above, I get "System.NullPointerException: Attempt to de-reference a null object: Trigger.UpdateSalesAreaToUserCount: line 29, column 1" on line 29  (which for me is the: u.Sales_Area_Field_Rep__c --, i.e the original issue I first had). So I assume then that I'm wrong about cosChanged..
Margaret FleischakerMargaret Fleischaker
Sorry about that! cosChanged should hold all of the Sales Areas that have a change in field rep. So it should be defined and populated in the first for loop.
if(Trigger.isUpdate){
	Set<Id> fieldRepIds = new Set<Id>();
	List<Sales_Area__c> cosChanged = new List<Sales_Area__c>();

	//filter for Sales Areas that have had a change in Field Rep
	for(Sales_Area__c co : Trigger.new){
		Sales_Area__c coOld = Trigger.oldMap.get(co.Id);
		if(coOld.Field_Rep__c != co.Field_Rep__c){
			fieldRepIds.add(coOld.Field_Rep__c);
			fieldRepIds.add(co.Field_Rep__c);
			cosChanged.add(co);
		}
	}

And just to reiterate what I said in my first post - before testing, please make sure there is a value in the the Sales_Area_Field_Rep__c field on the user. Or add in null checks like the below:
 
//decrement Sales Area Field Rep for the old field rep value
			if(!String.isBlank(coOld.Field_Rep__c)){
				User u = fieldReps.get(coOld.Field_Rep__c);
				if(u.Sales_Area_Field_Rep__c == null){
					u.Sales_Area_Field_Rep__c = 0;
				} else {
					u.Sales_Area_Field_Rep__c --;
				}
			}

			//increment Sales Area Field rep for the new field rep value
			if(!String.isBlank(co.Field_Rep__c)){
				User u = fieldReps.get(co.Field_Rep__c);
				if(u.Sales_Area_Field_Rep__c == null){
					u.Sales_Area_Field_Rep__c = 0;
				}
				u.Sales_Area_Field_Rep__c ++;
			}

 
This was selected as the best answer
John AthitakisJohn Athitakis
This appears to work! THANK YOU SO MUCH!