Skip to content

Commit

Permalink
Merge branch 'main' of github.com:flowable/flowable-engine into flowa…
Browse files Browse the repository at this point in the history
…ble-release-7.1.0
  • Loading branch information
tijsrademakers committed Feb 9, 2024
2 parents 6e894c1 + 98fde0c commit 3b11213
Show file tree
Hide file tree
Showing 67 changed files with 1,969 additions and 20 deletions.
33 changes: 33 additions & 0 deletions .github/workflows/graal-native.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Flowable Graal Build

on:
push:
branches:
- main
- 'flowable-release-*'

env:
MAVEN_ARGS: >-
-B -V --no-transfer-progress
-Dhttp.keepAlive=false -Dmaven.wagon.http.pool=false -Dmaven.wagon.httpconnectionManager.ttlSeconds=120
jobs:
test_graal:
name: Linux Graal Native
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: graalvm/setup-graalvm@v1
with:
java-version: 17
distribution: graalvm
- name: Cache Maven Repository
uses: actions/cache@v3
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Install
run: ./mvnw install -Pdistro ${MAVEN_ARGS} -DskipTests=true -Dmaven.javadoc.skip=true
- name: Test
run: ./mvnw test -PnativeTest,native,distro,errorLogging ${MAVEN_ARGS} -Dmaven.test.redirectTestOutputToFile=false -pl modules/flowable-spring-boot/flowable-spring-boot-samples/flowable-spring-boot-sample-native
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.flowable.app.engine.impl.aot;

import org.flowable.common.engine.impl.aot.FlowableMyBatisResourceHintsRegistrar;
import org.springframework.aot.hint.ResourceHints;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;

/**
* @author Filip Hrisafov
*/
public class FlowableAppRuntimeHints implements RuntimeHintsRegistrar {

@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
ResourceHints resourceHints = hints.resources();
resourceHints.registerPattern("org/flowable/app/db/liquibase/flowable-app-db-changelog.xml");
FlowableMyBatisResourceHintsRegistrar.registerMappingResources("org/flowable/app/db/mapping", hints, classLoader);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
org.springframework.aot.hint.RuntimeHintsRegistrar=\
org.flowable.app.engine.impl.aot.FlowableAppRuntimeHints
3 changes: 3 additions & 0 deletions modules/flowable-batch-service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@
<flowable.osgi.export.additional>
org.flowable.batch.service.db.mapping.entity
</flowable.osgi.export.additional>
<flowable.osgi.import.additional>
org.springframework*;resolution:=optional
</flowable.osgi.import.additional>
</properties>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.flowable.batch.service.impl.aot;

import org.flowable.common.engine.impl.aot.FlowableSqlResourceHintsRegistrar;
import org.springframework.aot.hint.ResourceHints;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;

/**
* @author Filip Hrisafov
*/
public class FlowableBatchServiceRuntimeHints implements RuntimeHintsRegistrar {

@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
ResourceHints resourceHints = hints.resources();
FlowableSqlResourceHintsRegistrar.registerSqlResources("org/flowable/batch/service/db", resourceHints);

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
org.springframework.aot.hint.RuntimeHintsRegistrar=\
org.flowable.batch.service.impl.aot.FlowableBatchServiceRuntimeHints
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,12 @@ public void run() {
if (changeTypeValue.equals(variableListenerData.getChangeType()) || VariableListenerEventDefinition.CHANGE_TYPE_ALL.equals(changeTypeValue) ||
(VariableListenerEventDefinition.CHANGE_TYPE_UPDATE_CREATE.equals(changeTypeValue) &&
(VariableListenerEventDefinition.CHANGE_TYPE_CREATE.equals(variableListenerData.getChangeType()) || VariableListenerEventDefinition.CHANGE_TYPE_UPDATE.equals(variableListenerData.getChangeType())))) {

itVariableListener.remove();
CommandContextUtil.getAgenda().planTriggerPlanItemInstanceOperation(planItemInstance);
triggeredPlanItemInstance = true;

if (!variableListenerData.containsProcessedElementId(planItemInstance.getPlanItemDefinitionId())) {
CommandContextUtil.getAgenda().planTriggerPlanItemInstanceOperation(planItemInstance);
triggeredPlanItemInstance = true;
variableListenerData.addProcessedElementId(planItemInstance.getPlanItemDefinitionId());
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.flowable.cmmn.engine.impl.aot;

import org.flowable.common.engine.impl.aot.FlowableMyBatisResourceHintsRegistrar;
import org.flowable.variable.service.impl.QueryVariableValue;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.ResourceHints;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;

/**
* @author Filip Hrisafov
*/
public class FlowableCmmnRuntimeHints implements RuntimeHintsRegistrar {

@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
ResourceHints resourceHints = hints.resources();
FlowableMyBatisResourceHintsRegistrar.registerMappingResources("org/flowable/cmmn/db/mapping", hints, classLoader);
resourceHints.registerPattern("org/flowable/cmmn/db/liquibase/flowable-cmmn-db-changelog.xml");
resourceHints.registerPattern("org/flowable/cmmn/db/liquibase/flowable-cmmn-db-changelog-crdb.xml");
resourceHints.registerPattern("org/flowable/impl/cmmn/parser/*.xsd");

hints.reflection()
.registerType(QueryVariableValue.class, MemberCategory.INVOKE_PUBLIC_METHODS);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.flowable.cmmn.model.CmmnModel;
import org.flowable.common.engine.api.repository.EngineDeployment;
import org.flowable.common.engine.impl.util.IoUtil;
import org.flowable.common.engine.impl.util.NativeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -74,11 +75,15 @@ protected CmmnResourceEntity createResourceEntity() {
}

public boolean shouldCreateDiagram(CaseDefinitionEntity caseDefinition, EngineDeployment deployment) {
if (NativeUtil.inNativeImage()) {
// Do not create diagram in native image
return false;
}
if (deployment.isNew() && caseDefinition.hasGraphicalNotation()
&& CommandContextUtil.getCmmnEngineConfiguration().isCreateDiagramOnDeploy()) {

// If the 'getProcessDiagramResourceNameFromDeployment' call returns null, it means
// no diagram image for the process definition was provided in the deployment resources.
// no diagram image for the case definition was provided in the deployment resources.
return ResourceNameUtil.getCaseDiagramResourceNameFromDeployment(caseDefinition, deployment.getResources()) == null;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
org.springframework.aot.hint.RuntimeHintsRegistrar=\
org.flowable.cmmn.engine.impl.aot.FlowableCmmnRuntimeHints
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,74 @@ public void testTriggerVariableEventListenerInStageOnlyCreate() {

assertCaseInstanceEnded(caseInstance);
}

@Test
@CmmnDeployment
public void testTriggerMultipleVariableEventListeners() {
CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder().caseDefinitionKey("variableListener").start();

// 5 plan items reachable
assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().count()).isEqualTo(5);
assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().list())
.extracting(PlanItemInstance::getPlanItemDefinitionType, PlanItemInstance::getPlanItemDefinitionId, PlanItemInstance::getState)
.containsExactlyInAnyOrder(
tuple(PlanItemDefinitionType.VARIABLE_EVENT_LISTENER, "variableEventListener", PlanItemInstanceState.AVAILABLE),
tuple(PlanItemDefinitionType.VARIABLE_EVENT_LISTENER, "variableEventListener2", PlanItemInstanceState.AVAILABLE),
tuple(PlanItemDefinitionType.HUMAN_TASK, "taskA", PlanItemInstanceState.ACTIVE),
tuple(PlanItemDefinitionType.HUMAN_TASK, "taskB", PlanItemInstanceState.AVAILABLE),
tuple(PlanItemDefinitionType.HUMAN_TASK, "taskC", PlanItemInstanceState.AVAILABLE)
);

if (CmmnHistoryTestHelper.isHistoryLevelAtLeast(HistoryLevel.ACTIVITY, cmmnEngineConfiguration)) {
assertThat(cmmnHistoryService.createHistoricPlanItemInstanceQuery().list())
.extracting(HistoricPlanItemInstance::getPlanItemDefinitionType, HistoricPlanItemInstance::getPlanItemDefinitionId, HistoricPlanItemInstance::getState)
.containsExactlyInAnyOrder(
tuple(PlanItemDefinitionType.VARIABLE_EVENT_LISTENER, "variableEventListener", PlanItemInstanceState.AVAILABLE),
tuple(PlanItemDefinitionType.VARIABLE_EVENT_LISTENER, "variableEventListener2", PlanItemInstanceState.AVAILABLE),
tuple(PlanItemDefinitionType.HUMAN_TASK, "taskA", PlanItemInstanceState.ACTIVE),
tuple(PlanItemDefinitionType.HUMAN_TASK, "taskB", PlanItemInstanceState.AVAILABLE),
tuple(PlanItemDefinitionType.HUMAN_TASK, "taskC", PlanItemInstanceState.AVAILABLE)
);
}

// create different variable
cmmnRuntimeService.setVariable(caseInstance.getId(), "var2", "test");

assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemDefinitionType(PlanItemDefinitionType.VARIABLE_EVENT_LISTENER).count()).isEqualTo(2);

// create var1 variable to trigger variable event listener
cmmnRuntimeService.setVariable(caseInstance.getId(), "var1", "test");

// variable event listener should be completed
assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemDefinitionType(PlanItemDefinitionType.VARIABLE_EVENT_LISTENER).count()).isZero();
assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().list())
.extracting(PlanItemInstance::getPlanItemDefinitionType, PlanItemInstance::getPlanItemDefinitionId, PlanItemInstance::getState)
.containsExactlyInAnyOrder(
tuple(PlanItemDefinitionType.HUMAN_TASK, "taskA", PlanItemInstanceState.ACTIVE),
tuple(PlanItemDefinitionType.HUMAN_TASK, "taskB", PlanItemInstanceState.ACTIVE),
tuple(PlanItemDefinitionType.HUMAN_TASK, "taskC", PlanItemInstanceState.ACTIVE)
);

assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemDefinitionId("taskB").planItemInstanceStateActive().count()).isEqualTo(1);
assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemDefinitionId("taskC").planItemInstanceStateActive().count()).isEqualTo(1);

if (CmmnHistoryTestHelper.isHistoryLevelAtLeast(HistoryLevel.ACTIVITY, cmmnEngineConfiguration)) {
assertThat(cmmnHistoryService.createHistoricPlanItemInstanceQuery().list())
.extracting(HistoricPlanItemInstance::getPlanItemDefinitionType, HistoricPlanItemInstance::getPlanItemDefinitionId, HistoricPlanItemInstance::getState)
.containsExactlyInAnyOrder(
tuple(PlanItemDefinitionType.VARIABLE_EVENT_LISTENER, "variableEventListener", PlanItemInstanceState.COMPLETED),
tuple(PlanItemDefinitionType.VARIABLE_EVENT_LISTENER, "variableEventListener2", PlanItemInstanceState.COMPLETED),
tuple(PlanItemDefinitionType.HUMAN_TASK, "taskA", PlanItemInstanceState.ACTIVE),
tuple(PlanItemDefinitionType.HUMAN_TASK, "taskB", PlanItemInstanceState.ACTIVE),
tuple(PlanItemDefinitionType.HUMAN_TASK, "taskC", PlanItemInstanceState.ACTIVE)
);
}


assertCaseInstanceNotEnded(caseInstance);
cmmnTaskService.createTaskQuery().list().forEach(t -> cmmnTaskService.complete(t.getId()));
assertCaseInstanceEnded(caseInstance);
}

@Test
@CmmnDeployment
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/CMMN/20151109/MODEL"
xmlns:flowable="http://flowable.org/cmmn"
targetNamespace="http://flowable.org/cmmn">
<case id="variableListener" name="Variable listener">
<casePlanModel id="casePlanModel">
<planItem id="planItemA" name="A" definitionRef="taskA"/>
<planItem id="variableEventListenerPlanItem" definitionRef="variableEventListener"/>
<planItem id="planItemB" name="B" definitionRef="taskB">
<entryCriterion id="entryTaskB" sentryRef="sentryOnVariableEventListener"/>
</planItem>
<planItem id="variableEventListenerPlanItem2" definitionRef="variableEventListener2"/>
<planItem id="planItemC" name="C" definitionRef="taskC">
<entryCriterion id="entryTaskC" sentryRef="sentryOnVariableEventListener2"/>
</planItem>
<sentry id="sentryOnVariableEventListener">
<planItemOnPart id="sentryOnvariableEvent" sourceRef="variableEventListenerPlanItem">
<standardEvent>occur</standardEvent>
</planItemOnPart>
</sentry>
<sentry id="sentryOnVariableEventListener2">
<planItemOnPart id="sentryOnvariableEvent2" sourceRef="variableEventListenerPlanItem2">
<standardEvent>occur</standardEvent>
</planItemOnPart>
</sentry>
<humanTask id="taskA" name="A"/>
<eventListener id="variableEventListener" flowable:eventType="variable" flowable:variableName="var1" />
<humanTask id="taskB" name="B"/>
<eventListener id="variableEventListener2" flowable:eventType="variable" flowable:variableName="var1" />
<humanTask id="taskC" name="C"/>
</casePlanModel>
</case>
</definitions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.flowable.dmn.engine.impl.aot;

import org.flowable.common.engine.impl.aot.FlowableMyBatisResourceHintsRegistrar;
import org.springframework.aot.hint.ResourceHints;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;

/**
* @author Filip Hrisafov
*/
public class FlowableDmnRuntimeHints implements RuntimeHintsRegistrar {

@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
ResourceHints resourceHints = hints.resources();
FlowableMyBatisResourceHintsRegistrar.registerMappingResources("org/flowable/dmn/db/mapping", hints, classLoader);
resourceHints.registerPattern("org/flowable/dmn/db/liquibase/flowable-dmn-db-changelog.xml");
resourceHints.registerPattern("org/flowable/impl/dmn/parser/*.xsd");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
org.springframework.aot.hint.RuntimeHintsRegistrar=\
org.flowable.dmn.engine.impl.aot.FlowableDmnRuntimeHints
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.flowable.common.engine.impl.aot;

import org.flowable.common.engine.impl.persistence.entity.ByteArrayRefTypeHandler;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.ResourceHints;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;

/**
* @author Filip Hrisafov
*/
public class FlowableCommonRuntimeHints implements RuntimeHintsRegistrar {

@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
ResourceHints resourceHints = hints.resources();
resourceHints.registerPattern("META-INF/services/liquibase.hub.HubService");
resourceHints.registerPattern("META-INF/services/liquibase.license.LicenseService");
resourceHints.registerResourceBundle("org.flowable.common.engine.impl.de.odysseus.el.misc.LocalStrings");
// If we can detect which DB is being used we can perhaps register only the appropriate DB file
resourceHints.registerPattern("org/flowable/common/db/properties/*.properties");
FlowableSqlResourceHintsRegistrar.registerSqlResources("org/flowable/common/db", resourceHints);

hints.reflection()
.registerType(ByteArrayRefTypeHandler.class, MemberCategory.values());
}
}
Loading

0 comments on commit 3b11213

Please sign in to comment.