Since Summer’14 it has been possible to invoke a Flow from Apex, through the oddly named Interview system class method start. This blog talks about using this as a means to provide an extensibility mechanism, as an alternative option to asking an Apex developer to implement an Apex interface you’ve exposed. Clicks not code plugins!
Prior to Summer’14 it was only possible to embed a Flow in a Visualforce page, using the the flow:interview component, as described here. But this of course required a UI and hence user interaction to drive it. What if you wanted to allow admins to extend or customise the flow of some Apex logic using Flow from a none UI context?
Enter trigger ready-flows, first introduced as part of the Summer’14 pilot for running Flow from Workflow, which itself is still in Pilot, thought the ability to create trigger ready-flows is now generally available, yipee! Here’s what the docs have to say about them…
You can also build trigger-ready flows. A trigger-ready flow is a flow that can be launched without user interaction, such as from a flow trigger workflow action or the Apex interview.start method. Because trigger-ready flows must be able to run in bulk and without user interaction, they can’t contain steps, screens, choices, or dynamic choices in the active flow version—or the latest flow version, if there’s no active version.
This blog will present the following three examples of calling trigger-ready flows from Apex.
- Hello World, returning a text value set in a Flow
- Calc, shows passing in values to a Flow and returning the result of some processing.
- Record Updater, shows passing in some SObject records to the Flow for processing and returning them.
Hello World Example
Here is a simple example that invokes a Flow that just returns a string value defined within the Flow.


The following Apex code calls the above Flow and outputs to the Debug log.
// Call the Flow
Map<String, Object> params = new Map<String, Object>();
Flow.Interview.ReturnHelloWorld helloWorldFlow = new Flow.Interview.ReturnHelloWorld(params);
helloWorldFlow.start();
// Obtain the results
String returnValue = (String) helloWorldFlow.getVariableValue('ReturnValue');
System.debug('Flow returned ' + returnValue);
This outputs the following to the Debug log…
11:18:02.684 (684085568)|USER_DEBUG|[13]|DEBUG|Flow returned Hello from the Flow World!
Calc Example
This example passes in a value, which is manipulated by the Flow and returned.

The following code invokes this Flow, by passing the X and Y values in through the Map.
// Call the Flow
Map<String, Object> params = new Map<String, Object>();
params.put('X', 10);
params.put('Y', 5);
Flow.Interview.Calc calcFlow = new Flow.Interview.Calc(params);
calcFlow.start();
// Obtain the results
Double returnValue = (Double) calcFlow.getVariableValue('ReturnValue');
System.debug('Flow returned ' + returnValue);
This outputs the following to the Debug log…
12:09:55.190 (190275787)|USER_DEBUG|[24]|DEBUG|Flow returned 15.0
Record Updater Example
With the new SObject and SObject Collection types in Summer’14 we can also pass in SObject’s. For example to apply some custom defaulting logic before the records are processed and inserted by the Apex logic. The following simple Flow loops over the records passed in and sets the Description field.


This code constructs a list of Accounts, passes them to the Flow and retrieves the updated list after.
// List of records
List<Account> accounts = new List<Account>{
new Account(Name = 'Account A'),
new Account(Name = 'Account B') };
// Call the Flow
Map<String, Object> params = new Map<String, Object>();
params.put('Accounts', accounts);
Flow.Interview.RecordUpdater recordUpdaterFlow = new Flow.Interview.RecordUpdater(params);
recordUpdaterFlow.start();
// Obtain results
List<Account> updatedAccounts =
(List<Account>) recordUpdaterFlow.getVariableValue('Accounts');
for(Account account : updatedAccounts)
System.debug(account.Name + ' ' + account.Description);
The follow debug update shows the field values set by the Apex code and those by the Flow…
13:10:31.060 (60546122)|USER_DEBUG|[39]|DEBUG|Account A Description set by Flow
13:10:31.060 (60588163)|USER_DEBUG|[39]|DEBUG|Account B Description set by Flow
Summary
Calling Flows from Apex is quite powerful to provide more complex extensibility back into the hands of admins vs developers. Though depending on your type of solution is somewhat hampered by the lack of the ability to dynamically create a subscriber configured Flow. As such for now is really only useful for none packaged Apex code deployments in production environment, where the referenced Flow’s can be edited (managed packaged Flows cannot be edited).
Despite this, for custom Apex code deployments to production it is quite powerful as it allows tweaks to the behaviour of solutions to be made without needing a developer to go through Sandbox and redeployment etc. Of course your also putting a lot of confidence in the person defining the Flows as well, so use this combo wisely with your customers!
Upvote: I’ve raised an Idea here to allow Apex to Dynamically create Flow Interview instances, with this in place ISV and packaged applications can make more use of this facility to provide clicks not code extensibility to their packaged application logic.
Update: Blog post Flow Factory presents a workaround to the dynamic calling problem.
Like this:
Like Loading...