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)
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.
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
Verified with the reproducer from Anton.