0

I'm running a batch update on tasks and my task trigger handler is throwing a null pointer exception error. If I go through and update the tasks individually, I don't have any issues with them. If I run a batch of 2000, 1600 will update and 400 will throw the error. I'm completely at a loss why this is happening.

The following line is where I'm getting the null pointer errors:

if(String.ValueOf(t.WhatId).left(3) == '003'){

Complete code:

public class TaskTriggerHandler {
    String stdRecTypeId = [SELECT id from RecordType WHERE sObjectType = 'Task' AND Name = 'Standard'].id;

    //execute after insert/after update
    public void isAfterInsertTask(Map<Id, Task> newTaskTriggerMap){
        Set<Id> acctIds = new Set<Id>();
        Set<Id> opptyIds = new Set<Id>();

        Map<Id, Id> contactIdAcctIdMap = new Map<Id, Id>();
        List<Id> contactIds = new List<Id>();
        for(Task t : newTaskTriggerMap.values()){
            if(t.whoId != NULL){
                contactIds.add(t.whoId);
            }
        }
        for(Contact c : [SELECT Id, AccountId FROM Contact WHERE id IN :contactIds]){
            contactIdAcctIdMap.put(c.Id, c.AccountId);
        }
        //loop through tasks and put account/oppty id's into sets
        for(Task t : newTaskTriggerMap.values()){
            if(t.WhatId == NULL && String.valueOf(t.WhoId).left(3) == '003'){
                acctIds.add(contactIdAcctIdMap.get(t.whoId));
            } else if(t.whatId != NULL && String.valueOf(t.WhatId).left(3) == '001'){
                acctIds.add(t.AccountId);
            } else if(t.whatId != NULL && String.valueof(t.WhatId).left(3) == '006'){
                opptyIds.add(t.whatId);
            }
        }
        List<Account> acctsToUpdate = new List<Account>();
        //execute account update logic
        if(!acctIds.isEmpty()){
            List<Account> accts = [SELECT id, Number_of_Scheduled_Activities__c,
                                   Number_of_Completed_Activities__c, Next_Activity_Date__c,
                                   Last_Completed_Activity_Date__c, Next_Activity_Assigned_To__c
                                   FROM Account WHERE Id IN :acctIds];
            List<Task> acctTasks = [SELECT id, ActivityDate, OwnerId, IsClosed, AccountId, WhatId, RecordTypeId
                                    FROM Task WHERE AccountId = :acctIds];
            List<Opportunity> acctOpptys = [SELECT id, AccountId, IsClosed, CloseDate 
                                            FROM Opportunity WHERE AccountId IN :acctIds AND IsClosed = False 
                                            ORDER BY CloseDate ASC];
            Map<Id, List<Task>> mapAcctidsTasks = new Map<Id, List<Task>>();
            for(Task t : acctTasks){
                if(!mapAcctIdsTasks.containsKey(t.AccountId)){
                    mapAcctIdsTasks.put(t.AccountId, new List<Task>());
                }
                mapAcctIdsTasks.get(t.AccountId).add(t);
            }

            Map<Id, List<Opportunity>> mapAcctIdOpptys = new Map<Id, List<Opportunity>>();
            if(!acctOpptys.isEmpty()){
                for(Opportunity o : acctOpptys){
                    if(!mapAcctIdOpptys.containsKey(o.AccountId)){
                        mapAcctIdOpptys.put(o.AccountId, new List<Opportunity>());
                    }
                    mapAcctIdOpptys.get(o.AccountId).add(o);
                }
            }
            List<Task> tasksToUpdate = new List<Task>();
            //loop through accounts and increment task counters tasks 
            for(Account a : accts){
                Decimal numOpenTasks = 0;
                Decimal numClosedTasks = 0;
                Date nextScheduled; 
                Date lastCompleted = a.Last_Completed_Activity_Date__c;
                Id nextAssigned = a.Next_Activity_Assigned_To__c;
                if(!mapAcctIdOpptys.isEmpty()){
                    for(Task t : mapAcctIdsTasks.get(a.id)){
                        Task updatedTask = new Task(id=t.id);
//The following line is where I'm getting the null pointer errors

                        if(String.ValueOf(t.WhatId).left(3) == '003'){

                               updatedTask.whatId = mapAcctIdOpptys.get(t.WhatId)[0].Id;
                               tasksToUpdate.add(updatedTask);
                           }
                        if(!t.IsClosed){
                            numOpenTasks++;
                            if((nextScheduled == NULL || t.ActivityDate <= nextScheduled) && 
                               t.ActivityDate >= date.today()){
                                   nextAssigned = t.OwnerId;
                                   nextScheduled = t.ActivityDate;
                               }
                        }
                        if (t.IsClosed){
                            numClosedTasks++;
                            if(lastCompleted == NULL || t.ActivityDate >= lastCompleted){
                                lastCompleted = t.ActivityDate;
                            }
                        }
                    }
                }
                Account acctToUpdate = new Account(Id = a.id);
                Boolean wasUpdated = false;
                if(nextAssigned != a.Next_Activity_Assigned_To__c){
                    acctToUpdate.Next_Activity_Assigned_To__c = nextAssigned;
                    wasUpdated = true;
                }
                if(nextScheduled != a.Next_Activity_Date__c){
                    acctToUpdate.Next_Activity_Date__c = nextScheduled;
                    wasUpdated = true;
                }
                if(lastCompleted != a.Last_Completed_Activity_Date__c){
                    acctToUpdate.Last_Completed_Activity_Date__c = lastCompleted;
                    wasUpdated = true;
                }
                if(numClosedTasks != a.Number_of_Completed_Activities__c){
                    acctToUpdate.Number_of_Completed_Activities__c = numClosedTasks;
                    wasUpdated = true;
                }
                if(numOpenTasks != a.Number_of_Scheduled_Activities__c){
                    acctToUpdate.Number_of_Scheduled_Activities__c = numOpenTasks;
                    wasUpdated = true;
                }
                if(wasUpdated){
                    acctsToUpdate.add(acctToUpdate);
                }
            }
            if(!acctsToUpdate.isEmpty()){
                update acctsToUpdate;
            }
            if(!tasksToUpdate.isEmpty()){
                update tasksToUpdate;
            }
        }
1
  • Neither WhoId or WhatId is a required field on Task - see Sobject Ref
    – cropredy
    Commented Dec 6, 2017 at 17:10

1 Answer 1

2

Just add a guard clause. You should never enforce that a field is not null by just assuming it will always be populated.

Instead use:

if (t.WhatId != null && t.WhatId.getSObjectType() == Contact.sObjectType)
5
  • thank you! IT was a combo of referencing contact when I meant to reference account (details, details) and how I referenced. Thank you! Totally solved it!
    – cuppajoe22
    Commented Dec 6, 2017 at 17:29
  • Huh. Under what situation would WhatId be a Contact Id?
    – sfdcfox
    Commented Dec 6, 2017 at 18:11
  • @sfdcfox Just translating the OP's code directly (they were checking against the '003' prefix). Sounds like they meant to check for Account.sObjectType, which is just one more reason this syntax is preferable, since it is much more explicit.
    – Adrian Larson
    Commented Dec 6, 2017 at 18:12
  • @sfdcfox - I don't think a contact could be the whatId? I think Account/Opportunity are the usual references. I think contact is always a whoId. It was my mistake when I wrote the original code - I missed that I was referencing the wrong object. And Adrian is right - I went through and replace my references to '003' or '001' with Sobject.sObjectType instead. Much easier to keep track of.
    – cuppajoe22
    Commented Jan 19, 2018 at 18:28
  • @cuppajoe22 WhatId is never a ContactId or LeadId. It will always be something else, like an Account, Opportunity, or Case. That's exactly why we recommend using the SObjectType objects, to avoid mistakes like that.
    – sfdcfox
    Commented Jan 19, 2018 at 18:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .