+ Start a Discussion
hal9001hal9001 

Why does trigger behavior differ - web interface vs data loader

I'm having fun trying bulkifying my triggers.  Maybe too much fun!

 

Anyway, in the code below, about 8 lines form the bottom, there is this line:

        b.Balance__c = b.Balance__c + trans.Qty__c;

This line works fine when adding data through the web interface, but fails with a NullPointerException when I use the data loader.  

 

If I change the line to:

b.Balance__c =  trans.Qty__c;

Then the data loader does not err out.  So I know the problem is when I try to add in the current balance.  Could it be that my table is named Balance__c and it also also has a column named Balance__c?  But it works through the web interface, just not through the data loader.

 

 

Any idea why?  I believe it is thoroughly bulikified.

trigger afterInsertUpdateTrans on Trans__c (after insert, after update) {
    // create a map of existing balance records
    // since locations and equipment are dynamic,
    // balance records are not created until a transaction containing the location and equipment is added
    // there is a single unique balance record for very combination of location and equipment that has a transaction
    // Balance_Key__c is a calculated variable that concatenates the Location Id and Equipment Id
    // Balance_Key__c is defined on both the Trans__c and Balance__c tables
    Map<string,Id> balanceMap = new  Map<string,id>();
    for (Balance__c myBals : [select Balance_Key__c,Id from Balance__c]) {
        balanceMap.put(myBals.Balance_Key__c,myBals.Id);
    }

    string bk;       // to hold the results of the lookup of the key into balanceMap

    // add any missing balance records
    
    List<Balance__c> balanceToInsert = new List<Balance__c>{}; 
    for (Trans__c trans : Trigger.new) 
     {
     bk = balanceMap.get(trans.Balance_Key__c);
     If (bk==null){  // add a row to balanceToInsert
         Balance__c b = new Balance__c();
         b.Location__c = trans.Location__c;
         b.Equipment__c = trans.Equipment__c;
         balanceToInsert.add(b);
     }
    
     }    
    insert balanceToInsert;
    // finished adding any missing balance records



    // make a map of balance records
    map<string, Balance__c> balanceMap2 = new map<string, Balance__c>([select Balance_Key__c, id,Balance__c from Balance__c]);            
    Id balanceObjectId; // to hold the results of the lookup of the key into Balances 

    Map<string,Id> balanceLookup = new  Map<string,id>();
    for (Balance__c myBals : [select Balance_Key__c,Id from Balance__c]) {
        balanceLookup.put(myBals.Balance_Key__c,myBals.Id);
    }

   List<Balance__c> balanceToUpdate = new List<Balance__c>{};

    for (Trans__c trans : Trigger.new) 
 {

     balanceObjectId = balanceLookup.get(trans.Balance_Key__c); 

     Balance__c b = balanceMap2.get(balanceObjectId);
     
     If (trigger.IsInsert){
         // the next line works in the web interface
         // but fails in apex data loader with a System.NullPointerException
         b.Balance__c = b.Balance__c + trans.Qty__c;
         } Else {
         b.Balance__c = b.Balance__c + trans.Qty__c - System.Trigger.oldMap.get(trans.Id).Qty__c;
        }
    balanceToUpdate.add(b);
}
update balanceToUpdate;

}

 

Best Answer chosen by Admin (Salesforce Developers) 
Aar3538Aar3538

Hello,

 

Is it possible that when using dataloader you might not be mapping Balance__c?

 

Currently your code is setup to do Balance = Balance + Qty however if Balance is null then null + null  will cause a null pointer exception. 

 

Perhaps throw an if statement to check if Balance__c is null right before that to see if thats the case, and if so then just make Balance__c = trans.Qty__c.

 

Hope this helps!

 

 

All Answers

Aar3538Aar3538

Hello,

 

Is it possible that when using dataloader you might not be mapping Balance__c?

 

Currently your code is setup to do Balance = Balance + Qty however if Balance is null then null + null  will cause a null pointer exception. 

 

Perhaps throw an if statement to check if Balance__c is null right before that to see if thats the case, and if so then just make Balance__c = trans.Qty__c.

 

Hope this helps!

 

 

This was selected as the best answer
hal9001hal9001

Actually, I'm loading records for another table through the data loader.  The trigger adds "child" records.

 

But I took your advice and tested for null, and it resolved my issue!  I'm not sure why the values were coming up null only through the dataloader, especially when they weren't actually null.  

 

Here is what I did:

 

decimal o = b.Balance__c;
if (o == null)
o = 0;

 

and then I substituted o for b.Balance__c to do the updates.