1

I have a custom object Booking__c which has a Related List of a custom object Notes__c. I want to reuse useful Notes for new Bookings as if any existing Note could be a template. On Notes__c I have fields Name, Visibility__c, Note__c(text area), Booking__c(lookup to Booking__c), Template(lookup to Notes__c). When Template__c is populated with an existing Note, I want to populate all the new Notes fields with the existing Note.

With the code below, i'm receiving an error:

populateNotefromNoteTemplate: execution of BeforeInsert caused by: System.NullPointerException: Attempt to de-reference a null object Trigger.populateNotefromNoteTemplate: line 21, column 1

Here is my code:

trigger populateNotefromNoteTemplate on Note__c (before insert , before update) {
    if(trigger.isbefore && trigger.isinsert)
    {
        Set<ID> NoteIds = new Set<ID>();

        for(Note__c note : trigger.new)
        {
            NoteIds.add(note.Template__c);    
        }

        list <Note__c> notelist = [SELECT ID, Name, Visibility__c, Note__c FROM 
                                   Note__c WHERE ID IN:NoteIds];

        MAP<ID , Note__c> mapNote = new MAP<ID , Note__c>();
        for(Note__c n : Notelist)
        {
            mapNote.put(n.id, n);
        }

        for(Note__c note : trigger.new)
        {
            if(trigger.oldmap.get(note.Id).Template__c != note.Template__c){
                if(note.Template__c!=null)
                {
                    if(mapNote.containskey(note.Template__c))
                    {
                        Note__c n = mapnote.get(note.Template__c);
                        note.Name = n.Name;
                        note.Visibility__c = n.Visibility__c;
                        note.Note__c = n.Note__c;
                    }
                }
                else
                {
                    note.Name = null;
                    note.Visibility__c= null;
                    note.Note__c = null;
                }
            }
        }
    }
}
2
  • is there any particular reason why you would rather not use the process builder? – glls May 6 '17 at 21:54
  • as per the error message, populateNotefromNoteTemplate is null, hence your trigger is failing – glls May 6 '17 at 21:59
1

You cannot access trigger.old nor trigger.oldMap in the before insert trigger context. They are both null. Note from Trigger Context Variables:

Variable    Usage
old         Returns a list of the old versions of the sObject records.
            This sObject list is only available in update and delete triggers.

oldMap      A map of IDs to the old versions of the sObject records.
            This map is only available in update and delete triggers.

If you want to filter for records which have a Template__c value which is new or changed, you would instead check:

if (trigger.oldMap != null || trigger.oldmap.get(note.Id).Template__c != note.Template__c)

You might also consider reading up on trigger best practices, specifically:

  • One Trigger Per Object
    The way you have named your trigger implies you would write a separate file for each piece of trigger functionality. The industry standard is to incorporate all of your trigger logic into one trigger, so that you have fine-grained control over order of execution.
  • Logic-less Triggers
    One way to keep your trigger files from growing mighty unwieldy is to move the logic into an Apex Class (or several, more likely).

In light of these practices, I recommend you adopt a handler pattern and service layer in the long run. You might also take a look at filtering libraries out there, of which Selector is a fine example.

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.