I already successfully collecting the list of data from callout another system as json body to the inner class to accomodate custom information:

Here is the apex class of the inner class:

public class InvoiceHeaderListController {

    public class ResponseData {
        public List<InvoiceData> receivableInvoices{get;set;}
        public String lastRowNum{get;set;}
        public Boolean hasNext{get;set;}

    public class InvoiceData {
        public String id{get;set;}
        public BusinessPartnerData businessPartner{get;set;}
        public String invoiceNumber{get;set;}
        public String invoiceAmount{get;set;}
        public Datetime invoiceDate{get;set;}
        public Datetime dueDate{get;set;}
        public String invoiceStatus{get;set;}
        public Boolean isCarriedOver{get;set;}
        public Datetime paymentDate{get;set;}
        public String contractingEntity{get;set;}
        public String settlement{get;set;}
        public ReferenceData reference{get;set;}
        public List<ChargeData> charges{get;set;}

    public class BusinessPartnerData {
        public String id{get;set;}
        public String name{get;set;}
        public String country{get;set;}
        public ReferenceBPData reference{get;set;}

    public class ReferenceBPData {
        public String teraHotelId{get;set;}
        public String legalCountryIdISOAlpha2{get;set;}

    public class ReferenceData {
        public String paymentOutId{get;set;}
        public String teraHotelId{get;set;}
        public String businessUnit{get;set;}

    public class ChargeData {
        public String chargeId{get;set;}
        public String chargeTypeName{get;set;}
        public String chargeBaseAmount{get;set;}
        public String chargePercentage{get;set;}
        public String chargeFixedAmount{get;set;}
        public String chargeTotalAmount{get;set;}

    public String getFromAnotherSystem() {
        //do callout

    public List<InvoiceData> getInvoiceHeaderRows(ResponseData rd) {
        List<InvoiceData> resultList = rd.receivableInvoices;
        return resultList;

    //get the response as json body
    String responseString = getFromAnotherSystem();

    //get the data and map to inner class
    ResponseData rData = (InvoiceHeaderListController.ResponseData) JSON.deserialize(responseString, InvoiceHeaderListController.ResponseData.class);
    List<InvoiceData> invoiceDataList = getInvoiceHeaderRows(rData);

    //do apex batch using inner class
    InvoiceHeaderBatch ihBatch = new InvoiceHeaderBatch(invoiceDataList);
    Database.executeBatch(ihBatch, 100);

And then when I create the apex batch:

global class InvoiceHeaderBatch implements Database.Batchable<sObject>, Database.Stateful, Database.AllowsCallouts {
    global List<InvoiceHeaderListController.InvoiceData> invoiceDataList = new List<InvoiceHeaderListController.InvoiceData>();

    global InvoiceHeaderBatch(List<InvoiceHeaderListController.InvoiceData> invDataList) {
        this.invoiceDataList = invDataList;

    global System.Iterable<sObject> start(Database.BatchableContext bc) {
        return this.invoiceDataList;

    global void execute(Database.BatchableContext bc, List<InvoiceHeaderListController.InvoiceData> scope) {


    global void finish(Database.BatchableContext bc) {


I'm getting compile error:

global methods do not support parameter type of List<InvoiceHeaderListController.InvoiceData>

Do I have to create unnecessary custom object only to store this custom information as the apex batch does not support inner class? Or I'm missing something?


I modify the visibility of the inner class to global

public global InvoiceHeaderListController {

    global class ResponseData {
        public List<InvoiceData> receivableInvoices{get;set;}
        public String lastRowNum{get;set;}
        public Boolean hasNext{get;set;}

Now I'm getting the compile error:

Class InvoiceHeaderBatch must implement the method: void Database.Batchable<SObject>.execute(Database.BatchableContext, List<SObject>)

Why my inner class identified as non sObject class?

1 Answer 1


You are using Custom Iterator. So you need to implement same as well.

InvoiceHeaderBatch implements Database.Batchable<InvoiceHeaderListController.InvoiceData>

Here is a complete code sample for you.

public with sharing class SimpleBatchApex implements Database.Batchable<String>
    public Iterable<String> start(Database.BatchableContext BC)
        return new List<String> { 'Do something', 'Do something else', 'And something more' };

    public void execute(Database.BatchableContext info, List<String> strings)
        // Do something really expensive with the string!
        String myString = strings[0];

    public void finish(Database.BatchableContext info) { }


  • 1
    I see. So the Database.Batchable must be specifically declared as custom inner class
    – Rival
    Jul 16, 2018 at 4:26
  • @Rival yup. we need to do that. Jul 16, 2018 at 4:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .