Bug 1161574 - "java.lang.RuntimeException: Process instance XXX is disconnected." with SingletonRuntimeManager without CMT/BMT
Summary: "java.lang.RuntimeException: Process instance XXX is disconnected." with Sing...
Keywords:
Status: CLOSED NOTABUG
Alias: None
Product: JBoss BPMS Platform 6
Classification: Retired
Component: jBPM Core
Version: 6.0.3
Hardware: Unspecified
OS: Unspecified
high
high
Target Milestone: ER3
: 6.1.0
Assignee: Maciej Swiderski
QA Contact: Marek Baluch
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2014-11-07 11:16 UTC by Toshiya Kobayashi
Modified: 2015-09-01 10:15 UTC (History)
4 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2015-09-01 10:15:34 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)
rewards-basic-bpms603-singleton-no-outer-tx.zip (44.81 KB, application/zip)
2014-11-07 11:16 UTC, Toshiya Kobayashi
no flags Details
rewards-basic.zip (100.06 KB, application/zip)
2015-01-02 09:20 UTC, Jiri Svitak
no flags Details
server-log-bpms610er3.log (187.93 KB, text/plain)
2015-01-07 14:44 UTC, Jiri Svitak
no flags Details
rewards-basic-BZ1161574-singleton-taskService.zip (89.41 KB, application/zip)
2015-01-13 07:32 UTC, Toshiya Kobayashi
no flags Details

Description Toshiya Kobayashi 2014-11-07 11:16:32 UTC
Created attachment 954903 [details]
rewards-basic-bpms603-singleton-no-outer-tx.zip

Description of problem:

"java.lang.RuntimeException: Process instance XXX is disconnected." is thrown with SingletonRuntimeManager + HumanTask application (even without CMT/BMT) under load.

