function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Hermann OuréHermann Ouré 

Error Too many callout 101 when calling Queueable class from Batch

Hello I have a batch calling a queueable class. But when running the batch, I have an error Too many callout 101.
I know I need to reduce the size of the callout but not sure how to implement it in my code
Could someone help?
Thanks

Queueable class
public class QueueableSubStepMaster implements Queueable, Database.AllowsCallouts {
    
    //class variable of type List
    private List<Sub_Step_Master__c> subStepMasterList;
    
    //Constructor
	public QueueableSubStepMaster(List<Sub_Step_Master__c> listSubStepMaster){
		this.subStepMasterList = listSubStepMaster;
	}
	
	public void execute(QueueableContext qc){
		for(Sub_Step_Master__c subStepMaster : subStepMasterList){
            //Map<String,String> layoutFieldMap = new Map<String,String>{'Sub_Step__c'=> 'String'}; to test batch (batch seems to work OK)!!!
			Map<String,String> layoutFieldMap = getFieldsOnLayoutForRecordType('Sub_Step__c',subStepMaster.RecordTypeName__c);
            subStepMaster.Layout_Field__c = prettyPrintLayoutFields(layoutFieldMap);
		}
		update subStepMasterList;
	}
    
    private String prettyPrintLayoutFields(Map<String,String> layoutFieldMap){
        
        //Print Map Key-Value pairs using toString();
        String result;
        result = layoutFieldMap.toString();
        
        //Print keys from Map using String.join(); //string.join(map.keyset(),',');
        /*String result = '';
        set<string> strSet = layoutFieldMap.keySet();
        List<String> StrList = new List<String>();
        StrList.addall(strSet);
        result = String.join(StrList , ',');*/
	
        System.debug('String result ' +result);
        return result;
    }
    
	private static Map<String,String> getFieldsOnLayoutForRecordType(String sobjectName, String recordTypeName){
		Map<String,String> result = new Map<String,String>();
		
		String url = system.URL.getSalesforceBaseUrl().toExternalForm() 
				   + '/services/data/v52.0/sobjects/'
				   + sObjectName
				   + '/describe/layouts/' 
				   + getRecordTypeId(sobjectName, recordTypeName);
        system.debug(url);
		httprequest req = buildRequest(url);
		try{
			http h = new http();
			httpresponse res = h.send(req);
			if(res.getStatusCode() == 200){
				result = getFieldsFromLayoutString(res.getBody());
			}
		}catch(exception ex){
			system.debug('ERROR: ' + ex.getMessage());
		}
		return result;
	}
	private static Map<String,String> getFieldsFromLayoutString(String jsonString){
		Map<String,String> result = new Map<String,String>();
        
        Map<String,Object> layoutMap = (Map<String,Object>)JSON.deserializeUntyped(jsonString);
        
        List<Map<String, Object>> data = new List<Map<String, Object>>();
        
		List<Object> detailSectionList = (List<Object>)layoutMap.get('detailLayoutSections'); //added H.O
        
		for(Object section : detailSectionList){
			Map<String,Object> sectionMap = (Map<String,Object>)section;
			for(Object sectionLayoutRow : (List<Object>)sectionMap.get('layoutRows')){
				Map<String,Object> sectionLayoutRowMap = (Map<String,Object>)sectionLayoutRow;
				for(Object liObject : (List<Object>)sectionLayoutRowMap.get('layoutItems')){
                    LayoutItem li = new LayoutItem((Map<String,Object>)liObject);
					String label = li.label;
					if(label != null && label != ''){
                        for(Object lc : li.layoutComponents){
                            Map<String,Object> lcMap = (Map<String,Object>)lc;
                            if((String)lcMap.get('type') == 'field'){
                            	String field = (String)lcMap.get('value');
                                result.put(field,label);
                            }
                        }
					}
				}
			}
		}
		return result;
	}
    
