5

I have the following list in a trigger.

list<Employees__c> employeesToUpdate   = new list<Employees__c>();

I want to pass the list to a Future method. All I really need is the ID of the Employee__c record.

I am getting the following error from my future method.

Unsupported parameter type List<Employees__c>

Here is my future method:

public class EmployeeBenefitSummaries {
    @future
    public static void generateSummaries( List<Employees__c> emps) {
        // Get Employee and sessions for counts
       ***CODE***
    }
}
  • 3
    do a List<Id> instead of List<Employee__c> – kurunve Jul 13 '16 at 20:21
15

According to the documentation here:

Methods with the future annotation must be static methods, and can only return a void type. The specified parameters must be primitive data types, arrays of primitive data types, or collections of primitive data types. Methods with the future annotation cannot take sObjects or objects as arguments.

You'll have to pass a List<Id> rather than a List<Employee__c>.

  • 5
    Even better, pass a Set<ID> and avoid dupes. :D – Sebastian Kessel Jul 13 '16 at 20:46
7

+1 for passing the IDs.

But for completeness, be aware that you can use a string to pass complex data, with JSON being the obvious format choice. So JSON.serialize, pass that string to the @future and then JSON.deserialize in the future method.

  • I was going to bring that up, but wasn't sure of his use case for this process – EricSSH Jul 13 '16 at 22:09
  • Probably best to avoid this approach unless it is truly necessary. Still, it is worth mention so +1 all the same. – Adrian Larson Jul 13 '16 at 22:12
  • @EricSSH Yeah not likely to fit the question, just wanted to add it for e.g. where some non-persisted data needs passing and someone has hit this question via Google. – Keith C Jul 13 '16 at 22:12
7

SFDC wants you to send ID's because it wants to re-query back out the data because an @future can fire anytime after it is called, the issue is that items in your List<Employees__> can change, so by re querying out your List you will ensure that you have the most up to date values for your list. Todd is correct but I wanted to explain it a little bit more

What you could do is from the start build a `Map or convert it

 List<Employees__c> employeesToUpdate = new List<Employees__c>();
 Map<Id, Employees__c> employeeMap = new Map<Id, Employees__c>(employeesToUpdate);

Then call your method.. Also by having that handler method at the top you will be able reuse the method for other @future calls and it will also ensure that you call it properly and only once

EmployeeBenefitSummaries.requestFutureCall(employeeMap.keySet(), FUTURE_REQUEST_EMPLOYEE_SUM )

public class EmployeeBenefitSummaries 
{
    private static final String FUTURE_REQUEST_EMPLOYEE_SUM;
    private static Boolean employeeSumRequestMade = false;

    public static void requestFutureCall(Set<ID> employeeIds, String actionType)
    { 
        if(!System.isFuture() && !System.isBatch() && !System.isScheduled())
        {
            if(actionType == FUTURE_REQUEST_EMPLOYEE_SUM && !employeeSumRequestMade)
            {
                employeeSumRequestMade = true;
                groupSummaryFuture(employeeIds);
            }
        }  
    }    


     @future
     public static void groupSummaryFuture(Set<ID> employeeIds) 
     {
       buildGroupSummaries(employeeIds);
     }

     private static void buildGroupSummaries(Set<ID> employeeIds)
     {
        //Requery using your employeeIds
        //Now you can buildGroupSummaries without having to go through a future also, all you have to do is pass it a set of employee ids
        //Do your logic 
     }
}
6

The other answers are spot-on but if at some point in the future (so-to-speak) of your application and you need to pass a list of objects, you can use the Queueable interface in lieu of @future.

Queueable jobs are similar to future methods in that they’re both queued for execution, but they provide you with these additional benefits.

Getting an ID for your job: When you submit your job by invoking the System.enqueueJob method, the method returns the ID of the new job. This ID corresponds to the ID of the AsyncApexJob record. You can use this ID to identify your job and monitor its progress, either through the Salesforce user interface in the Apex Jobs page, or programmatically by querying your record from AsyncApexJob.

Using non-primitive types: Your queueable class can contain member variables of non-primitive data types, such as sObjects or custom Apex types. Those objects can be accessed when the job executes.

Chaining jobs: You can chain one job to another job by starting a second job from a running job. Chaining jobs is useful if you need to do some processing that depends on another process to have run first.

  • Didn't realise that - good to know +1. – Keith C Jul 14 '16 at 8:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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