Flow: Create/Update CustomMetadata

Image

As of now, you can GET custom metadata records in flows but you cannot create or update them.

Using this invocable class you can create/update custom metadata records in Flows.

You can access the repository here:

https://github.com/mhamzas/Flow-Create-Update-Custom-Metadata

The code is self explanatory but I have tried my best to do better commenting for others to understand what’s going on here.

/**
 * @description       : This invocable class will allow you to update/create customMetadata using Flow/Process Builder.
 * @author            : M Hamza Siddiqui @ mhamzas.com
 * @group             : Cloudjunction Advisors, Inc.
 * @last modified on  : 01-21-2021
 * @last modified by  : M Hamza Siddiqui @ mhamzas.com
 * Modifications Log 
 * -----------------
 * Ver   Date         Author                             		Modification
 * 1.0   01-22-2021   M Hamza Siddiqui @ mhamzas.com		   Initial Version
**/
global class UpdateCMD implements Metadata.DeployCallback {

    /*An invocable variable used as input or output variables in the process builder*/
    global class ActionRequest {
        @InvocableVariable(required = true)
        public List<sObject> data;
    }
    //This invocable method is used for processing the business by taking the input from process builder/flow
    @InvocableMethod(label = 'Create/Update Custom Metadata')
        global static void invokeService(List <ActionRequest> requests) {
          for (ActionRequest requestObj: requests) {
              //Accessing the values from process builder/flow when record is inserted
              for(sObject obj : requestObj.data){
                  //System.debug('requestObj.sObject@@:' + obj);
                  //System.debug('requestObj.ObjectType@@:' + obj.getSObjectType());
                  // Getting all the Populated fields in a Map
                  Map<String, Object> fieldsToValue = obj.getPopulatedFieldsAsMap();
                  Map<String, Object> metadataFieldValueMap = new Map<String, Object>();
                  String MetadataDevName; // To Store Custom Metadata Record API/Developer name
                  String MetadataLabel; // To Store Custom Metadata Label name
                  // Looping on all the populated fields
                  for (String fieldName : fieldsToValue.keySet()){
                      System.debug('field name is ' + fieldName + ', value is ' + fieldsToValue.get(fieldName));
                      // We don't want to add system fields to the Map for update, so here is some simple logic
                      if(fieldName == 'Label'){
                          MetadataLabel = (String)fieldsToValue.get(fieldName);
                      } else if(fieldName == 'DeveloperName'){
                          MetadataDevName = (String)fieldsToValue.get(fieldName);
                      } else if(fieldName != 'Id' && fieldName != 'Language' && fieldName != 'MasterLabel' && fieldName != 'NamespacePrefix' && fieldName != 'QualifiedApiName') {
                          // Populating Map for Processing later
                          metadataFieldValueMap.put(fieldName, fieldsToValue.get(fieldName));
                      }
                  }
                  
                  System.debug('Label is ' + MetadataLabel + '& DeveloperName is ' + MetadataDevName);
                  // Making sure to have either Label or Developer Name for the CMD record to process
                  if(String.isBlank(MetadataDevName) && String.isBlank(MetadataLabel)){
                      throw createCustomException('Make sure to add "Label" attribute in assignemnt for Create and "DeveloperName" for update.');
                  } else { 
                      //if MetadataDevName available, which means the record exists already - Processing UPDATE
                      if(!String.isBlank(MetadataDevName)){
                          UpdateCMD.updateCustomMetadata(String.valueof(obj.getSObjectType()),MetadataDevName, MetadataLabel,metadataFieldValueMap);
                      } else { // Creating a new Custom Metadata record
                          //if ID not available - CREATE
                          UpdateCMD.createCustomMetadata(String.valueof(obj.getSObjectType()), MetadataLabel, metadataFieldValueMap);
                      }
                  }
                  // END
              }
          }
    }
    
    /* Custom Metadata Deploy Methods */
    /* ============================================================*/
    //Inteface method 
    public void handleResult(Metadata.DeployResult result, Metadata.DeployCallbackContext context) {
        if (result.status == Metadata.DeployStatus.Succeeded) {
            //Success
            System.debug('Success Result-' + result);
        } else {
            //Failed
            System.debug('Failed Result-' + result);
            throw createCustomException(String.valueof(result));
        }
    }
     
    //Create Custom Metadata record
    public static void createCustomMetadata(String metdataName, String label, Map<String, Object> metadataFieldValueMap){
        String recordDevName = label.replaceAll(' ', '_');
        Metadata.CustomMetadata cMetadata = new Metadata.CustomMetadata();
        cMetadata.fullName = metdataName + '.' + recordDevName;
        cMetadata.label = label;
         
        for(String key : metadataFieldValueMap.keySet()){
            Metadata.CustomMetadataValue cMetadataValue = new Metadata.CustomMetadataValue();
            cMetadataValue.Field = key;
            cMetadataValue.Value = metadataFieldValueMap.get(key); 
            cMetadata.values.add(cMetadataValue);
        }
         
        Metadata.DeployContainer mdContainer = new Metadata.DeployContainer();
        mdContainer.addMetadata(cMetadata);
        UpdateCMD callback = new UpdateCMD();
        Id jobId = Metadata.Operations.enqueueDeployment(mdContainer, callback);
    }
     
    //Update Custom Metadata record
    public static void updateCustomMetadata(String metdataName, String recordDevName, String label, Map<String, Object> metadataFieldValueMap){
        Metadata.CustomMetadata cMetadata = new Metadata.CustomMetadata();
        cMetadata.fullName = metdataName + '.' + recordDevName;
        cMetadata.label = label;
         
        for(String key : metadataFieldValueMap.keySet()){
            Metadata.CustomMetadataValue cMetadataValue = new Metadata.CustomMetadataValue();
            cMetadataValue.Field = key;
            cMetadataValue.Value = metadataFieldValueMap.get(key); 
            cMetadata.values.add(cMetadataValue);
        }
         
        Metadata.DeployContainer mdContainer = new Metadata.DeployContainer();
        mdContainer.addMetadata(cMetadata);
        UpdateCMD callback = new UpdateCMD();
        Id jobId = Metadata.Operations.enqueueDeployment(mdContainer, callback);
    }

    /* Flow Exception Handling */
    /* ============================================================*/
    public class CustomException extends Exception {}
    
    static CustomException createCustomException(String message) {
        CustomException ex = new CustomException(message);
        ex.setMessage(message);
        return ex;
    }
}

Happy Coding!

Leave a Comment