+ Start a Discussion
alxalx 

Null Pointer in Trigger

Hey all,

 

I have a NullPointerException in my trigger. The purpose of the trigger is to use Snapshot to find its parent Opportunity's Owner Id, then apply this Id to Snapshot.

 

 

trigger Insert_RelatedOwnerID_as_SnapShotPipeForecast_by_Opp on SnapShot_Pipe_Forecast_by_Opp__c (before insert) {
		Map<Id, SnapShot_Pipe_Forecast_by_Opp__c> smap = new Map<Id, SnapShot_Pipe_Forecast_by_Opp__c>([select id, Opportunity_lookup__r.OwnerId from SnapShot_Pipe_Forecast_by_Opp__c where id in :Trigger.newMap.keySet()]);
         	
         	for(SnapShot_Pipe_Forecast_by_Opp__c s: Trigger.new){
              s.OwnerId = smap.get(s.Id).Opportunity_lookup__r.OwnerId;
			}
}

 

 

 

The exception is thrown on line 2, column 191. I'm sure it's an easy fix, but I can't see it.

 

Any help is appreciated.

Best Answer chosen by Admin (Salesforce Developers) 
gtindugtindu

Try the following and post your debug log...

 

trigger Insert_RelatedOwnerID_as_SnapShotPipeForecast_by_O pp on SnapShot_Pipe_Forecast_by_Opp__c (before insert) {
	List<Id> opportunityLookups = new List<Id>();
	for ( SnapShot_Pipe_Forecast_by_Opp__c ss : Trigger.new) {
		opportunityLookups.add( ss.Opportunity_Lookup__c );
		System.debug('Opportunity Relationship: ' + ss.Opportunity_Lookup__c);
	}

	Map<Id, Opportunity> smap = new Map<Id, Opportunity>([select id, OwnerId from Opportunity where id in :opportunityLookups]);

	System.debug ('Opportunity Map: ' + smap);
         	
	for ( SnapShot_Pipe_Forecast_by_Opp__c s : Trigger.new ) {
		// Added debug output
		System.debug ('Current OwnerId: ' + s.OwnerId);
		System.debug ('Has Matching Opportunity Map Entry: ' + smap.containsKey ( s.Opportunity_Lookup__c ));
		if (smap.containsKey ( s.Opportunity_Lookup__c ) )
			System.debug ('Matching Opportunity Map Entry: ' + smap.get ( s.Opportunity_Lookup__c ));

		// Added if... check to ensure that a matching record exists in the list before dereferencing
		if ( smap.containsKey ( s.Opportunity_Lookup__c ) )  
			s.OwnerId = smap.get(s.Opportunity_Lookup__c).OwnerId;
	}
}

I added a debug line on the first iteration to build the lookup.  Is it possible that the Opportunity_Lookup__c field is blank?

All Answers

gtindugtindu

You want to make this an after insert trigger for 2 reasons.  

 

1. You won't be able to reference newMap in a before insert scenario.

2. Your for ... loop would also fail as s.Id would be null.

 

Ids won't yet be assigned during a before insert operation.

 

[edit below]
Alternatively - seeing that you're trying to assign the owner and might not be able to update from within an after operation you could amend your code as such to work as-is.

 

trigger Insert_RelatedOwnerID_as_SnapShotPipeForecast_by_O pp on SnapShot_Pipe_Forecast_by_Opp__c (before insert) {
	List<Id> opportunityLookups = new List<Id>();
	for ( SnapShot_Pipe_Forecast_by_Opp__c ss : Trigger.new) {
		opportunityLookups.add( ss.Opportunity_Lookup__c );
	}

	Map<Id, Opportunity> smap = new Map<Id, Opportunity>([select id, OwnerId from Opportunity where id in :opportunityLookups]);
         	
	for ( SnapShot_Pipe_Forecast_by_Opp__c s : Trigger.new ) {
		// Added if... check to ensure that a matching record exists in the list before dereferencing
		if ( smap.containsKey ( s.Opportunity_Lookup__c ) )  
			s.OwnerId = smap.get(s.Opportunity_Lookup__c).OwnerId;
	}
}
alxalx

I have tried after insert, but i get a Read only error: 

 

: execution of AfterInsert caused by: System FinalException: Record is read-only: Trigger.Insert_RelatedOwnerID_as_SnapShotPipeForecast_by_Opp: line 5, column 15

 

