cancel
Showing results for 
Search instead for 
Did you mean: 

V 5.16 - Cancel parallel task with candidate causes referential integrity violation on constraint 'AKT_FK_TSKASS_TASK'

dsc_
Champ in-the-making
Champ in-the-making
Hello,

we have modeled the following workflow:
A user requests a vacation. After that an approver can approve this request or the requestor can revoke it. This is the relevant part of our BPMN:


<?xml version="1.0" encoding="UTF-8" ?>
<definitions id="definitions" targetNamespace="http://activiti.org/bpmn20" xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn" xmlns:cell="http://khaos.eu/cell">

   <process id="test" name="test">

      <startEvent id="start"></startEvent>
      
      <userTask id="Request" activiti:assignee="${requestor}">
      </userTask>
      
      <transaction id="innerTransaction">
         <startEvent id="innerStart"></startEvent>
         
         <parallelGateway id="split"></parallelGateway>
         <userTask id="Revoke" activiti:assignee="${requestor}">
         </userTask>
   
         
         <userTask id="Approve" activiti:candidateGroups="${approverRole}">
         </userTask>
         
           <exclusiveGateway id="join"></exclusiveGateway>
         
         <endEvent id="innerEnd">
            <cancelEventDefinition />
         </endEvent>
         
         <sequenceFlow sourceRef="innerStart" targetRef="split"></sequenceFlow>
      
         <sequenceFlow sourceRef="split" targetRef="Task"></sequenceFlow>
         <sequenceFlow sourceRef="split" targetRef="RevokeTask"></sequenceFlow>
         <sequenceFlow sourceRef="RevokeTask" targetRef="join"></sequenceFlow>
         <sequenceFlow sourceRef="Task" targetRef="join"></sequenceFlow>
         <sequenceFlow sourceRef="join" targetRef="innerEnd"></sequenceFlow>
      
      </transaction>
      
      <boundaryEvent id="transactionCancelled" attachedToRef="innerTransaction">
         <cancelEventDefinition />
      </boundaryEvent>
      
       
      <endEvent id="end"></endEvent>
      
      
      <sequenceFlow sourceRef="start" targetRef="StartTask"></sequenceFlow>
      <sequenceFlow sourceRef="StartTask" targetRef="innerTransaction"></sequenceFlow>
      
      
      <sequenceFlow sourceRef="innerTransaction" targetRef="end"></sequenceFlow>
      <sequenceFlow sourceRef="transactionCancelled" targetRef="end"></sequenceFlow>

   </process>
</definitions>


This worked fine until we updated to activiti 5.16.

The following test throws an SQLException, telling us that the foreign key "ACT_FK_TSKASS_TASK" is violated.

Test:

@Test
public void revoke() {
   // start instance with variables ["requestor" = "req", "approverRole" = "approver"]
   testEngine.start("requestor", "req", "approverRole", "approver");
   testEngine.getAssert().countTasks(1);
   Task startTask = testEngine.getEngine().getTaskService().createTaskQuery().taskDefinitionKey("Start")
         .singleResult();

   testEngine.getEngine().getTaskService().complete(startTask.getId());
   testEngine.getAssert().countTasks(2);

   Task revokeTask = testEngine.getEngine().getTaskService().createTaskQuery().taskDefinitionKey("Revoke")
         .singleResult();
   testEngine.getEngine().getTaskService().complete(revokeTask.getId());

   testEngine.getAssert().countTasks(0);
}


Exception:



10:30:18.590 [main] DEBUG o.a.e.i.interceptor.CommandContext - Error while closing command context
org.apache.ibatis.exceptions.PersistenceException:
### Error updating database.  Cause: org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "ACT_FK_TSKASS_TASK: PUBLIC.ACT_RU_IDENTITYLINK FOREIGN KEY(TASK_ID_) REFERENCES PUBLIC.ACT_RU_TASK(ID_) ('18')"; SQL statement:
delete from ACT_RU_TASK where
     
        ID_ = ?
      or 
        ID_ = ? [23503-173]
