The ability to create custom fields is a key feature when it comes to customising. Shortly followed by using features like Validation Rules, Workflow, Process Builder, Flow etc. Have you ever developed a solution that also offers the capability to consume user defined fields dynamically? If so you will have used a Custom Object or Custom Setting with a text field to store the field name/s to use.
The Problem:
Using text fields to capture field names has the following challenges and downsides:
- Poor user experience. Unless you develop a Visualforce or Lightning UI users have to know the field API name and enter it correctly in the text field.
- Validation code. While optional, its worth adding some validation to ensure the user enters the correct API name during configuration.
- Changes to field definitions. Once configured there is no guarantee the admin or another user will not inadvertently rename or even delete a field your config references. Resulting in runtime problems when the user next runs your code.
- Migrating configuration. If admins need to move configurations between sandbox and production or developers simply want to prepackage configurations they have to make sure they manually include any custom fields referenced.
- Reading configuration. Reading your configuration requires using the Apex Describe API, which requires a good understanding of namespaces, something not always apparent. Basically its much more complex than things can first appear!
In contrast when using platform tools to reference fields and you attempt to delete a field you are prevented from doing so, if for example a Workflow currently references it. Its also possible to rename fields without breaking references to them. Change Sets and Packaging also automatically discover referenced fields for you.
The Solution:
Using Field Relationships you can now reference custom fields in the same way platform tools do and resolve the above problems with zero code! First head on over to the Setup menu and create yourself a Custom Metadata Type. Next you need to create two Metadata Relationship fields to support your field reference.
The next screen shows a list of either other Custom Metadata Types in the org plus Entity Definition and/or Field Definition. These latter two are two critical objects that have mostly been hiding in the background for several years. They first surfaced in the Tooling API documentation here and here, but are now (in part) accessible from Apex. These are essentially objects who’s records represent all objects (entities) and fields in the org.
You must create at least one Entity Definition relationship field before creating a Field Definition relationship field (the option will not show in the drop down until you do). Creating your Entity Definition relationship field is much like creating lookup fields. When you create a FieldDefinition relationship field, you must state which Entity Definition relationship field controls it (a bit like related pick lists).
In order to explore this i recreated my Rollup Summary custom metadata type from the rollup tool. This currently uses text fields to let the admin user define the parent object and child objects used in the rollup and the related fields. And so i wanted to see what it would look like with this new feature. The resulting user experience is very pleasing! The following screenshot is the native UI, no custom Visualforce code at all!
Firstly when creating or editing custom metadata records object and field drop down lists are rendered for you. When you change a controlling Entity Definition (Object) relationship field (e.g. the Parent Object field) the related Field Definition relationship fields controlled by that field are dynamically updated (e.g. Aggregate Result Field and Relationship Field fields) to list the corresponding fields of the selected object.
Secondly when you save and view custom metadata records the relationships can be navigated via links, so the user can go direct to the object or field definition, very cool!
So far we have addressed issues 1 and 2 from our list above without writing any code! Next lets try to break things. Try to delete the Number of Locations custom field on the Account object and see what happens.
Also try to rename the API name of the Number of Locations field. Basically the platform allows this to happen and yet if you reload the custom metadata record referencing it, things still appear to be intact! This is due to the fact that the relationship is not using the API name, but the field ID, which of course does not change. So thats issue 3, solved!
Next lets try to Package just our custom metadata record above and see what happens. Although i have not tested it i expect the same to be true when using Change Sets. As you can see the platform has figured out through the relationships that the package needs to include the referenced Number of Locations custom field as well. Nice!
NOTE: Take a look at this blog for an example of packaging custom metadata type records based on a packaged custom metadata type.
So thats issue 4 solved, what about the coding challenge 5? Surely thats still business as usual right? Nope, basically by leveraging the QualifiedAPIName field on the EntityDefinition and FieldDefinition objects we can quickly resolve the fully qualified name (including namespace) of the objects and fields being referenced. Note that this will always be valid (since its not stored), so no need to revalidate this before using it!
for(LookupRollupSummary__mdt rollup : [SELECT ParentObject__r.QualifiedAPIName, ChildObject__r.QualifiedAPIName, RelationshipField__r.QualifiedAPIName, AggregateResultField__r.QualifiedAPIName, FieldToAggregate__r.QualifiedAPIName FROM LookupRollupSummary__mdt]) { System.debug( 'Relationship Field: ' + rollup.ChildObject__r.QualifiedAPIName + '.' + rollup.AggregateResultField__r.QualifiedAPIName); }
This outputs the following in the debug log.
DEBUG|Relationship Field: Opportunity.NumberofLocations__c
If you are not yet familiar with Custom Metadata take a look at my earlier blog and related links below. You can also check out the second edition of my book out Friday 31st March, where i cover a number of Custom Metadata configuration use cases throughout. Enjoy!
- Custom Metadata Relationship Considerations
- Custom Metadata Field Relationships Spring’17
- Introducing custom metadata types: the app configuration engine for Force.com
- How to use custom metadata types to save years of development on app configurations
- Testing Custom Metadata Types
- SFDCConfig (Sample Configuration App by Salesforce)
- Custom Metadata Loader
- Sample application for custom metadata types: “Reusable picklists” framework and tooling.
- Community Chatter Group
- Implementation Guide
- Summer’15 Release Notes
