In the recent past we've replaced two very old s-control type and html mashups with visual force pages and web services. This changes along with a few other visual force pages built into our standard Account page has create a scenario where we are hitting the Concurrent Request error a few times a week.
I have taken some time to redesign one of the java web services to implement an asynchronous pattern. I'm trying to get the apex callout to use continuation.
Since this is not processing related but necessary to fully load the UI, I want this continuation to execute on load of the page. Right now, I can get the class to load but in the debugger timeline view, no callout is made.
In articles I've read it appears only possible to have the section of the visual force page reloaded on some action. Do I need to call the Continuation straight from my visualforce page or can the extension call it and bubble the response up?
Visualforce page:
<apex:page standardController="Account" extensions="InformationExtension2">
<apex:outputPanel id="Info">
<table id="summary">
<tr><th colspan="5"><apex:outputText >{!id}</apex:outputText></th></tr>
<tr class="summaryHeaderRow">
<th></th>
<th colspan="3" class="headerRow">Registration</th>
<th colspan="3" class="headerRow">Accounts</th>
<th class="headerRow">Value</th>
<th class="headerRow">As Of</th>
<th class="headerRow">%</th>
</tr>
<!-- Additional Table Information-->
</apex:outputPanel>
</apex:page>
Extension:
public InformationExtension2(ApexPages.StandardController controller) {
this.acct = (Account)controller.getRecord();
custId = getThisCustId();
getInformation();
}
public void getInformation()
{
System.debug(custId);
InformationContinuation continuation = new InformationContinuation(custId);
InformationSubtotal subtotals = new InformationSubtotal();
Information info = new Information();
try{
Object testing = continuation.getInfoCon();
if(testing==null)
{
System.debug(LoggingLevel.FINE,'Continuation returned null');
}
else{
System.debug(LoggingLevel.FINE,'Continuation returned with response');
System.debug(LoggingLevel.FINE,'Continuation returned '+continuation.pi);
info=continuation.pi;
}
.... Additional Processing
}
}
Class containing the continuation
public class InformationContinuation {
String custId{get;set;}
String requestLabel;
Object result;
public Information info;set;}
/*Constructor*/
public InformationContinuation(String custId)
{
this.custId = custId;
}
//Action Method
public Object getInfoCon(){
//create continuation with timeout
Continuation con = new Continuation(60);
//Set the callback method for the resonse
con.continuationMethod = 'processResponse';
//Create the callout request
HttpRequest req = new HttpRequest();
req.setClientCertificateName('InfoService');
req.setMethod('GET');
req.setEndpoint(SERVICE_ENDPOINT+this.custId);
//Add callout request to continuation
this.requestLabel = con.addHttpRequest(req);
return con;
}
public Object processResponse(){
System.debug(LoggingLevel.FINE,'received response to process');
//get the response by using the unique label
HttpResponse response = Continuation.getResponse(this.requestLabel);
Integer statusCode = response.getStatusCode();
//Check the status code
if(statusCode==2000)
{
System.debug(LoggingLevel.ERROR,'The request timeout was reached');
return null;
}
if(statusCode==2001)
{
System.debug(LoggingLevel.ERROR,'There was a connection failure');
return null;
}
if(statusCode==2002)
{
System.debug(LoggingLevel.ERROR,'The request timeout was reached');
return null;
}
if(statusCode==2003)
{
System.debug(LoggingLevel.ERROR,'The response hasn\'t arrived. Also means the async '
+'framework hasn\'t resumed');
return null;
}
if(statusCode==2004)
{
System.debug(LoggingLevel.ERROR,'The response is too large');
return null;
}
if(String.isEmpty(response.getBody())){
info=null;
System.debug(LoggingLevel.ERROR,'Response from webservice is empty, blank or null');
}else
{ //Process the JSON response }...
}
}