### The error may involve org.activiti.engine.impl.persistence.entity.TaskEntity.bulkDeleteTask-Inline
### The error occurred while setting parameters
### SQL: delete from ACT_RU_TASK where                 ID_ = ?       or           ID_ = ?
### Cause: org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "ACT_FK_TSKASS_TASK: PUBLIC.ACT_RU_IDENTITYLINK FOREIGN KEY(TASK_ID_) REFERENCES PUBLIC.ACT_RU_TASK(ID_) ('18')"; SQL statement:
delete from ACT_RU_TASK where
     
        ID_ = ?
      or 
        ID_ = ? [23503-173]
   at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:23) ~[mybatis-3.2.5.jar:3.2.5]
   at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:150) ~[mybatis-3.2.5.jar:3.2.5]
   at org.apache.ibatis.session.defaults.DefaultSqlSession.delete(DefaultSqlSession.java:161) ~[mybatis-3.2.5.jar:3.2.5]
   at org.activiti.engine.impl.db.DbSqlSession$BulkCheckedDeleteOperation.execute(DbSqlSession.java:340) ~[activiti-engine-5.16.jar:5.16]
   at org.activiti.engine.impl.db.DbSqlSession.flushRegularDeletes(DbSqlSession.java:824) ~[activiti-engine-5.16.jar:5.16]
   at org.activiti.engine.impl.db.DbSqlSession.flushDeletes(DbSqlSession.java:788) ~[activiti-engine-5.16.jar:5.16]
   at org.activiti.engine.impl.db.DbSqlSession.flush(DbSqlSession.java:588) ~[activiti-engine-5.16.jar:5.16]
   at org.activiti.engine.impl.interceptor.CommandContext.flushSessions(CommandContext.java:211) ~[activiti-engine-5.16.jar:5.16]
   at org.activiti.engine.impl.interceptor.CommandContext.close(CommandContext.java:137) ~[activiti-engine-5.16.jar:5.16]
   at org.activiti.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:66) [activiti-engine-5.16.jar:5.16]
   at org.activiti.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:37) [activiti-engine-5.16.jar:5.16]
   at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:40) [activiti-engine-5.16.jar:5.16]
   at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:35) [activiti-engine-5.16.jar:5.16]
   at org.activiti.engine.impl.TaskServiceImpl.complete(TaskServiceImpl.java:166) [activiti-engine-5.16.jar:5.16]
   at de.astrumit.pls.process.RevokeSingleTask.RevokeSingleTaskTest.revoke(RevokeSingleTaskTest.java:42) [test-classes/:na]
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_11]
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_11]
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_11]
   at java.lang.reflect.Method.invoke(Method.java:483) ~[na:1.8.0_11]
   at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) [junit-4.11.jar:na]
   at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) [junit-4.11.jar:na]
   at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) [junit-4.11.jar:na]
   at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) [junit-4.11.jar:na]
   at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) [junit-4.11.jar:na]
   at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) [junit-4.11.jar:na]
   at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) [junit-4.11.jar:na]
   at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) [junit-4.11.jar:na]
   at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) [junit-4.11.jar:na]
   at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) [junit-4.11.jar:na]
   at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) [junit-4.11.jar:na]
   at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) [junit-4.11.jar:na]
   at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) [junit-4.11.jar:na]
   at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) [junit-4.11.jar:na]
   at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) [junit-4.11.jar:na]
   at org.junit.runners.ParentRunner.run(ParentRunner.java:309) [junit-4.11.jar:na]
   at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) [.cp/:na]
   at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) [.cp/:na]
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) [.cp/:na]
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) [.cp/:na]
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) [.cp/:na]
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) [.cp/:na]
Caused by: org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "ACT_FK_TSKASS_TASK: PUBLIC.ACT_RU_IDENTITYLINK FOREIGN KEY(TASK_ID_) REFERENCES PUBLIC.ACT_RU_TASK(ID_) ('18')"; SQL statement:
delete from ACT_RU_TASK where
     
        ID_ = ?
      or 
        ID_ = ? [23503-173]
   at org.h2.message.DbException.getJdbcSQLException(DbException.java:331) ~[h2-1.3.173.jar:1.3.173]
   at org.h2.message.DbException.get(DbException.java:171) ~[h2-1.3.173.jar:1.3.173]
   at org.h2.message.DbException.get(DbException.java:148) ~[h2-1.3.173.jar:1.3.173]
   at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:421) ~[h2-1.3.173.jar:1.3.173]
   at org.h2.constraint.ConstraintReferential.checkRowRefTable(ConstraintReferential.java:438) ~[h2-1.3.173.jar:1.3.173]
   at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:314) ~[h2-1.3.173.jar:1.3.173]
   at org.h2.table.Table.fireConstraints(Table.java:880) ~[h2-1.3.173.jar:1.3.173]
   at org.h2.table.Table.fireAfterRow(Table.java:897) ~[h2-1.3.173.jar:1.3.173]
   at org.h2.command.dml.Delete.update(Delete.java:100) ~[h2-1.3.173.jar:1.3.173]
   at org.h2.command.CommandContainer.update(CommandContainer.java:79) ~[h2-1.3.173.jar:1.3.173]
   at org.h2.command.Command.executeUpdate(Command.java:235) ~[h2-1.3.173.jar:1.3.173]
   at org.h2.jdbc.JdbcPreparedStatement.execute(JdbcPreparedStatement.java:193) ~[h2-1.3.173.jar:1.3.173]
   at sun.reflect.GeneratedMethodAccessor7.invoke(Unknown Source) ~[na:na]
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_11]
   at java.lang.reflect.Method.invoke(Method.java:483) ~[na:1.8.0_11]
   at org.apache.ibatis.logging.jdbc.PreparedStatementLogger.invoke(PreparedStatementLogger.java:55) ~[mybatis-3.2.5.jar:3.2.5]
   at com.sun.proxy.$Proxy6.execute(Unknown Source) ~[na:na]
   at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:41) ~[mybatis-3.2.5.jar:3.2.5]
   at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:66) ~[mybatis-3.2.5.jar:3.2.5]
   at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:45) ~[mybatis-3.2.5.jar:3.2.5]
   at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:100) ~[mybatis-3.2.5.jar:3.2.5]
   at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:75) ~[mybatis-3.2.5.jar:3.2.5]
   at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:148) ~[mybatis-3.2.5.jar:3.2.5]
   … 39 common frames omitted



