fflib-apex-common
fflib-apex-common copied to clipboard
System.NullPointerException fflib_SObjectDomain.cls - null sobjectType
This may be an edge case but the following bit of fflib_SobjectDomain fails when constructing a domain class with an empty list of non-concrete Sobjects.
Assume Foo__c is the Sobject with a Foos.cls domain class. Some other class decides to instantiate the Foos as follows:
Foos foos = new Foos((List<Foo__c>) SomeClass.getSobjectsFromXXX(someIdSet));
where SomeClass.getSobjectsFromXXX(..) returns a list of non-concrete SObjects (for example, a list of Sobjects containing only the ID field). In the NPE example, the list is empty.
Even though there is an explicit cast of the (empty) list of Sobjects to an (empty) list of Foo__c, in Apex, the SobjectType of the cast list is NULL, not Foo__c.SobjectType.
Hence, when the constructor for Foos is called that in turn invokes the base class constructor, the line:
this(sObjectList, sObjectList.getSObjectType());
resolves to a call to the alternative constructor with two arguments: an empty list of Foo__c and an sObjectType of null. Hence, the line:
SObjectDescribe = sObjectType.getDescribe(); blows up with a NPE.
So, what to do?
Workaround is to have the Foos constructor look like this:
public Foos(Foo__c[] foos) {
super(foos,Foo__c.SObjectType);
}
But, given the way Apex works, perhaps an exception should be thrown in fflib_SObjectDomain if the one argument constructor is called with an unascertainable, i.e. null, SObjectType and an error message suggesting use of the two argument constructor.
fflib_SObjectDomain excerpt
public fflib_SObjectDomain(List<SObject> sObjectList)
{
this(sObjectList, sObjectList.getSObjectType());
}
public fflib_SObjectDomain(List<SObject> sObjectList, SObjectType sObjectType)
{
// Ensure the domain class has its own copy of the data
Records = sObjectList.clone();
// Capture SObjectType describe for this domain class
SObjectDescribe = sObjectType.getDescribe(); // NPE here
// Configure the Domain object instance
Configuration = new Configuration();
}
Yep i think thats a solid enhancement idea. Thanks.