Purpose: I have a small requirement where i need to modify a global picklist values (i.e. add new values / deactivate existing values) from outside salesforce and to use those values in our daily business of creating/updating Account records of multiple record types.
There is already a well written article that show a working solution using tooling API for modifying global picklist values using tooling API.
Create/Update Global Value Set using Tooling API
But, there is a followup problem to this. I have a custom picklist field in Account object (i.e. with multiple Record types) that is referring to the above Global picklist. The new value added to the above global picklist is not available for use in account records untill the value is also addded to the account recordtypes. I am not able to find any solution of how to add the new global picklist values to the account records types.
Approach 1: I have used a similar tooling API to retrieve the specific record type using the following code
HttpRequest request = new HttpRequest();
Id account_recordtype_Id = 'xxxxxxxxxxxxxxxx';
request.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm() + '/services/data/v41.0/tooling/sobjects/RecordType/' + account_recordtype_Id);
request.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionId());
request.setMethod('GET');
HttpResponse response = (new Http()).send(request);
String resposeJSON = response.getBody();
System.debug('resposeJSON: ' + resposeJSON);
Problem in above approach: If i was able to get all picklists as part of above response, i would modify it accordingly and send a PATCH request to update the RecordType with new picklistvalues. But the above code is not getting me any custom picklist values as part of Metadata in JSON.
Approach 2: I have used Metadata API to retrieve the specific record type & update it with latest picklist value using the following code.
Reference link: Add new picklist values to all Record Types that use this Global Value Set
MetadataService.MetadataPort service = new MetadataService.MetadataPort();
service.SessionHeader = new MetadataService.SessionHeader_element();
service.SessionHeader.sessionId = UserInfo.getSessionId();
MetadataService.RecordType recordType = (MetadataService.RecordType) service.readMetadata(
'RecordType', new String[] { 'Account.Account_RecordType' }
).getRecords()[0];
MetadataService.RecordTypePicklistValue cusPik;
for(MetadataService.RecordTypePicklistValue rpk : recordType.picklistValues) {
if(rpk.picklist == 'CustomPicklist__c') {
cusPik = rpk;
break;
}
}
MetadataService.PicklistValue newVal = new MetadataService.PicklistValue();
newVal.fullName = 'test option';
newVal.default_x=false;
cusPik.values.add(newVal);
service.updateMetadata(new MetadataService.Metadata[] { recordType });
Problem in above approach: The above code is updating the recordtype by adding the new picklist value "test option", but everytime i execute the above code, it is throwing System.CalloutException: IO Exception: Read timed out exception. I am not sure why this is happening.
Any help in resolving this issue either using tooling/metadata api is appreciated.
System.CalloutException: IO Exception: Read timed out exception
is a generic error. You can try increasing the timeout but if that doesn't work, you should generate the debug logs and add the relevant excerpt from there that shows where the timeout is happening.