During last years fun with IoT and the LittleBits devices, i developed a package imaginatively called Salesforce LittleBits Connector. My aim for that connector was to allow none coders, to have some fun with IoT and Salesforce. Instead of requiring Apex code to control devices and respond to events i wanted to allow the user to leverage Flows. When building it a previously observed limitation with the Apex integration with Flow surfaced again…
Whats the problem?
While Apex can create a Flow that is known at the time code is written, it cannot dynamically create a Flow determined at runtime. My blog entry Calling Flow from Apex goes into what is currently possible and highlights this restriction towards the end. This idea proposes that Salesforce adds something like the following to Apex…
// Create the Flow named in the userDefinedFlow variable Flow.Interview.Interview anyFlow = Flow.Interview.newInstance(userDefinedFlow, flowParams); // Run the Flow anyFlow.start(); // Retrieve a value from one of its variables String outputValue = (String) anyFlow.getVariableValue('outputVarName)';
Current solutions…
Salesforce describes the current options for launching Flow here, one of which is indeed via its REST API, which if called from Apex would provide the facility we are looking for here, however i wanted to avoid HTTP callout and the limitations that entails. With the Salesforce LittleBits Connector i solved the problem using an Apex interface, the utilisation of the factory pattern and a Tab that provides a facility to manage the code generation of a Flow factory class.
The following code snippet from the tool shows how the Flow factory approach works. It uses Apex type.forName to create an instance of the above generated class (from the unmanaged namespace of the org).
// Get a Type reference to the Flow Factory class Type typeFactory = Type.forName('', 'lbc_LittleBitsFlowFactory'); if(typeFactory==null) { System.debug(FlowFactoryClass + ' class not found.'); return; } // Create an instance of the Flow Factory ILittleBitsFlowFactory flowFactory = (ILittleBitsFlowFactory) typeFactory.newInstance(); // Create an instance of the Flow via the factory newInstance method Flow.Interview flow = flowFactory.newInstance(flowName, flowParams); // Start and interact with the Flow as normal if(flow!=null) flow.start();
The interface looks like this…
// Interface implemented by the generated Flow Factory class global interface ILittleBitsFlowFactory { Flow.Interview newInstance(String flowName, Ma<String, Object> params); }
The key with this solution is the Tab above that provides a means for the Admin user to dynamically create or refresh the lbc_LittleBitsFlowFactory Apex code which has access to the specific Flows. This class lives as an unmanaged class in the org. Before we look at how the Tab works, lets take a closer look at what it generates in the org.
/** * Auto Generated and Deployed by the LittleBits Connector package (lbc) **/ global class lbc_LittleBitsFlowFactory implements lbc.ILittleBitsFlowFactory { public Flow.Interview newInstance(String flowName, <String, Object&amp> params) { if(flowName == 'FlowTest') return new Flow.Interview.FlowTest(params); if(flowName == 'HandleKioskActivity') return new Flow.Interview.HandleKioskActivity(params); if(flowName == 'HandledHandshake') return new Flow.Interview.HandledHandshake(params); return null; } }
Note: I found that i needed the class to be marked as global at the time, i suspected this might have been that the packaged code was not Aloha status. If your not packaging your solutions code, this your code runs in the unmanaged namespace, you’ll find that you don’t need global and public will be fine. The Tab also generates an Apex Test for the above code as well, to ensure code coverage is satisfied.
The Tab itself scans the configurations of the tool for references to Flow names, in this case it was LittleBits Device Subscriptions, it could also utilise the Apex Metadata API listMetadata as well. The former approach does keep the generated code focused on the Flows needed by the tool. The page then uses the Apex Metadata API to deploy the generated code to the org. If you want to review this code in more detail take a look at ManageFlowFactoryController and the manageflowfactory page.
Summary
I find Flow to be a hugely liberating technology for creating solutions without requiring coding skills on Salesforce. I hope to wrap the above solution in a standalone open source solution that contains a dynamic Flow API and the Tab above, such that others can start to integrate Flow into other tools as I did with the LittleBits connector. Meanwhile please enjoy reviewing the approach in its current form and let me know your thoughts!
Note: Key to this solution is the use of the Apex Metadata API to deploy the factory code. I have learnt recently that Salesforce are increasing security around Apex execution invoked from Lightning Components (via @AuraEnabled annotated methods). The implication of this is that UserInfo.getSessionId does not return an API capable Session Id. This effectively blocks such code from calling any Salesforce API’s (including Metadata API) via Http callouts using the users Session Id. I’ll be looking at means in the future to use oAuth to formalise access like this.
Update: See blog Flow Factory.
March 21, 2016 at 9:59 pm
Where do I find documentation on Declarative Lookup Rollup Summaries Tool. I’m installing it in a Sandbox and getting errors when trying to create the Remote Site Setting.
March 23, 2016 at 9:00 am
Sure, its here, https://github.com/afawcett/declarative-lookup-rollup-summaries/blob/master/README.markdown. There is also a link to a Salesforce Community Chatter Group.
Pingback: Introducing the Flow Factory | Andy in the Cloud
August 10, 2016 at 10:31 pm
About your note saying ‘UserInfo.getSessionId does not return an API capable Session Id’ – Can you point me to a salesforce documentation that mentions this.
August 12, 2016 at 10:04 am
As far as I know it is not, not sure why, perhaps they consider it a security issue to document it or it’s just simply never been that stable or well know by the doc team, just guessing though….
Pingback: Adding Clicks not Code Extensibility to your Apex with Lightning Flow | Developer Force Blog