4

I have a usecase where when an account is updated, an after update trigger is fired. This trigger will call a future method which will call a SOAP API to assign the relevant territory assignment rules. I cannot use Apex to invoke assignment rules; this is a limitation and has been documented below: https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_header_assignmentruleheader.htm

During this entire process, the assignment rule is assigned properly. The issue is that somehow the trigger is invoked the 2nd time, which is calling the webservice again. And in the logs, I am seeing this exception:

System.CalloutException: Callout loop not allowed

How can I stop the recursive trigger? I checked this link, but seems like this is of no help. https://blog.jeffdouglas.com/2009/10/02/preventing-recursive-future-method-calls-in-salesforce/

UPDATE: As per the blog, to avoid recursive trigger, I defined a boolean variable

public static boolean inFutureContext = false;

and inside the future method, I am setting the value of this variable to true. In the trigger, this is how I am checking

if (!Territory2Controller.inFutureContext) {
   Territory2Controller.runTerritoryRules(accountIds);
}

So when the trigger is fired for the 1st time, inFutureContext is false. Future method is called where I am setting inFutureContext to true. As API is called, so it will invoke the trigger again. But value of inFutureContext is still false.

Code is provided in the link below: https://gist.github.com/iamsonal/d5ed44ca4dea45ee6f7002cb361be703

  • Can you please provide a code snippet where that stuff happens. So far I understand that the future method uses SOAP API to udate the same account. If this is so, then it's the source of the recursion. In such a case you need to specify a condition in your trigger that would check if a current account has already been assigned to a territory, and if it is, just skip it. – Eduard Jul 16 '18 at 11:40
  • Yes, I have specified a condition by declaring a static variable. I have updated the post. Issue is same as before. – snl Jul 16 '18 at 13:03
  • 2
    Can you set a field value like a pick-list with some status while making the callout and refer the field status in your trigger? – codeyinthecloud Jul 16 '18 at 13:46
  • I know Rajesh, this will surely work. But this is a workaround, and I am looking to solve this without creating any other field. Maybe there is something wrong with my approach. – snl Jul 16 '18 at 13:58
1

You can always use the isFuture() method from System class instead of a variable which returns true if the currently executing code is invoked by code contained in a method annotated with future; false otherwise. Link

if (!System.isFuture()) {
   Territory2Controller.runTerritoryRules(accountIds);
}

Also make sure that the web-service is not called from anywhere else.

  • From future method, I am calling SOAP API, so if I check the value System.isFuture() inside the trigger, it will always be false. – snl Jul 16 '18 at 13:35
  • 1
    Yes (please note the ! sign) It will be false for first time so, the trigger execute and call webservice (Future Context = false). The web service will execute in future context and when the trigger is invoked again due to assignments, since the process which invoked the trigger was in future context, the trigger will not execute again. – manjit5190 Jul 16 '18 at 13:41
  • I made the changes as suggested by you. So when the trigger is invoked 2nd time, it is still going inside the trigger. The reason, I assume, is its the web service which is updating the record which invoked the trigger, and not the future method, even though the web service is executing from a future method. Had I were updating the record directly from future method, maybe it wouldn't had invoked the trigger 2nd time. – snl Jul 16 '18 at 13:55
0

You need to set this flag before calling the future method. The reason is Salesforce allows making callouts before any DML statement. In your case you call the future method which do the following:

  1. Make a callout (asynchronous) to a SOAP API resource, which updates the same account

    ---!!! Here a new execution context is created by the SOAP API resource. --- But a this time inFutureContext is still false, thus recursion. This would always happen if a call to a SOAP API resource is synchronous (I mean the actual call to SOAP API).

  2. Updates the flag inFutureContext. - this will never be executed do to synchronous (1) will never return success.

  • But even if I set this flag to true before calling the future method, the problem will still remain same. As I will be executing SOAP API resource, so inFutureContext variable will be false inside the trigger. – snl Jul 16 '18 at 13:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.