AnsweredAssumed Answered

Asynchronous task/transaction cancelation

Question asked by vanquis on Aug 17, 2015
Latest reply on Aug 20, 2015 by vanquis
Hello all,

I'm using Activiti 5.18 with Oracle DB. I'm trying to implement asynchronous cancel for subprocesses (transactions) and I have encountered a problem with DB constraint.
Here is the stack trace:

org.apache.ibatis.exceptions.PersistenceException:
### Error updating database.  Cause: java.sql.SQLIntegrityConstraintViolationException: ORA-02292: naruszono więzy spójności (VANQUIS.ACT_FK_TASK_EXE) - znaleziono rekord podrzędny

### The error may involve org.activiti.engine.impl.persistence.entity.ExecutionEntity.deleteExecution-Inline
### The error occurred while setting parameters
### SQL: delete from ACT_RU_EXECUTION where ID_ = ? and REV_ = ?
### Cause: java.sql.SQLIntegrityConstraintViolationException: ORA-02292: naruszono więzy spójności (VANQUIS.ACT_FK_TASK_EXE) - znaleziono rekord podrzędny

   at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:23)
   at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:150)
   at org.apache.ibatis.session.defaults.DefaultSqlSession.delete(DefaultSqlSession.java:161)
   at org.activiti.engine.impl.db.DbSqlSession$CheckedDeleteOperation.execute(DbSqlSession.java:292)
   at org.activiti.engine.impl.db.DbSqlSession.flushRegularDeletes(DbSqlSession.java:921)
   at org.activiti.engine.impl.db.DbSqlSession.flushDeletes(DbSqlSession.java:887)
   at org.activiti.engine.impl.db.DbSqlSession.flush(DbSqlSession.java:612)
   at org.activiti.engine.impl.interceptor.CommandContext.flushSessions(CommandContext.java:211)
   at org.activiti.engine.impl.interceptor.CommandContext.close(CommandContext.java:137)
   at org.activiti.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:66)
   at org.activiti.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:31)
   at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:40)
   at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:35)
   at org.activiti.engine.impl.TaskServiceImpl.complete(TaskServiceImpl.java:175)
   at SignalBoundaryCancelSubprocess.main(SignalBoundaryCancelSubprocess.java:79)
Caused by: java.sql.SQLIntegrityConstraintViolationException: ORA-02292: naruszono więzy spójności (VANQUIS.ACT_FK_TASK_EXE) - znaleziono rekord podrzędny

   at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:447)
   at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
   at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:951)
   at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:513)
   at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:227)
   at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531)
   at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:208)
   at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1046)
   at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1336)
   at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3613)
   at oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:3714)
   at oracle.jdbc.driver.OraclePreparedStatementWrapper.execute(OraclePreparedStatementWrapper.java:1378)
   at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:41)
   at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:66)
   at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:45)
   at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:100)
   at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:75)
   at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:148)
   … 13 more


It appears when using tools marked as experimental (CancelEndEvent + transaction subprocess + CancelBoundaryEvent) as well as while using just simple IntermediateSignalThrowingEvent + SignalCatching boundary event with cancelActivity="true" on a transaction subprocess. The error occurs, when the cancel signal comes and I have still a UserTask opened in progress inside the subprocess. My guess is that the cancel just goes straight into the DB and tries to delete the execution without any status checking, despite the fact that there is still a Task in progress. Probably the key is that 2 actions are going in parallel here (async=true, exlusive=false).

To achieve the behavior described above I'm using a parallel gateway in order to fork the execution into 2 concurrent branches. Then one branch asynchronically sends interrupt to the other one.

I've got 3 questions:
1. Am I doing something wrong here?
2. Is it a bug or asynchronous cancels are just not supported yet?
3. If there is another way to asynchronously cancel an ongoing activity, could You please tell me what it is?

Here is my bpmn:

<?xml version='1.0' encoding='UTF-8'?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/processdef">
  <signal id="interrupt" name="Interrupt" activiti:scope="global"/>
  <process id="SimpleCancel" name="SimpleCancel" isExecutable="true">
    <startEvent id="startprocess"/>
    <userTask id="initialtask" name="InitialTask"/>
    <parallelGateway id="parallelgateway"/>
    <userTask id="interrupttask" name="InterruptTask" activiti:async="true" activiti:exclusive="false"/>
    <intermediateThrowEvent id="cancelsignalthrow">
      <signalEventDefinition signalRef="interrupt"/>
    </intermediateThrowEvent>
    <transaction id="subprocess" name="subProcess">
      <startEvent id="startsubprocess"/>
      <userTask id="firsttask" name="FirstTask" activiti:async="true" activiti:exclusive="false"/>
      <endEvent id="endsubprocess"/>
      <sequenceFlow id="s6" sourceRef="startsubprocess" targetRef="firsttask"/>
      <sequenceFlow id="s7" sourceRef="firsttask" targetRef="endsubprocess"/>
    </transaction>
    <userTask id="aftercancel" name="AfterCancel" activiti:async="true" activiti:exclusive="false"/>
    <userTask id="finaltask" name="FinalTask" activiti:async="true" activiti:exclusive="false"/>
    <endEvent id="endprocess"/>
    <sequenceFlow id="s1" sourceRef="startprocess" targetRef="initialtask"/>
    <sequenceFlow id="s2" sourceRef="initialtask" targetRef="parallelgateway"/>
    <sequenceFlow id="s3" sourceRef="parallelgateway" targetRef="subprocess"/>
    <sequenceFlow id="s4" sourceRef="parallelgateway" targetRef="interrupttask"/>
    <sequenceFlow id="s5" sourceRef="interrupttask" targetRef="cancelsignalthrow"/>
    <sequenceFlow id="s8" sourceRef="subprocess" targetRef="finaltask"/>
    <sequenceFlow id="s9" sourceRef="finaltask" targetRef="endprocess"/>
    <sequenceFlow id="s10" sourceRef="cancelboundarysignalcatch" targetRef="aftercancel"/>
    <sequenceFlow id="s11" sourceRef="aftercancel" targetRef="endprocess"/>
    <boundaryEvent id="cancelboundarysignalcatch" attachedToRef="subprocess" cancelActivity="true">
      <signalEventDefinition signalRef="interrupt"/>
    </boundaryEvent>
  </process>

  <bpmndi:BPMNDiagram id="BPMNDiagram_SimpleCancel">
    <bpmndi:BPMNPlane bpmnElement="SimpleCancel" id="BPMNPlane_SimpleCancel">
      <bpmndi:BPMNShape bpmnElement="startprocess" id="BPMNShape_startprocess">
        <omgdc:Bounds height="30.0" width="30.0" x="96.63336181640625" y="244.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="initialtask" id="BPMNShape_initialtask">
        <omgdc:Bounds height="80.0" width="100.0" x="186.63336181640625" y="219.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="parallelgateway" id="BPMNShape_parallelgateway">
        <omgdc:Bounds height="40.0" width="40.0" x="375.0" y="239.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="interrupttask" id="BPMNShape_interrupttask">
        <omgdc:Bounds height="80.0" width="100.0" x="345.0" y="345.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="cancelsignalthrow" id="BPMNShape_cancelsignalthrow">
        <omgdc:Bounds height="30.0" width="30.0" x="380.0" y="519.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="subprocess" id="BPMNShape_subprocess">
        <omgdc:Bounds height="160.0" width="278.0" x="538.6333618164062" y="179.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="startsubprocess" id="BPMNShape_startsubprocess">
        <omgdc:Bounds height="30.0" width="30.0" x="555.0" y="244.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="firsttask" id="BPMNShape_firsttask">
        <omgdc:Bounds height="80.0" width="100.0" x="629.6333618164062" y="219.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="endsubprocess" id="BPMNShape_endsubprocess">
        <omgdc:Bounds height="28.0" width="28.0" x="774.6333618164062" y="245.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="aftercancel" id="BPMNShape_aftercancel">
        <omgdc:Bounds height="80.0" width="100.0" x="784.6333618164062" y="434.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="finaltask" id="BPMNShape_finaltask">
        <omgdc:Bounds height="80.0" width="100.0" x="861.6333618164062" y="219.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="endprocess" id="BPMNShape_endprocess">
        <omgdc:Bounds height="28.0" width="28.0" x="1006.6333618164062" y="245.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="cancelboundarysignalcatch" id="BPMNShape_cancelboundarysignalcatch">
        <omgdc:Bounds height="30.0" width="30.0" x="753.4867711020827" y="324.28905936873736"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="s2" id="BPMNEdge_s2">
        <omgdi:waypoint x="286.63336181640625" y="259.15703866929493"/>
        <omgdi:waypoint x="375.43594746690496" y="259.43594746690496"/>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="s1" id="BPMNEdge_s1">
        <omgdi:waypoint x="126.63336181640625" y="259.0"/>
        <omgdi:waypoint x="186.63336181640625" y="259.0"/>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="s9" id="BPMNEdge_s9">
        <omgdi:waypoint x="961.6333618164062" y="259.0"/>
        <omgdi:waypoint x="1006.6333618164062" y="259.0"/>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="s7" id="BPMNEdge_s7">
        <omgdi:waypoint x="729.6333618164062" y="259.0"/>
        <omgdi:waypoint x="774.6333618164062" y="259.0"/>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="s8" id="BPMNEdge_s8">
        <omgdi:waypoint x="816.6333618164062" y="259.0"/>
        <omgdi:waypoint x="861.6333618164062" y="259.0"/>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="s5" id="BPMNEdge_s5">
        <omgdi:waypoint x="395.0" y="425.0"/>
        <omgdi:waypoint x="395.0" y="519.0"/>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="s6" id="BPMNEdge_s6">
        <omgdi:waypoint x="585.0" y="259.0"/>
        <omgdi:waypoint x="629.6333618164062" y="259.0"/>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="s10" id="BPMNEdge_s10">
        <omgdi:waypoint x="775.0981386803538" y="352.75345013642476"/>
        <omgdi:waypoint x="814.9923169526834" y="434.0"/>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="s3" id="BPMNEdge_s3">
        <omgdi:waypoint x="414.5337317991687" y="259.4662682008313"/>
        <omgdi:waypoint x="538.6333618164062" y="259.24633740424224"/>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="s11" id="BPMNEdge_s11">
        <omgdi:waypoint x="869.2380129791969" y="434.0"/>
        <omgdi:waypoint x="1011.4737120077149" y="269.5877672519819"/>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="s4" id="BPMNEdge_s4">
        <omgdi:waypoint x="395.424" y="278.576"/>
        <omgdi:waypoint x="395.1593625498008" y="345.0"/>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>


Here is also the simple process diagram:
[img]http://i.imgur.com/l6WrsFj.png[/img]

I'm looking forward to Your help.

Regards,
Vanquis

Outcomes