function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Seth PayneSeth Payne 

execution of BeforeInsert caused by: System.NullPointerException: Argument cannot be null.

The error above is the used when i have this code:

 trigger HD5HashGeneratorContact1 on Contact (before insert, before update) {
   
    for (contact c : Trigger.new){
        if (c.HD5Hash__c == null) {
            c.HD5Hash__c = EncodingUtil.convertToHex(Crypto.generateDigest('MD5', Blob.valueOf(c.id)));          
   
        break;
        }
    }

When I change the code to after insert this is the error i get:

execution of AfterInsert caused by: System.FinalException: Record is read-only:


trigger HD5HashGeneratorContact1 on Contact (after insert, before update) {
   
    for (contact c : Trigger.new){
        if (c.HD5Hash__c == null) {
            c.HD5Hash__c = EncodingUtil.convertToHex(Crypto.generateDigest('MD5', Blob.valueOf(c.id)));          
   
        break;
        }
    }
}
}

What do i need to do to be able to generate a MD5 Hash out of the contact ID?

Thanks,
Seth
Best Answer chosen by Seth Payne
logontokartiklogontokartik
On a Before Insert trigger, you will not have the Id, populated, and on the After Insert Trigger, you can modify the record as it is marked as final.

Instead you can on an after insert trigger,
            call another apex class that has asynchronous method that updates your contact. Something like 
            Build new instance of the contact list and update them. 
trigger HD5HashGeneratorContact1 on Contact (after insert, before update) {
   
   Set<Id> contactIds = new Set<Id>();

    for (contact c : Trigger.new){
        if (c.HD5Hash__c == null) {
            contactIds.add(c.Id);
        }
    }

 ContactUtil.updateHD5Hash(contactIds);

}

You can write the Apex class 

public with sharing class ContactUtil {

 @future
 public static void updateHD5Hash(Set<Id> contactIds){

    List<Contact> updatedContacts  = new List<Contact>();
    updatedContacts = [Select Id, HD5Hash__c from Contact where Id in :contactIds];
    for(Contact c : updatedContacts){
           
        c.HD5Hash__c = EncodingUtil.convertToHex(Crypto.generateDigest('MD5', Blob.valueOf(c.id)));
  
   }

   update updatedContacts;

  }


}



You can also create a new instance of all the contacts you want to update in trigger and update them within trigger. Something like 

trigger HD5HashGeneratorContact1 on Contact (after insert, before update) {
  
   Set<Id> contactIds = new Set<Id>();

    for (contact c : Trigger.new){
        if (c.HD5Hash__c == null) {
            contactIds.add(c.Id);
        }
    }

    List<Contact> updatedContacts  = new List<Contact>();
    updatedContacts = [Select Id, HD5Hash__c from Contact where Id in :contactIds];
    for(Contact c : updatedContacts){
          
        c.HD5Hash__c = EncodingUtil.convertToHex(Crypto.generateDigest('MD5', Blob.valueOf(c.id)));
 
   }
 
   update updatedContacts;

}



All Answers

Ankit AroraAnkit Arora
First error is because you are using contact id which is not inserted yet. And in later code you are updating the same record which is in trigger context. If you want to execute this code on after insert then you can write a separate class with a future method and write update logic there. So once the record is created send the Id to future method and get your record updated.
logontokartiklogontokartik
On a Before Insert trigger, you will not have the Id, populated, and on the After Insert Trigger, you can modify the record as it is marked as final.

Instead you can on an after insert trigger,
            call another apex class that has asynchronous method that updates your contact. Something like 
            Build new instance of the contact list and update them. 
trigger HD5HashGeneratorContact1 on Contact (after insert, before update) {
   
   Set<Id> contactIds = new Set<Id>();

    for (contact c : Trigger.new){
        if (c.HD5Hash__c == null) {
            contactIds.add(c.Id);
        }
    }

 ContactUtil.updateHD5Hash(contactIds);

}

You can write the Apex class 

public with sharing class ContactUtil {

 @future
 public static void updateHD5Hash(Set<Id> contactIds){

    List<Contact> updatedContacts  = new List<Contact>();
    updatedContacts = [Select Id, HD5Hash__c from Contact where Id in :contactIds];
    for(Contact c : updatedContacts){
           
        c.HD5Hash__c = EncodingUtil.convertToHex(Crypto.generateDigest('MD5', Blob.valueOf(c.id)));
  
   }

   update updatedContacts;

  }


}



You can also create a new instance of all the contacts you want to update in trigger and update them within trigger. Something like 

trigger HD5HashGeneratorContact1 on Contact (after insert, before update) {
  
   Set<Id> contactIds = new Set<Id>();

    for (contact c : Trigger.new){
        if (c.HD5Hash__c == null) {
            contactIds.add(c.Id);
        }
    }

    List<Contact> updatedContacts  = new List<Contact>();
    updatedContacts = [Select Id, HD5Hash__c from Contact where Id in :contactIds];
    for(Contact c : updatedContacts){
          
        c.HD5Hash__c = EncodingUtil.convertToHex(Crypto.generateDigest('MD5', Blob.valueOf(c.id)));
 
   }
 
   update updatedContacts;

}



This was selected as the best answer
Seth PayneSeth Payne
Thank you both for the quick responses.  Katrik, I used your second solution and it seems to be working fine.