The Winter ’24 release of the Salesforce Platform, generally available as of Oct 16th, added some important quality-of-life improvements for Apex developers. In this blog post, we’ll walk you through the latest Apex updates introduced in the Winter ’24 release and explore these updates with practical code examples to see how they simplify writing business logic. You can see some of them in action in the apex-recipes sample app.

DataWeave in Apex

Your application may often have the need to read, parse, and transform data between different data formats, such as CSV, JSON, XML, and Apex objects. To transform between formats, you need code that requires knowing the specifics of each format.

DataWeave in Apex simplifies data transformations between formats. It integrates MuleSoft’s DataWeave library into the Apex runtime, enabling the execution of DataWeave scripts. These scripts use MuleSoft’s DataWeave language to easily transform data without you having to write complex code to serialize and parse data. You can create DataWeave scripts as metadata and call them directly from Apex code. This feature streamlines data transformations in Apex. There is also a new UI, which is part of the Setup screen, where you can view DataWeave scripts in Salesforce.

Note – You don’t have to be a MuleSoft customer or have any specific Salesforce license to use DataWeave in Apex.

Let’s take a look at a code example from the Apex recipe that shows how to use DataWeave in Apex to convert a CSV string to Contact object records in Salesforce.

The DataWeave script csvToContacts.dwl for converting CSV string to Contacts in Salesforce is shown below.

The above script is deployed as metadata. The platform then automatically creates an Apex class DataWeaveScriptResource.csvToContacts with a method execute to transform a CSV string into Contact records.

The following is an example code snippet from apex-recipes using DataWeaveScriptResource.csvToContacts.

You can check if the code is functional or not using the code snippets below.

For complete code, check the code in the TransformSobjectsInDataWeave.cls and TransformSobjectsInDataWeave_Tests.cls files in apex-recipes. As you can see from the recipe, you can simply focus on your business logic rather than writing your own parsers.

We have added byte-size recipes to make it easier for you to learn DataWeave in Apex. Be sure to check the folder DataWeaveInApex Recipes, which includes basic examples of using static and dynamic syntax, CSV to JSON conversion, and recipes that show how to transform CSV/JSON into Apex objects. For more examples, see the DataWeaveInApex repo.

To learn more about how to write DataWeave scripts, we recommend using the DataWeave playground and online tutorial. Also, use the DataWeave 2.0 (Beta) VisualStudio code extension to build and test your DataWeave scripts. This extension is also available in Code Builder.

Comparator interface and Collator class for sorting

Prior to the Winter ’24 release, if you had to sort a list of non-primitive data types, you had to write a wrapper class implementing a Comparable interface. With the new Comparator interface, you can now implement sort orders without wrapper classes. List.sort() now accepts a class implemented using a Comparator interface (see docs).

The code for the AccountShippingCountryComparator implementing a custom sort order from apex-recipes is shown below.

The following is example code that shows how to use the above class to sort a list of Accounts using the ShippingCountry field by using comparators.

You can check complete code with more use cases in the ListSortingRecipes.cls Apex class.

Sort lists based on user locale using the Collator class

Every language has specific rules for sorting or “collating” strings into an ordered list. For instance, in Danish, the letter Æ comes after Z. To ensure proper sorting according to the user’s locale, you can use the new Collator class. The following code example demonstrates how to sort a list of strings based on the user’s locale.

If your business logic relies on a specific sort order, avoid using the Collator class in code that can be executed by users with different locales. The Collator class sorts strings based on the locale, so the sort order may vary for users in different locales.

For loops now support iterables

Previously, if you had an iterable, you needed a more verbose syntax using a while loop, and you explicitly needed to call .iterator(). With Winter ’24, you can now easily iterate through lists or sets using an iterable variable with a for loop syntax.

Let’s take an example Apex class from apex-recipes that used the while loop syntax.

In the above code, IterableApiClient implements an iterable of the RecordPage type. You can check the complete code in IterableApiClient.cls.

The above code can be simplified with for loop syntax as shown below.

Check IterationRecipes.cls on how we use the for loop syntax to simplify the code.

Queueable enhancements

Apex queueable gets important improvements in Winter ’24. You can now set the maximum depth for chained queueable jobs, and also ensure that duplicate jobs are not enqueued to reduce race conditions and record locking.

Set maximum depth for chained queueable jobs

If you have implemented retry logic using chained queueable Apex jobs, you may want to limit the number of retry attempts. You can now do this by setting a maximum depth for your chained queueable Apex jobs using the AsyncOptions class (see docs). Use this class to pass as a parameter to the System.enqueueJob() method to define the maximum stack depth for queueable transactions, as well as the minimum queueable delay in minutes.

Note that the ability to set the minimum queueable delay was introduced a few releases ago. Use the minimum queueable delay to avoid busy polling or waiting.

Below is example code that shows how to set the maximum stack depth for your queueable job.

Prevent duplicate queueable jobs

Duplicate queueable jobs can cause race conditions and record locking. We have seen this scenario when invoking queueable jobs from a trigger, and the trigger executes multiple times causing duplicate jobs.

Use the QueueableDuplicateSignature class (see docs) methods addId(), addInteger(), and addString() to build a unique signature for your queueable job. Use the DuplicateSignature property in the AsyncOptions class to store the queueable job signature.

The following example code shows how to build unique signatures to avoid duplicate queueing of jobs.

Attempting to add more than one Queueable job to the processing queue with the same signature results in a DuplicateMessageException when enqueuing subsequent jobs. This can be handled by the developer as shown in the above code.


The Winter ’24 release of the Salesforce Platform has brought significant improvements for Apex developers. These updates are a testament to Salesforce’s commitment to enhancing the developer experience and streamlining the process of writing business logic in Apex. So, be sure to explore these exciting features and stay ahead in the world of Apex development. Happy coding!

Additional references

About the author

Mohith Shrivastava is a Developer Advocate at Salesforce with a decade of experience building enterprise-scale products on the Salesforce Platform. He is presently focusing on the Salesforce Developer Tools, Apex, and Lightning Web Components at Salesforce. Mohith is currently among the lead contributors on Salesforce Stack Exchange, a developer forum where Salesforce Developers can ask questions and share knowledge. You can follow him on X (Formerly Twitter) and LinkedIn.

Get the latest Salesforce Developer blog posts and podcast episodes via Slack or RSS.

Add to Slack Subscribe to RSS