String Replacement in Apex

In one of their latest releases, Salesforce launched the feature to replace snippets of your metadata source files with specific values – right before you deploy them. In this article, we are going to take a look at this new addition and cover it so that you can start implementing it in your projects.

What is String Replacement in Apex?

String replacement in Apex allows you to automatically replace strings in your metadata source files with specific values right before you deploy the files to an org. This replacement is just temporary because the changes are not written to your project, just to the deployed files. This can be particularly useful in certain scenarios – Named Credentials, Connected Apps, just to name a few of them.

Why would you use String Replacement in Apex?

You might be wondering why you would use string replacement. Just as an example, here are some use cases taken from the Salesforce Developers’ official documentation  that might sound familiar to you – in which string replacement can be applied:

  • Probably one of the most common use cases: a Named Credential contains an endpoint that you use for testing. But when you deploy the source to your production org, you want to specify a different endpoint.
  • One use case regarding a very common security issue: an ExternalDataSource contains a password that you don’t want to store in your repository, but you’re required to deploy the password along with your metadata.
  • You deploy near-identical code to multiple orgs. You want to conditionally swap out some values depending on which org you’re deploying to.

String Replacement options

This feature is quite flexible, accepting a range of different options:

  • You can specify a single file with filename, or a collection of files using the glob property (for instance, **/classes/*.cls) in which the string should be replaced.
  • You can indicate a stringToReplace or a regular expression in the regexToReplace property.
  • You can replace the string with the value of an ENV variable (replaceWithEnv), and with the contents of a file (replaceWithFile).
  • You may add conditions for when to replace the string using replaceWhenEnv.

Configuring String Replacement

Configuring string replacements is as simple as adding a replacements property to your sfdx-project.json file. This property, as we have seen, accepts multiple entries that consist of keys that define different characteristics:

  • Source file or files that contain the string to be replaced
  • The string to be replaced
  • The replacement value

Replacement keys (to be elaborated further)

You can specify the following keys in the replacements property.

Location of files: at least one of the following properties is required.

  • Filename: single file that contains the string to be replaced.
  • glob: the collection of files that contain the string to be replaced. For instance: **/classes/*.cls.

String to be Replaced: at least one of the following properties is required.

  • stringToReplace: the string to be replaced.
  • regexToReplace: regex that specifies a string pattern to be replaced.

Replacement value: at least one of the following properties is required.

  • replaceWithEnv: specifies that the string is replaced with the value of the environment variable.
  • replaceWithFile: specifies that the string is replaced with the contents of a file.

Conditional Processing: this property is optional.

  • replaceWhenEnv: specifies that a string replacement occurs only when a specific environment variable is set to a specific value. You may use env to specify the environment variable and value to specify the value that triggers the string replacement.

String Replacement Example

As mentioned earlier, utilizing the string replacement feature is straightforward – simply include a ‘replacements’ property in your sfdx-project.json file. In this example, we will demonstrate how to create a basic application that can dynamically generate various metadata types.


<!--?xml version="1.0" encoding="UTF-8" ?-->

<namedcredential xmlns="http://soap.sforce.com/2006/04/metadata">

    <allowmergefieldsinbody>false</allowmergefieldsinbody>

    <allowmergefieldsinheader>false</allowmergefieldsinheader>

    <endpoint>https://{HEROKUINSTANCE}.herokuapp.com</endpoint>

    <generateauthorizationheader>true</generateauthorizationheader>

    <label>heroforgeApp</label>

    <principaltype>Anonymous</principaltype>

    <protocol>NoAuthentication</protocol>

</namedcredential>
"replacements": [
  {
    "filename": "force-app/main/default/namedCredentials/heroforgeApp.namedCredential-meta.xml",
    "stringToReplace": "{HEROKUINSTANCE}",
    "replaceWithEnv": "PRODUCTION_INSTANCE",
    "replaceWhenEnv": [{
      "env": "DEPLOY_DESTINATION",
      "value": "PRODUCTION"
    }]
  },
  {
    "filename": "force-app/main/default/namedCredentials/heroforgeApp.namedCredential-meta.xml",
    "stringToReplace": "{HEROKUINSTANCE}",
    "replaceWithEnv": "UAT_INSTANCE",
    "replaceWhenEnv": [{
      "env": "DEPLOY_DESTINATION",
      "value": "UAT"
    }]
  }
]

One of the most important aspects reflected in this example is that metadata templates can reside in the project folder and remain unchanged despite multiple deployments.

Considerations and Limitations

From the Salesforce Developers’ official documentation, we can extract the following considerations and limitations:

  • If you configure multiple string replacements in multiple files, the performance of the deployment can degrade. Ensure to use the filename key when possible, to make sure that you open only one file. If you must use glob, try limiting the number of files that are opened by specifying a single directory or metadata type.
  • When not doing string replacement, Salesforce CLI simply zips up all static resources when it first encounters their directory and deploys them as-is. If you configure string replacement for a large static resource directory, the CLI must inspect a lot more files than usual, which can degrade performance.
  • The force:mdapi:deploy command does not support string replacement.
  • If your deployment times out, or you specify the –wait 0 flag of force:source:deploy, and then run force:source:deploy:report to see what happened, the deployed files contain string replacements as usual. However, the output of force:source:deploy:report does not display the same string replacement information as force:source:deploy –verbose would have.
  • Always use forward slashes for directories ( / ), even on Windows.
  • Both JSON and regex use the backslash ( \ ) as an escape character. As a consequence, when you use regex to match a dot, you must use two backslashes for the regexToReplace value. To match a single backlash, use three of them.

Summary

In conclusion, String Replacement in Apex appears to be a reliable option for metadata deployments, particularly in cases such as Connected Apps and Named Credentials. This new feature will enhance development capabilities and improve application development. It allows developers to work directly with metadata and avoid more complex methods, such as lengthy JavaScript files, making it a significant advancement in metadata deployments.

References

https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_ws_string_replace.htm

https://developer.salesforce.com/blogs/2023/01/developer-tooling-updates-learn-moar-spring-23

https://www.pablogonzalez.io/string-replacements/

No Comments

Sorry, the comment form is closed at this time.