Developer Memo: Working With Metadata Service

There are some powerful data structures that are currently available only through retrieval and deployment via the metadata API. For example, the Process Builder Converter tool works by first retrieving a process builder process as a piece of flow metadata, then editing the metadata so it can be opened in Flow Builder, and then deploying the modified flow metadata as a new, separate flow.

In general, using metadata deployment and retrieval is the last resort you should use. If your data is accessible via the UI API, the Tooling API, or via a REST interface, those are likely to be preferable. One reason is that metadata deployment may trigger a recompilation of all of the apex classes on your org, and that will pause your deployment until it’s finished. So while metadata deployment will generally go very quickly on developer edition orgs, it might be much slower on a production org. (As a note, you can control whether your metadata deployments trigger a recompilation with this checkbox:

Despite these issues, sometimes Metadata deployment is a great tool to use. The Process Builder example is a good one.

Another example involves creating, editing, and deleting ListViews via a Flow Action. While ListViews can be read via UI API and REST, they can only be created, edited, or deleted by doing metadata deployment of ListView metadata.

How to Incorporate Metadata Deployment and Retrieval

There are two sets of tools you can use to build Flow Actions and Screen Components that use Metadata Deployment and Retrieval.

Method 1: Assembling your Metadata Using Andy’s Objects

The first tool is the legendary Apex Metadata Service created by Andy Fawcett. This abstracts a lot of gnarly SOAP transactions into nice clean API’s. Here’s an example of a Flow Action making use of the Metadata Service to create ListViews:

The reason this works is that MetadataService has gone and created a wrapper class for each piece of Salesforce metadata. In the code above, you can see that we’re able to reference MetadataService.ListView(). Once we have one of the ListView objects, we can simply fill it with updated values, and then call createMetadata on it. There are similar methods for updating, deleting and reading.

You can peruse the vast set of available objects by scrolling through the main class file here.

Method 2: Assembling Your Metadata By Hand

When we went to create the process builder converter, though, we weren’t able to use the above method. The reason is that the current MetadataService only has updated metadata through API version 42, from 2017. We needed to create flow metadata that used brand new additions that had only been added in version 48.0

You can see here, that the Flow definition in Metadata Service (era 2017)…

lacks the brand new metadata element that stores new Flow triggering information:

Hopefully, someone will update the MetadataService to the latest API. In the meantime, you can solve this problem because the MetadataService also provides direct access to lower level deploy and retrieve methods that don’t require you to populate one of the metadata objects.

When you operate at this lower level, you have to directly parse and modify the metadata xml. Then you have to zip it up with base 64 encoding, and then you call MetadataService’s ‘deploy’ method directly. This has been implemented asynchronously, so we carry it out via a Flow screen component called TransferMetadata that can sit there on a flow screen and poll until a response is received.

While this may sound a little intimidating, you can just take and copy the code we used.

Introducing the MetadataService BaseLibrary

To streamline the efforts of developers who want to build tools like Create or Edit ListViews, we’ve packaged the necessary MetadataService files into a useful package that you can just require as a dependency. This package leaves out some extraneous files from the repo but has everything necessary to carry out deployment and retrieval.

In general we’re starting to move towards base libraries to avoid collisions and simplify packaging for new actions and developments.

Install it here.