2

Offset can take only 2000 records, but I need more. How can I send to the callout side 1 mln or more records with pagination and step of 100-200 records per 1 page? I mean when callout request for 100 records, then for 100 more etc., till we have records on the HttpGet service side.

@HttpGet
global static List<Item__c> getItem(){
    RestRequest req = RestContext.request;

    List<Item__c> itemList;
    RestResponse res = new RestResponse();
    RestContext.response = res;

    try{
        itemList = [SELECT Id, Full_Name__c FROM Item__c];
        res.responseBody = Blob.valueOf(JSON.serialize(itemList));
    } catch(Exception e){
        System.debug('Error:  ' + e.getMessage());
    }
    return itemList;
}

Callout:

public class Callout {    
public static String webTokenBody(){
        String requestBody = 'my_web_token_string';
        return request;
}

public class webTok{
        public String webToken{get;set;}    
}

public static HttpRequest createRequestForToken(String service){
        String requestBody = webTokenBody();
        HttpRequest ourRequest = new HttpRequest();
        ourRequest.setBody(requestBody);
        ourRequest.setMethod(service);
        ourRequest.setEndpoint('https://my.salesforce.com/services/oauth2/token');
        return ourRequest;
}

public static HttpRequest createRequestForService(String token, String method){
        HttpRequest finalRequest = new HttpRequest();
        finalRequest.setHeader('Authorization','Bearer ' + token);
        finalRequest.setHeader('Content-Type','application/json');
        finalRequest.setHeader('accept','application/json');
        finalRequest.setMethod(method);
        finalRequest.setEndpoint('https://my.salesforce.com/services/apexrest/endpoint/');
        return finalRequest;
}

public static HttpResponse getCalloutResponseContents() {   
        Http ourHttp = new Http();
        HttpRequest requestForToken = createRequestForToken('GET');
        HttpResponse responseToken = ourHttp.send(requestForToken);
        webTok objAuthenticationInfo = (webTok)JSON.deserialize(responseToken.getbody(), webTok.class);

        if(objAuthenticationInfo.webToken != null){
            HttpRequest requestForService = createRequestForService(objAuthenticationInfo.webToken, 'GET');
            HttpResponse responseService = ourHttp.send(requestForService);
            itemsList = (List<Item2__c>)JSON.deserialize(responseService.getBody(), List<Item2__c>.class);                
                for(Item2__c i : itemsList) {
                    i.Id =null;
                }
                return responseService;
            }
    }
    }

Can I do that with Database.QueryLocator on the HttpGet service side? If yes - how?

1 Answer 1

4

Simply put, you can't. While is trivial to build a service that returns, say, up to 50,000 rows, there's simply no mechanism for preserving a QueryLocator across Apex Code transactions, and with one exception (Visualforce), you can't query more than 50,000 rows per transaction (and even that limit is still only exactly 1,000,000, no more). The best you'd be able to do is create a service where the client-side programs passes in the last known ID, and you'd just continue from there:

@HttpGet
global static List<Item__c> getItem(){
  Id reqId = RestContext.request.params.get('recordId');
  if(reqId != null) {
    return [SELECT Full_Name__c FROM Item__c WHERE Id > :reqId ORDER BY Id LIMIT 200];
  } else {
    return [SELECT Full_Name__c FRIM Item__c ORDER BY Id LIMIT 200];
  }
}

Your client would then do something like this:

/services/apexrest/Items

Which would give a list of 200 items; your code would then call the next page:

/services/apexrest/Items?recordId=a010000000abcde

For replicating millions of records, consider just using a normal query. Unless you're specifically trying to circumvent security/sharing settings, your client can just request the data directly:

/services/data/v44.0/query?q=select+full_name__c+from+item__c

It will include automatic pagination, requires no code, and is a standard function.

7
  • The problem is I have a batch on Callout side. And an upsert function. So, if I have some changes in old records on Service side - it updates them on Callout side. How can I get at least 50,000? And yeah, it's really strange. I think that organisations who work with API Data sending can work also with 1 mln records too. No?
    – user60684
    Commented Nov 25, 2018 at 16:09
  • I updated my code with callout. Is it wrong way?
    – user60684
    Commented Nov 25, 2018 at 16:38
  • I also get an image (contentversion) with base64encode (service ) / base64decode (callout). "Currently base64 fields are not supported in queries with the Bulk API."
    – user60684
    Commented Nov 25, 2018 at 17:04
  • 1 more thing: Id reqId = RestRequest.request.getParams().get('recordId'); - Variable does not exist: RestRequest.request. Is this just template?
    – user60684
    Commented Nov 25, 2018 at 19:52
  • 1
    @user60684 That's what I get for forgetting to check the documentation, I suppose. It's just params. See additional edit. Also might be worth your time to read the docs.
    – sfdcfox
    Commented Nov 25, 2018 at 20:03

You must log in to answer this question.

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