cancel
Showing results for 
Search instead for 
Did you mean: 

Process started in Activiti Explorer results in integrity constraint violation, but starting programmatically is OK

slehman
Champ in-the-making
Champ in-the-making
I'm making the case for Activiti at my company and have been getting my feet wet by trying to figure out how to work with some long-running asynchronous processes.   The receive task looks like the way to go, but I've already run into a problem.

My process is simply  start -> receive -> end.   When I start a process programmatically, I can signal the execution, and things work as expected.  But when I start the process using Activiti Explorer (running as a standalone .war), after signaling the execution, I see an exception:

SEVERE: Error while closing command context
org.apache.ibatis.exceptions.PersistenceException:
### Error updating database.  Cause: org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "ACT_FK_IDL_PROCINST: PUBLIC.ACT_RU_IDENTITYLINK FOREIGN KEY(PROC_INST_ID_) REFERENCES PUBLIC.ACT_RU_EXECUTION(ID_) ('3070')"; SQL statement:
delete from ACT_RU_EXECUTION where ID_ = ? [23503-171]
   at org.h2.message.DbException.getJdbcSQLException(DbException.java:329)
   at org.h2.message.DbException.get(DbException.java:169)
   at org.h2.message.DbException.get(DbException.java:146)
   at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:414)
   at org.h2.constraint.ConstraintReferential.checkRowRefTable(ConstraintReferential.java:431)
   at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:307)
   at org.h2.table.Table.fireConstraints(Table.java:873)
   at org.h2.table.Table.fireAfterRow(Table.java:890)
   at org.h2.command.dml.Delete.update(Delete.java:99)
   at org.h2.command.CommandContainer.update(CommandContainer.java:75)
   at org.h2.command.Command.executeUpdate(Command.java:230)
   at org.h2.server.TcpServerThread.process(TcpServerThread.java:334)
   at org.h2.server.TcpServerThread.run(TcpServerThread.java:150)
   at java.lang.Thread.run(Unknown Source)


I can see the entries in ACT_RU_IDENTITYLINK that are created only when Explorer is used to start the process, but I am at a loss for what I need to do to make this work.

My process definition is:

<?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">
 
  <process id="myVacationRequest" name="My Vacation request">
    <startEvent id="request" >
    </startEvent>
    <sequenceFlow id="flow1" sourceRef="request" targetRef="wait2" />
    <receiveTask id="wait2" name="wait"/>
    <sequenceFlow id="flow2a" sourceRef="wait2" targetRef="theEnd1" />
    <endEvent id="theEnd1" />
  </process>
</definitions>

The code I'm using is:

      ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
      if (processEngine == null) {
         log.error("Could not start Activiti Engine");
      }
      else {
         RepositoryService repositoryService = processEngine.getRepositoryService();
         repositoryService.createDeployment()
           .addClasspathResource("VacationRequest.bpmn20.xml")
           .deploy();
              
         log.info("Number of process definitions: " + repositoryService.createProcessDefinitionQuery().count());           
          
         // This process will complete as expected
          String procId = processEngine.getRuntimeService().startProcessInstanceByKey("myVacationRequest").getId();

         
          // Start a process in Activiti Explorer - it will result in an exception at the end of the process
          try {
            Thread.sleep(30000);
         } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
         }

          // Lookup executions in our wait activity, and signal them to advance
          RuntimeService rs = processEngine.getRuntimeService();
         List<Execution> executions = rs.createExecutionQuery().processDefinitionKey("myVacationRequest").activityId("wait2").list();
         
         for (Execution execution : executions) {
            log.info("Found execution " + execution.getId());
            try {
               rs.signal(execution.getId());
            } catch (RuntimeException e) {
               System.out.println(e.getMessage());
            }
         }
      }


Is there some other key step to using the Receive task that I'm missing?

Thanks,

Scott
4 REPLIES 4

slehman
Champ in-the-making
Champ in-the-making
Hmm, guess I should have previewed first - sorry about that!

My process definition is
<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">
 
  <process id="myVacationRequest" name="My Vacation request">
 
    <startEvent id="request" >
    </startEvent>
   
    <sequenceFlow id="flow1" sourceRef="request" targetRef="wait2" />
   
    <receiveTask id="wait2" name="wait"/>
       
    <sequenceFlow id="flow2a" sourceRef="wait2" targetRef="theEnd1" />
   
    <endEvent id="theEnd1" />
   
  </process>
 
</definitions>
</code>

and the code I'm using is :

<code>
  ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
  if (processEngine == null) {
   log.error("Could not start Activiti Engine");
  }
  else {
   RepositoryService repositoryService = processEngine.getRepositoryService();
   repositoryService.createDeployment()
     .addClasspathResource("VacationRequest.bpmn20.xml")
     .deploy();
        
   log.info("Number of process definitions: " + repositoryService.createProcessDefinitionQuery().count());           
    
   // This process will complete as expected
      String procId = processEngine.getRuntimeService().startProcessInstanceByKey("myVacationRequest").getId();

     
      // Start a process in Activiti Explorer - it will result in an exception at the end of the process
      try {
    Thread.sleep(30000);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }

      // Lookup executions in our wait activity, and signal them to advance
      RuntimeService rs = processEngine.getRuntimeService();
   List<Execution> executions = rs.createExecutionQuery().processDefinitionKey("myVacationRequest").activityId("wait2").list();
  
   for (Execution execution : executions) {
    log.info("Found execution " + execution.getId());
    try {
     rs.signal(execution.getId());
    } catch (RuntimeException e) {
     System.out.println(e.getMessage());
    }
   }
  }

</code>

slehman
Champ in-the-making
Champ in-the-making
I think my problem is an incorrect assumption about how Activiti Explorer was intended to be used with standalone applications - can someone confirm?

I had Explorer running in an Tomcat instance, and I was running the code in a separate process.  While the deployed process appears in Explorer, I'm guessing the problem is related to starting a process in one engine, and then sending the signal  another engine.   If I deploy similar code to the Tomcat instance, I do not see the exception.

Is this not something that is supported?  I was hoping all I had to do was point Explorer and my app to the same database and I'd be able to use Explorer for user tasks.  Perhaps I need to integrate explorer into my app instead?

Thanks

slehman
Champ in-the-making
Champ in-the-making
Looks like I found the problem - one project was using 5.9, vs Activiti Explorer 5.12.1.  For some reason, Eclipse wasn't showing the latest versions when selecting dependencies, but after changing the XML directly, the problem has gone away, so perhaps it was just some different in DB schemas.

jbarrez
Star Contributor
Star Contributor
The 'fix' sounds very strange, as the error in the beginning is something we saw in Activiti 5.12….