Skip to content

Commit

Permalink
Merge branch 'main' into dbmSpringBoot3.1.3
Browse files Browse the repository at this point in the history
  • Loading branch information
tijsrademakers authored Aug 29, 2023
2 parents 70f08aa + 2b94a80 commit c44f9a2
Show file tree
Hide file tree
Showing 12 changed files with 252 additions and 12 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Flowable (V6)
Flowable (V7)
========

[Maven Central:
Expand Down Expand Up @@ -33,9 +33,11 @@ The Flowable downloads can be found on https://www.flowable.org/downloads.html.

The distribution contains most of the sources as jar files. The source code of Flowable can be found on https://github.com/flowable/flowable-engine.

### JDK 8+
### JDK 17+

Flowable runs on a JDK higher than or equal to version 8. Use the JDK packaged with your Linux distribution or go to [adoptium.net](https://adoptium.net/) and click on the *Latest LTS Release* button. There are installation instructions on that page as well. To verify that your installation was successful, run `java -version` on the command line. That should print the installed version of your JDK.
Flowable V7 runs on a Java higher than or equal to version 17. Use the JDK packaged with your Linux distribution or go to [adoptium.net](https://adoptium.net/) and click on the *Latest LTS Release* button. There are installation instructions on that page as well. To verify that your installation was successful, run `java -version` on the command line. That should print the installed version of your JDK.

[Flowable V6](https://github.com/flowable/flowable-engine/tree/flowable6.x) is still maintained and supports Java 8+.

### Contributing

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ protected ChangePlanItemStateBuilderImpl prepareChangeStateBuilder(CaseInstance
CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);
if (cmmnEngineConfiguration.isFallbackToDefaultTenant() && cmmnEngineConfiguration.getDefaultTenantProvider() != null) {

if (!Objects.equals(destinationTenantId, cmmnEngineConfiguration.getDefaultTenantProvider().getDefaultTenant(caseInstance.getId(), ScopeTypes.CMMN, caseDefinitionToMigrateTo.getKey()))) {
if (!Objects.equals(destinationTenantId, cmmnEngineConfiguration.getDefaultTenantProvider().getDefaultTenant(caseInstance.getTenantId(), ScopeTypes.CMMN, caseDefinitionToMigrateTo.getKey()))) {
throw new FlowableException("Tenant mismatch between Case Instance ('" + caseInstance.getTenantId() + "') and Case Definition ('" + destinationTenantId + "') to migrate to");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1850,6 +1850,97 @@ void testMultiTenantCaseInstanceMigrationWithDefaultTenantDefinition() {
}
}

@Test
void testMultiTenantCaseInstanceMigrationWithCustomDefaultTenantProvider() {
DefaultTenantProvider originalDefaultTenantValue = cmmnEngineConfiguration.getDefaultTenantProvider();
cmmnEngineConfiguration.setFallbackToDefaultTenant(true);
CustomTenantProvider customTenantProvider = new CustomTenantProvider();
cmmnEngineConfiguration.setDefaultTenantProvider(customTenantProvider);

try {
// Arrange
CmmnDeployment deployment = cmmnRepositoryService.createDeployment()
.name("my deploy")
.addClasspathResource("org/flowable/cmmn/test/migration/one-task.cmmn.xml")
.tenantId("tenant1-default")
.deploy();

CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder()
.caseDefinitionKey("testCase")
.tenantId("tenant1")
.start();

deployment = cmmnRepositoryService.createDeployment()
.name("my deploy")
.addClasspathResource("org/flowable/cmmn/test/migration/two-task.cmmn.xml")
.tenantId("tenant1-default")
.deploy();

CaseDefinition destinationDefinition = cmmnRepositoryService.createCaseDefinitionQuery().deploymentId(deployment.getId()).singleResult();

// Act
cmmnMigrationService.createCaseInstanceMigrationBuilder()
.migrateToCaseDefinition(destinationDefinition.getId())
.addActivatePlanItemDefinitionMapping(PlanItemDefinitionMappingBuilder.createActivatePlanItemDefinitionMappingFor("humanTask2"))
.migrate(caseInstance.getId());

// Assert
CaseInstance caseInstanceAfterMigration = cmmnRuntimeService.createCaseInstanceQuery()
.caseInstanceId(caseInstance.getId())
.singleResult();
assertThat(caseInstanceAfterMigration.getCaseDefinitionId()).isEqualTo(destinationDefinition.getId());
assertThat(caseInstanceAfterMigration.getCaseDefinitionKey()).isEqualTo("testCase");
assertThat(caseInstanceAfterMigration.getCaseDefinitionName()).isEqualTo("Two Task Test Case");
assertThat(caseInstanceAfterMigration.getCaseDefinitionVersion()).isEqualTo(2);
assertThat(caseInstanceAfterMigration.getCaseDefinitionDeploymentId()).isEqualTo(destinationDefinition.getDeploymentId());
List<PlanItemInstance> planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery()
.caseInstanceId(caseInstance.getId())
.list();
assertThat(planItemInstances).hasSize(2);
assertThat(planItemInstances)
.extracting(PlanItemInstance::getCaseDefinitionId)
.containsOnly(destinationDefinition.getId());
assertThat(planItemInstances)
.extracting(PlanItemInstance::getName)
.containsExactlyInAnyOrder("Task 1", "Task 2");
assertThat(planItemInstances)
.extracting(PlanItemInstance::getState)
.containsOnly(PlanItemInstanceState.ACTIVE);

List<Task> tasks = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).list();
assertThat(tasks).hasSize(2);
for (Task task : tasks) {
assertThat(task.getScopeDefinitionId()).isEqualTo(destinationDefinition.getId());
cmmnTaskService.complete(task.getId());
}

assertThat(cmmnRuntimeService.createCaseInstanceQuery().caseInstanceId(caseInstance.getId()).count()).isZero();

if (CmmnHistoryTestHelper.isHistoryLevelAtLeast(HistoryLevel.ACTIVITY, cmmnEngineConfiguration)) {
assertThat(cmmnHistoryService.createHistoricCaseInstanceQuery().caseInstanceId(caseInstance.getId()).count()).isEqualTo(1);
assertThat(cmmnHistoryService.createHistoricCaseInstanceQuery().caseInstanceId(caseInstance.getId()).singleResult().getCaseDefinitionId())
.isEqualTo(destinationDefinition.getId());

List<HistoricPlanItemInstance> historicPlanItemInstances = cmmnHistoryService.createHistoricPlanItemInstanceQuery()
.planItemInstanceCaseInstanceId(caseInstance.getId()).list();
assertThat(historicPlanItemInstances).hasSize(2);
for (HistoricPlanItemInstance historicPlanItemInstance : historicPlanItemInstances) {
assertThat(historicPlanItemInstance.getCaseDefinitionId()).isEqualTo(destinationDefinition.getId());
}

List<HistoricTaskInstance> historicTasks = cmmnHistoryService.createHistoricTaskInstanceQuery().caseInstanceId(caseInstance.getId()).list();
assertThat(historicTasks).hasSize(2);
for (HistoricTaskInstance historicTask : historicTasks) {
assertThat(historicTask.getScopeDefinitionId()).isEqualTo(destinationDefinition.getId());
}
}

} finally {
cmmnEngineConfiguration.setFallbackToDefaultTenant(false);
cmmnEngineConfiguration.setDefaultTenantProvider(originalDefaultTenantValue);
}
}

@Test
void testMultiTenantCaseInstanceMigrationWithTargetDefaultTenantDefinition() {
DefaultTenantProvider originalDefaultTenantValue = cmmnEngineConfiguration.getDefaultTenantProvider();
Expand Down Expand Up @@ -3324,4 +3415,12 @@ void withSentryIfPartEventDeferred() {
// with stages
// with new expected case variables

protected class CustomTenantProvider implements DefaultTenantProvider {

@Override
public String getDefaultTenant(String tenantId, String scope, String scopeKey) {
return tenantId + "-default";
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -254,4 +254,58 @@ public void testExitPlanModelWithExpression() {
assertCaseInstanceEnded(caseInstance);
}

@Test
@CmmnDeployment(resources = {"org/flowable/cmmn/test/runtime/ExitCriteriaTest.testStageExitCriteriaWithCondition.cmmn", "org/flowable/cmmn/test/runtime/dummyCase.cmmn"})
public void testStageExitCriteriaWithConditionNotTriggering() {
CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder().caseDefinitionKey("conditionStage").start();
UserEventListenerInstance userInstance = cmmnRuntimeService.createUserEventListenerInstanceQuery().caseInstanceId(caseInstance.getId()).planItemDefinitionId("triggerDummyCase").singleResult();
cmmnRuntimeService.completeUserEventListenerInstance(userInstance.getId());

assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().caseInstanceId(caseInstance.getId()).planItemDefinitionId("dummyCase").planItemInstanceStateActive().count()).isEqualTo(1);
assertThat(cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).taskDefinitionKey("humanTask2").count()).isEqualTo(1);

Task task = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).taskDefinitionKey("closeStage").singleResult();
cmmnTaskService.complete(task.getId());

assertThat(cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).taskDefinitionKey("humanTask2").count()).isEqualTo(1);

CaseInstance dummyCaseInstance = cmmnRuntimeService.createCaseInstanceQuery().caseInstanceParentId(caseInstance.getId()).singleResult();
task = cmmnTaskService.createTaskQuery().caseInstanceId(dummyCaseInstance.getId()).singleResult();
cmmnTaskService.complete(task.getId());

assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().caseInstanceId(caseInstance.getId()).planItemDefinitionId("dummyCase").planItemInstanceStateActive().count()).isEqualTo(0);

task = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).taskDefinitionKey("humanTask2").singleResult();
cmmnTaskService.complete(task.getId());

PlanItemInstance stagePlanItemInstance = cmmnRuntimeService.createPlanItemInstanceQuery().caseInstanceId(caseInstance.getId()).planItemDefinitionId("referenceStage").singleResult();
cmmnRuntimeService.completeStagePlanItemInstance(stagePlanItemInstance.getId());

assertCaseInstanceEnded(caseInstance);
}

@Test
@CmmnDeployment(resources = {"org/flowable/cmmn/test/runtime/ExitCriteriaTest.testStageExitCriteriaWithCondition.cmmn", "org/flowable/cmmn/test/runtime/dummyCase.cmmn"})
public void testStageExitCriteriaWithConditionTriggering() {
CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder().caseDefinitionKey("conditionStage").start();
UserEventListenerInstance userInstance = cmmnRuntimeService.createUserEventListenerInstanceQuery().caseInstanceId(caseInstance.getId()).planItemDefinitionId("triggerDummyCase").singleResult();
cmmnRuntimeService.completeUserEventListenerInstance(userInstance.getId());

CaseInstance dummyCaseInstance = cmmnRuntimeService.createCaseInstanceQuery().caseInstanceParentId(caseInstance.getId()).singleResult();
Task task = cmmnTaskService.createTaskQuery().caseInstanceId(dummyCaseInstance.getId()).singleResult();
cmmnTaskService.complete(task.getId());

assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().caseInstanceId(caseInstance.getId()).planItemDefinitionId("dummyCase").planItemInstanceStateActive().count()).isEqualTo(0);
assertThat(cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).taskDefinitionKey("humanTask2").count()).isEqualTo(1);

task = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).taskDefinitionKey("closeStage").singleResult();
cmmnTaskService.complete(task.getId());

assertThat(cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).taskDefinitionKey("humanTask2").count()).isEqualTo(0);

