Chaining executions with actionFunction

A problem was posed recently for another developer in the forcedotcom community where he was running out of http callouts while trying to use a REST API service. I figured this is the perfect reason to take a break and post a new blog post.

One solution I’ve used in the past to get around issues like this when working in VisualForce is to chain actions together. This solution uses actionFunction with names that are set in the controller. If after the rerender the string is not null the oncomplete javascript will kick off the next action in turn giving another 10 callouts if necessary. I tend to use this solution frequently with slight modifications between booleans to call the same action.

One example of this is calling a web service that has a timeout set. You can chain the action to a boolean in the oncomplete which will start the action again until you stop it with the boolean, usually after 3 or so tries.

I’m still a newbie to WordPress so I’m getting used to the code highlighting plugins. SyntaxHighlighter takes issue with my xml have self closing tags, so just know the actionfunctions and commandbutton don’t require a specific closing tag like that, it can use the standard /> closing tag. This doesn’t apply anymore, code highlighting was fixed finally

ChainedActionController.cls

public class ChainedActionController {
    public ChainedActionController() { }
    
    private Integer chainMax = 5;
    private Integer chainCount = 0;
    
    
    public String outputText {
        get {
            if(outputText == null) outputText = '';
            return outputText;
        }
        set;
    }
    
    public String chainedActionFunction {
        get {
            if(chainedActionFunction == null) chainedActionFunction = '';
            return chainedActionFunction;
        }
        set;
    }
    
    public void actionOne() {
        this.outputText = 'actionOne set this text';
        
        // set the next chain if we haven't exceeded the defined max count
        if(chainCount++ < chainMax) {
            this.chainedActionFunction = 'actionTwo';
        } else { 
            this.chainedActionFunction = '';
        }
    }
    
    public void actionTwo() {    
        this.outputText = 'actionTwo set this text';
        
        // this could also be done with booleans depending on your use case
        if(chainCount++ < chainMax) {
            this.chainedActionFunction = 'actionOne';
        } else { 
            this.chainedActionFunction = '';
        }
    }
    
}

ChainedActionExample.page

<apex:page controller="ChainedActionController">
    <apex:form id="inputForm">
        <div style="border: 1px solid #777; background-color: #efefef; color: #444; padding: 5px;">
             output: {!outputText}
        </div>        
        <br/><br/>
        Status:
        <apex:actionStatus id="actOne">
            <apex:facet name="start">
                Action one is running!
            </apex:facet>
        </apex:actionStatus>
        <apex:actionStatus id="actTwo">
            <apex:facet name="start">
                Action one is running!
            </apex:facet>
        </apex:actionStatus>
        <br/><br/>
        <apex:actionFunction status="actOne" name="actionOne" action="{!actionOne}" rerender="inputForm" oncomplete="if('{!chainedActionFunction}' != '') eval('{!chainedActionFunction}();')" />
        <apex:actionFunction status="actTwo" name="actionTwo" action="{!actionTwo}" rerender="inputForm" oncomplete="if({!chainedActionFunction}) eval('{!chainedActionFunction}();')"/>
        <apex:commandButton status="actOne" action="{!actionOne}" rerender="inputForm" oncomplete="if({!chainedActionFunction}) eval('{!chainedActionFunction}();')" value="Start"/>
    </apex:form>
</apex:page>

Leave a Reply

Your email address will not be published. Required fields are marked *