0

I have a visualforce page that creates a record, and then assigns a permission set to the User and updates some of the fields on the user.

The update for the Permission Set Assignment needs to be a future method. However, I can't get the page to reload when the future method is complete.

Are there any design patterns for VisualForce that uses a future method and then populates a table with the result after its finished.

 @Future
    public static void setPermissionSet(Id userId, String permissionSetName) {
        PermissionSet ps = [SELECT Id FROM PermissionSet WHERE Name = :permissionSetName LIMIT 1];


// Create a PermissionSetAssignment record to assign the permission set to the user


            PermissionSetAssignment psa = new PermissionSetAssignment();
            psa.AssigneeId = userId;
            psa.PermissionSetId = ps.Id;



// Insert the PermissionSetAssignment record
        insert psa;
    }

I call this from a save method in the controller class.

public void save(){

        System.debug('SAVING');
        Savepoint sp = Database.setSavepoint();


        try{
            checkEmailOption();

            insert con;
            ApexPages.Message myMsg = new ApexPages.Message(ApexPages.Severity.CONFIRM, 'SUCCESS: You have commissioned ' + [SELECT Id, Name FROM Contact WHERE Id =: this.c.Id].Name);
            ApexPages.addMessage(myMsg);
            this.conTypes = GetConTypes();

            if (assignPermInput == true && emailOption!=ADF_Utilities.defaultValue) {
                updateUser();
            }


            checkFuture();
            this.psa = getPermissionAssignments();
            this.con = new Classification_Type_Contact__c(Contact__c = this.c.Id );

        } catch (Exception e){

            System.debug(e.getMessage());
            ApexPages.Message myMsg = new ApexPages.Message(ApexPages.Severity.ERROR, 'Oops... ' + e.getMessage());
            ApexPages.addMessage(myMsg);
            Database.rollback(sp);
        }

    }

1 Answer 1

1

Future methods don't run until after the current transaction completes. Further, you can't get an ID to check for a future method. Instead, use Queueable, and break your logic up into two parts.

Id jobId;
public void save() {
  jobId = System.enqueueJob(new CreateUserPermQueueable());
}
public void saveWait() {
   AsyncApexJob job = [SELECT Status FROM AsyncApexJob WHERE Id = :jobId FOR UPDATE];
   if(job.Status == 'Completed') {
     doMoreStuff();
   }
}

In Visualforce itself, you'll use an apex:actionFunction to be called oncomplete from the save method:

<apex:actionFunction action="{!saveWait}" reRender="form" name="saveWaitJS" />
<apex:commandButton action="{!save}" oncomplete="saveWaitJS()" label="Save" reRender="form" />
3
  • Is the "doMoreStuffe" where you would do a SOQL query to repopulate the table?
    – thinker
    Commented Apr 21, 2023 at 13:38
  • do you know if this will resubmit the form as well?
    – thinker
    Commented Apr 21, 2023 at 14:31
  • 1
    @thinker (a) yes, and (b) yes, though I use rerender in this example to avoid a full screen reload/form submit, so it would be a seamless experience for the user.
    – sfdcfox
    Commented Apr 21, 2023 at 15:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .