1

I wrote an APEX trigger to check for duplicates before a record is created or saved to ensure there are no duplicates. However, since the variables are empty (before record creation) I keep getting the following error message:

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

APEX Trigger:

trigger COIDuplicateTrigger on COI__c (before insert,before update) {
// creates trigger on the COI object to occur before insert or before update of record
    map<Id,COI__c> existingCOImap = new  map<Id,COI__c>([Select Id, Name, Company__c From COI__c]);
// maps variable to store data queried from SOQL statement

    for(COI__c i : Trigger.new){
        if(i.Name == existingCOImap.get(i.Id).Name && i.Company__c == existingCOImap.get(i.Id).Company__c){
            i.addError('Error! Duplicate COI record found.');
        }
    }       
}
// loop to see if data from name AND company fields match a COI record. if TRUE then throws error message.

Any tips on how to work around this?

Thanks!

Mercury1986

  • I don't know what you're use case is but you shouldn't have to check for something like this.. – EricSSH Nov 24 '15 at 23:12
  • Use case is a requirement to have a custom error message. – All about the W Nov 24 '15 at 23:17
2

By querying every COI__c object your trigger will become slower as the number of COI__c objects grows and eventually will fail entirely when there are more than 50,000 objects because of the "Total number of records retrieved by SOQL queries" governor limit. Not a good design choice. Also in a before insert the ID values have not yet been assigned.

A solution is to add a formula field - lets call it Key__c - that combines (appends) the fields that you want to check for uniqueness. (You can also ask Salesforce support to add an index to this field to speed access.)

Then your trigger becomes:

trigger COIDuplicateTrigger on COI__c (before insert, before update) {

    String message = 'Error! Duplicate COI record found.';

    Set<String> newKeys = new Set<String>();
    for(COI__c coi : Trigger.new) {
        String key = coi.Name + coi.Company__c;
        if (newKeys.contains(key)) coi.addError(message);
        else newKeys.add(key);
    }

    Set<String> existingKeys = new Set<String>();
    for (COI__c coi : [select Key__c from COI__c where Key__c in :newKeys]) {
        existingKeys.add(coi.Key__c);
    }

    for(COI__c coi : Trigger.new) {
        String key = coi.Name + coi.Company__c;
        if (existingKeys.contains(key)) coi.addError(message);
    }
}
  • Unfortunately, it is giving issues saying "keys" is not defined. Could you repost with comments? Helps scrubs like me analyze and understand how this solution is better. Again A+, calling out the limits teaches me to think long term, rather than some chopped up solution! – All about the W Nov 25 '15 at 3:07
  • 1
    @Mercury86 I had :keys in the query rather than :newKeys; changed now. As others have mentioned, using a trigger only makes sense if the message is going to be more complicated i.e. it includes some information from the objects. – Keith C Nov 25 '15 at 8:37
1

No reason to write at trigger at all really (Unless you want to control the error message).

Just create a Unique Field and use a workflow to set it to the value of coi.Name + coi.Company__c

Then if a record is being inserted that is a duplicate an error message will be present that it is a duplicate value of xxx record with a link to the record.

  • I am currently using the Unique Field as a stop gap solution. I do need to control the error message as this is a piece of a larger business process. – All about the W Nov 25 '15 at 3:12
0

As you already said, the error is because your query does not have the record you are trying to fetch which results in a null pointer exception on existingCOImap.get(i.Id) . The record is not in the database and hence your query map would not have it.

How about an easier way to do this avoiding code? use validation rules to avoid duplicates

  • I currently have the validation rule as a short-term solution. However, I need a more user friendly error message. – All about the W Nov 24 '15 at 22:55
  • @Mercury86 - A lot of work for a message that is not more informative than the default. – Eric Nov 25 '15 at 2:16
  • It is more work, but the flexibility to change the error message will come in handy as I plan to put a more detailed error message in the future. This is part of a larger business process. Great learning experience however! – All about the W Nov 25 '15 at 3:00

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.