0

I thought I had already posted this, but I guess not (if so, please feel free to direct me to my original post and delete/merge this one). I have a before insert trigger on leads, it calls an apex class that calls a managed packaged callout class (for verifying email addresses). The callout is working and I can verify that in the managed package ui based on the bogus or solid email addresses I enter.

I used an @future static method in the apex class, with other static getters that (I would think) would return various static variable values, but that's not happening.

I am not getting any compile errors, and again the verification runs as it should. But a couple custom lead fields (i.e. isValidated) are not being updated by the static methods in the class that I am calling from the trigger.

I included debug lines to verify, and even though the debugs show that the values are correct (when the managed package lines are included) the debug logs show null for the lines verifying a variable's value in my trigger.

Is this simply a managed package/permissions issue? the methods and properties within the needed package are listed as global so I thought I could successfully call those, but apparently not.

Any assistance would be appreciated. I have some experience with java, and limited experience with Salesforce development. As I said it's working, but fields are not updating so I can't fire other automation based on the results. I'm sure there's a simple explanation for what's happening. If somebody can point me in the right direction, that'd be helpful (I can post my code if needed).

1 Answer 1

5

Your trigger and your @future method are executing in different transaction contexts. The lifespan of a static variable is a transaction. As a result, your trigger Apex cannot access the values of any static variables that are set during the execution of an @future method. (In fact, during the execution of the trigger, the @future method has not even started executing yet - it's simply queued for execution in, well, the future).

There is no solution allowing you to return information that results from a callout synchronously into the execution context of a trigger, full stop. You'll have to move any data updates that need to happen consequent to the callout into the @future context.


Rolled up from comments:

We want to callout to validate an email address before a lead is committed to the database.

This is not possible in a trigger. You can't make a synchronous callout from a trigger, so in order to block invalid data, you have two choices:

  • Validate on the front end (i.e., a Lightning component or Visualforce page) before initiating a save.
  • Clean up on the back end, i.e., have your asynchronous callout context do whatever work needs to be done to handle bad data after it's committed.

Ultimately, regardless of approach, how CAN I make a callout before a record is committed (and then call a process builder to call an autolaunched flow based on results)?

Those things can't happen together. As above, the callout has to be either before the save starts (on the front end) or after the save succeeds (in Apex). Your declarative automation cannot start until late in the save process, so that would have to happen from your asynchronous Apex making the callout after the save completes.

upsides/downsides of @queuable vs @future? and what effects they have on bulkification?

The easy answer is "use Queueable". It's newer, it can chain itself if you need to, you can pass complex values to it, etc.

Bulkification is a complex question but you definitely need to be aware of Queueable limits; you can't fire one per record. And you'll need to be especially careful if your trigger gets invoked from a batch process, where the Queueable limit is much lower.

5
  • Hey David, thanks a bunch for your response. That clears up one question I had which was transaction context (I was thinking if the trigger was calling the @future method that they would exist in the same context so that makes sense that they don't since...derp...one is in the future).
    – david5712
    Feb 1, 2021 at 15:49
  • So I've read umpteen million articles on this, and I know that only primitives can be passed to @future methods, so if my trigger is a lead trigger, is this where I need to create a map/set and pass that instead so that I can update those fields? Also, do you have any suggestions about how to approach this from a different angle? We want to callout to validate an email address before a lead is committed to the database, and then based on the results, call a process builder that calls a flow for other actions. I assume even if I resolve all of this, bulkification will be another obstacle
    – david5712
    Feb 1, 2021 at 15:53
  • "We want to callout to validate an email address before a lead is committed to the database," - that's impossible in a trigger. You'd have to do it on the front end. "is this where I need to create a map/set and pass that instead so that I can update those fields" - you can use a Queueable instead of a future to pass a non-primitive value. "bulkification will be another obstacle" - absolutely right.
    – David Reed
    Feb 1, 2021 at 17:37
  • Hey David, you've been very helpful so thank you for taking the time to respond. 1. "that's impossible in a trigger. You'd have to do it on the front end.". Can you clarify what you mean by front end? (apologies for being so green) Are you saying I'll need a lightning web component or what? 2. Ultimately, regardless of approach, how CAN I make a callout before a record is committed (and then call a process builder to call an autolaunched flow based on results)?
    – david5712
    Feb 1, 2021 at 19:26
  • I'm fluent in programming enough to figure it out, but I need to know where to look. 3. I will be sure to google until my ears bleed so as not to clutter up the se questions here, but can you tell me the upsides/downsides of @queuable vs @future? and what effects they have on bulkification? You are so appreciated, so thank you in advance.
    – david5712
    Feb 1, 2021 at 19:26

You must log in to answer this question.

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