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
Leo DarkstarLeo Darkstar 

How to invoke Apex Class with Process Builder

I am attempting to start this Apex class with Process Builder, triggered by a field change. I've never done this before and I'm unsure what invoke code needs to be added in order to accomplish this. I tried adding @InvocableMethod but I'm getting an error telling me this :

 

Compile Error: Unsupported parameter type String. 
Valid invocable parameters must be List types like List<T> 
where T is a supported type at line 26 column 27

It is a class which is currently being invoked with a Lightning Component button in a record.

public class UpdateContactPCRController {

    @InvocableMethod
    public static String  updateContact(String recordId){        
       
        String contactId = '';       
        
        List<Contact> contactToBeupdate = new List<Contact>();        
        
        if(String.isNotBlank(recordId)){            
            
            List<Program_Contact_Role__c> programContacList = [SELECT Id,Contact__c,Program_Name__c FROM Program_Contact_Role__c WHERE Id =:recordId AND Contact__c != null];
            contactId = programContacList[0].Contact__c;
            
            if(String.isNotBlank(contactId)){
                
                contactToBeupdate = [Select Id,Pardot_Action_Trigger__c,PCR_Register_Button_Link__c,PCR_URL_for_UI__c FROM Contact Where Id =: contactId Limit 1];                
                
                contactToBeupdate[0].Program_Contact_Role_Id__c = recordId;
            }
                        List<Program_Communication_Recipients__c> programCommunicationRecs = [Select Id,Name,
                                  Program_Communication__r.Program__r.Buyer__r.Name,Receipient__c,                
                                              From Program_Communication_Recipients__c Where 
                                                           Program_Communication__r.Program__c =: programContacList[0].Program_Name__c AND 
                                                           Receipient__c =: programContacList[0].Id];                                           
                                
                
                    contactToBeupdate[0].PCR_Welcome_Message__c = String.valueOf(programCommunicationRecs[0].Program_Communication__r.Welcome_Message__c);                                                    

        if(contactToBeupdate.size() > 0){
            update contactToBeupdate;  
        }
        
        return 'Updated Successfully';
    }
}

Thank you very much for any help you can give with this. It is very appreciated.
Best Answer chosen by Leo Darkstar
vishal-negandhivishal-negandhi

Hi Leo, 

If you read through this - https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_annotation_InvocableMethod.htm

An invocable method needs to have a List as its parameter and can only return List. 

Below modified code should surely work for you

 

public class UpdateContactPCRController {

