function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Will Jones 18Will Jones 18 

Page not refreshing based off controller/visualforce page

I have a controller that I built based off this article:

http://www.soliantconsulting.com/blog/2012/08/view-triggers-salesforce-trigger-opportunity-contact-roles

However the issues is after I add a contact role and return to the opportunity page, the fields are not updated. It only updates when I do a manual page refresh.

Here is my controller:
 
public without sharing class OppHelper {
    public Opportunity opp;
    public OppHelper( ApexPages.StandardController stdController ) {
        opp = ( Opportunity )stdController.getRecord();        
    }
    public void insertOppContacts(){
        OppHelper.insertOppContactsFuture( opp.Id );    
    }
    @future public static void insertOppContactsFuture( Id oppId ) {
        Contact[] contactList = [ SELECT Id, FirstName, LastName, Email FROM Contact
                             WHERE Id IN ( SELECT ContactId FROM OpportunityContactRole
                                         WHERE OpportunityId = :oppId AND isPrimary = True ) ];
        Opportunity opp = [ SELECT Id, Primary_Contact__c FROM Opportunity WHERE Id = :oppId ];
        
        for( Contact contact : contactList ) {
            opp.Primary_Contact__c = contact.Id;
        }
        update opp;
    }
}



Here is my visualforce page:
 
<apex:page standardController="Opportunity" extensions="OppHelper" action="{!insertOppContacts}" />

 
MTBRiderMTBRider
Add a class variable:
 
private PageReference pageRef = ApexPages.currentPage();

Have your insertOppContractsFuture method return PageReference and then return pageRef:
 
public PageReference insertOppContactsFuture(Id oppId) {

   ...

    return pageRef;
}

Also, why is insertOppContactsFuture a @future method?   That is usually used when you are making web services call outs.

 
Will Jones 18Will Jones 18
Hey MTBRider,

Based upon the original link I gave up top, it suggested using the @future method:

Write a very simple Apex controller that has a constructor and one method with a future annotation. The future annotation will ensure there's no lack time when the page is loaded due to the "hidden" Apex processing you'll be doing:

So short answer I added it because the original code had it.

I'm still new to the developer side of Salesforce so I'm not exactly sure where I was suppose to make the changes you suggested. I did it as below, but it did not work:
 
public without sharing class OppHelper {
    public Opportunity opp;
    private PageReference pageRef = ApexPages.currentPage();
    public OppHelper( ApexPages.StandardController stdController ) {
        opp = ( Opportunity )stdController.getRecord();        
    }
    public PageReference insertOppContacts(){
        OppHelper.insertOppContactsFuture( opp.Id );
        return pageRef;    
    }
    @future public static void insertOppContactsFuture( Id oppId ) {
        Contact[] contactList = [ SELECT Id, FirstName, LastName, Email FROM Contact
                             WHERE Id IN ( SELECT ContactId FROM OpportunityContactRole
                                         WHERE OpportunityId = :oppId AND isPrimary = True ) ];
        Opportunity opp = [ SELECT Id, Primary_Contact__c FROM Opportunity WHERE Id = :oppId ];
        
        for( Contact contact : contactList ) {
            opp.Primary_Contact__c = contact.Id;
        }
        update opp;
        
    }
}



 
MTBRiderMTBRider
Ok, sorry, I did not look at the link originally and thought you were trying to built just a standard VF page and controller.  
The way you have it may work sometimes and not other times since the insertOppContacts method is calling a future method, it will not wait for that future method to complete before returning the pageRef, thus the update may not have happened yet when it tries to refresh.

Your could try doing having the pageRef returned by the same method that is doing the update.  So like this:


@future public static PageReference insertOppContactsFuture( Id oppId ) { 
   Contact[] contactList = [ SELECT Id, FirstName, LastName, Email FROM Contact WHERE Id IN ( SELECT ContactId 
                               FROM OpportunityContactRole 
                                WHERE OpportunityId = :oppId AND isPrimary = True ) ]; 
   Opportunity opp = [ SELECT Id, Primary_Contact__c 
                        FROM Opportunity WHERE Id = :oppId ]; 
   for( Contact contact : contactList ) { 
     opp.Primary_Contact__c = contact.Id; 
   }  
   update opp; 
   return pageRef;
}
But, with the @future in there I am not sure how it is going to behave.  The @future allows the code to continue to execute instead of waiting for insertOppContactsFuture to finish executing, so the refresh may not happen or may happen at a time when you do not want it to happen (like when the user has started to edit something else).

The example that you used looks to be a method to keep a roll up field fresh on an Opportunity record when the roll up value is based on what contacts are in the associated Opp contact role.  The problem that the code solved is that there is not Opp Contact Role triggers in Salesforce so when an Opp contact changes, the roll up value will not refresh.  If all you are trying to do is automatically add the primary contact to the opportunity, maybe keep it simple and just do that with a Opportunity Trigger?
 
Will Jones 18Will Jones 18
Thanks for the feedback MTBRider. Unfortunately it does not allow the use of "PageReference" with "@future".

The issue with using an Opportunity Trigger is that when a contact role is added from the related list, there is no "save" that occurs on the opportunity. So a trigger would not catch it. I need for the fields to be populated on the opportunity whether a save occurs or not.

I wonder if eliminating the "@future" would be the best thing to do. Any issues you can think of by going this route?
Will Jones 18Will Jones 18
Even without the @future it still does not update properly. Only when I manually refresh. Could there be something that needs to be update on the visualforce page instead? To refresh the page when the action is done?
DeveloperSudDeveloperSud
Hi Will ........did u find any solution to this problem?