+ Start a Discussion
kshannonkshannon 

Apex Trigger de-reference null object when created by API, but not with data import/native ui

I have a trigger that is called before insert on "Revenue__c" object. Simply put it is checking the newly entered "Canvas_Id__c" field to match within a custom setting and then take the value from the custom setting and apply it to the Canvas__c field. Pretty straight forward and works with dataloader and native creation, but when running from API call, it seems that it is not able to reference the custom setting details/
 
trigger RevenueCanvasName on Revenue__c (before insert, before update) {
    public static List<Revenue__c> updateRevenueList;
    for (Integer i = 0; i < Trigger.new.size(); i++){
        if(Trigger.new[i].Canvas_Id__c != null || Trigger.new[i].Canvas_Id__c != Trigger.old[i].Canvas_Id__c){
            String cid = String.valueOf(Trigger.new[i].Canvas_Id__c);
            Trigger.new[i].Canvas__c = Canvas__c.getInstance(''+cid+'').Canvas__c;
        }
    }
}

Running on command line API I receive error of:

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

Trigger.RevenueCanvasName: line 6, column 1

Is there a difference referencing custom settings via the API? This has me stumped...
Best Answer chosen by kshannon
kshannonkshannon
Finally able to figure it out, it turns out the value that is in cid is actually "1.0" or "5.0" in decimal form instead of integer. Ultimately the fix for this was to change the cid assignment to:

String cid = String.valueOf(Trigger.new[i].Canvas_Id__c.intvalue());

This way it ensures that the referenced number is not a decimal and will in fact find the appropriate associated custom setting. Appreciate the help again on this! Canvas_Id__c is a number with no decimal places, but apparently when referencing it in the trigger via API call it's coming out as a decimal.

All Answers

Mahesh DMahesh D
Hi Shannon,

Please use the below code:
 

 
trigger RevenueCanvasName on Revenue__c (before insert, before update) {
    public static List<Revenue__c> updateRevenueList;
    for (Integer i = 0; i < Trigger.new.size(); i++){
        if(Trigger.new[i].Canvas_Id__c != null && (Trigger.isInsert || Trigger.new[i].Canvas_Id__c != Trigger.old[i].Canvas_Id__c)){
            String cid = String.valueOf(Trigger.new[i].Canvas_Id__c);
			if(Canvas__c.getInstance(''+cid+'') != null)
				Trigger.new[i].Canvas__c = Canvas__c.getInstance(''+cid+'').Canvas__c;
        }
    }
}


Please do let me know if it helps you.

Regards,
Mahesh
kshannonkshannon
Thanks Mahesh, This avoids the error, but does not execute the trigger properly. I guess the root of the problem is that when inserting via API the Trigger.new[i].Canvas_Id__c is null, I'm not sure as to why that would happen. When doing this with data loader or by native UI the trigger works fine. When calling via databasedotcom gem on ruby it doesn't properly execute.

Revenue__c.create({RecordTypeId: "xxxxxxxx", Canvas_Id__c: 3, Account__c: "xxxxxx"}) has the issue where the trigger sees Canvas_Id__c as null only when calling from API for some reason. Do you know if the trigger doesn't function the same if you call from a rest API? Very strange as the dataloader is using the API call I would assume.
Mahesh DMahesh D
Hi Shannon,

Option 1:

Please make sure that API is sending the information for Canvas_Id__c field.

Option 2:

Please make sure that the corresponding Custom Settings is available in the Org.

Option 3:

Please make sure that the Interface user is having permission for Canvas_Id__c field.

Regards,
Mahesh
kshannonkshannon
Checked the debug logs in the call, it's showing Canvas_Id__c is indeed being sent.

The Custom Setting is properly setup

Permissions are all fine, as I said I was able to load the same data by just using Data Loader. I'll have to dig in and see if it's an issue with the API call itself..
Mahesh DMahesh D
Hi Shannon,

Please take the below code and provide the debug messages:
 
trigger RevenueCanvasName on Revenue__c (before insert, before update) {
    public static List<Revenue__c> updateRevenueList;
    for (Integer i = 0; i < Trigger.new.size(); i++){
        if(Trigger.new[i].Canvas_Id__c != null && (Trigger.isInsert || Trigger.new[i].Canvas_Id__c != Trigger.old[i].Canvas_Id__c)){
            String cid = String.valueOf(Trigger.new[i].Canvas_Id__c);
			System.debug('===========cid:'+cid);
			System.debug('===========Canvas__c.getInstance:'+Canvas__c.getInstance(cid));
			if(Canvas__c.getInstance(''+cid+'') != null)
				Trigger.new[i].Canvas__c = Canvas__c.getInstance(''+cid+'').Canvas__c;
        }
    }
}

If the Canvas_Id__c is an SFDC Id then it may be sending 15 digits vs 18 digits is one of the reason not getting the Custom Settings.

Please do let me know if it helps you.

Regards,
Mahesh
kshannonkshannon
Finally able to figure it out, it turns out the value that is in cid is actually "1.0" or "5.0" in decimal form instead of integer. Ultimately the fix for this was to change the cid assignment to:

String cid = String.valueOf(Trigger.new[i].Canvas_Id__c.intvalue());

This way it ensures that the referenced number is not a decimal and will in fact find the appropriate associated custom setting. Appreciate the help again on this! Canvas_Id__c is a number with no decimal places, but apparently when referencing it in the trigger via API call it's coming out as a decimal.
This was selected as the best answer