I need to create a schedulable Apex job which will send Sales Order Number from Case Object to my integration platform Web Service as JSON. This will be re-mapped and sent to another system, re-mapped again and send to be received by REST HTTP PATCH back in Salesforce.
I never worked in APEX and never had much experience before so I struggle a bit. To schedule I use Apex Schedule rather than CRON_EXP. I don't have a clue why the code below doesn't execute as it supposed to.
global class calloutPOSTClass implements Schedulable{
global void execute (SchedulableContext ctx){
List<Case> salesordernumber = [SELECT Sales_Order_Number__c
FROM Case
WHERE Sales_Order_Number__c != null AND
Status = 'Approved'];
}
//future callout method to post http request
@future (Callout=true)
public static void getPickedShippedUpdate(String salesordernumber){
Http http = new Http();
HttpRequest req = new HttpRequest();
req.setEndpoint('https://myendpoint');
req.setMethod('POST');
req.setHeader('Content-Type', 'application/json');
req.setBody('{"SONUMBER":"' + salesordernumber + '"}');
HttpResponse response = http.send(req);
}
}
Also, I struggle with creating test classes for @future callouts, if someone would be able to explain it or give me some tips I'd be very grateful.
Thanks!
Best Answer
You have to explicitly call your future method with each sales order number found by your scheduler. Since your
execute()
method performs a query and then does no work, you're not going to see a result of it - the query contents are simply discarded.There is a broader architectural issue, though. The limit for future method invocations in a transaction is 50:
This means that the moment your query returns more than 50 records, you'll be receiving limits exceptions.
Further, your class doesn't make any attempt to guard against reprocessing the same records, nor does it alter the record status when callouts are sent. If your class is scheduled on a tight timeline, you may process the same 50+ records repeatedly. I won't propose a solution to this because it's going to be quite specific to the callout/callback flow you're building here.
On the limits side, the very easy patch is to put a
LIMIT 50
clause in your SOQL query. That means you'll process up to 50 records each time your scheduler goes off, and everything else will have to wait. If your throughput is >50 Cases per time interval of this class running, you'll never catch up. Probably not the way you want to go unless you're doing very little volume!The better way to approach would be to build a schedulable Batch Apex class (you can implement both
Schedulable
andBatchable
interfaces in the same class) and have yourSchedulable
execute()
method create and enqueue a Batch Apex invocation. Your Batch Apex could run with a batch size of 50, to avoid the governor limit, and utilize the same query in itsstart()
method.Batch Apex will get you significantly higher throughput, and it's architecturally a sounder solution as you have more control over your limits consumption while maintaining performance.
For more, see Batch Apex.
If the intent is to do a more real-time process (not every N hours), a Queueable chain pattern may be something you want to look into.