Salesforce Developers Blog

Passing Objects to Future Annotated Methods

Avatar for Quinton WallQuinton Wall
The future annotation is a great feature in the Salesforce Platform. However, it only supports primitives for argument methods. Using the JSON serialize|deserialize methods, you can easily pass sObjects and custom objects. Here’s how.
Passing Objects to Future Annotated Methods
June 18, 2013
Listen to this article
0:00 / 0:00

The future annotation is a great feature on the Salesforce Platform to allow you to execute custom logic asynchronously. I often use them to perform callouts within the context of a database trigger.  However, one of the restrictions of future annotations is that you can not pass sObjects or objects as arguments to the annotated method. I regularly use encapsulation to pass a collection of parameters, or even an sObject, but this won’t work in @future method:

1@future
2static void doFutureCall(List<AddressHelper> addresses) {
3  //do something
4}

But thankfully there is a way you can do. The secret sauce is the JSON serialize|deserialize methods.

Take the example of an AddressHelper object referred to above. This is encapsulated convenience object to help me pass around address details. (note:For simplicity, this helper object just includes strings, but it could easily include other types including objects, sobjects, collections etc.)

1/**
2 * Sample encapsulated class
3 * $author: qwall@salesforce.com
4 */
5public with sharing class AddressHelper {
6
7	public String street {set; get;}
8	public String city {set; get;}
9	public String state {set; get;}
10	public String zip {set; get;}
11
12    public AddressHelper(String s, String c, String st, String z) {
13    	street = s;
14    	city = c;
15    	state = st;
16    	zip = z;
17    }
18}

Using the JSON serialize method I can easily pass this to an @future method.

1public with sharing class AddressFuture {
1public AddressFuture () {
2
3	List<String> addresses = new List<String>();
4	AddressHelper ah1 = new AddressHelper('1 here st', 'San Francisco', 'CA', '94105');
5	AddressHelper ah2 = new AddressHelper('2 here st', 'San Francisco', 'CA', '94105');
6	AddressHelper ah3 = new AddressHelper('3 here st', 'San Francisco', 'CA', '94105');
7
8	//serialize my objects
9	addresses.add(JSON.serialize(ah3));
10	addresses.add(JSON.serialize(ah2));
11	addresses.add(JSON.serialize(ah3));
12
13	doFutureCall(addresses);
14
15  }

And then, within my future method, all I need to do is deserialize the object, and you are good to go.

1@future
2    static void doFutureCall(List<String> addressesSer) {
3
4    	AddressHelper currAddress = null;
5
6       for (String ser : addressesSer)
7       {
8
9       	 currAddress = (AddressHelper) JSON.deserialize(ser, AddressHelper.class);
10       	 System.debug('Deserialized in future:'+currAddress.street);
11       }
12    }

That’s it. JSON.serialize|deserialize makes it amazingly simple to pass objects, even ones with complex nested relationships, to @future annotated methods. There are time though that a particular object can not be serialized due to the underlying inheritance structure. One such example is the Pattern class in Apex.

To handle these outliers, I often create my own custom getSerializable() method on my custom object.

That’s about it. You can grab the complete code for the examples above as a gist here.