[SalesForce] Scheduled Apex, Callouts and Running a Batch

I don't think what I am trying to do can be done with my current setup, but before I embark on some rework, I just wanted to check I haven't missed an approach…

I have a scheduled class that executes a batch. So far so good. But to run that batch, I need to check a date from an external web service to include in the SOQL – and this is where I am running into a problem. A scheduled class can only make a callout if the callout is run in an @future context. But sadly, a class running as @future can't then execute a batch, or even schedule a batch to run in the future using system.schedulebatch. So is there any approach that would let me schedule a class to make a callout, and then also execute/schedule a batch that I am missing? Right now, I am thinking I need my scheduled class to make the callout via @future and have the @future update a custom setting with the results, and have the scheduled class also schedule a class to execute my batches run in x mins to allow time for @future to run?

Best Answer

Why not just perform the callout in your Batch Apex start method? This means you will always start the Batch Apex job from your Scheduled apex job, but i think is on balance better than having to marshall schedule jobs between @future jobs?

public with sharing class BatchWithCallout 
   implements Database.Batchable<SObject>, Database.AllowsCallouts 
{
    public Database.QueryLocator start(Database.BatchableContext BC) 
    { 
        // Callout for Date
        HttpRequest request = new HttpRequest();
        request.setEndpoint('http://www.timeapi.org/pdt/next+monday');
        request.setMethod('GET');
        Http http = new Http();
        HttpResponse response = http.send(request);
        String dateValue = response.getBody();
        List<String> dateParts = dateValue.split('T');

        // Query with date returned
        return Database.getQueryLocator(
              'select Id from Opportunity where CloseDate < ' + dateParts[0]); 
    }

    public void execute(Database.BatchableContext info, List<SObject> opportunities) {}

    public void finish(Database.BatchableContext info) { }
}