0 votes
762 views
in REST API by

1 Answer

0 votes
by (30.6k points)

Two different questions hide in there:

Are REST calls from BPM thread safe? Yes - every service execution runs on its own thread with its own BPMRESTRequest / HttpURLConnection objects; nothing is shared between concurrent executions unless you put it into a static Java field or a shared business object. Java integrations must be written thread safe (no mutable statics; connection pools instead of a shared connection), because the same class serves parallel executions.

How is concurrency handled?

  • Inbound (clients calling BPM's REST API): concurrent calls are served by the WebContainer thread pool; the engine serialises conflicting work on the same instance with row locks - two clients finishing the same task at the same time: one succeeds, the other gets an error (task already completed / CWTBG0019E optimistic lock) - handle it by re-reading. Idempotency is your job: use a business key (the request id) to detect duplicate starts.
  • Outbound (BPM calling REST services): the number of parallel calls equals the number of parallel service executions (thread pools: WebContainer for coach-triggered services, event manager for system tasks / UCAs); cap it with the event manager thread pool and with the external system's rate limits (a retry with back-off in a wrapper service, or an API gateway in front). Connection reuse: HttpURLConnection keeps alive per JVM; long-running or slow endpoints need explicit timeouts, otherwise threads pile up.
  • Transactions: an outbound REST call is not transactional; if the BPD step fails after the call, the call is not rolled back - make the target idempotent (PUT with a key, or check-before-create) so that retry of the failed step is safe.
  • Same instance, parallel branches: two branches calling REST and writing the same variable - by-value mapping means the last one to complete wins; write to different variables and merge.
// wrapper with timeout and retry with back-off (server-side script)
function callWithRetry(fn, attempts) {
  for (var i = 1; ; i++) {
    try { return fn(); }
    catch (e) { if (i >= attempts || !/timed out|503|429/i.test(String(e))) throw e; java.lang.Thread.sleep(500 * Math.pow(2, i)); }
  }
}
tw.local.result = callWithRetry(function () { var c = new java.net.URL(tw.local.url).openConnection(); c.setConnectTimeout(5000); c.setReadTimeout(20000); /* ... */ return read(c); }, 4);

References

Related questions

0 votes
1 answer 2.2k views
0 votes
1 answer 997 views
asked May 15, 2016 in REST API by anonymous
0 votes
1 answer 2.5k views
0 votes
1 answer 874 views
0 votes
1 answer 859 views
0 votes
1 answer 1.9k views
0 votes
1 answer 2.1k views
0 votes
1 answer 1.0k views
0 votes
1 answer 2.1k views
0 votes
1 answer 1.2k views
+1 vote
1 answer 923 views
0 votes
1 answer 670 views

723 questions

807 answers

98 comments

4.9k users

Join BPM Community Discord Channel

Welcome to BPM Tips Q&A, Community wiki/forum where you can ask questions and receive answers from other IBM BPM experts and members of the community. Users with 2000 points will automatically be promoted to expert level.
Created by Dosvak LLC
Our Youtube Channel
...