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
andrew.kallio@npd.comandrew.kallio@npd.com 

dupe preventer works when data is entered via SF interface but not when same data comes via web form

Hello,

I have written a trigger that is designed to handle leads that come from a specific web-to-lead form and prevent them from becoming duplicates. The trigger allows the new lead to insert and uses its data to query the remaining records for matches on email. If it finds any other Leads or Contacts the util class will update them with the info that was entered in the web-to-lead form, and then delete the lead that came via web-to-lead.

 

I have deployed this to production and it seems to work well in most cases. However, every once in a while a null ponter exception is thrown, and the incoming lead is prevented from being inserted at all.  The null pointer exception that is thrown is the same exception that was thrown for pretty much every other bug I had to battle through to get this deployed.

 

With the past occurence of this error I did the following:

 

When the error is thrown we receive an email from Salesforce that contains all of the data that was submitted via the web-to-lead form(the data we lost because the trigger failed). I took that data and entered it into SF via the user interface exactly as it is in the email. I did this expecting to get the same error, but instead no error was thrown and the code worked as expceted. I then tried entering the same into the web-to-lead form, and the error was thrown.

 

Does anyone have any ideas why this might be?

 

 

 

trigger leadAfterInsertUpdate on Lead (after insert) {
    
    if(UserInfo.getUserId() <> '00500000006z3qKAAQ'){
        
        Map<String,ID> newLeadsMap = new Map<String,String>();
        
        for(Lead newLead : Trigger.new) {
            if((null != newLead.Email) && (newLead.MarketingCampaign__c == 'Web-Marketing-Opt In Web Page-200807') && (Trigger.isInsert || newLead.Email != Trigger.oldMap.get(newLead.Id).Email)) {
                if(newLeadsMap.containsKey(newLead.Email)) {
                    newLead.Email.addError('Another new lead is already using this email address.');
                }else if (null != newLead.Email){
                    newLeadsMap.put(newLead.Email, newLead.Id);
                }
            }
        }
        
        if(newLeadsMap.keySet().size() > 0) {
            leadHandler.leadDeDuper(newLeadsMap);
        }
    }

}

 

public class leadHandler {

    Public Static Void leadDeDuper(Map<String,ID> newLeads) {
       
        Map<id,Lead> newLeadMap = new Map <ID, Lead>([Select Id, FirstName, LastName, Phone, PrimaryAreaOfInterest__c, Blog__c, Email, Country_of_Interest__c, HasOptedOutOfEmail,Press_Releases__c,Insights_Newsletter__c,Product_Announcements__c,Marketing_Opt_Out__c from Lead Where ID IN: newLeads.values()]);
        Set<Lead> leadsToDeleteSet = new Set<Lead>();
        List<Lead> existingLeads = new List<Lead>();
        List<Contact> existingContacts = new List<Contact>();
               
        
        //finds existing Leads where their email equals the incoming Lead
       for(Lead leadB : [select Id, FirstName, LastName,PrimaryAreaofInterest__c,Country_of_Interest__c, Phone, Blog__c,Email,HasOptedOutofEmail,Product_Announcements__c, MarketingCampaign__c, Insights_Newsletter__c,Press_Releases__c,Marketing_Opt_Out__c from Lead where Email IN :newLeads.KeySet() And IsConverted = False]) {
          
            for(ID newLeadID : newLeads.values()) {
            	if(newLeadID <> leadB.ID) {
		            //updates fields in existing leads
		            leadB.HasOptedOutOfEmail = false;
		            leadB.Marketing_Opt_Out__c = false;
		            leadB.FirstName = newLeadMap.get(newLeads.get(leadB.email)).FirstName;
		            leadB.PrimaryAreaOfInterest__c = newLeadMap.get(newLeads.get(leadB.email)).PrimaryAreaOfInterest__c;
		            leadB.Press_Releases__c = newLeadMap.get(newLeads.get(leadB.email)).Press_Releases__c;
		            leadB.Insights_Newsletter__c = newLeadMap.get(newLeads.get(leadB.email)).Insights_Newsletter__c;
		            leadB.Product_Announcements__c = newLeadMap.get(newLeads.get(leadB.email)).Product_Announcements__c;
		            leadB.Blog__c =newLeadMap.get(newLeads.get(leadB.email)).Blog__c;
		            leadB.Country_of_Interest__c =newLeadMap.get(newLeads.get(leadB.email)).Country_of_Interest__c;
		            
		            
		            if(null != newLeadMap.get(newLeads.get(leadB.email)).LastName) {
		            	leadB.LastName = newLeadMap.get(newLeads.get(leadB.email)).LastName;
		            }
		            
		            if(null != newLeadMap.get(newLeads.get(leadB.email)).Phone) {
		            	leadB.Phone = newLeadMap.get(newLeads.get(leadB.email)).Phone;
		            }		            
		            
		            if(null == leadB.Rating) {
		            	leadB.Rating = 'Z - Not Contacted - Unknown Quality';
		            }
		            
		            if(null == leadB.Status) {
		            	leadB.Status = 'New Leads - Not Yet Working';
		            }
		            
		            if(leadB.Status == 'Dead Leads - No Future Opport') {
		            	leadB.Status = 'Archived Leads - Possible Future Opport';
		            }
		            
		            if(null == leadB.Lead_Type__c) {
		            	leadB.Lead_Type__c = 'Inbound - Web Form';
		            }
		            
		            if(null == leadB.LeadSource) {
		            	leadB.LeadSource = 'Other';
		            }
		            
		            existingLeads.add(leadB);
            	} else {
            		leadsToDeleteSet.add(newLeadMap.get(newLeads.get(leadB.Email)));
            	}
            }
        }
       
        if(existingLeads.size()>0) {
            update existingLeads;
        }
        //finds existing contacts where their email equals the incoming leads
        for(Contact contactA : [select ID, Name, Email, HasOptedOutofEmail, Insights_Newsletter__c, Press_Releases__c from Contact where Email IN :newLeads.keySet()]) {
                       
            
            //updates the existing contact         
            contactA.HasOptedOutOfEmail = false;
            contactA.Insights_Newsletter__c = newLeadMap.get(newLeads.get(contactA.email)).Insights_Newsletter__c;
            contactA.Press_Releases__c = newLeadMap.get(newLeads.get(contactA.email)).Press_Releases__c;
            contactA.Product_Announcements__c = newLeadMap.get(newLeads.get(contactA.email)).Product_Announcements__c;
            contactA.Blog__c = newLeadMap.get(newLeads.get(contactA.email)).Blog__c;
            contactA.FirstName = newLeadMap.get(newLeads.get(contactA.email)).FirstName;
            contactA.Phone = newLeadMap.get(newLeads.get(contactA.email)).Phone;
            
            if(null != newLeadMap.get(newLeads.get(contactA.email)).LastName) {
            	contactA.LastName = newLeadMap.get(newLeads.get(contactA.email)).LastName;
            }
            
            if(null == contactA.JobFunction__c) {
            	contactA.JobFunction__c = 'Other';
            }
            
            if (null == contactA.ContactType__c) {
            	contactA.ContactType__c = 'Other';
            }
            
            if (null == contactA.NPD_Client_Satisfaction_Survey__c) {
            	contactA.NPD_Client_Satisfaction_Survey__c = 'No';
            }
            
            leadsToDeleteSet.add(newLeadMap.get(newLeads.get(contactA.email)));
            existingContacts.add(contactA);
        }
      
        if(existingContacts.size()>0) {
            update existingContacts;
        }
       
        if(existingLeads.size()>0 || existingContacts.size()>0) {
       
            List<Lead> leadsToDelete = new List<Lead>();
           
            for(Lead leadToDelete : leadsToDeleteSet) {
            	leadsToDelete.add(leadToDelete);
            }
            
            delete leadsToDelete;
    }
       
        }
}

 

 

 

 

