cancel
Showing results for 
Search instead for 
Did you mean: 

Join multiple (non-interrupting/cancel activitiy=false) message boundary executions

mreiterer
Champ in-the-making
Champ in-the-making
Hi all,

how do i join multiple (non-interrupting/cancel activitiy=false) message boundary executions, which start an async, non-exclusive task?

Below is my process defintion file.

Thanks in advance.
Markus



<?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/test">
  <message id="startSubMessage" name="startSubMessage"></message>
  <message id="testMessage" name="testMessage"></message>
  <process id="test-boundary-parallel" name="My process" isExecutable="true">
    <startEvent id="startevent1" name="Start"></startEvent>
    <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="receivetask1"></sequenceFlow>
    <scriptTask id="scripttask1" name="Script Task" scriptFormat="groovy" activiti:autoStoreVariables="false">
      <script>println "after join"
  </script>
    </scriptTask>
    <endEvent id="endevent1" name="End"></endEvent>
    <sequenceFlow id="flow3" sourceRef="scripttask1" targetRef="endevent1"></sequenceFlow>
    <receiveTask id="receivetask1" name="Receive Task"></receiveTask>
    <boundaryEvent id="boundarymessage1" name="Message" attachedToRef="receivetask1" cancelActivity="false">
      <messageEventDefinition messageRef="testMessage"></messageEventDefinition>
    </boundaryEvent>
    <serviceTask id="servicetask1" name="Service Task" activiti:async="true" activiti:exclusive="false" activiti:class="com.prepressdigital.genericcrud.activiti.TestTask"></serviceTask>
    <sequenceFlow id="flow12" sourceRef="boundarymessage1" targetRef="servicetask1"></sequenceFlow>
    <sequenceFlow id="flow16" sourceRef="receivetask1" targetRef="scripttask1"></sequenceFlow>
  </process>
  </definitions>
8 REPLIES 8

martin_grofcik
Confirmed Champ
Confirmed Champ
Hi Markus,

If you refer to your previous post with waiting on an asynchronous response in the receive task. I would prefer asynchronous service call in one process instance and after that process instance can be finished.
To handle messages I would prefer message start event and handle responses in the separate process instance.
We had a case when service responses were faster than DB commits - nobody is listening to the message - message is lost.

Regards
Martin

mreiterer
Champ in-the-making
Champ in-the-making
Thanks Martin for your answer.

I want to keep the main flow alive till all messages are handled. So would it be the best to notify the main flow via a signal or message event from the "message handling" flow ?

martin_grofcik
Confirmed Champ
Confirmed Champ
Hi Markus,

I think, message handling flow -> notification main process won't solve the issue.

Regards
Martin

mreiterer
Champ in-the-making
Champ in-the-making
Do you have any suggestions ?

Hi,
you should register message catching events before service call (in multiple parallel threads).

Regards
Martin

jbarrez
Star Contributor
Star Contributor
You don't need to join them, you can simply let them go to and end event and they will cease to exist.

Unless you want to wait until all of them are completed. In that case you need to know the number of 'branches' up front, and use something like a multi instance embedded subprocess.

mreiterer
Champ in-the-making
Champ in-the-making
Thanks. That brought me one big step ahead !

I don't know the number of branches, i just get an "end" signal from the external system so i know no new branches will be created.

At least i need need to notify the main flow of the outcome somehow. Do i run into concurrency / transaction issues here ? 
When i set the same variable from my branches i run into the following exception:


org.apache.ibatis.exceptions.PersistenceException:
### Error updating database.  Cause: org.h2.jdbc.JdbcSQLException: Referentielle Integrität verletzt: "ACT_FK_VAR_EXE: PUBLIC.ACT_RU_VARIABLE FOREIGN KEY(EXECUTION_ID_) REFERENCES PUBLIC.ACT_RU_EXECUTION(ID_) ('5')"
Referential integrity constraint violation: "ACT_FK_VAR_EXE: PUBLIC.ACT_RU_VARIABLE FOREIGN KEY(EXECUTION_ID_) REFERENCES PUBLIC.ACT_RU_EXECUTION(ID_) ('5')"; SQL statement:
delete from ACT_RU_EXECUTION where ID_ = ? and REV_ = ? [23503-186]
### 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: org.h2.jdbc.JdbcSQLException: Referentielle Integrität verletzt: "ACT_FK_VAR_EXE: PUBLIC.ACT_RU_VARIABLE FOREIGN KEY(EXECUTION_ID_) REFERENCES PUBLIC.ACT_RU_EXECUTION(ID_) ('5')"
Referential integrity constraint violation: "ACT_FK_VAR_EXE: PUBLIC.ACT_RU_VARIABLE FOREIGN KEY(EXECUTION_ID_) REFERENCES PUBLIC.ACT_RU_EXECUTION(ID_) ('5')"; SQL statement:
delete from ACT_RU_EXECUTION where ID_ = ? and REV_ = ? [23503-186]
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:284)
at org.activiti.engine.impl.db.DbSqlSession.flushRegularDeletes(DbSqlSession.java:834)
at org.activiti.engine.impl.db.DbSqlSession.flushDeletes(DbSqlSession.java:798)
at org.activiti.engine.impl.db.DbSqlSession.flush(DbSqlSession.java:595)
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.RepositoryServiceImpl.deleteDeployment(RepositoryServiceImpl.java:90)
at org.activiti.engine.impl.test.TestHelper.annotationDeploymentTearDown(TestHelper.java:116)
at org.activiti.engine.test.ActivitiRule.finished(ActivitiRule.java:265)
at org.activiti.engine.test.ActivitiRule.finishedQuietly(ActivitiRule.java:179)
at org.activiti.engine.test.ActivitiRule.access$400(ActivitiRule.java:86)
at org.activiti.engine.test.ActivitiRule$1.evaluate(ActivitiRule.java:135)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.h2.jdbc.JdbcSQLException: Referentielle Integrität verletzt: "ACT_FK_VAR_EXE: PUBLIC.ACT_RU_VARIABLE FOREIGN KEY(EXECUTION_ID_) REFERENCES PUBLIC.ACT_RU_EXECUTION(ID_) ('5')"
Referential integrity constraint violation: "ACT_FK_VAR_EXE: PUBLIC.ACT_RU_VARIABLE FOREIGN KEY(EXECUTION_ID_) REFERENCES PUBLIC.ACT_RU_EXECUTION(ID_) ('5')"; SQL statement:
delete from ACT_RU_EXECUTION where ID_ = ? and REV_ = ? [23503-186]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
at org.h2.message.DbException.get(DbException.java:179)
at org.h2.message.DbException.get(DbException.java:155)
at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:426)
at org.h2.constraint.ConstraintReferential.checkRowRefTable(ConstraintReferential.java:443)
at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:318)
at org.h2.table.Table.fireConstraints(Table.java:920)
at org.h2.table.Table.fireAfterRow(Table.java:938)
at org.h2.command.dml.Delete.update(Delete.java:100)
at org.h2.command.CommandContainer.update(CommandContainer.java:78)
at org.h2.command.Command.executeUpdate(Command.java:254)
at org.h2.jdbc.JdbcPreparedStatement.execute(JdbcPreparedStatement.java:198)
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)
… 33 more

jbarrez
Star Contributor
Star Contributor
Hmm could you post the latest version of your process xml so I can see what you're having now?