Search code examples
salesforceapexapex-trigger

how to fix System.NullPointerException: Attempt to de-reference a null object in apex class using Map<parentId, child>?


Getting the error in line " taskObj.OwnerId = ConMap.get(ben.contact__c).contact__r.OwnerId;" becasue the ownerid field is on contact.

Contact is the parent of benefit, Here I am getting all the benefits in start method. I want to add contactid only once if it has more than one child for that I used SET. I want to use maps as I need to get the contact OwnerId field from contact object which I am fetching in the query in start method. How do I Access contact.ownerId field using a map? below is the code.

 global Database.QueryLocator start(Database.BatchableContext bc) {
    Query='select contact__r.ownerId, contact__c, Task_creation_date__c, Status__c, task_created__c, type__c from Benefit__c Where Task_creation_date__c= TODAY AND Status__c IN (\'Active\',\'Pending\') AND Task_created__c =FALSE AND Type__c!=\'Short Term Medical\'';
    return Database.getQueryLocator(query);

}

global void execute(Database.BatchableContext bc, List<Benefit__c> scope){
    // process each batch of records

    List<Contact> contacts = new List<Contact>();
    List<Task> TaskList = new List<Task>();
    set<id> conset = New set<id>();
    Map<id,benefit__c> ConMap = new map<id,Benefit__c>();
    for (Benefit__c b : scope) {
            conset.add(b.contact__c);
            ConMap.put(b.contact__c, b);
            b.task_created__c = TRUE;
     }
      system.debug('contact and its benefit------'+ConMap);
     recordsProcessed = conset.size();
     //List<Contact> tempList = new List<Contact>();
    // tempList = [Select Id,OwnerId, firstname from Contact where Id IN:(conset)];
     if(!ConMap.isEmpty())
      {
       for(Benefit__c ben : ConMap.values())
       {
        Task taskObj = new Task();
                        taskObj.OwnerId = ConMap.get(ben.contact__c).contact__r.OwnerId;

I want to populate contact ownerid as the task ownerid but how do I access it from the map and keep the unique contact id in the map?


Solution

  • I re wrote the code to resolve this nd optimize the code as below.

    public with sharing class MyBatch implements Database.Batchable<AggregateResult>{
    public Iterable<AggregateResult> start(Database.BatchableContext context)
    {
        return [
            SELECT Contact__c, Contact__r.OwnerId owner FROM Benefit__c
            WHERE Contact__c != null AND ...
            GROUP BY Contact__c, Contact__r.OwnerId
        ];
    }
    public void execute(Database.BatchableContext context, List<AggregateResult> scope)
    {
        Set<Id> contactIds = new Set<Id>();
        List<Task> tasks = new List<Task>();
        for (AggregateResult aggregate : scope)
        {
            Id ownerId = (Id)aggregate.get('owner');
            Id contactId = (Id)aggregate.get('Contact__c');
    
            contactIds.add(contactId);
            tasks.add(new Task(OwnerId=ownerId, /*other fields*/));
        }
        insert tasks;
    
        List<Benefit__c> benefits = [
            SELECT Id FROM Benefit__c WHERE Contact__c IN :contactIds
        ];
        for (Benefit__c benefit : benefits)
            benefit.Task_Created__c = true;
        update benefits;
    }
    public void finish(Database.BatchableContext context) { /*additional logic*/ }}