1

I have a functional simple proof of concept before insert trigger that uses a custom metadata type to translate field values into English that are populated from web forms that exist in multiple language.

I'm now doing the 'right thing' by moving the logic to a class, but running into unexpected issues with this error:

DML statement cannot operate on trigger.new or trigger.old

Other posts suggest instantiating a new record and setting the Id, but that results in another error, presumably bc this is a before insert trigger and the Id does not exist yet.

MISSING_ARGUMENT, Id not specified in an update call

So I find myself stumped - how do I update the fields on the records in trigger.new in a before insert trigger when using an apex class for the logic?

Trigger code

trigger LeadBeforeInsert on Lead (before insert) {
 leadAction.translateVentureNomination(trigger.new);
}

Apex Class (also not sure if i need static methods or not in here, but that is a separate question)

public class leadAction {
    
    static list<Lead_Field_Translation_Mapping__mdt> tmapList = new list<Lead_Field_Translation_Mapping__mdt>([select label,english_value__c, local_value__c from Lead_Field_Translation_Mapping__mdt]);
    static map<string,string> tmap = new map<string,string>();
    
    public leadAction(){        
            for (Lead_Field_Translation_Mapping__mdt ftm : tmapList){
                tmap.put(ftm.local_value__c,ftm.english_value__c);
            }
    }
    
    public static void translateVentureNomination(list<lead> leads){            
        list<lead> updateList = new list<lead>();
        for (lead l : leads){ 
        //+add better error handling        
        if(tmap.get(l.Country_of_Election__c) == null){
            utils_logging.writeToLog('error translating country of election', 'lead before insert trigger');
        }
        else (l.country_of_election__c = tmap.get(l.Country_of_Election__c));

        list<string> tpopList = l.target_population__c.split(';');                
        string tpop = '';
        for(string s : tpopList){
            //system.debug('s = ' + s);            
            tpop += tmap.get(s.trim())+';';    
        }        
        l.target_population__c = tpop;
        updateList.add(l);
    }
        update updateList;
        
        
    }
}
3

In BeforeTrigger you can change the value of the Lead directly and do not perform DML, as it will be changed. So, in your method, just remove the updateList and the DML statement, and it will work.

Other issue is that the tmap will be empty so you won’t have the right values. You can do your map static (as is) and populate directly in your method instead of in constructor.

3
  • Thanks for the idea, I tried that already and my tests failed. That worked fine in the trigger itself, but not when I moved the logic to the class.
    – gorav
    Sep 14 at 20:06
  • 1
    There can be two issues, 1 is that your map is not populated as the method is static and you do not instantiate the class so that constructor is not executed. Another issue can be that there is other logic changing this field value in after trigger or other automations. Sep 14 at 20:20
  • thanks that was it - the static stuff thows me off still, makes sense now that you say it. no DML statements required at all!
    – gorav
    Sep 14 at 20:28

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.