I discovered something this week: you can’t pass sObjects as parameters to methods that are decorated with the @future annotation in SalesForce. It is documented, I’d just missed it previously – it is there just read carefully. Oh, bummer, I like passing sObjects around.

I decided to solve the issue by serializing the sObject to a string, passing the string to the @future method and then deserializing it back into the sObject.

The serialization part of the problem is already solved for us by the string.valueOf() method. I say solved; it doesn’t provide a complete solution, for example it won’t traverse relationships, but it’s complete enough for my current needs.

The deserialization is, unfortunately, not such a simple solution. SalesForce don’t provide us with a method such as Schema.sObjectFrom( string input ). This means that we need to parse the string back into an object ourselves.

The output from the string.valueOf() method can be generalised like this:

<sobjecttype>:{<field1>=<value1>, <field2>=<value2>, …, <fieldn>=<valuen>}

At first glance this string looks fairly easy to parse we have the sObject type listed so we can easily instantiate one of those and then for the fields we have commas and equal signs that we can use as delimiters. However after two more seconds of thought you soon come to realise that it is, indeed, too good to be true. The problem lies in the fact that the values of the fields can potentially be any string of characters; this includes commas and equal signs. Suddenly the parsing of the string isn’t such a simple prospect.

In fact to find any delimiters that are 100% reliable is an impossible task. So what can we do instead? The approach I decided to opt consists of a two pronged attack. The first part of the solution prepends the string “, ” that’s &lt;comma><space> to the string between the curly braces. Then applying the following regular expression to the result: Pattern.compile( ‘, ([^ ]*?)=’ )

This returns a series of matches and in each match two groups of characters. The second prong is to look at the second grouping in each match and see if it is a valid field name for that object. Whilst not fool proof this provides a fairly high level of certainty that we’re breaking the data up correctly.

After we’ve broken the string down correctly it’s simply a case of checking the types and adding the data to the right field in our new sObject.

There is one slight oddity; if we have an Id then we have to instantiate the sObject with the Id, which means looping through the fields and if there is an Id there then recreating the result sObject.

The resulting code can be install from this unmanaged package.

An obvious limitation to this, and any kind of non-SalesForce deserialization, is that we cannot update certain fields such as LastModifiedDate. This will always be the case and as such something that we have to live with, if you need this information from the original sObject then you’ll have to pas it to the method separately. But at least you don’t have to pass every field this way.

Overall I’m happy with this as a solution to the problem but it is clearly very brittle; if SalesForce change the way in which string.valueOf() works we’re doomed. The solution to this is to control both sides of the equation and that’s what I plan to do next. Customising both sides of the process should allow for the creation of a much more robust solution.

You may have noticed that the class above implements an interface called Serializer.  I have done this to allow me to write more implementations of the serialization code and to be able to swap it in and out with ease.  Over the next few days I will get this code up onto Google Code and try and make a start on the better serializer implementation.  Updates to hopefully follow soon.