	private static String getRecordTypeId(String sobjectName, String recordTypeName){
        //use condition to avoid RecordType returning null
        if(Schema.getGlobalDescribe().get(sObjectName).getDescribe().getRecordTypeInfosByName().get(recordTypeName) != null) {
            return Schema.getGlobalDescribe().get(sObjectName).getDescribe().getRecordTypeInfosByName().get(recordTypeName).getRecordTypeId();

        } else {
            return null;
        }
	}

	private static HttpRequest buildRequest(String url){
		HttpRequest result = new HttpRequest();
		system.debug(url);
		result.setendpoint(url);
		result.setmethod('GET');
		result.setHeader('Authorization', 'OAuth ' + UserInfo.getSessionId());       
		result.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionID());
		return result;
	}
	
	private class LayoutItem{
		public boolean editableForNew;
		public boolean editableForUpdate;
		public string label;
		public List<Object> layoutComponents;
		public boolean placeholder;
		public boolean required;
        
        public LayoutItem(Map<String,Object> liMap){
            editableForNew = (Boolean)liMap.get('editableForNew');
            editableForUpdate = (Boolean)liMap.get('editableForUpdate');
            label = (String)liMap.get('label');
            layoutComponents = (List<Object>)liMap.get('layoutComponents');
            placeholder = (Boolean)liMap.get('placeholder');
            required = (Boolean)liMap.get('required');
        }
	}
	
}

Batch Class
public class BatchSubStepMasterProcessor implements Schedulable, Database.Batchable<sObject> {
    
    public void execute(SchedulableContext sc) {
        Id batchProcessId = Database.executeBatch(this);
    }
    
    public Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator('SELECT Id, Name, Layout_Field__c, RecordTypeName__c FROM Sub_Step_Master__c');  
    }
    
    public void execute(Database.BatchableContext bc, List<Sub_Step_Master__c > scope) {
        System.enqueueJob(new QueueableSubStepMaster(new List<Sub_Step_Master__c>(scope)));
        System.debug('#### UPDATED Scope Size ' + scope.size());
    }
    
    public void finish(Database.BatchableContext info) {
       System.debug('Done'); 
    }

}

//Database.executeBatch(new BatchSubStepMasterProcessor());

​​​​​​​
 
Suraj Tripathi 47Suraj Tripathi 47
Hi Hermann,
you can execute your batch like :
BatchSubStepMasterProcessor bcn = new BatchSubStepMasterProcessor() ;
ID batchProcessid = Database.executeBatch(bcn, 1000);
you can increase the chunk size according to your need.
 
please let me know if it is of any help. Please mark this answer as the best answer.
Thanks.
Hermann OuréHermann Ouré
Hello Suraj,
Do I need to implement it this way?
public class BatchSubStepMasterProcessor implements Schedulable, Database.Batchable<sObject> {
    
    public void execute(SchedulableContext sc) {
        //Id batchProcessId = Database.executeBatch(this);
        BatchSubStepMasterProcessor bcn = new BatchSubStepMasterProcessor() ;
        Id batchProcessId = Database.executeBatch(bcn, 1000);
    }
    
    public Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator('SELECT Id, Name, Layout_Field__c FROM Sub_Step__c');  
    }
    
    public void execute(Database.BatchableContext bc, List<Sub_Step__c > scope) {
        System.enqueueJob(new QueueableSubStepMaster(new List<Sub_Step__c>(scope)));
        System.debug('#### UPDATED Scope Size ' + scope.size());
    }
    
    public void finish(Database.BatchableContext info) {
       System.debug('Done'); 
    }

}

//Database.executeBatch(new BatchSubStepMasterProcessor());

Because when doing this
public void execute(SchedulableContext sc) {
        BatchSubStepMasterProcessor bcn = new BatchSubStepMasterProcessor() ;
        Id batchProcessId = Database.executeBatch(bcn, 1000);
    }

I still get the error Too Many Callout 101
 
mukesh guptamukesh gupta
Hi Hermann,

Please use below:-
id batchprocessid = Database.executebatch(batchapex,100);

if you need any assistanse, Please let me know!!

Kindly mark my solution as the best answer if it helps you.

Thanks
Mukesh