    @InvocableMethod
    public static List<String> updateContact(List<String> recordId){        
       
		String contactId = '';       
       
	    List<Contact> contactToBeupdate = new List<Contact>();        
        
        if(recordId.size()> 0){            
            
            List<Program_Contact_Role__c> programContacList = [SELECT Id,Contact__c,Program_Name__c FROM Program_Contact_Role__c WHERE Id =:recordId[0] AND Contact__c != null];
            contactId = programContacList[0].Contact__c;
            
            if(String.isNotBlank(contactId)){
                
                contactToBeupdate = [Select Id,Pardot_Action_Trigger__c,PCR_Register_Button_Link__c,PCR_URL_for_UI__c FROM Contact Where Id =: contactId Limit 1];                
                
                contactToBeupdate[0].Program_Contact_Role_Id__c = recordId[0];
            }
                        List<Program_Communication_Recipients__c> programCommunicationRecs = [Select Id,Name,
                                  Program_Communication__r.Program__r.Buyer__r.Name,Receipient__c,                
                                              From Program_Communication_Recipients__c Where 
                                                           Program_Communication__r.Program__c =: programContacList[0].Program_Name__c AND 
                                                           Receipient__c =: programContacList[0].Id];                                           
                                
                
                    contactToBeupdate[0].PCR_Welcome_Message__c = String.valueOf(programCommunicationRecs[0].Program_Communication__r.Welcome_Message__c);                                                    

        if(contactToBeupdate.size() > 0){
            update contactToBeupdate;  
        }
        List<String> response = new List<String>();
        response.add('Updated Successfully');
		return response;
    }
}

This should fix the problem.

All Answers

vishal-negandhivishal-negandhi

Hi Leo, 

Invocable methods can only have a parameter type of List, so your code needs to be modified a bit
 

@InvocableMethod
    public static String  updateContact(List<String> recordId){        
       
        String contactId = '';       
        
        List<Contact> contactToBeupdate = new List<Contact>();        
        
        if(record.size() > 0){            
            
            List<Program_Contact_Role__c> programContacList = [SELECT Id,Contact__c,Program_Name__c FROM Program_Contact_Role__c WHERE Id =:recordId[0] AND Contact__c != null];
            contactId = programContacList[0].Contact__c;

.....
You are still sending just one Id but it will be in a List parameter because that is what Invocable method supports.
I hope this helps.
vishal-negandhivishal-negandhi
Also, this line would change

contactToBeupdate[0].Program_Contact_Role_Id__c = recordId;

TO 

contactToBeupdate[0].Program_Contact_Role_Id__c = recordId[0];
Leo DarkstarLeo Darkstar

Hello Vishal,

 

Thank you so much for your help with this. I have made the changes you have listed but am still getting this error : 

Error: InvocableMethod methods do not support return type of String at line 28 column 27

That is a reference to this line : 

public static String  updateContact(List<String> recordId){
 

I'm wondering if it is just easier to write a trigger for this instead of making the alterations necessary for Process Builder ? If that is a better way of doing it can you give some guidance on that instead ? Thank you so much again. 

 

vishal-negandhivishal-negandhi

Hi Leo, 

If you read through this - https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_annotation_InvocableMethod.htm

An invocable method needs to have a List as its parameter and can only return List. 

Below modified code should surely work for you

 

public class UpdateContactPCRController {

    @InvocableMethod
    public static List<String> updateContact(List<String> recordId){        
       
		String contactId = '';       
       
	    List<Contact> contactToBeupdate = new List<Contact>();        
        
        if(recordId.size()> 0){            
            
            List<Program_Contact_Role__c> programContacList = [SELECT Id,Contact__c,Program_Name__c FROM Program_Contact_Role__c WHERE Id =:recordId[0] AND Contact__c != null];
            contactId = programContacList[0].Contact__c;
            
            if(String.isNotBlank(contactId)){
                
                contactToBeupdate = [Select Id,Pardot_Action_Trigger__c,PCR_Register_Button_Link__c,PCR_URL_for_UI__c FROM Contact Where Id =: contactId Limit 1];                
                
                contactToBeupdate[0].Program_Contact_Role_Id__c = recordId[0];
            }
                        List<Program_Communication_Recipients__c> programCommunicationRecs = [Select Id,Name,
                                  Program_Communication__r.Program__r.Buyer__r.Name,Receipient__c,                
                                              From Program_Communication_Recipients__c Where 
                                                           Program_Communication__r.Program__c =: programContacList[0].Program_Name__c AND 
                                                           Receipient__c =: programContacList[0].Id];                                           
                                
                
                    contactToBeupdate[0].PCR_Welcome_Message__c = String.valueOf(programCommunicationRecs[0].Program_Communication__r.Welcome_Message__c);                                                    

        if(contactToBeupdate.size() > 0){
            update contactToBeupdate;  
        }
        List<String> response = new List<String>();
        response.add('Updated Successfully');
		return response;
    }
}

This should fix the problem.
This was selected as the best answer
Leo DarkstarLeo Darkstar
Vishal,

I'm sorry for getting back to you so late on this. I have not had a chance to fully test this, but this did save properly and it does appear that the class is now available in Proc Builder. Thank you so much for all of your help with this. I truly appreciate all of your time and help !
Leo DarkstarLeo Darkstar

Vishal,

 

I tried implementing this and apparently the callout which executed at this line : 

 

contactToBeupdate[0].PCR_Welcome_Message__c = String.valueOf...

Is causing this type of error : 

You have uncommitted work pending. Please commit or rollback before calling out


So, I think I may be unable to invoke the class with a Process Builder since the data updates can only happen after the callout...? 

If that's the case, could I invoke this code somehow through a trigger which runs BeforeUpdate...? If so, what would that look like ? I would need it to be invoked with an IsChanged(SendEmail__c) type of criteria. Can you show me that please ? Thank you so much for all of your help.