Usually if apex code attempts to access an sObject field that wasn't retrieved via SOQL I get an exception like:
System.SObjectException: SObject row was retrieved via SOQL without querying the requested field: Opportunity.Namespace_CustomField_c
This if useful, as it tells me to go back to the SOQL query that retrieved the Opportunity and add the CustomField__c field to the select.
However, I've noticed that the exception isn't always thrown. Instead the field in question is just null.
Has anyone else encountered this and have any idea why it happens?
As an example of the issue:
global with sharing class CustomController {
public Opportunity opp {get; set;}
global void method1(Id oppId) {
opp = [Select o.Id, o.Type, o.IsWon, Error_Message__c
From Opportunity o where id =:oppId limit 1 FOR UPDATE];
// Setting this field appears prevents any further SObjectExceptions
// NB: This was added after the question was originally asked to highlight the issue.
opp.Error_Message__c = '';
System.debug('opp.CustomField__c: ' + opp.CustomField__c);
method2(opp);
}
public void method2(Opportunity opp) {
if(opp.CustomField__c != null) {
System.debug('DoStuff');
}
}
}
- Create an instance of a custom controller class
CustomController
- Invoke the public method
method1
on the above class that takes an Opportunity Id - The public method
method1
runs a SOQL query to retrieve the Opportunity and a number of fields, but not CustomField__c. The retrieved Opportunity is assigned to a public propertyopp
on the controller. - The Opportunity property
opp
is passed as a parameter to another method in the custom controller class. (I'm aware that this isn't necessary as the method would otherwise be able to see the value via the public property) - The method
method2
that received the Opportunity checks if the custom field is not null before attempting to use the value to do some other updates.
If I create an instance of the custom controller in anonymous apex and invoke the method from point 2 no SObjectException is thrown and the CustomField__c value is always null.
If I create an instance of the custom controller in anonymous apex, run the same SOQL query and pass the resulting Opportunity directly to the method in point 4 I get the expected SObjectException.