Bug 1208056

Summary: Concurrent process execution will fail if it references a new user/group
Product: [Retired] JBoss BPMS Platform 6 Reporter: Anton Giertli <agiertli>
Component: jBPM CoreAssignee: Alessandro Lazarotti <alazarot>
Status: CLOSED EOL QA Contact: Marián Macik <mmacik>
Severity: high Docs Contact:
Priority: high    
Version: 6.0.3CC: frank, kverlaen, mbaluch
Target Milestone: DR1   
Target Release: 6.2.0   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2020-03-27 20:08:10 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Anton Giertli 2015-04-01 09:41:45 UTC
Description of problem:


If
(Multiple processes are started concurrently) AND (they reference a new user OR group, which is not in ORGANIZATIONALENTITY yet)

The process execution of one of the process will fail with 

Caused by: org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: "PRIMARY_KEY_C6 ON PUBLIC.ORGANIZATIONALENTITY(ID)"; SQL statement:
insert into OrganizationalEntity (DTYPE, id) values ('User', ?) [23505-168]

Version-Release number of selected component (if applicable):
6.0.3

How reproducible:

always
Steps to Reproduce:
1. The reproducer is here
https://github.com/fgreg/humantask-example-generic
Some other tests and scenario are here
http://pastebin.com/QwRMGJnA
The workaround is to start the single instance of process before starting them concurrently

as shown here
https://github.com/agiertli/humantask-example-generic

Actual results:
This scenario 

Expected results:
It's expected that jBPM engine handles this situation better. We have customer proposing one of these two options:

1) Does BPM really need to propagate this particular exception to the caller? In this case, BPM is trying to insert a user but the user is already there. Can't BPM just continue? The state it was trying to achieve has already been achieved so why fail?

2) If you must throw this exception back to the caller; can it be a more descriptive exception than WorkflowRuntimeException? UserAlreadyPresentException or something similar so I can retry only for this exception?


Additional info:

Most likely, the one process fails if it tries to execute following method
https://github.com/droolsjbpm/jbpm/blob/master/jbpm-human-task/jbpm-human-task-core/src/main/java/org/jbpm/services/task/commands/UserGroupCallbackTaskCommand.java#L105

 (storing user/group into ORGANIZATIONALENTITY table)

Comment 3 Frank Greguska 2015-04-01 15:30:05 UTC
Just adding a little more context.

The stated workaround is only valid in the simplest of cases where users are statically defined and can all be inserted once at application startup.

In a production system where new Users can be added at any time, there is no practical way to guarantee that when a new user is added one and only one process is executed by the BPM engine.

To workaround that problem it is necessary to wrap all calls to ksession.startProcess() in a try catch as shown in  http://pastebin.com/AuNUsjNm. Inside the catch you simply resubmit the process a second time.

This is obviously not ideal for a number of reasons.

1) Developers need to be aware that for every process they start, they must include this try/catch statement. Ideal solution would be to not require this.

2) When the error occurs, the first process instance is Aborted and a new one is started. This results in extra process execution information that could be confusing to users.

3) Only option is to catch the generic WorkflowRuntimeException, which could be caused by this problem or any number of other problems. Granted, the catch logic could be more sophisticated but a more descriptive Exception would be better.

Comment 4 Maciej Swiderski 2015-04-02 14:56:46 UTC
fixed by utilizing optimistic lock exception interceptor by extending it to deal with constraint violation exceptions as well. That means in case of constraint violation exception engine with automatically retry after some delay (50 ms).
It is enabled on both ksession and task service by default so should cover this case completely.

drools
master:
https://github.com/droolsjbpm/drools/commit/2c6f2a9f4eb07661aeefcad372f5010fcbf9acdb

jbpm
master:
https://github.com/droolsjbpm/jbpm/commit/c472bf6e108b51fcda06918053d55683465fe308

Comment 6 Marián Macik 2015-10-21 12:17:56 UTC
Verified with the reproducer from Anton.