I have all read, write, execute rights to everything.. So I don't really understand what's going on here...

gtindugtindu

You can't do a direct assignment in an after trigger.  see my edit above - it will take you to the promised land. 

I had already crafted the original response before i noticed that you were trying to update a field on the record.

alxalx

gtindu,

 

So i tried your code, it compiles and runs in sandbox, but when creating a new Snapshot object, it does not change the Snapshot Owner Id to the Opp ID. Instead the Owner Id is still me(the creator).

 

I appreciate your help!

 

 

gtindugtindu

alx,

 

Try adding a few System.Debug line in the for loop - and check the debug logs to see if the opportunity is being found and/or the ownerid is different.

 

trigger Insert_RelatedOwnerID_as_SnapShotPipeForecast_by_O pp on SnapShot_Pipe_Forecast_by_Opp__c (before insert) {
	List<Id> opportunityLookups = new List<Id>();
	for ( SnapShot_Pipe_Forecast_by_Opp__c ss : Trigger.new) {
		opportunityLookups.add( ss.Opportunity_Lookup__c );
	}

	Map<Id, Opportunity> smap = new Map<Id, Opportunity>([select id, OwnerId from Opportunity where id in :opportunityLookups]);

	System.debug ('Opportunity Map: ' + smap);
         	
	for ( SnapShot_Pipe_Forecast_by_Opp__c s : Trigger.new ) {
		// Added debug output
		System.debug ('Current OwnerId: ' + s.OwnerId);
		System.debug ('Has Matching Opportunity Map Entry: ' + smap.containsKey ( s.Opportunity_Lookup__c ));
		if (smap.containsKey ( s.Opportunity_Lookup__c ) )
			System.debug ('Matching Opportunity Map Entry: ' + smap.get ( s.Opportunity_Lookup__c ));

		// Added if... check to ensure that a matching record exists in the list before dereferencing
		if ( smap.containsKey ( s.Opportunity_Lookup__c ) )  
			s.OwnerId = smap.get(s.Opportunity_Lookup__c).OwnerId;
	}
}
alxalx

gtindu,

 

Here is my debug log:

18.0 APEX_CODE,DEBUG;APEX_PROFILING,INFO;CALLOUT,INFO;DB,INFO;VALIDATION,INFO;WORKFLOW,INFO
9:38:19.689|EXECUTION_STARTED
9:38:19.689|CODE_UNIT_STARTED|[EXTERNAL]|01qS00000000NZJ|Insert_RelatedOwnerID_as_SnapShotPipeForecast_by_Opp on SnapShot_Pipe_Forecast_by_Opp trigger event BeforeInsert for [new]
9:38:19.691|METHOD_ENTRY|[4,3]|LIST<Id>.add(Id)
9:38:19.691|METHOD_EXIT|[4,3]|LIST<Id>.add(Id)
9:38:19.691|SOQL_EXECUTE_BEGIN|[7,55]|Aggregations:0|select id, OwnerId from Opportunity where id in :opportunityLookups
9:38:19.696|SOQL_EXECUTE_END|[7,55]|Rows:0
9:38:19.696|METHOD_ENTRY|[9,2]|System.debug(String)
9:38:19.696|USER_DEBUG|[9,2]|DEBUG|Opportunity Map: {}
9:38:19.696|METHOD_EXIT|[9,2]|System.debug(String)
9:38:19.696|METHOD_ENTRY|[13,3]|System.debug(String)
9:38:19.696|USER_DEBUG|[13,3]|DEBUG|Current OwnerId: 005000000073Z85AAE
9:38:19.696|METHOD_EXIT|[13,3]|System.debug(String)
9:38:19.696|METHOD_ENTRY|[14,3]|System.debug(String)
9:38:19.696|METHOD_ENTRY|[14,58]|MAP<Id,Opportunity>.containsKey(Id)
9:38:19.696|METHOD_EXIT|[14,58]|MAP<Id,Opportunity>.containsKey(Id)
9:38:19.696|USER_DEBUG|[14,3]|DEBUG|Has Matching Opportunity Map Entry: false
9:38:19.696|METHOD_EXIT|[14,3]|System.debug(String)
9:38:19.696|METHOD_ENTRY|[15,7]|MAP<Id,Opportunity>.containsKey(Id)
9:38:19.697|METHOD_EXIT|[15,7]|MAP<Id,Opportunity>.containsKey(Id)
9:38:19.697|METHOD_ENTRY|[19,8]|MAP<Id,Opportunity>.containsKey(Id)
9:38:19.697|METHOD_EXIT|[19,8]|MAP<Id,Opportunity>.containsKey(Id)
9:38:19.697|CUMULATIVE_LIMIT_USAGE
9:38:19.697|LIMIT_USAGE_FOR_NS|(default)|
  Number of SOQL queries: 1 out of 20
  Number of query rows: 0 out of 1000
  Number of SOSL queries: 0 out of 0
  Number of DML statements: 0 out of 20
  Number of DML rows: 0 out of 100
  Number of script statements: 8 out of 10200
  Maximum heap size: 0 out of 300000
  Number of callouts: 0 out of 10
  Number of Email Invocations: 0 out of 10
  Number of fields describes: 0 out of 10
  Number of record type describes: 0 out of 10
  Number of child relationships describes: 0 out of 10
  Number of picklist describes: 0 out of 10
  Number of future calls: 0 out of 10
  Number of find similar calls: 0 out of 0
  Number of System.runAs() invocations: 0 out of 20

