[SalesForce] Updating a visualforce page with the return value of a future call

I am triggering an API call to an external service in my visualforce page. I want to show the response (for example, success/error messages) of the API call without refreshing the page.

What I was doing before that DIDN'T work:

In my controller, I was parsing the return value of the API call and storing it as a static variable in the controller.

public static List<CustomErrorMsg> failureErrorList {get; set;}

@future(callout=true)
public static void doRequest()
{
     //make the API call to an external service
     //JSON parse the response
     while(parser.nextToken() != null)
     {
         //parsing logic
         failureErrorList.add(new CustomErrorMsg(parsedObject));
     }

}

In the visualforce page:

<apex:page controller="myController">
    <apex:form >
    <apex:pageBlock>
       <apex:pageBlockButtons >
           <apex:commandButton rerender ="errorList" value="Refresh"/>
       </apex:pageBlockButtons>
    </apex:pageBlock>

    <!--  errors -->
    <apex:pageBlock render="{!NOT(ISNULL(failureErrorList))}" id="errorList">
        <apex:pageBlockSection >
            <apex:pageBlockTable value="{!failureErrorList}" var="f">
                <apex:column value="{!f.ErrorObj}"/>
                    <apex:column value="{!f.ErrorMsg}"/>
                </apex:pageBlockTable>
         </apex:pageBlockSection>
    </apex:pageBlock>
    </apex:form>    
</apex:page>

In my debug log, I can see Salesforce getting my failureErrorList, but nothing shows up on the page itself. I suspect that failureErrorList is null in the scope of that rerender call, even though failureErrorList looks fine in the scope of the doRequest() method.

Best Answer

Static variables are not serialized, and so are usually unsuitable for displaying data on a Visualforce page. Furthermore, asynchronous calls technically occur after the end of the transaction, so you have no way of getting the information after the fact. Instead, consider using an apex:actionFunction with an apex:actionStatus element to let the user know you're doing something, and make the function call and member variable non-static and, of course, not asynchronous.