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:

 

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

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.)

/**
 * Sample encapsulated class
 * $author: [email protected]
 */
public with sharing class AddressHelper {

	public String street {set; get;}
	public String city {set; get;}
	public String state {set; get;}
	public String zip {set; get;}

    public AddressHelper(String s, String c, String st, String z) {
    	street = s;
    	city = c;
    	state = st;
    	zip = z;
    }
}

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

public with sharing class AddressFuture {
    public AddressFuture () {

	List<String> addresses = new List<String>();
	AddressHelper ah1 = new AddressHelper('1 here st', 'San Francisco', 'CA', '94105');
	AddressHelper ah2 = new AddressHelper('2 here st', 'San Francisco', 'CA', '94105');
	AddressHelper ah3 = new AddressHelper('3 here st', 'San Francisco', 'CA', '94105');

	//serialize my objects
	addresses.add(JSON.serialize(ah3));
	addresses.add(JSON.serialize(ah2));
	addresses.add(JSON.serialize(ah3));

	doFutureCall(addresses);

  }

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

  @future
    static void doFutureCall(List<String> addressesSer) {

    	AddressHelper currAddress = null;

       for (String ser : addressesSer)
       {

       	 currAddress = (AddressHelper) JSON.deserialize(ser, AddressHelper.class);
       	 System.debug('Deserialized in future:'+currAddress.street);
       }
    }

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. For example, I use this strategy within the Chatter Blacklist app to pass a patternHelper object to an @future method.

/**
     * return a serializable version of the patternhelper
     */
    public PatternHelperSerializable getSerializable()
    {
    	//instead of passing the Pattern object, let's just pass the regex string from
        //via Pattern.pattern() method
    	return new PatternHelperSerializable(blacklistedWord, p.pattern(), origPostBody, postCreatedById);
    }

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

tagged , , Bookmark the permalink. Trackbacks are closed, but you can post a comment.
  • Adam Purkiss

    Nice article! I’ve always used lists of Ids and grab the data once in the future method. But I’ll definitely consider this approach in the future (wondering why I didn’t think of this before…) One thing I noticed is the less-than/greater-than blocks of code got stripped out.

    • quintonwall

      Damn CSS. Thanks for picking it up. I fixed it now.

  • Anonymous

    That’s a neat trick! Will definitely give that a spin over using ids and queries.

  • Anonymous

    The trick out now!, this can be considered for Javascript Remoting feature as well, you can serialize js object and pass it string.

  • mohit srivastav

    Excellent post!Nice to know this way of passing parameters in future calls.

  • http://www.tgerm.com/ Abhinav Gupta

    Nice post quintonwall, what I am left with, after reading this post is pros/cons of re-querying required records by ids in FUTURE context vs deserialize JSON to restore the object back.

    A few points that are bugging me are :

    - If the custom object is transformed out of few calculations in sobjects, we might not be seeing the latest and greatest information at present in database. As we might be using a stale JSON representation of Sobject info, at the time when future method is invoked.

    - Heap requirement and processing required to restore the structure back vs querying the required information back.

    - Added complexity in doing this stuff, vs simple query to restore back.

    - If database I/O is not involved and we just need to pass a complex object graph and restore it back in future call for further processing, this JSON ser/deser. pattern looks awesome.

    Looking forward for more thoughts on this pattern !

  • Srikanth

    Good illustration.. very interesting

  • Kevin O’Hara

    I’ve been doing this JSON dance for a while. Works great for doing async trigger processing when you need to process Trigger new vs old.

    When I discovered this a while back I wrote a class to allow for simple async DML -> https://github.com/kevinohara80/Force.com-Helper-Classes#asynccls

  • Raj Chilukuri

    Neat Hack!! We have to weigh against cost of SOQL query