Salesforce Visual Workflow – Can Flow Commit Changes Prior to Invoking a Method

I'm trying to get some advanced architecture setup for my company, but I'm running into an issue with my design; looking for help.

I'm attempting to execute an API call from Flow, but I'm getting the dreaded CalloutException: You have uncommitted work pending. Please commit or rollback before calling out.. I know this means I need to put @Future on my call out, but I'm wondering if anyone knows of a way to put that function into the flow? Is there any element that would commit the work of my transaction?

The main reason I ask is I want to get the response of the call out into the flow – meaning I cannot use the future annotation as it prevents the response from being returned. If nothing else works I'm going to have to leverage the response (as an inserted record) to trigger a follow up flow, but this is a heavier design than I'd like and creates some security considerations.

I've attempted using a wait element, but it appears the method invoked is still considered part of the same transaction. I setup an absolute alert for 0.016777 hours (1 minute) after current time, but still receiving the error. I'm going to try a relative alert to see if that works.

TL;DR: I'm looking for a way to get Flow to commit work prior to a specific element. Is there a way to do this?

Best Answer

There is nothing that can explicitly cause a commit in a way that gets rid of this error in live code. System.runAs prevents this error, but only for unit tests (because System.runAs only works in unit tests). You can use an InvocableMethod in a flow, and from there, kick off a future method, thereby splitting the transaction in two; the future method can safely perform the callout after the flow's current transaction completes and is committed.

public class DoCalloutFromFlow {
    @InvocableMethod(label='Do Callout', description='Performs a callout after the flow completes')
    public static void doCallout(Id[] params) {
        futureCallout(params);
    }
    @future(callout=true)
    public static void futureCallout(Id[] params) {
        // Do your callouts here
    }
}

Note: You can actually cause commits during a Visual Flow, as each screen element ends a transaction. However, when you're using any sort of Process Flow, you're already in DML-land and can't perform a callout.