Saleforce HTTP callouts limit workaround
I need to do tons of requests to an external service that, unfortunately, doesn't allow me to put multiple action requests within one single HTTP request, so that each action I want to send to this external service I have to do an HTTP request. Problem: Salesforce allows you to do only ten HTTP requests per execution. I could use Batch Jobs to schedule all the requests I need, but Batch Jobs are executed when resources are free, and I want to have the requests to be sent almost in real time, not "when Salesforce has time to do it".
Some explication:
So, here's the workaround. The key is that the limit is "per execution", and an AJAX call (done through a standard Visualforce <apex:actionFunction>) is actually a single execution. I can "loop" in Javascript to do requests as long as I need it.
Let's have a look at the code.
The controller:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | public with sharing class testJavascript { public String requestStatus { get; set; } public String requestMore { get; set; } public Integer requestNumber { get; set; } public Integer requestCurrent { get; set; } public testJavascript () { requestStatus = '' ; requestMore = '' ; requestNumber = 10000 ; requestCurrent = 0 ; } public void doRequest () { if (requestCurrent <= requestNumber) { Http http = new Http(); for (Integer startPoint = requestCurrent; (requestCurrent <= requestNumber) && ((requestCurrent - startPoint) < 10 ); requestCurrent++) { HttpRequest req = new HttpRequest(); req.setMethod( 'GET' ); HTTPResponse res = http.send(req); } requestStatus = requestCurrent + ' out of ' + requestNumber + ' processed' ; } if (requestCurrent >= requestNumber) requestMore = 'false' ; else requestMore = 'true' ; } } |
1 |
The page:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | < apex:page controller = "testJavascript" > < apex:form > < apex:outputpanel id = "status" > Status: {!requestStatus} < script >requestContinue = {!requestMore};</ script > </ apex:outputpanel > < script > function requestMore() { if (requestContinue) doRequest(); } </ script > < button onclick = "if (doRequest()) return false; else return false;" >Start</ button > < apex:actionfunction action = "{!doRequest}" name = "doRequest" oncomplete = "requestMore()" rerender = "status" > </ apex:actionfunction ></ apex:form > |
Some explication:
- In the controller I have a request counter (requestCurrent, set to 0 at beginning) and a request amount (requestNumber, set to 10000 at beginning) and a method, doRequest(), that, given those two variables, executes the next 10 HTTP requests (increasing the counter) and updates the status String (requestStatus) and the requestMore String/Boolean, setting it to true if other requests are needed (if the counter is lower than the request amount we need) or false if not.
- In the page I have an <apex:actionFunction> pointing to this method, that rerenders the status panel. In the panel I show the status string and I update a Javascript global variable (requestContinue) with the String/Boolean given in requestMore by the doRequest() APEX method.
- The actionFunction has an oncomplete attribute that calls another Javascript function, requestMore(), that is in the page code. This function checks for requestContinue value (updated after each rerender): if true calls again the doRequest() actionFunction and 10 more requests are executed, if false it does nothing.
The user has just to push the <button> (that does the first actionFunction call) to start the loop.
Nice, isn't it? :-)
No comments :
Post a Comment