2

I am using the Metadata API wrapper from https://github.com/financialforcedev/apex-mdapi to dynamically add picklist values to an existing field.

@Future(Callout=true)
private static void updateValueSet(Set<String> newTopics, String fieldName) {
    MetadataService.MetadataPort mdapi = new MetadataService.MetadataPort();
    mdapi.SessionHeader = new MetadataService.SessionHeader_element();
    mdapi.SessionHeader.sessionId = UserInfo.getSessionId();

    MetadataService.CustomField fieldMdApi = (MetadataService.CustomField)
            mdapi.readMetadata('CustomField', new String[] { fieldName }).getRecords()[0];

    for(MetadataService.CustomValue existingTopic : fieldMdApi.valueSet.valueSetDefinition.value) {
        newTopics.add(existingTopic.fullName);
    }

    for(String missing : newTopics) {
        MetadataService.CustomValue value = new MetadataService.CustomValue();
        value.fullName = missing;
        value.default_x = false ;
        value.isActive = true;

        fieldMdApi.valueSet.valueSetDefinition.value.add(value);
    }

    mdapi.updateMetadata(new List<MetadataService.Metadata>{ fieldMdApi });
}

I have found some unclear hint that doing both is not possible in one "go" but I can remember that this once worked. If this indeed doesn't work how could I activate them in a second run? I am already using @future.

  • 2
    As far as I remember, there were certains issues regarding SessionID in the future method. Is that possible that session is not valid at the moment of execution? – kurunve Jul 8 at 12:51
  • It's creating the new Picklist values but they are not activated. So I think there is no SessionId issue. – Robert Sösemann Jul 8 at 13:25
  • 3
    Indeed, session works as expected... I have tried your code and it seems to be working as expected, and picklist values are active under condition that newTopics are not changed at line 11 (otherwise it will fail with duplicates because of fieldMdApi.valueSet.valueSetDefinition.value already contains given values once) – kurunve Jul 8 at 14:40
  • @kurunve can you add that as a real answer please. It indeed solved my issue. Thanks a lot! – Robert Sösemann Jul 8 at 15:21
2

In the given particular scenario, issue might occur due to duplicate values in picklist value set for chosen field.

In case if field is retrieved by MetadataService, it already contains existing active value set definitions (as fieldMdApi.valueSet.valueSetDefinition.value).

Since salesforce does not allow to have duplicate picklist values, there are no need to add existing picklist values second time to the collection, but rather remove them from newTopics in order to guarantee uniqueness.

Following snippet should be working as expected:

@future(callout=true)
private static void updateValueSet(Set<String> newTopics, String fieldName) {
    MetadataService.MetadataPort mdapi = new MetadataService.MetadataPort();
    mdapi.SessionHeader = new MetadataService.SessionHeader_element();
    mdapi.SessionHeader.sessionId = UserInfo.getSessionId();

    MetadataService.CustomField fieldMdApi = (MetadataService.CustomField)
            mdapi.readMetadata('CustomField', new String[] { fieldName }).getRecords()[0];

    for(MetadataService.CustomValue existing : fieldMdApi.valueSet.valueSetDefinition.value) {
        if (newTopics.contains(existing.fullName)) {
            newTopics.remove(existing.fullName);
        }
    }

    for(String missing : newTopics) {
        MetadataService.CustomValue value = new MetadataService.CustomValue();
        value.fullName = missing;
        value.default_x = false ;
        value.isActive = true;

        fieldMdApi.valueSet.valueSetDefinition.value.add(value);
    }

    mdapi.updateMetadata(new List<MetadataService.Metadata>{ fieldMdApi });
}

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.