PlanItemInstance stagePlanItemInstance = cmmnRuntimeService.createPlanItemInstanceQuery().caseInstanceId(caseInstance.getId()).planItemDefinitionId("referenceStage").singleResult();
cmmnRuntimeService.completeStagePlanItemInstance(stagePlanItemInstance.getId());

assertCaseInstanceEnded(caseInstance);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/CMMN/20151109/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:flowable="http://flowable.org/cmmn" xmlns:cmmndi="http://www.omg.org/spec/CMMN/20151109/CMMNDI" xmlns:dc="http://www.omg.org/spec/CMMN/20151109/DC" xmlns:di="http://www.omg.org/spec/CMMN/20151109/DI" xmlns:design="http://flowable.org/design" targetNamespace="http://flowable.org/cmmn">
<case id="conditionStage" flowable:initiatorVariableName="initiator">
<casePlanModel id="onecaseplanmodel1" name="Case plan model">
<planItem id="planItemreferenceStage" name="Reference stage" definitionRef="referenceStage"></planItem>
<planItem id="planItemstageToBeClosedConditionally" name="Stage to be closed conditionally" definitionRef="stageToBeClosedConditionally">
<exitCriterion id="exitCriterion1" sentryRef="sentryexitCriterion1"></exitCriterion>
</planItem>
<sentry id="sentryexitCriterion1" flowable:triggerMode="onEvent">
<extensionElements>
<design:stencilid><![CDATA[ExitCriterion]]></design:stencilid>
</extensionElements>
<planItemOnPart id="sentryOnPartexitCriterion1" sourceRef="planItemcloseStage">
<standardEvent>complete</standardEvent>
</planItemOnPart>
<ifPart id="sentryIfPart_exitCriterion1">
<condition><![CDATA[${cmmnEngineConfiguration.getCmmnRuntimeService().createPlanItemInstanceQuery().caseInstanceId(planItemInstance.caseInstanceId).planItemDefinitionId('dummyCase').planItemInstanceStateActive().count() == 0}]]></condition>
</ifPart>
</sentry>
<stage id="referenceStage" name="Reference stage" flowable:includeInStageOverview="true">
<extensionElements>
<design:stencilid><![CDATA[ExpandedStage]]></design:stencilid>
</extensionElements>
<planItem id="planItemdummyCase" name="Dummy case" definitionRef="dummyCase">
<itemControl>
<repetitionRule flowable:counterVariable="repetitionCounter">
<extensionElements></extensionElements>
</repetitionRule>
</itemControl>
<entryCriterion id="entryCriterion1" sentryRef="sentryentryCriterion1"></entryCriterion>
</planItem>
<planItem id="planItemtriggerDummyCase" name="Trigger dummy case" definitionRef="triggerDummyCase">
<itemControl>
<repetitionRule flowable:counterVariable="repetitionCounter">
<extensionElements></extensionElements>
</repetitionRule>
</itemControl>
</planItem>
<sentry id="sentryentryCriterion1">
<extensionElements>
<design:stencilid><![CDATA[EntryCriterion]]></design:stencilid>
</extensionElements>
<planItemOnPart id="sentryOnPartentryCriterion1" sourceRef="planItemtriggerDummyCase">
<standardEvent>occur</standardEvent>
</planItemOnPart>
</sentry>
<caseTask id="dummyCase" name="Dummy case" flowable:fallbackToDefaultTenant="true" flowable:sameDeployment="true">
<caseRefExpression><![CDATA[dummyCase]]></caseRefExpression>
</caseTask>
<userEventListener id="triggerDummyCase" name="Trigger dummy case" />
</stage>
<stage id="stageToBeClosedConditionally" name="Stage to be closed conditionally" flowable:includeInStageOverview="true">
<extensionElements>
<design:stencilid><![CDATA[ExpandedStage]]></design:stencilid>
</extensionElements>
<planItem id="planItemcloseStage" name="Close stage" definitionRef="closeStage"></planItem>
<planItem id="planItemhumanTask2" name="Human task" definitionRef="humanTask2"></planItem>
<sentry id="sentryentryCriterion2">
<extensionElements>
<design:stencilid><![CDATA[EntryCriterion]]></design:stencilid>
</extensionElements>
<planItemOnPart id="sentryOnPartentryCriterion2" sourceRef="planItemcloseStage">
<standardEvent>complete</standardEvent>
</planItemOnPart>
</sentry>
<humanTask id="closeStage" name="Close stage" flowable:assignee="${initiator}" />
<humanTask id="humanTask2" name="Human task" flowable:assignee="${initiator}" />
</stage>
</casePlanModel>
</case>
</definitions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/CMMN/20151109/MODEL"
xmlns:dc="http://www.omg.org/spec/CMMN/20151109/DC"
xmlns:di="http://www.omg.org/spec/CMMN/20151109/DI"
xmlns:cmmndi="http://www.omg.org/spec/CMMN/20151109/CMMNDI"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
targetNamespace="http://flowable.org/cmmn">

