Chaining Asynchronous Callouts

If the order of the callouts matters, or when a callout is conditional on the response of another callout, you can chain callout requests. Chaining callouts means that the next callout is made only after the response of the previous callout returns. For example, you might need to chain a callout to get warranty extension information after the warranty service response indicates that the warranty expired. You can chain up to three callouts.

The following Visualforce and Apex examples show how to chain one callout to another. The Visualforce page is shown first. The Visualforce page contains a button that invokes the action method invokeInitialRequest in the controller. The Visualforce process is suspended each time a continuation is returned. The Visualforce process resumes after each response is returned and renders each response in the outputPanel component.

1<apex:page controller="ChainedContinuationController" showChat="false" showHeader="false">
2   <apex:form >
3      <!-- Invokes the action method when the user clicks this button. -->
4      <apex:commandButton action="{!invokeInitialRequest}" value="Start Request" reRender="panel"/>  
5   </apex:form>
6
7   <apex:outputPanel id="panel">
8       <!-- Displays the response body of the initial callout. -->   
9       <apex:outputText value="{!result1}" />
10       
11       <br/>
12       <!-- Displays the response body of the chained callout. -->
13       <apex:outputText value="{!result2}" />
14   </apex:outputPanel> 
15   
16</apex:page>

This example show the controller class for the Visualforce page. The invokeInitialRequest method creates the first continuation. The callback method (processInitialResponse) processes the response of the first callout. If this response meets a certain condition, the method chains another callout by returning a second continuation. After the response of the chained continuation is returned, the second callback method (processChainedResponse) is invoked and processes the second response.

1public with sharing class ChainedContinuationController {
2
3    // Unique label for the initial callout request
4    public String requestLabel1;
5    // Unique label for the chained callout request
6    public String requestLabel2;
7    // Result of initial callout
8    public String result1 {get;set;}
9    // Result of chained callout
10    public String result2 {get;set;}
11    // Endpoint of long-running service
12    private static final String LONG_RUNNING_SERVICE_URL1 = 
13        '<Insert your first service URL>';
14    private static final String LONG_RUNNING_SERVICE_URL2 = 
15        '<Insert your second service URL>';
16           
17    // Action method
18    public Object invokeInitialRequest() {
19      // Create continuation with a timeout
20      Continuation con = new Continuation(60);
21      // Set callback method
22      con.continuationMethod='processInitialResponse';
23      
24      // Create first callout request
25      HttpRequest req = new HttpRequest();
26      req.setMethod('GET');
27      req.setEndpoint(LONG_RUNNING_SERVICE_URL1);
28      
29      // Add initial callout request to continuation
30      this.requestLabel1 = con.addHttpRequest(req);              
31      
32      // Return the continuation
33      return con;  
34    }
35    
36    // Callback method for initial request
37    public Object processInitialResponse() {   
38      // Get the response by using the unique label
39      HttpResponse response = Continuation.getResponse(this.requestLabel1);
40      // Set the result variable that is displayed on the Visualforce page
41      this.result1 = response.getBody();
42           
43      Continuation chainedContinuation = null;
44      // Chain continuation if some condition is met
45      if (response.getBody().toLowerCase().contains('expired')) {
46          // Create a second continuation 
47          chainedContinuation = new Continuation(60);
48          // Set callback method
49          chainedContinuation.continuationMethod='processChainedResponse';
50          
51          // Create callout request
52          HttpRequest req = new HttpRequest();
53          req.setMethod('GET');
54          req.setEndpoint(LONG_RUNNING_SERVICE_URL2);
55          
56          // Add callout request to continuation
57          this.requestLabel2 = chainedContinuation.addHttpRequest(req); 
58      }
59      
60      // Start another continuation 
61      return chainedContinuation;  
62    }    
63    
64    // Callback method for chained request
65    public Object processChainedResponse() {   
66      // Get the response for the chained request
67      HttpResponse response = Continuation.getResponse(this.requestLabel2);
68      // Set the result variable that is displayed on the Visualforce page
69      this.result2 = response.getBody();
70           
71      // Return null to re-render the original Visualforce page
72      return null;
73    }
74}

The response of a continuation must be retrieved before you create a new continuation and before the Visualforce request is suspended again. You can’t retrieve an old response from an earlier continuation in the chain of continuations.

Note