Take the 2-minute tour ×
Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

I have a trigger and an Account handler. I have an error on record insert. Trigger calls

Accounthandler.OnAfterInsert(Trigger.new, Trigger.newMap);

Here is a simplified version of the handler top method:

public void OnAfterInsert(Account[] newAccounts, Map<Id, Account> newAccountMap){
    if(!System.isFuture() && !System.isBatch()){
        myMethod(null, newAccounts, null, newAccountMap);
    }
}

Now the method itself:

private void identifyAndGeoCodeAccounts(Account[] oldAccounts, Account[] updatedAccounts, Map<ID, Account> oldAccountMap, Map<ID, Account> newAccountMap){
        Set<Id> ChangedAddressIDs = new Set<Id>();
        for(Account a : updatedAccounts){
            system.debug('evaluating account ' + a);
            if( 
                ( a.BillingCountry != null && oldAccounts == null )

                 // Error happens in line above, saying that a.BillingCountry is null object

                || 
                (
                    a.BillingStreet != oldAccountMap.get(a.id).BillingStreet ||
                    a.BillingCity != oldAccountMap.get(a.id).BillingCity ||
                    a.BillingState != oldAccountMap.get(a.id).BillingState ||
                    a.BillingPostalCode != oldAccountMap.get(a.id).BillingPostalCode ||
                    a.BillingCountry != oldAccountMap.get(a.id).BillingCountry
                )
                || 
                ( //otherstuff ) 
            ) {
                ChangedAddressIDs.add(a.id);
            }
        }
        if(ChangedAddressIDs.size() == 1){
            //dostuff
        } else if(ChangedAddressIDs.size() == 0){
            system.debug('ChangedAddressIDs.sizes = 0');
            return;
        } else {
            //system.debug('ChangedAddressIDs.size > 1');
            //do other stuff
        }
    }

And here is the test code:

    @isTest static void hasGeocode() {
            test.startTest();
            Account a = new Account(name='TestAccount');
            //a.BillingCountry = 'US';
            insert a;
            test.stopTest();
            //other stuff after asynch stuff happens
        }

Pretty straightforward. When I populate BillingCountry in the test, all is good. When I don't, all fails. I can debug the Account a and I have no problems. It even shows BillingCountry as null. Any ideas, StackExchangers?

The error is that I'm de-referencing a null object, and it refers specifically to the "a.BillingCountry != null" part. I've isolated it down to that. But a.BillingCountry is included when I debug the Account; even if it is null, my conditional should allow for it to be true, so the first part of the IF clause should be true on insert, so it should add the Id to the Set. But it has an error specifically with a.BillingCountry.

share|improve this question

2 Answers 2

up vote 1 down vote accepted

crop1645 is right in that the error is your second major OR grouping. If the first condition is not satisfied, only then will the second condition be evaluated, and you only want that to happen if there is an oldaccounts. You could do this through trigger awareness (which can make it a little harder to unit test), or you can just make sure you don't evaluate it if there are no oldaccounts:

||
(oldaccounts != null &&     
    (a.BillingStreet != oldAccountMap.get(a.id).BillingStreet ||
    a.BillingCity != oldAccountMap.get(a.id).BillingCity ||
    a.BillingState != oldAccountMap.get(a.id).BillingState ||
    a.BillingPostalCode != oldAccountMap.get(a.id).BillingPostalCode ||
    a.BillingCountry != oldAccountMap.get(a.id).BillingCountry))
||
share|improve this answer
    
Ah, now I understand. This is interesting. Yes, you are correct and my IF statement's second part was tripping me up. HOWEVER, the error message said the wrong line, so I hope that someone at salesforce.com sees this and can get the platform to say that the problem is in the second part of the IF and not the first part. Weird... Thanks for the sleuthing. –  DavidSchach Jul 31 '13 at 1:02

I believe the error is in your 'or' condition. SFDC will report the if condition statement's first line and not pinpoint it down to the actual conditional expression (which is spread over multiple lines in your code)

When a.billingCountry is non null, the first condition is true and APEX won't bother to even evaluate the or condition(s). When it is null, then the or condition(s) get evaluated

As this is an insert operation, Trigger.oldMap won't be available - see APEX Doc http://www.salesforce.com/us/developer/docs/apexcode/index_Left.htm#StartTopic=Content/apex_triggers_context_variables.htm?SearchType=Stem

You'll need to be isInsert vs isUpdateaware

share|improve this answer
    
I agree on all that. The code errors at the conditional and never exists the IF clause. I've narrowed it down to "a.BillingCountry != null" for the error. I know oldMap isn't available, and as you can see I've accounted for that. It doesn't error at "oldAccounts == null" so I have no problems there. The code can't be isInsert aware because I've pulled it from the trigger to a handler class, but it is effectively aware because I check if the old list is null. –  DavidSchach Jul 30 '13 at 23:14
    
@David oldAccounts is not the same as oldAccountMap. If a.billingCountry is null, then the first if condition is false and APEX will immediately start evaluating the or condition(s). –  crop1645 Jul 30 '13 at 23:25
1  
@David - also, as an FYI - one can always do if (Trigger.isExecuting && Trigger.isInsert) within any class. Trigger context variables are not limited in use to just a .trigger file. That said, testing for null in the right places and right ways is clearer - especially as I can see you are using a pattern –  crop1645 Jul 30 '13 at 23:27

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.