<case id="dummyCase" name="Dummy Case">
<casePlanModel id="myPlanModel" name="My CasePlanModel">
<planItem id="planItemcompleteDummyCase" name="Complete dummy case" definitionRef="completeDummyCase" />
<humanTask id="completeDummyCase" name="Complete dummy case" />
</casePlanModel>
</case>

</definitions>
Original file line number Diff line number Diff line change
Expand Up @@ -147,14 +147,14 @@ public void testGetCaseInstances() throws Exception {
url = CmmnRestUrls.createRelativeResourceUrl(CmmnRestUrls.URL_CASE_INSTANCE_COLLECTION) + "?startedBefore=" + getISODateString(futureCal.getTime());
assertResultsPresentInDataResponse(url, id);

url = CmmnRestUrls.createRelativeResourceUrl(CmmnRestUrls.URL_CASE_INSTANCE_COLLECTION) + "?startedBefore=" + getISODateString(historicCal.getTime());;
url = CmmnRestUrls.createRelativeResourceUrl(CmmnRestUrls.URL_CASE_INSTANCE_COLLECTION) + "?startedBefore=" + getISODateString(historicCal.getTime());
assertResultsPresentInDataResponse(url);

// Case instance started after
url = CmmnRestUrls.createRelativeResourceUrl(CmmnRestUrls.URL_CASE_INSTANCE_COLLECTION) + "?startedAfter=" + getISODateString(historicCal.getTime());;
url = CmmnRestUrls.createRelativeResourceUrl(CmmnRestUrls.URL_CASE_INSTANCE_COLLECTION) + "?startedAfter=" + getISODateString(historicCal.getTime());
assertResultsPresentInDataResponse(url, id);

url = CmmnRestUrls.createRelativeResourceUrl(CmmnRestUrls.URL_CASE_INSTANCE_COLLECTION) + "?startedAfter=" + getISODateString(futureCal.getTime());;
url = CmmnRestUrls.createRelativeResourceUrl(CmmnRestUrls.URL_CASE_INSTANCE_COLLECTION) + "?startedAfter=" + getISODateString(futureCal.getTime());
assertResultsPresentInDataResponse(url);

// Case instance state
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
*/
public abstract class AbstractVariableComparatorExpressionFunction extends AbstractFlowableVariableExpressionFunction {

protected enum OPERATOR { LT, LTE, GT, GTE, EQ };
protected enum OPERATOR { LT, LTE, GT, GTE, EQ }

public AbstractVariableComparatorExpressionFunction(List<String> functionNameOptions, String functionName) {
super(functionNameOptions, functionName);
Expand Down
Loading

0 comments on commit c44f9a2

Please sign in to comment.