1

I have a scenario where I am saving custom metadata for an external API configuration. I want to deploy all the metadata, then after the deploy job is done, make a callout to the API to verify the configuration is correct.

My callback class looks like this:

public with sharing class DeployCallback implements Metadata.DeployCallback {
  CallbackRunnable runnable;

  public DeployCallback() {
  }

  public DeployCallback(CallbackRunnable runnable) {
    this.runnable = runnable;
  }

  public void handleResult(
    Metadata.DeployResult result,
    Metadata.DeployCallbackContext context
  ) {
    Id deployJobId = context.getCallbackJobId();

    switch on (result.status) {
      when Succeeded {
        if (runnable != null && runnable.runOnSuccess)
          runnable.run();
      }
      when SucceededPartial {
        // The deployment succeeded, but some components might not have been successfully deployed. Check Metadata.DeployResult for more details.
        if (runnable != null && runnable.runOnSuccess)
          runnable.run();
      }
      when Failed {
        // Deployment was not successful
        if (runnable != null && runnable.runOnFail)
          runnable.run();
      }
      when Canceled {
        // Deployment was not successful
      }
      when Pending, InProgress, Canceling {
        // Queued or state changing
      }
    }
  }

  public virtual class CallbackRunnable {
    public Boolean runOnSuccess;
    public Boolean runOnFail;

    public CallbackRunnable() {
    }

    public virtual void run() {
    }
  }
}

My runnable implementation looks like this:

  private class APIConfigPostDeploy extends DeployCallback.CallbackRunnable {
    APIConfigPostDeploy() {
      this.runOnSuccess = true;
    }
    public override void run() {
      APIService apiService = new APIService();
      apiService.verifyConfigCallout();
    }
  }

The apiService.verifyConfigCallout() does a HTTP call using the settings that were just deployed.

And of course we are enqueueing the deploy job like this:

Metadata.Operations.enqueueDeployment(theMetadata, callback);

I keep getting the error:

Callout not allowed from this future method. Please enable callout by annotating the future method. eg: @Future(callout=true)

None of the methods in my call chain are future methods, and calling the apiService.verifyConfigCallout() directly works just fine. It only fails with this error when being called from within the deploy callback.

My assumption is that the Metadata.Operations does its callback as a future. I'm wondering if anyone has run into this and has a workaround?

1 Answer 1

2

Without documentation, it's kind of hard to tell, but the easiest solution would be to call a Queueable from your callback to make the callout. I realize this is a bit roundabout, but it should work with minimal modification to what you already have. Remember to use Database.AllowsCallouts on your Queueable to allow the callout to happen.

2
  • I tried that and still got the future method error, but maybe I forgot to implement Database.AllowCallouts. Seems like I would have got another message, which also give me some suspicious the issue is actually within my downstream call stack. The other problem is the second queueable was too slow for my application. I'm thinking of sending a lighting event down to the UI and programmatically click the button we have for the users to execute the API test manually.
    – Shanerk
    Commented Nov 24, 2020 at 17:00
  • @Shane That's probably a reasonable solution. I didn't want to make any assumptions about the environment you're using, but a message back to the client would most likely work.
    – sfdcfox
    Commented Nov 24, 2020 at 17:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .