+ Start a Discussion

Visualforce page not updating correctly with batch apex job result



Could anyone assist me with the following issue I have:


I have created an apex class that does some querying of accounts and custom objects in preparation to making a query for the related contact records. Basically I have a Product/services object that is referenced in a PArticipation Details object that is in turn referenced in an Account. Therefore the class would return ALL contacts at the accounts for a certain Product/Service.

Since some of those product/services are very famous, there are some that return over 10,000 contacts and for that reason, that part of the querying must be done in an apex batch job.


I have debugged the results and the contacts list is updated with the scope list in the execute method, BUt for some reason the visualforce page is not updated with the resulting list. Below is the code of the visualforce page and the controller:



global class contact_fromAcc_by_ProdServ implements Database.Batchable<sObject> {
    VRDbg.VRDebugLogger vrdl = new VRDbg.VRDebugLogger();
    public Id selectedProduct {get;set;}
    public List<Account> accs;
    private List<Contact> contacts= new List<Contact>();
    public List<Id> pdsAccIds = null;
    public Products_Services__c currentProduct;   
    public List<Participation_Detail__c> tempPDList;
    public List<Contact> ContactList {get{return contacts;}set;} 
    public contact_fromAcc_by_ProdServ(ApexPages.StandardController standard) {
    public contact_fromAcc_by_ProdServ() {
    //Product Service List objects - PROPERTY
    public List<SelectOption> PS_Items {
        get {
            List<selectOption> options = new List<selectOption>();
            options.add(new SelectOption('','-- Choose a Product/Service --'));
            for(Products_Services__c p: [SELECT Id, Name,Type__c from Products_Services__c WHERE P_S_Status__c = 'Active' ORDER BY Name ASC]){
               // this.currentProduct = p;
                options.add(new SelectOption(p.Id,p.Name));
                selectedProduct = p.Id;}
                return options;

    //Method to calculate contact list
public void updateContactList() {        
        if (selectedProduct != NULL) {
            pdsAccIds = new List<Id>();
            tempPDList = [Select p.Account__c 
                          From Participation_Detail__c p 
                          WHERE p.Product_Service__c = :selectedProduct AND p.Status__c = 'Current'];
            //get Account Ids in temp PD list.
             for(Participation_Detail__c pd: tempPDList){
                if(pd.Account__c != null){
            //execute batch job to get contact data from Account listing.
            if(this.pdsAccIds != null){
                Database.executeBatch(this, 50000);
                ContactList = contacts;
    }//end method
      public void clearList (){
        //this.contacts = null;
      //////// Mandatory implementation of Batchable processes interface to retrieve contacts from SF
     global Database.queryLocator start (Database.BatchableContext ctx){
        return Database.getQueryLocator([SELECT
                                                c.Id, c.Full_Name__c, c.AccountId , 
                                                c.Account.Master_Account_Status__c , c.Account.Sub_Status_IMS__c, 
                                                c.Account.SubStatusSynXisCRS__c, c.Account.Sub_Status_Sabre_GDS__c, 
                                                c.Account.Sub_Status_Hotel_RFP__c, c.Account.Sub_Status_Internal__c , 
                                                c.Contact_Type__c, c.Email, c.HasOptedOutOfEmail, c.Subscriptions_SynXis_Selected__c, 
                                        FROM Contact c 
                                                c.No_Longer_with_this_Account__c !=True 
                                                AND c.EmailBouncedDate = null 
                                                AND Account.Id IN:pdsAccIds ]);
    global void execute(Database.BatchableContext BC, list<Contact> scope){
        for(Contact con:scope){
         vrdl.logIt('Contacts list size: ' + contacts.size() + ' || Scope list size: ' + scope.size() + 'ContactList method: ' + ContactList);
    global void finish(Database.BatchableContext BC){} 
}//end class

 and the visualforce page:


<!--Product/service name 
Account Owner (when AM is the Account Owner) 
Instead of Full Name make link to Contact record? 
Add Sub-Status fields 
Take out Fax field 
Email Opt Out? 
Maybe a link to the Participation Detail record?-->
<apex:page tabStyle="Products_Services__c"   controller="contact_fromAcc_by_ProdServ" pageStyle="Contact"  sidebar="false" standardStylesheets="true" showHeader="false" >  
<apex:pageBlock >
        <apex:sectionHeader /> 
        <font color="black" size="5" align="center">Contacts @ Accounts by Product Service</font><br/><br/>
         This page will let you select a Product/Service and it will list all the contacts that are related to accounts that contract that Product/Service via Participation Details. First select
         a Product/Service from the picklist below then wait for the contacts to be calculated and displayed onscreen. Once you can see the contacts, you can permorm regular view actions such as sort,
         export excel file, add/remove fields, etc.        
<!-- Page block to list all ProductServices-->
<apex:pageBlock >
    <apex:form >
        <apex:pageBlockSection title="     Active Product Services" showHeader="true" collapsible="false" dir="" columns="2">
               <apex:selectList value="{!selectedProduct}" size="1" multiselect="False" id="products" >
                   <apex:selectOptions value="{!PS_Items}" id="psi"/>
               <apex:commandButton action="{!updateContactList}" rerender="contactlist" status="Constatus" title="Click to update Contact list" value="Update Contact List" /> 
        <apex:pageBlockSection title=" Contacts List" showHeader="true" collapsible="false">
                <apex:pageBlockSectionItem >
                    <apex:commandButton value="Export to Excel" action="/apex/contacts_romAcc_by_ProdServ_EXCELexport"/>   
                <apex:pageBlockSectionItem >
                    <apex:actionStatus id="Constatus">
                        <apex:facet name="start" >'Updating Contact List...'</apex:facet>
            <apex:pageBlockSection >
               <apex:outputPanel id="contactlist" >
                  <apex:pageBlockTable width="100" value="{!ContactList}" var="c" id="dt" >
                     <apex:column >
                         <apex:facet name="header">Full Name</apex:facet>
                         <apex:outputLink value="/{!c.Id}" target="_blank">{!c.Full_Name__c}</apex:outputLink>

                     <apex:column value="{!c.AccountId}" width="250">
                         <apex:facet name="header">  Account Name  </apex:facet>

                     <apex:column value="{!c.Account.Master_Account_Status__c}">
                         <apex:facet name="header">Account Master Status</apex:facet>

                    <apex:column value="{!c.Account.SubStatusSynXisCRS__c}">
                         <apex:facet name="header">Sub Status Synxis CRS</apex:facet>

                    <apex:column value="{!c.Account.Sub_Status_Sabre_GDS__c }">
                         <apex:facet name="header">Sub Status Sabre GDS</apex:facet>
                      <apex:column value="{!c.Account.Sub_Status_Hotel_RFP__c}">
                         <apex:facet name="header">Sub Status Hotel RFP</apex:facet>
                     <apex:column value="{!c.Account.Sub_Status_IMS__c}">
                         <apex:facet name="header">Subscriptions - Customer Selected</apex:facet>
                      <apex:column value="{!c.Subscriptions_SynXis_Selected__c}">
                         <apex:facet name="header">Subscriptions - Synxis Selected</apex:facet>
                      <apex:column value="{!c.Subscriptions_Customer_Selected__c}">
                         <apex:facet name="header">Subscriptions - Customer Selected</apex:facet>
                      <apex:column value="{!c.HasOptedOutOfEmail}">
                         <apex:facet name="header">Email Opt Out</apex:facet>
         <apex:pageBlockSection >
             <apex:panelGrid columns="3"> 
                 <apex:commandButton value="Export to Excel" action="/apex/contacts_romAcc_by_ProdServ_EXCELexport"/>
                 <apex:outputLabel style="color:#404040;"> ***IMPORTANT: Due to SF restrictions, the EXPORT TO EXCEL button only works with  the Google CHROME or Mozilla FIREFOX browsers. If it is run from IE6/7 it will NOT download the excel file.***



Thank you!!!


Imran MohammedImran Mohammed

Batch Apex runs asynchronously, so any processed results will not be reflected on the Visualforce page.



What can I do to solve this? Is there another way that I could get this done?


The most important thing is to be able to export the list to excel, updating the visualforce page with the list can be discarded if impossible. BUT at the minimum I need to be able to export the batch apex results to an excel file.


It would be great if I could at least show a smaller version in the page (using regular query in the list and show the first 1000 items) and then the complete list to be exported to an excel file.



THank you!

Hi arishi0,

Did you found the solution for this.
If yes can you share with me.