September 7, 2012

Three Oddities With System Fields and Record Creation

There's more than a fair chance that any user, let alone administrator or developer, working on the force.com platform will be aware of the system fields which are present on each and every record. Aside from the Id field, the four that are often of interest to most people are the CreatedBy, CreatedDate, LastModifiedBy and LastModifiedDate fields, more often than not the last two in particular when searching for the culprit who changed some data for the worse.

Insert Triggers and The Dreaded null

Be wary of the fact that inside an insert trigger—where you no doubt know we only have trigger.new and trigger.newMap available and not their 'old' counterparts—these fields are always null. This would appear to be common sense when working with a trigger that fires before insert, but it may surprise you to know the CreatedBy and LastModifiedBy fields are null in 'after insert' triggers as well, even though the date stamps are filled and the Id now holds the shiny new unique identifier for the record.

I may well be wrong, but I assume that this is due to the order of execution of the platform and the fact that all of this is performed inside a transaction: nothing is committed to the database until the end of operations, step 16 out of 17 to be precise. Why the date stamps work and the user look-ups don't is something of a mystery without being able to look under the hood. The simple trigger below results in the field in question having a value comprising a valid date stamp followed by null.

trigger Contact_AfterInsert on Contact (after insert)
{
  list<Contact> contacts = new list<Contact>();
  for(Contact c : trigger.new)
  {
      contacts.add(
           new Contact(id = c.Id, Some_Text_Field__c = c.CreatedDate + ' : ' + c.CreatedBy));
  }
  update contacts;
}


Weirdness in action.

A Validation Rule Gotcha

One of my colleagues encountered a tricky problem where his validation rule seemed to work perfectly when updating a record, but not when creating a record. As it turned out, the snag was that his validation rule made use of the CreatedDate field, and custom validation rules are applied in step 4 of the data modification process right before the record is first saved to the database; the upshot being that once again, CreatedDate has a value of null!

]
This will not prevent contacts from being created on its own.

The Final Gotcha

Where things really start to get into sneaky territory is when you have a workflow which updates a field upon record creation: although update triggers etc. will be run again, custom validation rules are not, so even triggering an update in this way will not mean that the validation rule is applied.


No custom validation for you!

If however, you do a DML update after insert—in the manner of the trigger we saw earlier—the custom validation rules will be run again, thus giving the illusion that a rule using CreatedDate is functioning correctly upon record creation! So beware: if a validation using CreatedDate works on record creation and then mysteriously starts failing, you might want to see if any triggers have been altered without (or maybe even with) your knowing.

Related Posts