We also removed the transactional subprocess and fired an event after "Revoke" completes, which triggers a boundary-event on "Approve" with "cancelActivity=true". This led to the same error.

Thank you for looking into this issue!
3 REPLIES 3

dsc_
Champ in-the-making
Champ in-the-making
Updated test and process to simplify testing for you (no internal dependencies from us left and first version actually had some compilation errors):

Test:
<code>
package de.astrumit.pls.process.RevokeSingleTask;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.impl.history.HistoryLevel;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.task.Task;
import org.junit.Assert;
import org.junit.Test;

public class RevokeSingleTaskTest {
private static ProcessEngine createEngine(String file) {
  ProcessEngine engine = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration()
    .setHistoryLevel(HistoryLevel.FULL).buildProcessEngine();

  DeploymentBuilder builder = engine.getRepositoryService().createDeployment();

  InputStream processAsStream = RevokeSingleTaskTest.class.getResourceAsStream("/processes/test/" + file
    + ".bpmn20.xml");
  if (processAsStream == null) {
   throw new IllegalStateException("Unable to find '/processes/test/" + file + ".bpmn20.xml' on classpath");
  }
  builder.addInputStream(file + ".bpmn20.xml", processAsStream);

  builder.deploy();
  return engine;
}

@Test
public void revoke() {
  ProcessEngine engine = createEngine("RevokeSingleTask");

  Map<String, Object> variables = new HashMap<>();
  variables.put("requestor", "req");
  variables.put("approverRole", "approver");
  engine.getRuntimeService().startProcessInstanceByKey("test", variables);

  Task startTask = engine.getTaskService().createTaskQuery().taskDefinitionKey("Request").singleResult();

  engine.getTaskService().complete(startTask.getId());

  Task revokeTask = engine.getTaskService().createTaskQuery().taskDefinitionKey("Revoke").singleResult();

  engine.getTaskService().complete(revokeTask.getId());

  Assert.assertEquals(0, engine.getTaskService().createTaskQuery().count());

  engine.close();
}
}
</code>

ProcessDefinition (src/test/resources/processes/test/RevokeSingleTask.bpmn20.xml):
<code>
<?xml version="1.0" encoding="UTF-8" ?>
<definitions id="definitions" targetNamespace="http://activiti.org/bpmn20" xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn" xmlns:cell="http://khaos.eu/cell">

<process id="test" name="test">

  <startEvent id="start"></startEvent>
 
  <userTask id="Request" activiti:assignee="${requestor}">
  </userTask>
 
  <transaction id="innerTransaction">
   <startEvent id="innerStart"></startEvent>
  
   <parallelGateway id="split"></parallelGateway>
   <userTask id="Revoke" activiti:assignee="${requestor}">
   </userTask>

  
   <userTask id="Approve" activiti:candidateGroups="${approverRole}">
   </userTask>
  
         <exclusiveGateway id="join"></exclusiveGateway>
  
   <endEvent id="innerEnd">
    <cancelEventDefinition />
   </endEvent>
  
   <sequenceFlow sourceRef="innerStart" targetRef="split"></sequenceFlow>
 
   <sequenceFlow sourceRef="split" targetRef="Approve"></sequenceFlow>
   <sequenceFlow sourceRef="split" targetRef="Revoke"></sequenceFlow>
   <sequenceFlow sourceRef="Revoke" targetRef="join"></sequenceFlow>
   <sequenceFlow sourceRef="Approve" targetRef="join"></sequenceFlow>
   <sequenceFlow sourceRef="join" targetRef="innerEnd"></sequenceFlow>
 
  </transaction>
 
  <boundaryEvent id="transactionCancelled" attachedToRef="innerTransaction">
   <cancelEventDefinition />
  </boundaryEvent>
 
       
  <endEvent id="end"></endEvent>
 
 
  <sequenceFlow sourceRef="start" targetRef="Request"></sequenceFlow>
  <sequenceFlow sourceRef="Request" targetRef="innerTransaction"></sequenceFlow>
 
 
  <sequenceFlow sourceRef="innerTransaction" targetRef="end"></sequenceFlow>
  <sequenceFlow sourceRef="transactionCancelled" targetRef="end"></sequenceFlow>

</process>
</definitions>
</code>

frederikherema1
Star Contributor
Star Contributor
Thanks for the unit-test, I'll try it later today to see the result. In http://forums.activiti.org/content/sticky-how-write-unit-test you can find some tips on writing a test, a zip/gist of such a project is also a good way of providing us a test…

dsc_
Champ in-the-making
Champ in-the-making
See https://jira.codehaus.org/browse/ACT-2070

Thank you for looking into this issue!