I'm just trying to get started using this to implement fflib-apex-common, so that I can support packaging well. I may have missed something about how this is meant to be used, because there isn't much documentation yet. I think I have it fairly well understood though.
When I map Account to a selector it works perfectly. But if I map a custom SObject to a selector, it throws...
11:01:02:457 FATAL_ERROR System.InvalidParameterValueException: Invalid sobject provided. The Schema.describeSObject() methods does not support the 01i0r000000a9mu sobject as a parameter. The sobject provided does not exist.
11:01:02:000 FATAL_ERROR Class.ApplicationSObjectSelectorDIModule.configure: line 18, column 1
11:01:02:000 FATAL_ERROR Class.di_Binding.Resolver.loadBindings: line 263, column 1
11:01:02:000 FATAL_ERROR Class.di_Binding.Resolver.get: line 279, column 1
11:01:02:000 FATAL_ERROR Class.ApplicationSObjectSelector.incorporateAdditionalSObjectFields: line 33, column 1
11:01:02:000 FATAL_ERROR Class.ApplicationSObjectSelector.: line 50, column 1
11:01:02:000 FATAL_ERROR Class.tagr_RootsSelector.: line 9, column 1
11:01:02:000 FATAL_ERROR Class.tagr_RootsSelector.: line 6, column 1
11:01:02:000 FATAL_ERROR Class.tagr_RootsSelectorTest.getSObjectTypeTest: line 8, column 1
It's because the following line is expecting a name but getting an Id from the CMDT.
results = Schema.describeSObjects(new String[] { bindingConfig.BindingSObject__c.toLowerCase().trim() });
Here is my interface...
public interface tagr_IRootsSelector extends IApplicationSObjectSelector{
}
I just created a simple implementation of ApplicationSObjectSelector...
public class tagr_RootsSelector extends ApplicationSObjectSelector implements tagr_IRootsSelector{
public static tagr_IRootsSelector newInstance(){
return (tagr_IRootsSelector)Application.Selector.newInstance(tagr_Root__c.SObjectType);
}
public tagr_RootsSelector(){
this(true,true,true);
}
public tagr_RootsSelector(Boolean includeFieldSetFields, Boolean enforceCRUD, Boolean enforceFLS){
super(includeFieldSetFields, enforceCRUD, enforceFLS);
}
public Schema.SObjectType getSObjectType(){
return tagr_Root__c.sObjectType;
}
private List<Schema.SObjectField> getAdditionalSObjectFieldList(){
return new List<Schema.SObjectField>{};
}
// I Have added some different selector methods here. I have removed them for brevity as this bug happens when the class is constructed.
}
Then I just started to create a test class so that I could see it in action and make sure that I was understanding it...
@isTest
public class tagr_RootsSelectorTest{
@testSetup
private static void setup(){
}
@isTest
private static void getSObjectTypeTest(){
tagr_RootsSelector testSelector = new tagr_RootsSelector();
System.assertEquals(tagr_Root__c.sObjectType, testSelector.getSObjectType());
}
}
Run that test and you get the previously mentioned error.
It is simply because the CMDT returns an Id for custom SObjects rather than a name. Since describeSObjects expects the name, it fails. As I said previously, there doesn't appear to be a super easy way to convert from an Id to a name. Maybe I just don't know it though. From what I can tell, the only way is to do a global describe and then iterate all the types till you find the one with the Id you're looking for. I had thought of simply mapping all of that out in some central place so that it could be accessed by any of the classes.
Also, I actually originally saw the issue in a different place because I had a regular "di_Binding__mdt" that referenced a custom SObject in the "BindingObject__c" field. So, it is also a problem in that way.
Class.di_Injector.CustomMetadataModule.configure: line 147, column 1
Class.di_Binding.Resolver.loadBindings: line 259, column 1
Class.di_Binding.Resolver.get: line 279, column 1
Class.ApplicationSObjectSelector.incorporateAdditionalSObjectFields: line 33, column 1
Class.ApplicationSObjectSelector.: line 50, column 1
Class.tagr_RootsSelector.: line 9, column 1
Class.tagr_RootsSelector.: line 6, column 1
Class.tagr_RootsSelectorTest.getSObjectTypeTest: line 8, column 1
Essentially, if you're going to pull the BindingObject out of a CMDT that uses an entity field, you will need to translate any custom SObjects from Ids to Names or else use a different method of getting the describe info than Schema.describeSObjects. Unless you know a better way, I suppose the easiest solution is just to do a global describe from the beginning, mapping names to Types and use it to get the answer, rather than ever using Schema.describeSObjects.