doesn’t render when using continuation(asynchonous callout)

It seems like there’s a bug rerendering an <apex:map> from asynchronous callout.

On my sample page below I have two <apex:commandbutton> one executing an asynchronous callout(action="{!requestServiceAsync}") and the other one a synchronous callout(action="{!requestService}") and both rerenders the mapPanel which contains an <apex:map>.

If I click the button that executes the asynchronous callout, it doesn’t render the map when it finishes. While it renders properly when the synchronous callout is executed.

Am I missing something on how asynchronous callout renders an <apex:map> component or is this a bug?

Sample page below:

modified page from:(http://www.jitendrazaa.com/blog/salesforce/continuation-object-in-apex-asynchronous-callouts-for-long-running-request-live-demo/)

VF PAGE

<apex:page docType="html-5.0" showHeader="false" sidebar="false" controller="ISOtoCodeService">
<apex:form >
    <apex:pageBlock title="Continuation Demo">
        Country ISO :
        <apex:input label="Country ISO" value="{!countryISO}"/>
        <apex:commandButton action="{!requestServiceAsync}" value="Request Service Async" reRender="responseBlock, mapPanel"/>
        <apex:commandButton action="{!requestService}" value="Request Service" reRender="responseBlock, mapPanel"/>

    </apex:pageBlock>

    <apex:pageBlock title="Response from Webservice" id="responseBlock">

<pre> {!response} </pre>

    </apex:pageBlock>
</apex:form>
<style type="text/css">
    pre{
        font-size : 1.7em;
    }
</style>
<apex:outputPanel id="mapPanel">
    <apex:map rendered="true"
              scrollBasedZooming="false"
              width="80%"
              height="200px"
              mapType="satellite" 
              zoomLevel="18"
              center="1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA">

        <apex:mapMarker position="1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA"
                        title="1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA"/>
    </apex:map>
</apex:outputPanel>

Page Controller

public class ISOtoCodeService {
    public String countryISO {get;set;}
    public String response {get;set;} 

    private String baseSericeURL = 'http://services.groupkt.com/country/get/iso2code/';
    private String returnedContinuationId ;

    public ISOtoCodeService()
    {
        countryISO = 'IN';
    } 

    public Object requestServiceAsync(){

        //Timeout in seconds, 60 is limit
        Continuation con = new Continuation(60);

        // Set callback method
        con.continuationMethod='renderResponse';

        // Create callout request
        HttpRequest req = new HttpRequest();
        req.setMethod('GET');
        req.setEndpoint(baseSericeURL+countryISO);

        returnedContinuationId = con.addHttpRequest(req);

        return con;
    }

    public Object renderResponse() {
      // Get the response by using the unique label
      HttpResponse httpRes = Continuation.getResponse(returnedContinuationId);
      // Set the result variable that is displayed on the Visualforce page
      response = httpRes.getBody();
      // Return null to re-render the original Visualforce page
      return null;
    }

    public void requestService() {
        // Create callout request
        HttpRequest req = new HttpRequest();
        req.setMethod('GET');
        req.setEndpoint(baseSericeURL+countryISO);

        // Get the response by using the unique label
        Http http = new Http();
        HTTPResponse res = http.send(req);
        // Set the result variable that is displayed on the Visualforce page
        response = res.getBody();

    }

}

UPDATE: 22/06/2017———————

Thanks to @Daniel on his comment below for pointing out the difference on the return type of the async/sync methods. It seemed to have worked using a separate <apex:actionfunction> to render the panels.

I used the renderPage <apex:actionfunction> that renders the specified panels and then called it on oncomplete attribute of the async commandbutton.

I still don’t get why the <apex:map> doesn’t rerender properly from a continuation request because I’ve also tried putting the {!response} inside the mapPanel and it rendered properly using the async command button. Which means this might be a bug that is only specific for <apex:map> component

UPDATED VF PAGE

<apex:page docType="html-5.0" showHeader="false" sidebar="false" controller="ISOtoCodeService">
    <apex:form >
        <apex:pageBlock title="Continuation Demo">
            Country ISO :
            <apex:input label="Country ISO" value="{!countryISO}"/>
            <apex:commandButton action="{!requestServiceAsync}"  value="Request Service Async" oncomplete="renderPage();"/>
            <apex:commandButton action="{!requestService}" value="Request Service" reRender="responseBlock, mapPanel"/>
                                                                                               <!-- oncomplete="renderPageX();"    -->
            <apex:actionFunction name="renderPage" reRender="responseBlock,mapPanel"/>
        </apex:pageBlock>

        <apex:pageBlock title="Response from Webservice" id="responseBlock">

    <pre> {!response} </pre>

        </apex:pageBlock>

        <apex:outputPanel id="mapPanel">
            <apex:map rendered="true"
                      scrollBasedZooming="false"
                      width="80%"
                      height="200px"
                      mapType="satellite" 
                      zoomLevel="18"
                      center="1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA">

                <apex:mapMarker position="1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA"
                                title="1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA"/>
            </apex:map>
       </apex:outputPanel>
    </apex:form>
    <style type="text/css">
        pre{
            font-size : 1.7em;
        }
    </style>

</apex:page>

Answer

Attribution
Source : Link , Question Author : sfdx , Answer Author : Community

Leave a Comment