jkucerajkucera

I'm not sure why  you'd get an NPE sometimes, but not other times.

 

I suggest logging a case, but they may not be able to help much if it's not reproducible.  Perhaps they can try to match up your errors to internal errors however to see if there's an internal issue causing the failures.

andrew.kallio@npd.comandrew.kallio@npd.com

Hi J,

I did as you suggested and started a case with support. We have finally come to the conclusion that the error is thrown when the email address that is given begins with a capital letter. The code works fine when entering the exact same data and email address, but the email address has to begin lowercase.

 

The case  has been escalated. So I have no solution yet, but thought you might this info interesting.

 

-Andy

jkucerajkucera

Thnsks for updating the thread - that's pretty funky. 

 

For a workaround are you converting the string to lowercase for now?

andrew.kallio@npd.comandrew.kallio@npd.com

Yeah, it's pretty wacky. It must be related to the fact that emails are converted to lowercase by Salesforce.

 

So I tried using the toLowerCase method, but having trouble.  The challenge is that my Sandbox is not behaving the same as my production org. To begin with, I can' t recreate the behavior in the sandbox...the sandbox doesn't seem to care if the email is in lower or uppercase. Then, after adding the toLowerCase method I encounter the following: The code works fine if an Upper Case email is entered, but it fails if a LowerCase email is entered...do you know of a workaround?

 

The revised trigger is below with new section in bold.

 

 

 

trigger leadAfterInsertUpdate on Lead (after insert) {

if(UserInfo.getUserId() <> '00500000006z3qKAAQ'){

Map<String,String> newLeadsMap = new Map<String,String>();

for(Lead newLead : Trigger.new) {
if((null != newLead.Email) && (newLead.MarketingCampaign__c == 'Web-Marketing-Opt In Web Page-200807')) {
if(newLeadsMap.containsKey(newLead.Email)) {
newLead.Email.addError('Another new lead is already using this email address.');
}else {
newLeadsMap.put(newLead.Email.toLowerCase(), newLead.ID);
}
}
}

leadHandler.leadDeDuper(newLeadsMap);
}

}

 

 

jkucerajkucera

Perhaps save email to a string variable first and then add that string?

 

String emailString=newLead.Email;
newLeadsMap.put(emailString.toLowerCase(), newLead.ID);