A tutorial on how to convert existing Salesforce Apps to use Custom Metadata
At Dreamforce ’15 Aaron Slettehaugh, Avrom Roy-Faderman, Andrew Fawcett and I presented a session on Custom Metadata Types, you can watch the video below. In this blog post I will give some more of the detail of how we worked with this new feature.
What are Custom Salesforce Metadata Types
Custom Metadata Types were part of the Salesforce Summer ‘15 release and provide ISVs a way to include record data (or Custom Metadata) as part of a package. Previously it was only possible ship metadata like Cusotm Objects, Apex Classes, Visualforce Pages and Custom Settings in a package but the record data like instances of Custom Objects and Custom Settings could not be included. With Custom Metadata Types this is supported and it is a huge advance for ISVs. It is now possible to define a Custom Metadata Type which is very similar to a Custom Object or Custom Setting definition but rather than using a Data Loader or Apex code to load the record data, the records of these Custom Metadata Types are another form of metadata in the app called Custom Metadata. The Custom Metadata records can be queried just like normal records using SOQL.
Why should I use them?
Custom Metadata Types and Custom Metadata have many great and very valuable features. In my opinion, the most prominent feature is that Custom Metadata Types and Custom Metadata are packageable so they can really help reduce the amount of effort needed to populate records required by an application. It very common for managed packages to use Post Install Scripts to insert necessary records and settings using Apex code or with manual post intall instructions and the Data Loader. Both of these approaches require a lot of time and support. Post-Install Scipts can result in an abundance of Apex code to maintain, in the case of Dealmaker from The TAS Group we found that our Post-Install Script could be reduced from more than 11,000 lines of Apex to less than 1,000 by using Custom Metadata Types instead of our Custom Settings and certain Custom Objects. Manually loading the records using a Data Loader is cumbersome and time consuming as customers must be provided with documentation and support. With Custom Metadata Types the the records or Custom Metadata are deployed as part of the package install so no post install steps are needed. This means the effort maintaining Post Install Script Apex code (and releated Apex Test Classes) and / or post install documentation and the customer support involved are eliminated. This is a huge saving to both development and customer support functions of any ISV.
There is another way that Custom Metadata Types help to reduce the amount of Apex code in your app. Custom Metadata is test visible so Apex Test Classes can access the data without the need for setting up mock data for the records that would normally be inserted by the Post Install Script or Data Loader. It is not uncommon for Apex Test Classes mock data setup to account for more than 70% of a test classes so significant reductions in the amount code needed are possible. Test classes are also more effective when Custom Metadata Types are used because modifications to the Custom Metadata will impact the tests automatically but using Custom Settings or Custom Object records it would be possible to change records as part of an upgrade that should fail a test but unless the mock data is updated too this will not be caught in the tests.
A huge benefit of Custom Metadata is that they are upgradeable. These records can be updated in package upgrades just like Custom Objects, Visualforce Pages etc in your package. This is very significant because it enables ISVs to automatically manage and maintain the records required by the app. In the past identifying the records to update could require significant manual intervention or complex Apex code and this task was made more difficult again when customers have modified those records for their own purposes.
Custom Metadata Types allow you define the level of read / write access you want to provide to the Custom Metadata in your package. It is possible to have Custom Metadata hidden from customers so that your application can access and use the data but it cannot be accessed outside the package code. Alternatively you can make your Custom Metadata visible outside your app so that it can view using SOQL or just browsed in the UI. It is even possible to allow customers to add and update their own Custom Metadata for your Custom Metadata Types
Querying Custom Metadata does not count towards SOQL limits so your existing code would consume less of your SOQL record allowances if it was converted to use Custom Metadata Types. This will help to make you app more scalable for larger data sets.
What can I use them for?
Custom Metadata Types are ideal for any records that represent metadata for your app. This means that any records that represents configuration or structural data, rather records created during normal use of you app, could be good candidates for Custom Metadata Types. Custom Settings are good example of such a candidate as Salesforce intended these to be used for configuration of apps. Custom Objects are often good candidates too, for example Dealmaker has feature called TAS Assessment consisting of many questions and supporting information that are represented by Custom Objects. These questions are provided in Dealmaker and are not added to or changed in the normal use of Dealmaker and they determine what questions should be displayed to the users. The TAS Group often want to refine and update the default questions and we permit customers to modify or add to the questions to suit their own needs as an administrative task. This is an ideal scenario where a Custom Object could be replaced with Custom Metadata Types.
Are there any drawbacks or limitations?
Custom Metadata records are limited to a size of 10MB per managed package (or per org for unmanaged content), however there may be alterations to these limits in the future. If the Custom Setting or Custom Object you were considering converting has a very large set of data then it may not be suitable for Custom Metadata Types. There also limits on the number of types, fields etc, details are listed here.
Currently Custom Metadata Types do not support all of the functionality provided by Custom Objects and Custom Settings. At the time of writing this blog relationship fields are not supported for Custom Metadata Types although it is on the Salesforce Road Map. For Dealmaker we used text fields to store ID values in place of relationship fields on Custom Objects we were converting and then we handled the relationship in Apex code.
At the time of writing Custom Metadata cannot be accessed in reports or dashboards so deciding how important they are may influence your decision on how or what to use Custom Metadata Types for. Unlike Hierarchical Custom Settings, Custom Metadata Types are not accessible in formula fields, however Custom Metadata Types would not be an effective substitute for those anyway, they are more appropriate to replace List Custom Settings which are also not available in formulas.
How do I start using them?
As mentioned above Custom Settings are a good candidate for converting to Custom Metadata Types and because Custom Settings don’t support relationship fields they are ideal for this tutorial. If you look in the Custom Settings of your app and see any “List Custom Settings” these are the best candidates to convert. In this brief tutorial we will convert the following Custom Setting from Dealmaker and it’s related records to a Custom Metadata Type and Custom Metadata:
The first step is retrieve the metadata for your app using either your favorite IDE or the Migration Tools, ensuring that you have included the Custom Objects in your retrieve command. When the metadata is retrieved find the file that corresponds to the Custom Setting in the src/objects directory (the name of the file will end in “_Settings__c.object“) and take a note of its name, in our case the Custom Setting is called Team_View_Plus_Views__c.object. Now at the top level of you Salesforce project (the one containing the src directory) create the following XSLT file (please note I am not an XSLT expert so this can probably be significantly improved on):
Next we will use an ant target to apply this XSLT and convert the Custom Setting to a Custom Metadata Type that will be called Team_View_Plus_Views_CM__mdt.object:
This target applies the XSLT to the existing Custom Settings object and then renames it to the name we want while also removing any blank lines. When you run the target the new file will be added to the src directory. We now need to add this Custom Metadata Type to your org with the following Target:
This target creates a package containing the metadata for the new Custom Metadata Type and deploys it to the org. This target is using some of the tasks and concepts discussed in this previous blog post.
You should now look in the org to see the CMDT matches what you had for the Custom Setting. This is found in the setup menu under Develop > Custom Metadata Types.
You can browse and create the Custom Metadata records by clicking Manage Records from within Custom Metadata Types in the setup menu.
Once you have created the records you want you can now do a global replace replace of Team_View_Plus_Views__c with Team_View_Plus_Views__mdt in your triggers and Apex classes and deploy all the code. You may have to remove test code attempting to create mock records as it would have for the old Custom Setting. Now your app is using Custom Metadata Types for the first time, Congratulations! 🙂
Other useful extra information
If you want to learn more about Custom Metadata and Custom Metadata Types then the following blog posts from Aaron Slettehaugh and Andrew Fawcett will be very useful to you:
Stefan is a principle engineer with The TAS Group and has been working in software for over 10 years. Stefan's experience includes Force.com, Java, C++ and C# development, database administration, implementing Market Risk solutions for many leading financial institutions, leading large scale data migration projects and managing development and release procedures. When he is not coding Stefan can be found playing or watching rugby and doing D.I.Y. projects.