Why Invocable Methods Could Spell the End for Apex Triggers by Amnon Kruvi
Amnon Kruvi, Salesforce Solutions Architect
1218 Global – EMEA
Amnon.Kruvi@1218global.com
If you have written code on Salesforce before, chances are you have built an Apex trigger in your lifetime. However, on a platform that prides itself on its Clicks, Not Code mentality, the question must be begged: Are triggers the best solution to automate logic that cannot be handled by out-of-the-box declarative tools?
The Role of the System Administrator
Before we delve into this question, there is something that needs to be made clear: What is a system administrator?
Sure, a good system admin will configure a Salesforce org, manage its users and apps, and resolve issues on the system. But more than that, the administrator is often the person who decides what route a user needs to take in order to fulfill their tasks – what apps should be used, and how those apps should operate to achieve the best results for the business. And, if the need arises, the administrator can play the role of the app builder – modifying system behavior by creating workflow rules, processes, flows, and more.
Or in short: a fantastic, knowledgeable, capable resource.
Source: XKCD. Altered to remove swearing – we’re trying to be professional here.
And our role, as developers, is to allow administrators to achieve these requirements with as much flexibility as they require.
The Code Problem
Flexibility is where code fails administrators. When they install a trigger, they cannot edit its code. And when their requirements inevitably change – the code does not. When this happens, the only resort is to call upon the developer again (assuming they are still available), make that change, and go through an entire release cycle.
This includes small changes to the flow of the code – should this procedure run for every contact that goes into the system, or only for a certain record type? Imagine the frustration of having to call up the development team just because you installed a new app, which came with its own record types, and you need to make code changes just to decide which of them your procedure should process.
Invocable Methods are a Middle Ground
But what if a developer could write a procedure, and allow the system administrator to decide the conditions in which to execute it? That is exactly the issue Salesforce aims to resolve with their Invocable Methods mechanism.
These methods can be executed using two popular declarative tools: Process Builder, and Lightning Flow. They are written almost exactly like normal methods, can accept input parameters (with a few caveats), and can produce an output value. Here is an example:
@InvocableMethod(Label='Count Open Cases' Description='Returns a count of open cases for the provided contact')
public static List<Decimal> countOpenCases(List<Id> contactId) {
//Query the amount of open cases for all contacts
Map<Id, Decimal> mapResults = new Map<Id, Decimal>();
for (AggregateResult ar : [SELECT ContactId con, COUNT(Id) cnt
FROM Case
WHERE ContactId IN :contactId
AND IsClosed = false
GROUP BY ContactId]) {
//Store the amount of open cases for each contact in a map
mapResults.put((Id)ar.get('con'), (Decimal)ar.get('cnt'));
}
//Sort the amount of open cases into a list with the same order as the contactId list
List<Decimal> res = new List<Decimal>();
List<Contact> contactsToUpdate = new List<Contact>();
for (Id conId : contactId) {
Decimal val = mapResults.get(conId);
if (val == null) {
val = 0.0;
}
res.add(val);
contactsToUpdate.add(new Contact(Id = conId, Open_Cases__c = val));
}
//Store the amount of open cases on the contact records
update contactsToUpdate;
return res;
}
The function accepts an input (a list of contact IDs), produces an output (a list of open cases for each contact on the list), and even has a nifty label and description annotation which is bound to come in handy for app builders, as well as whoever ends up maintaining the code.
An administrator could use Process Builder to trigger this piece of code whenever a certain event happens to a record (for example, when a new case is created) and only when certain criteria are met (such as clients with a limited service contract) using the built-in criteria and decision steps built into process builder and flows. They can also store the return values back into flow variables and use them later on in decision steps!
This means Process Builder and Lightning Flow have become tools that can orchestrate the flow of logic and attach conditions to whether each method will be executed. This has long been the job of triggers, but now that power lies within the grasp of the declarative app builders. When they add a new record type to the organization, they can modify the process themselves and configure their preferred handling; they can create their own custom settings to toggle certain functionality on or off; they can trigger the code on record creation and record updates, and even limit it to only run when specific fields have been changed.
Getting Technical
So, what are the bits you need to know about creating Invocable Methods? Well, that’s simple!
To start with, you just need to add the @InvocableMethod annotation to any function. The annotation accepts two parameters: Label and Description. Use these to create a clear idea of what your method does – and they will show inside the process and flow builders.
Your Invocable Method can accept either no parameters, or one parameter. That parameter must be a list of values, and not a single instance. This is because flows and processes are bulkified, and the data from several instances may be sent to your method at once. This is a great thing when considering performance and governor limits!
If you need more than one parameter, you can create your own inner class with its own fields and accept a list of that class. The class can have many member variables, and those you mark with the annotation @InvocableVariable will be shown as possible input parameters in the flow or process.
public class CountParams {
@InvocableVariable(required=true)
public Id contactId;
@InvocableVariable
public Boolean commitToDatabase;
}
Another thing to keep in mind is that any one class can only have one Invocable Method. If you want more utilities, you need to create more classes.
Verdict: So, Are Triggers Dead?
The short answer is: No.
Apex triggers run in any of 8 contexts – a combination of before or after an event (insert, update, delete, undelete). Declarative tools in Salesforce only run in two contexts: after insert, and after update. This means that declarative logic cannot be executed when a record is deleted or undeleted and cannot make changes to a record before it is committed to the database. That remains the domain of triggers.
For after insert and update logic, however, it is becoming clear that declarative tools are slowly gaining an advantage with the help of code. After all, wouldn’t it be great if an admin, rather than submitting change requests to you, could handle these things by her or himself?
Isn’t it great to have a platform that is increasingly accessible to all?
About Amnon Kruvi
Salesforce Architect and Development leader with a background in startup companies and consultancy specializing in Force.com, CRM, and an assortment of web and mobile technologies.
Amnon has excelled as the technical lead to execute and manage projects from the very beginning stages to public release, and on to large international contracts. His technical expertise allows Amnon to analyze customer requirements, design a solution, and follow it to completion – either in a managing or development capacity.
About 1218 Global
A worldwide leader in consulting innovation, 1218 Global and its family of professional consulting companies (Convectus Solutions, and 1218 Global HR Solutions) were each founded with unique delivery capabilities. From systems implementations and upgrades to Managed Services (EMEA, APAC and USA), 1218 Global has developed a track record for measurably improving client productivity, effectiveness, and profitability.