19:18:24,832 WARN  [org.drools.persistence.SingleSessionCommandService] (http-/127.0.0.1:8080-9) Could not commit session: java.lang.RuntimeException: Process instance 11[com.sample.rewards-basic] is disconnected.
	at org.jbpm.process.instance.impl.ProcessInstanceImpl.getProcess(ProcessInstanceImpl.java:90) [jbpm-flow-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.jbpm.process.instance.impl.ProcessInstanceImpl.getContextInstance(ProcessInstanceImpl.java:161) [jbpm-flow-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.jbpm.workflow.instance.WorkflowRuntimeException.initialize(WorkflowRuntimeException.java:56) [jbpm-flow-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.jbpm.workflow.instance.WorkflowRuntimeException.<init>(WorkflowRuntimeException.java:42) [jbpm-flow-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.jbpm.workflow.instance.impl.NodeInstanceImpl.trigger(NodeInstanceImpl.java:161) [jbpm-flow-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.jbpm.ruleflow.instance.RuleFlowProcessInstance.internalStart(RuleFlowProcessInstance.java:35) [jbpm-flow-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.jbpm.process.instance.impl.ProcessInstanceImpl.start(ProcessInstanceImpl.java:226) [jbpm-flow-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.jbpm.workflow.instance.impl.WorkflowProcessInstanceImpl.start(WorkflowProcessInstanceImpl.java:363) [jbpm-flow-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.jbpm.process.instance.ProcessRuntimeImpl.startProcessInstance(ProcessRuntimeImpl.java:194) [jbpm-flow-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.jbpm.process.instance.ProcessRuntimeImpl.startProcess(ProcessRuntimeImpl.java:176) [jbpm-flow-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.jbpm.process.instance.ProcessRuntimeImpl.startProcess(ProcessRuntimeImpl.java:168) [jbpm-flow-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.drools.core.common.AbstractWorkingMemory.startProcess(AbstractWorkingMemory.java:1575) [drools-core-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.drools.core.impl.StatefulKnowledgeSessionImpl.startProcess(StatefulKnowledgeSessionImpl.java:366) [drools-core-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.drools.core.command.runtime.process.StartProcessCommand.execute(StartProcessCommand.java:121) [drools-core-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.drools.core.command.runtime.process.StartProcessCommand.execute(StartProcessCommand.java:40) [drools-core-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.drools.core.command.impl.DefaultCommandService.execute(DefaultCommandService.java:36) [drools-core-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.drools.core.command.impl.AbstractInterceptor.executeNext(AbstractInterceptor.java:41) [drools-core-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.drools.persistence.SingleSessionCommandService$TransactionInterceptor.execute(SingleSessionCommandService.java:533) [drools-persistence-jpa-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.drools.core.command.impl.AbstractInterceptor.executeNext(AbstractInterceptor.java:41) [drools-core-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.drools.persistence.jpa.OptimisticLockRetryInterceptor.execute(OptimisticLockRetryInterceptor.java:73) [drools-persistence-jpa-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.drools.persistence.SingleSessionCommandService.execute(SingleSessionCommandService.java:377) [drools-persistence-jpa-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.drools.core.command.impl.CommandBasedStatefulKnowledgeSession.startProcess(CommandBasedStatefulKnowledgeSession.java:232) [drools-core-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.jbpm.examples.ejb.ProcessBean.startProcess(ProcessBean.java:68) [classes:]


Steps to Reproduce:
- Unzip attached rewards-basic-bpms603-singleton-no-outer-tx.zip
- mvn clean install
- Deploy to EAP 6.2.2
- Start JMeter and open reward-basic.jmx in the zip
- Run JMeter with 1 thread as warm-up
- Run JMeter with 10 threads and 10 loop

* This application stops processing once an unexpected Exception is thrown, in order to avoid too many Exceptions. If you want to test again, please re-deploy the application.

Actual results:

Throws "java.lang.RuntimeException: Process instance XXX is disconnected."

Expected results:

No Exception

========
Feel free to let me know if you have difficulty in reproduction.

Comment 1 Toshiya Kobayashi 2014-11-07 11:21:20 UTC
My analysis:

JBPM-4249 addresses the issue about SingletonRuntimeManager with CMT/BMT. But this BZ is a different issue. I confirmed that it's reproducible with "no CMT/BMT in BPMS 6.0.3" and "Enabled TransactionLockInterceptor in jBPM 6.1.0.Final".

I debugged with byteman (you can find logsingleton.rule in the zip) and observed the log below:

19:18:24,741 INFO  [stdout] (http-/127.0.0.1:8080-5) approveTask (taskId = 17) by jiri
19:18:24,753 INFO  [stdout] (http-/127.0.0.1:8080-5) processTaskState : ksession = org.drools.core.command.impl.CommandBasedStatefulKnowledgeSession@1cdeb03b
19:18:24,783 INFO  [stdout] (http-/127.0.0.1:8080-9) startProcess : ksession = org.drools.core.command.impl.CommandBasedStatefulKnowledgeSession@1cdeb03b
19:18:24,783 INFO  [stdout] (http-/127.0.0.1:8080-5) execute : this = org.drools.persistence.SingleSessionCommandService@7c2970f1
19:18:24,787 INFO  [stdout] (http-/127.0.0.1:8080-5) execute : this = org.drools.persistence.SingleSessionCommandService@7c2970f1
19:18:24,798 INFO  [stdout] (http-/127.0.0.1:8080-5) execute : this = org.drools.persistence.SingleSessionCommandService@7c2970f1
19:18:24,798 INFO  [stdout] (http-/127.0.0.1:8080-5) execute : this = org.drools.persistence.SingleSessionCommandService@7c2970f1
19:18:24,799 INFO  [stdout] (http-/127.0.0.1:8080-5) execute : this = org.drools.persistence.SingleSessionCommandService@7c2970f1
19:18:24,799 INFO  [stdout] (http-/127.0.0.1:8080-5) execute : this = org.drools.persistence.SingleSessionCommandService@7c2970f1
19:18:24,799 INFO  [stdout] (http-/127.0.0.1:8080-5) execute : this = org.drools.persistence.SingleSessionCommandService@7c2970f1
19:18:24,800 INFO  [stdout] (http-/127.0.0.1:8080-5) execute : this = org.drools.persistence.SingleSessionCommandService@7c2970f1
19:18:24,800 INFO  [stdout] (http-/127.0.0.1:8080-5) execute : this = org.drools.persistence.SingleSessionCommandService@7c2970f1
19:18:24,810 INFO  [stdout] (http-/127.0.0.1:8080-9) execute : this = org.drools.persistence.SingleSessionCommandService@7c2970f1
19:18:24,813 INFO  [stdout] (http-/127.0.0.1:8080-9) execute : this = org.drools.persistence.SingleSessionCommandService@7c2970f1
19:18:24,823 INFO  [stdout] (http-/127.0.0.1:8080-5) disconnect : this = WorkflowProcessInstance9 [processId=com.sample.rewards-basic,state=1]
19:18:24,823 INFO  [stdout] (http-/127.0.0.1:8080-5) disconnect : this = WorkflowProcessInstance11 [processId=com.sample.rewards-basic,state=1]
19:18:24,825 INFO  [stdout] (http-/127.0.0.1:8080-9) getProcess null : this = WorkflowProcessInstance11 [processId=com.sample.rewards-basic,state=1]
19:18:24,832 INFO  [stdout] (http-/127.0.0.1:8080-9) getProcess null : this = WorkflowProcessInstance11 [processId=com.sample.rewards-basic,state=1]
19:18:24,832 INFO  [stdout] (http-/127.0.0.1:8080-9) getProcess null : this = WorkflowProcessInstance11 [processId=com.sample.rewards-basic,state=1]
19:18:24,832 WARN  [org.drools.persistence.SingleSessionCommandService] (http-/127.0.0.1:8080-9) Could not commit session: java.lang.RuntimeException: Process instance 11[com.sample.rewards-basic] is disconnected.
	at org.jbpm.process.instance.impl.ProcessInstanceImpl.getProcess(ProcessInstanceImpl.java:90) [jbpm-flow-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.jbpm.process.instance.impl.ProcessInstanceImpl.getContextInstance(ProcessInstanceImpl.java:161) [jbpm-flow-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.jbpm.workflow.instance.WorkflowRuntimeException.initialize(WorkflowRuntimeException.java:56) [jbpm-flow-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.jbpm.workflow.instance.WorkflowRuntimeException.<init>(WorkflowRuntimeException.java:42) [jbpm-flow-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.jbpm.workflow.instance.impl.NodeInstanceImpl.trigger(NodeInstanceImpl.java:161) [jbpm-flow-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.jbpm.ruleflow.instance.RuleFlowProcessInstance.internalStart(RuleFlowProcessInstance.java:35) [jbpm-flow-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.jbpm.process.instance.impl.ProcessInstanceImpl.start(ProcessInstanceImpl.java:226) [jbpm-flow-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.jbpm.workflow.instance.impl.WorkflowProcessInstanceImpl.start(WorkflowProcessInstanceImpl.java:363) [jbpm-flow-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.jbpm.process.instance.ProcessRuntimeImpl.startProcessInstance(ProcessRuntimeImpl.java:194) [jbpm-flow-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.jbpm.process.instance.ProcessRuntimeImpl.startProcess(ProcessRuntimeImpl.java:176) [jbpm-flow-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.jbpm.process.instance.ProcessRuntimeImpl.startProcess(ProcessRuntimeImpl.java:168) [jbpm-flow-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.drools.core.common.AbstractWorkingMemory.startProcess(AbstractWorkingMemory.java:1575) [drools-core-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.drools.core.impl.StatefulKnowledgeSessionImpl.startProcess(StatefulKnowledgeSessionImpl.java:366) [drools-core-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.drools.core.command.runtime.process.StartProcessCommand.execute(StartProcessCommand.java:121) [drools-core-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.drools.core.command.runtime.process.StartProcessCommand.execute(StartProcessCommand.java:40) [drools-core-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.drools.core.command.impl.DefaultCommandService.execute(DefaultCommandService.java:36) [drools-core-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.drools.core.command.impl.AbstractInterceptor.executeNext(AbstractInterceptor.java:41) [drools-core-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.drools.persistence.SingleSessionCommandService$TransactionInterceptor.execute(SingleSessionCommandService.java:533) [drools-persistence-jpa-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.drools.core.command.impl.AbstractInterceptor.executeNext(AbstractInterceptor.java:41) [drools-core-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.drools.persistence.jpa.OptimisticLockRetryInterceptor.execute(OptimisticLockRetryInterceptor.java:73) [drools-persistence-jpa-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.drools.persistence.SingleSessionCommandService.execute(SingleSessionCommandService.java:377) [drools-persistence-jpa-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.drools.core.command.impl.CommandBasedStatefulKnowledgeSession.startProcess(CommandBasedStatefulKnowledgeSession.java:232) [drools-core-6.0.3-redhat-6.jar:6.0.3-redhat-6]
	at org.jbpm.examples.ejb.ProcessBean.startProcess(ProcessBean.java:68) [classes:]
...

This indicates that thread#8080-9 was working inside the synchronized SingleSessionCommandService.execute() but thread#8080-5 disconnected the process instance (#11).

Why possible? Because thread#8080-5 called ProcessRuntimeImpl.clearProcessInstances() on afterCompletion() and the commit was issued by TaskTransactionInterceptor (not by SingleSessionCommandService$TransactionInterceptor).

Daemon Thread [http-/127.0.0.1:8080-5] (Suspended (breakpoint at line 235 in ProcessInstanceImpl)) (out of synch)	
	owns: Object  (id=21903)	
	owns: TaskTransactionInterceptor  (id=21904)	
	RuleFlowProcessInstance(ProcessInstanceImpl).disconnect() line: 235	
	RuleFlowProcessInstance(WorkflowProcessInstanceImpl).disconnect() line: 320	
	JPAProcessInstanceManager.clearProcessInstances() line: 164	
	ProcessRuntimeImpl.clearProcessInstances() line: 470	
	SingleSessionCommandService$SynchronizationImpl.afterCompletion(int) line: 463	
	TransactionSynchronizationContainer.afterCompletion(int) line: 26	
	JtaTransactionSynchronizationAdapter.afterCompletion(int) line: 22	
	SynchronizationImple.afterCompletion(int) line: 96	
	AtomicAction(TwoPhaseCoordinator).afterCompletion(int, boolean) line: 402	
	AtomicAction(TwoPhaseCoordinator).end(boolean) line: 103	
	AtomicAction(AtomicAction).commit(boolean) line: 162	
	TransactionImple.commitAndDisassociate() line: 1165	
	TransactionManagerImple(BaseTransaction).commit() line: 126	
	TransactionManagerDelegate(BaseTransactionManagerDelegate).commit() line: 75	
	ServerVMClientUserTransaction.commit() line: 167	
	JtaTransactionManager.commit(boolean) line: 210	
	TaskTransactionInterceptor.execute(Command<T>) line: 56	
	TaskCommandExecutorImpl.execute(Command<T>) line: 40	
	CommandBasedTaskService.complete(long, String, Map<String,Object>) line: 144	
	TaskBean.approveTask(String, long) line: 68 (out of synch)
...

So this disconnection can happen even during the other thread's synchronized SingleSessionCommandService.execute().

Comment 2 Toshiya Kobayashi 2014-11-07 12:46:28 UTC
Hmm, if my analysis is correct, TransactionLockInterceptor should be able to help...? I will test TransactionLockInterceptor again and investigate what is going on...

Comment 3 Toshiya Kobayashi 2014-11-08 14:12:49 UTC
Okay, I seemed to have misread my results before.

Now I have re-tested the following combinations:

A) BPMS 6.0.3 (6.0.3-redhat-6) + Singleton
 -> Frequent "Process instance XXX is disconnected."

B) jBPM 6.1.0.Final + Singleton 
 -> Frequent "Process instance XXX is disconnected."

C) jBPM 6.1.0.Final + Singleton + TransactionLockInterceptor enabled
 -> No issue

D) jBPM 6.1.0.Final + Singleton + BMT + TransactionLockInterceptor enabled
 -> Non-frequent "javax.persistence.TransactionRequiredException: No active JTA transaction on joinTransaction call"

So, I must say that TransactionLockInterceptor (JBPM-4249) fixed this BZ's issue as well. The pattern D) seems to tell that TransactionLockInterceptor is not perfect because it depends on transaction synchronization order. But anyway, this BZ will be fixed in BPMS 6.1.0 by enabling TransactionLockInterceptor.

Now, I feel like voting TransactionLockInterceptor default to "enabled" for SingletonRuntimeManager because this disconnect issue is reproducible with Human Task scenario even without CMT/BMT (Outer transaction by TaskTransactionInterceptor).

WDYT, Maciej?

---------------------------------
FYI) Log when pattern D) reproduced:
===
22:34:57,125 DEBUG [org.drools.persistence.jta.TransactionLockInterceptor] (http-/127.0.0.1:8080-9) About to register lock release handler by http-/127.0.0.1:8080-9
22:34:57,125 DEBUG [org.drools.persistence.jta.TransactionLockInterceptor] (http-/127.0.0.1:8080-1) About to get a lock on command service by http-/127.0.0.1:8080-1
22:34:57,125 INFO  [stdout] (http-/127.0.0.1:8080-9) Process started ... : processInstanceId = 271
22:34:57,126 INFO  [stdout] (http-/127.0.0.1:8080-5) approveTask (taskId = 539) by jiri
22:34:57,128 DEBUG [org.drools.persistence.jta.TransactionLockInterceptor] (http-/127.0.0.1:8080-9) Releasing on transaction completion by http-/127.0.0.1:8080-9
22:34:57,128 DEBUG [org.drools.persistence.jta.TransactionLockInterceptor] (http-/127.0.0.1:8080-9) Successfully released lock by http-/127.0.0.1:8080-9
22:34:57,128 DEBUG [org.drools.persistence.jta.TransactionLockInterceptor] (http-/127.0.0.1:8080-1) Lock taken by http-/127.0.0.1:8080-1
22:34:57,128 WARN  [org.drools.persistence.SingleSessionCommandService] (http-/127.0.0.1:8080-1) Could not commit session: javax.persistence.TransactionRequiredException: No active JTA transaction on joinTransaction call
	at org.hibernate.ejb.AbstractEntityManagerImpl.joinTransaction(AbstractEntityManagerImpl.java:1233) [hibernate-entitymanager-4.2.7.SP1-redhat-3.jar:4.2.7.SP1-redhat-3]
	at org.hibernate.ejb.AbstractEntityManagerImpl.joinTransaction(AbstractEntityManagerImpl.java:1183) [hibernate-entitymanager-4.2.7.SP1-redhat-3.jar:4.2.7.SP1-redhat-3]
	at org.drools.persistence.jpa.JpaPersistenceContext.joinTransaction(JpaPersistenceContext.java:66) [drools-persistence-jpa-6.1.0.Final.jar:6.1.0.Final]
	at org.drools.persistence.SingleSessionCommandService$TransactionInterceptor.execute(SingleSessionCommandService.java:490) [drools-persistence-jpa-6.1.0.Final.jar:6.1.0.Final]
	at org.drools.core.command.impl.AbstractInterceptor.executeNext(AbstractInterceptor.java:41) [drools-core-6.1.0.Final.jar:6.1.0.Final]
	at org.drools.persistence.jpa.OptimisticLockRetryInterceptor.execute(OptimisticLockRetryInterceptor.java:73) [drools-persistence-jpa-6.1.0.Final.jar:6.1.0.Final]
	at org.drools.core.command.impl.AbstractInterceptor.executeNext(AbstractInterceptor.java:41) [drools-core-6.1.0.Final.jar:6.1.0.Final]
	at org.drools.persistence.jta.TransactionLockInterceptor.execute(TransactionLockInterceptor.java:72) [drools-persistence-jpa-6.1.0.Final.jar:6.1.0.Final]
===

Comment 4 Maciej Swiderski 2014-11-13 12:24:46 UTC
thanks for details analysis Toshiya. 

Not fully convinced we should enable transaction lock interceptor by default but from the other hand don't see any negative side effects of doing so. Singleton runtime manager could simply enable it via environment so no need to set any system properties.

Shall we then enable it singleton runtime manager? Votes please :) 

And you're right, transaction lock interceptor is not perfect either but it does cover majority of cases where race condition might affect the execution but still leaves some cases uncovered as you mentioned due to transaction sync order. Although not sure we can do much about it.

Comment 5 Maciej Swiderski 2014-11-14 18:51:01 UTC
transaction lock interceptor enabled by default for singleton strategy, tough when there is any setting regarding transaction lock interceptor (either via environment entry or system property) defaults are not set.

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

6.2.x:
https://github.com/droolsjbpm/jbpm/commit/49f1d4977966544118e35337d4baba3138b1a0f6

Comment 6 Jiri Svitak 2015-01-02 09:20:30 UTC
Created attachment 975165 [details]
rewards-basic.zip

Toshiya,
Thank you for the reproducer. I was able to reproduce the issue as you reported it using BPMS 6.0.3 and EAP 6.1.1.

I had to update the example rewards-basic application for version 6.1.0.ER3 of BPM Suite, here is the current list of changes made:
https://mojo.redhat.com/docs/DOC-1005328

I got to a point, where the rewards-basic for BPMS 6.1.0.ER3 can be deployed on EAP 6.3, the rewards process can be started and the first task completed. However the second task does not appear in mary's list of tasks, so I cannot run your jmeter scenario. There is no exception.

Comment 7 Jiri Svitak 2015-01-02 09:23:25 UTC
Maciej,
Can you please take a look on rewards-basic web application updated for BPMS 6.1.0.ER3? The second human task does not appear, there is no exception and I am unable to verify the fix of this issue.

Comment 10 Maciej Swiderski 2015-01-07 12:34:23 UTC
Jiri,

since you inject TaskService it misses the event listener to inform process about task completion and thus it does not move to the second task. To overcome this you can simply add such a class you your project that will automatically bind it to every task service instance:

package org.jbpm.examples.util;

import javax.enterprise.context.ApplicationScoped;

import org.jbpm.services.task.wih.ExternalTaskEventListener;

@ApplicationScoped
public class CdiExternalTaskEventListener extends ExternalTaskEventListener {

}

Comment 11 Jiri Svitak 2015-01-07 14:44:29 UTC
Created attachment 977344 [details]
server-log-bpms610er3.log

Thanks Maciej!

I have added CdiExternalTaskEventListener as you suggested to the attached rewards-basic.zip, which uses BPM Suite 6.1.0.ER3. The problem with second task in the process has been fixed.

I have tried to run jmeter test plan with 10 threads and 10 loops.
I can confirm that the original problem has been fixed, there is no more message that the 'Process instance XXX is disconnected.'

p.s. However when the process instance id=64 is started, an OptimisticLockingException is thrown:

15:28:47,283 INFO  [stdout] (http-/127.0.0.1:8080-6) Process started ... : processInstanceId = 64
15:28:47,287 WARN  [com.arjuna.ats.arjuna] (http-/127.0.0.1:8080-10) ARJUNA012125: TwoPhaseCoordinator.beforeCompletion - failed for SynchronizationImple< 0:ffff0a221e05:7ccaf2d2:54ad423f:d03, org.hibernate.engine.transaction.synchronization.internal.RegisteredSynchronization@60ebdb57 >: javax.persistence.OptimisticLockException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.jbpm.services.task.impl.model.TaskImpl#125]

The whole server.log is attached.

Toshiya, is this expected? Thanks.

Comment 12 Jiri Svitak 2015-01-07 14:48:25 UTC
The reported problem has been fixed. Verified in BPM Suite 6.1.0.ER3.

There may be another problem, so if confirmed a new bugzilla will be filed.

Comment 13 Toshiya Kobayashi 2015-01-08 08:26:10 UTC
Hi Jiri,

I tested the attached rewards-basic.zip with 6.2.0-SNAPSHOT + EAP 6.3.0.

I also observed OptimisticLockException with 10 threads * 10 loops.

=====
17:07:17,475 INFO  [stdout] (http-/127.0.0.1:8080-1) retrieveTaskList by mary
17:07:17,476 INFO  [stdout] (http-/127.0.0.1:8080-1)  task.getId() = 104
17:07:17,476 INFO  [stdout] (http-/127.0.0.1:8080-1)  task.getId() = 103
17:07:17,478 INFO  [stdout] (http-/127.0.0.1:8080-1) approveTask (taskId = 104) by mary
17:07:17,483 INFO  [stdout] (http-/127.0.0.1:8080-10) retrieveTaskList by mary
17:07:17,483 INFO  [stdout] (http-/127.0.0.1:8080-10)  task.getId() = 104
17:07:17,483 INFO  [stdout] (http-/127.0.0.1:8080-10)  task.getId() = 103
17:07:17,486 INFO  [stdout] (http-/127.0.0.1:8080-10) approveTask (taskId = 104) by mary
17:07:17,494 INFO  [stdout] (http-/127.0.0.1:8080-7) Process started ... : processInstanceId = 53
17:07:17,496 WARN  [com.arjuna.ats.arjuna] (http-/127.0.0.1:8080-1) ARJUNA012125: TwoPhaseCoordinator.beforeCompletion - failed for SynchronizationImple<0:ffff7f000001:785d43fd:54ae2e2a:2c64, org.hibernate.engine.transaction.synchronization.internal.RegisteredSynchronization@3fded465 >: javax.persistence.OptimisticLockException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.jbpm.services.task.impl.model.TaskImpl#104]
	at org.hibernate.ejb.AbstractEntityManagerImpl.wrapStaleStateException(AbstractEntityManagerImpl.java:1413) [hibernate-entitymanager-4.2.14.SP1-redhat-1.jar:4.2.14.SP1-redhat-1]
...
=====

Thread#8080-1 and #8080-10 tried to start(or complete) the same task#104 so OptimisticLockException is an expected result. Please check the stdout logs to see if you face the same scenario.

Comment 14 Toshiya Kobayashi 2015-01-08 10:57:44 UTC
Jiri,

I think it's odd that TaskService is not singleton while RuntimeManager is singleton in the rewards-basic (So synchronization of TaskTransactionInterceptor.execute() doesn't work).

Don't you follow this practice?

- Use TaskService taken from RuntimeManager for write operations (e.g. start, complete etc.)

- Use independent TaskService (e.g. injected) for read operations

I wrote the practice based on PerProcessInstance but it would be applied to Singleton as well https://access.redhat.com/solutions/1278833

WDYT?

Comment 15 Toshiya Kobayashi 2015-01-08 11:00:46 UTC
I sent a PR for your master (PerProcessInstance).

https://github.com/jsvitak/jbpm-6-examples/pull/8

Comment 16 Toshiya Kobayashi 2015-01-13 07:32:55 UTC
Created attachment 979498 [details]
rewards-basic-BZ1161574-singleton-taskService.zip

Comment 18 Toshiya Kobayashi 2015-09-01 10:15:34 UTC
=== IMPORTANT NOTE ===

This BZ was marked as "VERIFIED" but actually, this is "NOTABUG".

The first reproducer "rewards-basic-bpms603-singleton-no-outer-tx.zip" uses an injected TaskService to complete a Task. This is an invalid use of API. If you use a TaskService (= SynchronizedTaskService) taken from Singleton RuntimeEngine, the transaction is protected and "Process instance XXX is disconnected" will not happen.

The last reproducer "rewards-basic-BZ1161574-singleton-taskService.zip" does correctly use a TaskService taken from Singleton RuntimeEngine so the "disconnected" issue is not reproducible even if you disable TransactionLockInterceptor.

So enabling TransactionLockInterceptor by default was not necessary. I filed another BZ to revert back the default.

https://bugzilla.redhat.com/show_bug.cgi?id=1258797


Note You need to log in before you can comment on or make changes to this bug.