1

I am at a loss as to why this trigger is throwing up a NullPointerException... it isn't clear to me, as I am querying for the OwnerId before I loop through my inserted tasks. The error message is as follows:

"Apex trigger TaskCreated caused an unexpected exception, contact your administrator: TaskCreated: execution of AfterInsert caused by: System.NullPointerException: Attempt to de-reference a null object: Trigger.TaskCreated: line 43, column 1"

 trigger TaskCreated on Task (after insert) {

    List<Task> insertedTasks =  [SELECT Id, WhoId, WhatId, OwnerId, Subject, ActivityDate, Priority, Description, Status, Type
                                    FROM Task 
                                    WHERE Id 
                                    IN :Trigger.newMap.keySet()];

    List<Task> caseTasks = new List<Task>();
    List<Id> caseIds = new List<Id>();
    List<Case> cases = new List<Case>();
    List<Task> tasksToDelete = new List<Task>();
    List<Task> tasksToInsert = new List<Task>();
    Task newTask = new Task();
    Id contactId;
    String whatId;


    //Loop through inserted tasks and grab those associated with a case, but with no contact referenced
    for(Task task : insertedTasks) { 
        whatId = task.WhatId; //Must write this to a String so we can use the startsWith function below

        if(whatId != null && task.WhoId == null){
            if(whatId.startsWith('500')){
                caseTasks.add(task);
                caseIds.add(task.WhatId);
            }
        }

        whatId = null;
    }

    cases = [SELECT Id, ContactId, Owner.Type  
                FROM Case 
                WHERE Id 
                IN :caseIds];

    //Loop through the cases and create new tasks that reference the case contacts
    for (Task task : caseTasks){
        for(Case c : cases){
            if(task.WhatId == c.Id && c.ContactId != null ){

                if(task.OwnerId == null || c.Owner.Type == 'Queue') newTask.OwnerId = '00550000004DHr4'; //Assign to LA team if still owned by a queue
                else newTask.OwnerId = task.OwnerId;

                newTask.Subject = task.Subject != null ? task.Subject : null;
                newTask.ActivityDate = task.ActivityDate != null ? task.ActivityDate : null;
                newTask.Priority = task.Priority != null ? task.Priority : null;
                newTask.Description = task.Description != null ? task.Description : null;
                newTask.Status = task.Status != null ? task.Status : null;
                newTask.WhatId = task.WhatId != null ? task.WhatId : null;
                newTask.Type = task.Type != null ? task.Type : null;
                newTask.WhoId = c.ContactId;

                tasksToInsert.add(newTask);
                tasksToDelete.add(task);
            }
        }

        newTask = null;
    }

    try{
        insert tasksToInsert;   //Insert new tasks that reference case contact
        delete tasksToDelete;   //Discard original tasks
    } catch (DmlException e){
        System.debug('Insert or Delete failed: ' + e);
        Mailer.getInstance().SendMailByEmail('TaskCreated Insert or Delete Failure', 'tasksToInsert size: ' + tasksToInsert.size() + 'tasksToDelete size: ' + tasksToDelete.size(), new String[] {'cconner@cbtnuggets.com'} );
    }
}

A little background story:

The trigger is attempting to populate the Contact field if the task is related to a case. I had to use an After Insert trigger because Salesforce hates the WhoId field and was failing silently when I tried to populate it in Before Insert. I had to take a sledgehammer approach to generating having this field populated with the insert and delete. I know, it's ugly, but I couldn't come up with a better solution for what I was trying to do...

  • I've dumped the trigger into notepad++, can you confirm that line 43 is "else newTask.OwnerId = task.OwnerId;" – Girbot Jun 4 '15 at 21:44
  • That's the correct line, yes. – Cara Conner Jun 4 '15 at 21:45
  • 1
    try changing the variable task to tsk or something other than a reserved or typed word. Sometimes it confuses the code as Task.OwnerID would be null (sObject.OwnerId) without being instantiated. Maybe it cannot tell that you mean the task variable and not the task sObject – Eric Jun 4 '15 at 22:00
  • Good idea, Eric, it's still giving me the same error unfortunately. – Cara Conner Jun 4 '15 at 22:07
5

At the bottom of your loop over caseTasks you set newTask to null so the next time round the loop you get an NPE.

for (Task task : caseTasks){
    ...
    newTask = null;
}

You should be creating a new Task instance within the loop rather than creating an instance once outside the loop.

It's generally best not to declare all your variables at the start of some code but instead declare and initialise them as you need them.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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