9:38:19.697|CUMULATIVE_LIMIT_USAGE_END

9:38:19.697|CODE_UNIT_FINISHED|Insert_RelatedOwnerID_as_SnapShotPipeForecast_by_Opp on SnapShot_Pipe_Forecast_by_Opp trigger event BeforeInsert for [new]
9:38:19.697|EXECUTION_FINISHED

 

 

The line "Opportunity Map: {}". The Map is empty, so thats why i keep getting this Null Pointer stuff, right?

 

gtindugtindu

Try the following and post your debug log...

 

trigger Insert_RelatedOwnerID_as_SnapShotPipeForecast_by_O pp on SnapShot_Pipe_Forecast_by_Opp__c (before insert) {
	List<Id> opportunityLookups = new List<Id>();
	for ( SnapShot_Pipe_Forecast_by_Opp__c ss : Trigger.new) {
		opportunityLookups.add( ss.Opportunity_Lookup__c );
		System.debug('Opportunity Relationship: ' + ss.Opportunity_Lookup__c);
	}

	Map<Id, Opportunity> smap = new Map<Id, Opportunity>([select id, OwnerId from Opportunity where id in :opportunityLookups]);

	System.debug ('Opportunity Map: ' + smap);
         	
	for ( SnapShot_Pipe_Forecast_by_Opp__c s : Trigger.new ) {
		// Added debug output
		System.debug ('Current OwnerId: ' + s.OwnerId);
		System.debug ('Has Matching Opportunity Map Entry: ' + smap.containsKey ( s.Opportunity_Lookup__c ));
		if (smap.containsKey ( s.Opportunity_Lookup__c ) )
			System.debug ('Matching Opportunity Map Entry: ' + smap.get ( s.Opportunity_Lookup__c ));

		// Added if... check to ensure that a matching record exists in the list before dereferencing
		if ( smap.containsKey ( s.Opportunity_Lookup__c ) )  
			s.OwnerId = smap.get(s.Opportunity_Lookup__c).OwnerId;
	}
}

I added a debug line on the first iteration to build the lookup.  Is it possible that the Opportunity_Lookup__c field is blank?

This was selected as the best answer
alxalx

gtindu,

 

thank you for sticking with me dude.

 

Opportunity Relationship is returning null.

18.0 APEX_CODE,DEBUG;APEX_PROFILING,INFO;CALLOUT,INFO;DB,INFO;VALIDATION,INFO;WORKFLOW,INFO
13:31:55.684|EXECUTION_STARTED
13:31:55.684|CODE_UNIT_STARTED|[EXTERNAL]|01qS00000000NZJ|Insert_RelatedOwnerID_as_SnapShotPipeForecast_by_Opp on SnapShot_Pipe_Forecast_by_Opp trigger event BeforeInsert for [new]
13:31:55.686|METHOD_ENTRY|[4,3]|LIST<Id>.add(Id)
13:31:55.687|METHOD_EXIT|[4,3]|LIST<Id>.add(Id)
13:31:55.687|METHOD_ENTRY|[5,3]|System.debug(String)
13:31:55.687|USER_DEBUG|[5,3]|DEBUG|Opportunity Relationship: null
13:31:55.687|METHOD_EXIT|[5,3]|System.debug(String)
13:31:55.687|SOQL_EXECUTE_BEGIN|[8,55]|Aggregations:0|select id, OwnerId from Opportunity where id in :opportunityLookups
13:31:55.694|SOQL_EXECUTE_END|[8,55]|Rows:0
13:31:55.694|METHOD_ENTRY|[10,2]|System.debug(String)
13:31:55.694|USER_DEBUG|[10,2]|DEBUG|Opportunity Map: {}
13:31:55.694|METHOD_EXIT|[10,2]|System.debug(String)
13:31:55.694|METHOD_ENTRY|[14,3]|System.debug(String)
13:31:55.694|USER_DEBUG|[14,3]|DEBUG|Current OwnerId: 005000000073Z85AAE
13:31:55.694|METHOD_EXIT|[14,3]|System.debug(String)
13:31:55.694|METHOD_ENTRY|[15,3]|System.debug(String)
13:31:55.694|METHOD_ENTRY|[15,58]|MAP<Id,Opportunity>.containsKey(Id)
13:31:55.694|METHOD_EXIT|[15,58]|MAP<Id,Opportunity>.containsKey(Id)
13:31:55.694|USER_DEBUG|[15,3]|DEBUG|Has Matching Opportunity Map Entry: false
13:31:55.694|METHOD_EXIT|[15,3]|System.debug(String)
13:31:55.694|METHOD_ENTRY|[16,7]|MAP<Id,Opportunity>.containsKey(Id)
13:31:55.694|METHOD_EXIT|[16,7]|MAP<Id,Opportunity>.containsKey(Id)
13:31:55.694|METHOD_ENTRY|[20,8]|MAP<Id,Opportunity>.containsKey(Id)
13:31:55.694|METHOD_EXIT|[20,8]|MAP<Id,Opportunity>.containsKey(Id)
13:31:55.694|CUMULATIVE_LIMIT_USAGE
13:31:55.694|LIMIT_USAGE_FOR_NS|(default)|
  Number of SOQL queries: 1 out of 20
  Number of query rows: 0 out of 1000
  Number of SOSL queries: 0 out of 0
  Number of DML statements: 0 out of 20
  Number of DML rows: 0 out of 100
  Number of script statements: 9 out of 10200
  Maximum heap size: 0 out of 300000
  Number of callouts: 0 out of 10
  Number of Email Invocations: 0 out of 10
  Number of fields describes: 0 out of 10
  Number of record type describes: 0 out of 10
  Number of child relationships describes: 0 out of 10
  Number of picklist describes: 0 out of 10
  Number of future calls: 0 out of 10
  Number of find similar calls: 0 out of 0
  Number of System.runAs() invocations: 0 out of 20

13:31:55.694|CUMULATIVE_LIMIT_USAGE_END

13:31:55.694|CODE_UNIT_FINISHED|Insert_RelatedOwnerID_as_SnapShotPipeForecast_by_Opp on SnapShot_Pipe_Forecast_by_Opp trigger event BeforeInsert for [new]
13:31:55.694|EXECUTION_FINISHED

 

At the moment the trigger compiles and runs, but still does not change Snapshot Owner to Opp owner. 

 

I dont understand why adding ss.Opportunity_lookup__c would return null, the code seems sound.

Which leads me to believe the custom object reference is at fault. When i use schema to try and run:

 

"Select s.Opportunity_lookup__c From SnapShot_Pipe_Forecast_by_Opp__c s"

 

I just get empty cells. In similar children of Opportunities with references back to their parents, there is some output with look up fields.

 

Is there somewhere in salesforce/sandbox where i can look at the documentation or code of custom objects? A previous dev created these things and it would be nice if i could follow his logic.

 

gtindugtindu

In this case - you're Opportunity lookup field is blank.  The data isn't being provided.


If the field is not set with a value by the user - it will not be able to reference an opportunity owner... you could setup a validation rule to require it perhaps.

alxalx

BAH,

 

I've been fooled. You're right the field wasn't getting populated properly. 

 

Other than that the code seems to run just fine right now.

 

Thank you so much gtindu.

gtindugtindu

No problem - i'll expect you to return the favor on one of my questions in the future :smileyhappy:

alxalx

Haha, i'll do my best to help you if that day comes.