11

I have an Apex class that calls out to a web service. The webservice doesn't allow multiple requests at the same time. I have an update trigger on Account that does the callout. So, if multiple users are managing accounts and do saves at more or less the same time, I'm getting errors from the webservice.

Is there a way to enforce mutual exclusion on critical code sections in Apex?

  • The callout queue approach is good, but I have to ask - is there any way to fix the webservice? Depending on how it's built, it might be easy to synchronize on that end. – kibitzer Jan 14 '14 at 22:08
  • Unfortunately it's a third party webservice over which we have no control whatsoever. – rael_kid Jan 15 '14 at 8:37
8

We had a similar issue, and settled on a "callout queue". Basically a custom object that contains all the information your callout needs (endpoint, body, GET/PUT/POST, etc). Then there's scheduled apex that grabs the next item on the queue and does what it needs to.

If you need to react to data returned from the endpoint, your custom object can contain the name of a static method made to handle returned data. The static method is served up via a factory class.

(We were more worried about endpoint downtime or communication issues, and our queue was built to ensure that every callout was eventually made, in order, but the queue will serve your purposes equally well.)

| improve this answer | |
  • Thanks for your answer. Seems like an okay solution, I'll look into it. Luckily for me, at the moment, there is no need to react on the data... – rael_kid Jan 14 '14 at 15:15
  • I actually didn't implement the solution yet, but it's the best answer to the question, so I'm accepting it. – rael_kid Jan 21 '14 at 12:46
1

Not sure if it fully covers your case but you could consider a semaphore approach: create a custom setting with a checkbox/boolean. The first trigger execution that fires the callout sets the Boolean to false, all "parallel" executions check the semaphore and do not fire the webservice request. After a successful invocation of the webservice the Boolean semaphore is set back to true by the @future method. Initially I wanted to suggest a public static Boolean variable as a semaphore (like handling recursive triggers) but due to the fact that the callouts from a trigger have to be asynchronous in an @future method you would loose the state of the static variable.

| improve this answer | |
  • This could be done, but how would the other "threads" know that the execution of the former has been finished and the semaphore has been released? Can I make Apex sleep? – rael_kid Jan 14 '14 at 16:04
  • no, i actually assumed that just skipping the "parallel" requests would be sufficient but i'm beginning to understand that you need all requests to be fired sequentially and that would bring us to matt's suggestion. sorry for the misunderstanding. – h9nry Jan 14 '14 at 16:28
  • No problem, the solution could be an option, if not in this case, maybe in other cases. Still worthwhile! – rael_kid Jan 14 '14 at 21:07

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.