Salesforce Apex Default Values Explained!
force.com standard and custom objects allow you to define fields with default values. However, there is a major confusion regarding the usage and availability of default values in Apex code. This confusion arises due to the fact that the native Salesforce user interface shows the default value pre-calculated, even before saving the record. But in Apex code, this is not true; the values are not available until you save and reload the record.
Here is a simple Sobject and a complete scenario that covers the whole story.
For illustration, a simple custom object named “TestObj” is created, as shown below:
This custom object has a single custom field named “DefValFld”. This field is a date field with a default value configured to be a formula: “TODAY() + 7”, as shown below:
Now this is what comes on the Salesforce native UI when the “New” button is clicked; please note that the formula is executed even before saving.
So this clearly indicates that Salesforce UI is pre-calculating the formula, even before saving. But if the same is tried in Apex code as follows, it will not work.
Here is the sample code:
TestObj__c testObj = new TestObj__c();
system.debug('Value before Save : ' + testObj.DefValFld__c);
insert testObj;
system.debug('Value after Save : ' + testObj.DefValFld__c);
testObj = [select id, DefValFld__c from TestObj__c where id=:testObj.Id limit 1];
system.debug('Value after Reload : ' + testObj.DefValFld__c);
Here is the output that I got on running the code snippet above:
line 2, column 1: Value before Save : null
line 3, column 1: Insert: SOBJECT:TestObj__c
line 3, column 1: DML Operation executed in 26 ms
line 4, column 1: Value after Save : null
line 5, column 11: SOQL query with 1 row finished in 6 ms
line 6, column 1: Value after Reload : 2010-02-01 00:00:00
So this indicates that Apex Code doesn’t get the default values calculated on creating a new Sobject(). So to get the default value in your Apex code, we need to reload the Sobject. Even if someone is trying to get the default value using getDescribe() calls, the result will be the same, i.e., no/null default value will be provided.
The same is shown below:
// Code
System.debug(TestObj__c.DefValFld__c.getDescribe().getDefaultValue());
// Output
NULL
The reason TestObj__c.DefValFld__c.getDescribe().getDefaultValue() is failing because the record’s default field might depend on some instance-level data using merge fields. So the value can’t be calculated in a static manner like this, i.e. without any instance reference. I tried default values with other field types like “text”, "number” and "date" but there was no success using the describe call. I am not sure why Salesforce gave this method.
Another way to get the values for non-formula-based default value fields is to use “getDescribe().getDefaultValueFormula()”. This call “returns the default value specified for this field if a formula is not used". So for a text field having a default value of “Hello World” it will return the correct value, as it's not using formula stuff. This still doesn’t work with PICK-Lists.
Here are some other useful facts about “SFDC Default Values” (From SFDC Knowledge Base):
If a default value is based on the value of a merge field, Salesforce.com uses the value of the merge field at the time the default value is executed. If the value of the merge field changes later, the default value is not updated.
Users can change or remove the default field value on a record.
Default values should not be assigned to fields that are both required and unique, as uniqueness errors may result.
If you make an activity custom field universally required, you must also provide a default value.
If an activity custom field is unique, you cannot provide a default value.
Default field values are different from formula fields in the following ways: they are only executed once, at record creation; they are not read-only; and the user can change the value but cannot restore the default field value.
Since the default value is inserted before users enter any values in the new record, you cannot use the fields on the current record to create a default field value. For example, you cannot create a default field value on a contact that uses the first initial and last name because those values are not available when you click New to create a contact record. However, you can use the record type because it is selected before the record edit page displays.
To apply a different default value for different record types, use the record type as a merge field in a CASE function within the default field value setup.
Fields that are not visible to the user due to field-level security are still available in the formula for a default field value.
Connect Offline and Connect for Outlook do not display default values. However, Salesforce.com inserts the default values when a user syncs unless the user entered a value.
Default field values are not available in the Self-Service portal.
Lead conversion, Web-to-Lead, and Web-to-Case do not execute default field values.