0

I have created an InvocableMethod method, but it is not visible in visual flow to add Apex Action.

public class ApprovalProcessService {

    @InvocableMethod
    public static List<ApprovalProcessResult> recallApprovalProcess(Id[] recordIds) {

        List<ProcessInstance> instances = [SELECT Id FROM ProcessInstance WHERE TargetObjectId = :recordIds[0] AND Status='Pending' limit 1];

        ApprovalProcessResult res = new ApprovalProcessResult();

        if(!instances.isEmpty()){
            List<ProcessInstanceWorkitem> workItems = [SELECT Id FROM ProcessInstanceWorkitem WHERE ProcessInstanceId = :instances[0].Id limit 1];

            Approval.ProcessWorkItemRequest req = new Approval.ProcessWorkItemRequest();

            req.setWorkItemId(workItems[0].Id);
            req.setAction('Removed'); // This means to remove/recall Approval Request
            req.setComments('Apex Recall Approval.');

            Approval.ProcessResult result = Approval.process(req);

            res.isSuccess = result.isSuccess();

            if(! res.isSuccess) {

                String errorMessage = '';
                for(Database.Error error: result.getErrors()){
                    errorMessage += error.getMessage();
                }

                res.message = errorMessage;
            }

        } else {
            res.isSuccess = true;
            res.message = null;
        }

        return new List<ApprovalProcessResult>{res};
    }

    public class ApprovalProcessResult {

        @InvocableVariable(required=true)
        public Boolean isSuccess; 

        @InvocableVariable(required=true)
        public String message;

    }
}

I am not getting, what is flaw in this code?

  • I wonder if it relates to the use of an inner class for the result? – Phil W May 23 at 6:58
  • is it in a managed package ? – Tarique Shamim May 23 at 7:01
  • @PhilW I tried without inner class and set return type as void of invocable method but still was not working. – Mukesh Saxena May 23 at 7:02
  • @TariqueShamim Nope! – Mukesh Saxena May 23 at 7:02
  • Can you please try making it global, I think only global classes with InnvocableMethod will be available to the flow. – Tarique Shamim May 23 at 7:05
1

I have got the solution for this. I just need to set label and description of InvocableMethod.

public class ApprovalProcessService {

    @InvocableMethod(label='Recall Approval Process' description='Recall Approval Process')
    public static List<ApprovalProcessResult> recallApprovalProcess(Id[] recordIds) {

        List<ProcessInstance> instances = [SELECT Id FROM ProcessInstance WHERE TargetObjectId = :recordIds[0] AND Status='Pending' limit 1];

        ApprovalProcessResult res = new ApprovalProcessResult();

        if(!instances.isEmpty()){
            List<ProcessInstanceWorkitem> workItems = [SELECT Id FROM ProcessInstanceWorkitem WHERE ProcessInstanceId = :instances[0].Id limit 1];

            Approval.ProcessWorkItemRequest req = new Approval.ProcessWorkItemRequest();

            req.setWorkItemId(workItems[0].Id);
            req.setAction('Removed'); // This means to remove/recall Approval Request
            req.setComments('Apex Recall Approval.');

            Approval.ProcessResult result = Approval.process(req);

            res.isSuccess = result.isSuccess();

            if(! res.isSuccess) {

                String errorMessage = '';
                for(Database.Error error: result.getErrors()){
                    errorMessage += error.getMessage();
                }

                res.message = errorMessage;
            }

        } else {
            res.isSuccess = true;
            res.message = null;
        }

        return new List<ApprovalProcessResult>{res};
    }

    public class ApprovalProcessResult {

        @InvocableVariable(required=true)
        public Boolean isSuccess; 

        @InvocableVariable(required=true)
        public String message;

    }
}

recordIds is working as input variable and ApprovalProcessResult as output variables.

0

Your class should be global.

global class ApprovalProcessService {

@InvocableMethod
public static List<ApprovalProcessResult> recallApprovalProcess(List<giveInPutToFlow> recordIds){

  // your own logic
  // I have passed List of wrapper class as parameter but It is not require you
      can go with your logic.

   return new List<ApprovalProcessResult>();
}


global class giveInPutToFlow{
    @InvocableVariable
    global Id recordIds;

}

}

  • It does not work to me. – Mukesh Saxena May 23 at 7:15
  • The documentation says it can be public; it doesn't have to be global. You only need it global if the process builder flow is in a different context to the code (e.g. the code is in a managed package and the process builder flow is in the subscriber org). – Phil W May 23 at 7:32
  • Ok , but best practice is to use global access modifier . we always try to write generic code not for the special case . @thanks For example , when we know that we will update contact always by user interface then also we don't write trigger that will run for single record , in this case also we write bulkify and generic trigger. – Akash Pundir May 23 at 8:18

Not the answer you're looking for? Browse other questions tagged or ask your own question.