You need to sign in to do that
Don't have an account?
VRK
System.calloutException:IO Exception:ReadTimeout
Hi i am performing picklist Update thorugh Metadata API...
it works for less data , But when we perform bulk data through Data
loader getting below error :
System.calloutException:IO Exception:ReadTimeout
i set Max 120 sec..But issue not solved for Bulk upload data.
Any ideas how to resolve
public class MetadataApiCallout {
//-------create new picklist value using metadata api call--------
//-------use below method for bulk insert&Deactivate Values.
@future(callout = true)
public static void createPicklistValue(String serializedObjectAPIMap, String serializedMap) {
Map < String, Map < String, String >> ObjectFieldApiMap = (Map < String, Map < String, String >> ) JSON.deserialize(serializedObjectAPIMap, Map < String, Map < String, String >> .class);
Map < String, Map < String, String >> picklistValueMap = (Map < String, Map < String, String >> ) JSON.deserialize(serializedMap, Map < String, Map < String, String >> .class); //----adding new values coming from compass helper.....
MetadataService.MetadataPort service = createService(); //-----Calling service method...
Map < String, String > schemaValueMap = new Map < String, String > ();
//Collect recordtypes for each object in required format
Map<String, List<String>> ObjectRtMap = new Map<String, List<String>>();
List<String> rtValueList = new List<String>();
for(RecordType rt : [SELECT Id, Name, developerName, SobjectType FROM RecordType WHERE SobjectType =:ObjectFieldApiMap.keySet()]){
rtValueList.add(rt.SobjectType + '.' + rt.developerName);
if(ObjectRtMap.containsKey(String.valueOf(rt.SobjectType).toUpperCase())){
List<String> rtValues = new List<String>();
rtValues = ObjectRtMap.get(String.valueOf(rt.SobjectType).toUpperCase());
rtValues.add(String.valueOf(rt.SobjectType + '.' + rt.developerName).toUpperCase());
ObjectRtMap.put(String.valueOf(rt.SobjectType).toUpperCase(), rtValues);
}
else{
List<String> rtValues = new List<String>();
rtValues.add(String.valueOf(rt.SobjectType + '.' + rt.developerName).toUpperCase());
ObjectRtMap.put(String.valueOf(rt.SobjectType).toUpperCase(), rtValues);
}
}
Map<String, List<MetadataService.PickListValue>> objFldMetaPickListValueMap = new Map<String, List<MetadataService.PickListValue>>();
List<MetadataService.CustomField> customFieldListToUpdate = new List<MetadataService.CustomField>();
for (String objectApiName: ObjectFieldApiMap.keySet()) {
for (String fieldAPi: ObjectFieldApiMap.get(objectApiName).keySet()) {
SobjectType objType = Schema.getGlobalDescribe().get(objectApiName);
Map < String, Schema.SObjectField > objFields = objType.getDescribe().fields.getMap();
SObjectField fieldName = objFields.get(fieldAPi);
Schema.DescribeFieldResult fieldResult = fieldName.getDescribe();
fieldResult = fieldResult.getSObjectField().getDescribe();
List < Schema.PicklistEntry > ple = fieldResult.getPicklistValues();
for (Schema.PicklistEntry pl: ple) {
if (pl.isActive()) {
schemaValueMap.put(pl.getValue(), pl.getLabel());
}
}
MetadataService.CustomField customField = new MetadataService.CustomField();
customField.fullName = objectApiName + '.' + fieldAPi;
customField.label = ObjectFieldApiMap.get(objectApiName).get(fieldAPi);
customField.type_x = 'Picklist';
MetadataService.ValueSet picklistValueSet = new MetadataService.ValueSet();
MetadataService.ValueSetValuesDefinition valueDefinition = new MetadataService.ValueSetValuesDefinition();
List < MetadataService.CustomValue > values = new List < MetadataService.CustomValue > ();
List<MetadataService.PickListValue> fldPickListValueList = new List<MetadataService.PickListValue>();
//Add Existing values back in
//condition for adding new values
//---for loop for adding new values from list-----------
for (String picklistValueInsert: picklistValueMap.get(fieldAPi).keySet()) {
MetadataService.CustomValue existingPLValue = new MetadataService.CustomValue();
existingPLValue.fullName = picklistValueInsert;
existingPLValue.default_x = false;
existingPLValue.label = picklistValueMap.get(fieldAPi).get(picklistValueInsert);
values.add(existingPLValue);
MetadataService.PickListValue fldPickListValue = new MetadataService.PickListValue();
fldPickListValue.fullName = picklistValueInsert;
fldPickListValue.default_x = false;
fldPickListValueList.add(fldPickListValue);
System.debug(picklistValueInsert);
}
objFldMetaPickListValueMap.put(objectApiName+'.'+fieldAPi, fldPickListValueList);
//------for loop for value deactivation.------------
for (String picklistValue: schemaValueMap.keySet()) {
if (!picklistValueMap.get(fieldAPi).containsKey(picklistValue)) { //---condition check. not adding those existing value which is not coming from helper code.
MetadataService.CustomValue existingPLValue = new MetadataService.CustomValue();
existingPLValue.fullName = picklistValue;
existingPLValue.isActive = False;
existingPLValue.default_x = false;
existingPLValue.label = schemaValueMap.get(picklistValue);
values.add(existingPLValue);
}
}
valueDefinition.value = values;
valueDefinition.sorted = false;
picklistValueSet.valueSetDefinition = valueDefinition;
customField.valueSet = picklistValueSet;
schemaValueMap.clear();
customFieldListToUpdate.add(customField);
}
}
//Update PicklistFields with new values
updateMetadata(service, splitMetadataIntoLists((MetadataService.Metadata[]) customFieldListToUpdate));
List<List<String>> combinedRtValueList = new List<List<String>>();
//Splitting into size of 10 to avoid limit
combinedRtValueList = splitListIntoLists(rtValueList);
List<MetadataService.RecordType> rtMetaList = new List<MetadataService.RecordType>();
for(Integer i=0; i<combinedRtValueList.size(); i++){
if(!Test.isRunningTest())
//read recordtype
rtMetaList.addAll((List<MetadataService.RecordType>) service.readMetadata('RecordType', combinedRtValueList[i]).getRecords());
}
Map<String, MetadataService.RecordType> rtMetaRTMap = new Map<String, MetadataService.RecordType>();
for(MetadataService.RecordType mRT : rtMetaList){
rtMetaRTMap.put(String.valueOf(mRT.fullName).toUpperCase(), mRT);
}
List<MetadataService.RecordType> recordTypeListToUpdate = new List<MetadataService.RecordType>();
for (String objectApiName: ObjectFieldApiMap.keySet()) {
for(String rt : ObjectRtMap.get(objectApiName.toUpperCase())){
MetadataService.RecordType recordType = new MetadataService.RecordType();
recordType = rtMetaRTMap.get(rt);
for (String fieldAPi: ObjectFieldApiMap.get(objectApiName).keySet()) {
// initialize the list of record type picklist values
MetadataService.RecordTypePicklistValue[] rtPickValues = new MetadataService.RecordTypePicklistValue[]{};
MetadataService.RecordTypePicklistValue rtPickValue = new MetadataService.RecordTypePicklistValue();
// Create the recordtypepicklist and add the list of picklist fields to the record type
rtPickValue.picklist = fieldAPi;
rtPickValue.values = objFldMetaPickListValueMap.get(objectApiName+'.'+fieldAPi);
System.debug(rtPickValue.values);
rtPickValues.add(rtPickValue);
if(!Test.isRunningTest())
recordType.picklistValues.addAll(rtPickValues);
}
System.debug(recordType.picklistValues.size());
recordTypeListToUpdate.add(recordType);
}
}
//Update RecordTypes
updateMetadata(service, splitMetadataIntoLists((MetadataService.Metadata[]) recordTypeListToUpdate));
}
//-----------create Metadata service----------------
public static MetadataService.MetadataPort createService() {
MetadataService.MetadataPort service = new MetadataService.MetadataPort();
service.SessionHeader = new MetadataService.SessionHeader_element();
service.SessionHeader.sessionId = UserInfo.getSessionId();
// service.timeout_x = 40000;
service.timeout_x = 120000;
return service;
}
//readMetadata and updateMetdata has a limit of 10 elements per one callout
//Spliting Metadata into lists of 10 elements to address above limit
//-----------Split Master List into small lists of size 10 each----------------
public static List<List<MetadataService.Metadata>> splitMetadataIntoLists(List<MetadataService.Metadata> listToSplit) {
List<List<MetadataService.Metadata>> metadataListOfLists = new List<List<MetadataService.Metadata>>();
for(Integer i = 0 ; i < (listToSplit.size() / 10)+1 ; i++){
List<MetadataService.Metadata> lstTemp = new List<MetadataService.Metadata>();
for(Integer j=(i*10);(j<(i*10)+10) && j<listToSplit.size() ; j++){
lstTemp.add(listToSplit.get(j));
}
metadataListOfLists.add(lstTemp);
}
return metadataListOfLists;
}
//-----------Split Master List into small lists of size 10 each----------------
public static List<List<String>> splitListIntoLists(List<String> listToSplit) {
List<List<String>> ListOfLists = new List<List<String>>();
for(Integer i = 0 ; i < (listToSplit.size() / 10)+1 ; i++){
List<String> lstTemp = new List<String>();
for(Integer j=(i*10);(j<(i*10)+10) && j<listToSplit.size() ; j++){
lstTemp.add(listToSplit.get(j));
}
ListOfLists.add(lstTemp);
}
return ListOfLists;
}
//-----------Update Metadata----------------
public static void updateMetadata(MetadataService.MetadataPort service, List<List<MetadataService.Metadata>> metadataToUpdate) {
for(Integer i=0; i<metadataToUpdate.size(); i++){
if(!Test.isRunningTest()) {
List<MetadataService.SaveResult> results = service.updateMetadata(metadataToUpdate[i]);
for(MetadataService.SaveResult r : results){
system.debug(r.errors);
}
}
}
}
}
it works for less data , But when we perform bulk data through Data
loader getting below error :
System.calloutException:IO Exception:ReadTimeout
i set Max 120 sec..But issue not solved for Bulk upload data.
Any ideas how to resolve
public class MetadataApiCallout {
//-------create new picklist value using metadata api call--------
//-------use below method for bulk insert&Deactivate Values.
@future(callout = true)
public static void createPicklistValue(String serializedObjectAPIMap, String serializedMap) {
Map < String, Map < String, String >> ObjectFieldApiMap = (Map < String, Map < String, String >> ) JSON.deserialize(serializedObjectAPIMap, Map < String, Map < String, String >> .class);
Map < String, Map < String, String >> picklistValueMap = (Map < String, Map < String, String >> ) JSON.deserialize(serializedMap, Map < String, Map < String, String >> .class); //----adding new values coming from compass helper.....
MetadataService.MetadataPort service = createService(); //-----Calling service method...
Map < String, String > schemaValueMap = new Map < String, String > ();
//Collect recordtypes for each object in required format
Map<String, List<String>> ObjectRtMap = new Map<String, List<String>>();
List<String> rtValueList = new List<String>();
for(RecordType rt : [SELECT Id, Name, developerName, SobjectType FROM RecordType WHERE SobjectType =:ObjectFieldApiMap.keySet()]){
rtValueList.add(rt.SobjectType + '.' + rt.developerName);
if(ObjectRtMap.containsKey(String.valueOf(rt.SobjectType).toUpperCase())){
List<String> rtValues = new List<String>();
rtValues = ObjectRtMap.get(String.valueOf(rt.SobjectType).toUpperCase());
rtValues.add(String.valueOf(rt.SobjectType + '.' + rt.developerName).toUpperCase());
ObjectRtMap.put(String.valueOf(rt.SobjectType).toUpperCase(), rtValues);
}
else{
List<String> rtValues = new List<String>();
rtValues.add(String.valueOf(rt.SobjectType + '.' + rt.developerName).toUpperCase());
ObjectRtMap.put(String.valueOf(rt.SobjectType).toUpperCase(), rtValues);
}
}
Map<String, List<MetadataService.PickListValue>> objFldMetaPickListValueMap = new Map<String, List<MetadataService.PickListValue>>();
List<MetadataService.CustomField> customFieldListToUpdate = new List<MetadataService.CustomField>();
for (String objectApiName: ObjectFieldApiMap.keySet()) {
for (String fieldAPi: ObjectFieldApiMap.get(objectApiName).keySet()) {
SobjectType objType = Schema.getGlobalDescribe().get(objectApiName);
Map < String, Schema.SObjectField > objFields = objType.getDescribe().fields.getMap();
SObjectField fieldName = objFields.get(fieldAPi);
Schema.DescribeFieldResult fieldResult = fieldName.getDescribe();
fieldResult = fieldResult.getSObjectField().getDescribe();
List < Schema.PicklistEntry > ple = fieldResult.getPicklistValues();
for (Schema.PicklistEntry pl: ple) {
if (pl.isActive()) {
schemaValueMap.put(pl.getValue(), pl.getLabel());
}
}
MetadataService.CustomField customField = new MetadataService.CustomField();
customField.fullName = objectApiName + '.' + fieldAPi;
customField.label = ObjectFieldApiMap.get(objectApiName).get(fieldAPi);
customField.type_x = 'Picklist';
MetadataService.ValueSet picklistValueSet = new MetadataService.ValueSet();
MetadataService.ValueSetValuesDefinition valueDefinition = new MetadataService.ValueSetValuesDefinition();
List < MetadataService.CustomValue > values = new List < MetadataService.CustomValue > ();
List<MetadataService.PickListValue> fldPickListValueList = new List<MetadataService.PickListValue>();
//Add Existing values back in
//condition for adding new values
//---for loop for adding new values from list-----------
for (String picklistValueInsert: picklistValueMap.get(fieldAPi).keySet()) {
MetadataService.CustomValue existingPLValue = new MetadataService.CustomValue();
existingPLValue.fullName = picklistValueInsert;
existingPLValue.default_x = false;
existingPLValue.label = picklistValueMap.get(fieldAPi).get(picklistValueInsert);
values.add(existingPLValue);
MetadataService.PickListValue fldPickListValue = new MetadataService.PickListValue();
fldPickListValue.fullName = picklistValueInsert;
fldPickListValue.default_x = false;
fldPickListValueList.add(fldPickListValue);
System.debug(picklistValueInsert);
}
objFldMetaPickListValueMap.put(objectApiName+'.'+fieldAPi, fldPickListValueList);
//------for loop for value deactivation.------------
for (String picklistValue: schemaValueMap.keySet()) {
if (!picklistValueMap.get(fieldAPi).containsKey(picklistValue)) { //---condition check. not adding those existing value which is not coming from helper code.
MetadataService.CustomValue existingPLValue = new MetadataService.CustomValue();
existingPLValue.fullName = picklistValue;
existingPLValue.isActive = False;
existingPLValue.default_x = false;
existingPLValue.label = schemaValueMap.get(picklistValue);
values.add(existingPLValue);
}
}
valueDefinition.value = values;
valueDefinition.sorted = false;
picklistValueSet.valueSetDefinition = valueDefinition;
customField.valueSet = picklistValueSet;
schemaValueMap.clear();
customFieldListToUpdate.add(customField);
}
}
//Update PicklistFields with new values
updateMetadata(service, splitMetadataIntoLists((MetadataService.Metadata[]) customFieldListToUpdate));
List<List<String>> combinedRtValueList = new List<List<String>>();
//Splitting into size of 10 to avoid limit
combinedRtValueList = splitListIntoLists(rtValueList);
List<MetadataService.RecordType> rtMetaList = new List<MetadataService.RecordType>();
for(Integer i=0; i<combinedRtValueList.size(); i++){
if(!Test.isRunningTest())
//read recordtype
rtMetaList.addAll((List<MetadataService.RecordType>) service.readMetadata('RecordType', combinedRtValueList[i]).getRecords());
}
Map<String, MetadataService.RecordType> rtMetaRTMap = new Map<String, MetadataService.RecordType>();
for(MetadataService.RecordType mRT : rtMetaList){
rtMetaRTMap.put(String.valueOf(mRT.fullName).toUpperCase(), mRT);
}
List<MetadataService.RecordType> recordTypeListToUpdate = new List<MetadataService.RecordType>();
for (String objectApiName: ObjectFieldApiMap.keySet()) {
for(String rt : ObjectRtMap.get(objectApiName.toUpperCase())){
MetadataService.RecordType recordType = new MetadataService.RecordType();
recordType = rtMetaRTMap.get(rt);
for (String fieldAPi: ObjectFieldApiMap.get(objectApiName).keySet()) {
// initialize the list of record type picklist values
MetadataService.RecordTypePicklistValue[] rtPickValues = new MetadataService.RecordTypePicklistValue[]{};
MetadataService.RecordTypePicklistValue rtPickValue = new MetadataService.RecordTypePicklistValue();
// Create the recordtypepicklist and add the list of picklist fields to the record type
rtPickValue.picklist = fieldAPi;
rtPickValue.values = objFldMetaPickListValueMap.get(objectApiName+'.'+fieldAPi);
System.debug(rtPickValue.values);
rtPickValues.add(rtPickValue);
if(!Test.isRunningTest())
recordType.picklistValues.addAll(rtPickValues);
}
System.debug(recordType.picklistValues.size());
recordTypeListToUpdate.add(recordType);
}
}
//Update RecordTypes
updateMetadata(service, splitMetadataIntoLists((MetadataService.Metadata[]) recordTypeListToUpdate));
}
//-----------create Metadata service----------------
public static MetadataService.MetadataPort createService() {
MetadataService.MetadataPort service = new MetadataService.MetadataPort();
service.SessionHeader = new MetadataService.SessionHeader_element();
service.SessionHeader.sessionId = UserInfo.getSessionId();
// service.timeout_x = 40000;
service.timeout_x = 120000;
return service;
}
//readMetadata and updateMetdata has a limit of 10 elements per one callout
//Spliting Metadata into lists of 10 elements to address above limit
//-----------Split Master List into small lists of size 10 each----------------
public static List<List<MetadataService.Metadata>> splitMetadataIntoLists(List<MetadataService.Metadata> listToSplit) {
List<List<MetadataService.Metadata>> metadataListOfLists = new List<List<MetadataService.Metadata>>();
for(Integer i = 0 ; i < (listToSplit.size() / 10)+1 ; i++){
List<MetadataService.Metadata> lstTemp = new List<MetadataService.Metadata>();
for(Integer j=(i*10);(j<(i*10)+10) && j<listToSplit.size() ; j++){
lstTemp.add(listToSplit.get(j));
}
metadataListOfLists.add(lstTemp);
}
return metadataListOfLists;
}
//-----------Split Master List into small lists of size 10 each----------------
public static List<List<String>> splitListIntoLists(List<String> listToSplit) {
List<List<String>> ListOfLists = new List<List<String>>();
for(Integer i = 0 ; i < (listToSplit.size() / 10)+1 ; i++){
List<String> lstTemp = new List<String>();
for(Integer j=(i*10);(j<(i*10)+10) && j<listToSplit.size() ; j++){
lstTemp.add(listToSplit.get(j));
}
ListOfLists.add(lstTemp);
}
return ListOfLists;
}
//-----------Update Metadata----------------
public static void updateMetadata(MetadataService.MetadataPort service, List<List<MetadataService.Metadata>> metadataToUpdate) {
for(Integer i=0; i<metadataToUpdate.size(); i++){
if(!Test.isRunningTest()) {
List<MetadataService.SaveResult> results = service.updateMetadata(metadataToUpdate[i]);
for(MetadataService.SaveResult r : results){
system.debug(r.errors);
}
}
}
}
}
Can you check the below blogs might answer your query
https://developer.salesforce.com/forums/?id=906F00000008riNIAQ
https://salesforce.stackexchange.com/questions/69639/webservice-callout-exception-io-exception-read-timed-out
Thanks.
I verify provided links, But not help for fix this issues
Thanks