Skip to content

Commit c8fba81

Browse files
Add definition variable container to support EL Resolvers to use the definition during deployment
1 parent d28e3ee commit c8fba81

12 files changed

Lines changed: 516 additions & 111 deletions
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/* Licensed under the Apache License, Version 2.0 (the "License");
2+
* you may not use this file except in compliance with the License.
3+
* You may obtain a copy of the License at
4+
*
5+
* http://www.apache.org/licenses/LICENSE-2.0
6+
*
7+
* Unless required by applicable law or agreed to in writing, software
8+
* distributed under the License is distributed on an "AS IS" BASIS,
9+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
* See the License for the specific language governing permissions and
11+
* limitations under the License.
12+
*/
13+
package org.flowable.common.engine.impl.el;
14+
15+
import java.util.Set;
16+
17+
import org.flowable.common.engine.api.variable.VariableContainer;
18+
19+
/**
20+
* A {@link VariableContainer} that carries definition context (definitionId, definitionKey, deploymentId, scopeType, tenantId)
21+
* for expression evaluation when no execution is active (e.g. during deployment).
22+
* This allows EL resolvers to look up the parent deployment and resolve definition-scoped expressions.
23+
*
24+
* @author Christopher Welsch
25+
*/
26+
public class DefinitionVariableContainer implements VariableContainer {
27+
28+
protected String definitionId;
29+
protected String definitionKey;
30+
protected String deploymentId;
31+
protected String scopeType;
32+
protected String tenantId;
33+
34+
public DefinitionVariableContainer(String definitionId, String definitionKey, String deploymentId, String scopeType, String tenantId) {
35+
this.definitionId = definitionId;
36+
this.definitionKey = definitionKey;
37+
this.deploymentId = deploymentId;
38+
this.scopeType = scopeType;
39+
this.tenantId = tenantId;
40+
}
41+
42+
public String getDefinitionId() {
43+
return definitionId;
44+
}
45+
46+
public String getDefinitionKey() {
47+
return definitionKey;
48+
}
49+
50+
public String getDeploymentId() {
51+
return deploymentId;
52+
}
53+
54+
public String getScopeType() {
55+
return scopeType;
56+
}
57+
58+
@Override
59+
public String getTenantId() {
60+
return tenantId;
61+
}
62+
63+
@Override
64+
public boolean hasVariable(String variableName) {
65+
return false;
66+
}
67+
68+
@Override
69+
public Object getVariable(String variableName) {
70+
return null;
71+
}
72+
73+
@Override
74+
public void setVariable(String variableName, Object variableValue) {
75+
76+
}
77+
78+
@Override
79+
public void setTransientVariable(String variableName, Object variableValue) {
80+
81+
}
82+
83+
@Override
84+
public Set<String> getVariableNames() {
85+
return Set.of();
86+
}
87+
}

modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/deployer/EventSubscriptionManager.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import org.flowable.eventsubscription.service.impl.persistence.entity.EventSubscriptionEntity;
4646
import org.flowable.eventsubscription.service.impl.persistence.entity.MessageEventSubscriptionEntity;
4747
import org.flowable.eventsubscription.service.impl.persistence.entity.SignalEventSubscriptionEntity;
48+
import org.flowable.common.engine.impl.el.DefinitionVariableContainer;
4849

4950
/**
5051
* Manages event subscriptions for newly-deployed process definitions and their previous versions.
@@ -173,7 +174,7 @@ protected void insertSignalEvent(SignalEventDefinition signalEventDefinition, St
173174
EventSubscriptionService eventSubscriptionService = processEngineConfiguration.getEventSubscriptionServiceConfiguration().getEventSubscriptionService();
174175
SignalEventSubscriptionEntity subscriptionEntity = eventSubscriptionService.createSignalEventSubscription();
175176

176-
String signalName = EventDefinitionExpressionUtil.determineSignalName(commandContext, signalEventDefinition, bpmnModel,null);
177+
String signalName = EventDefinitionExpressionUtil.determineSignalName(commandContext, signalEventDefinition, bpmnModel, processDefinition);
177178
subscriptionEntity.setEventName(signalName);
178179

179180
subscriptionEntity.setActivityId(startEvent.getId());
@@ -191,8 +192,9 @@ protected void insertMessageEvent(MessageEventDefinition messageEventDefinition,
191192

192193
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
193194
EventSubscriptionService eventSubscriptionService = processEngineConfiguration.getEventSubscriptionServiceConfiguration().getEventSubscriptionService();
195+
194196
// look for subscriptions for the same name in db:
195-
String messageName = EventDefinitionExpressionUtil.determineMessageName(commandContext, messageEventDefinition, null);
197+
String messageName = EventDefinitionExpressionUtil.determineMessageName(commandContext, messageEventDefinition, processDefinition);
196198
List<EventSubscriptionEntity> subscriptionsForSameMessageName = eventSubscriptionService
197199
.findEventSubscriptionsByName(MessageEventHandler.EVENT_HANDLER_TYPE, messageName, processDefinition.getTenantId());
198200

modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/deployer/TimerManager.java

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -73,18 +73,12 @@ protected List<TimerJobEntity> getTimerDeclarations(ProcessDefinitionEntity proc
7373
if (CollectionUtil.isNotEmpty(startEvent.getEventDefinitions())) {
7474
EventDefinition eventDefinition = startEvent.getEventDefinitions().get(0);
7575
if (eventDefinition instanceof TimerEventDefinition timerEventDefinition) {
76+
7677
TimerJobEntity timerJob = TimerUtil.createTimerEntityForTimerEventDefinition(timerEventDefinition, startEvent,
77-
false, null, TimerStartEventJobHandler.TYPE, TimerEventHandler.createConfiguration(startEvent.getId(),
78+
false, processDefinition, TimerStartEventJobHandler.TYPE, TimerEventHandler.createConfiguration(startEvent.getId(),
7879
timerEventDefinition.getEndDate(), timerEventDefinition.getCalendarName()));
7980

80-
if (timerJob != null) {
81-
timerJob.setProcessDefinitionId(processDefinition.getId());
82-
83-
if (processDefinition.getTenantId() != null) {
84-
timerJob.setTenantId(processDefinition.getTenantId());
85-
}
86-
timers.add(timerJob);
87-
}
81+
timers.add(timerJob);
8882

8983
}
9084
}

modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/AbstractDynamicStateManager.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import org.flowable.bpmn.model.UserTask;
5656
import org.flowable.bpmn.model.ValuedDataObject;
5757
import org.flowable.common.engine.api.FlowableException;
58+
import org.flowable.common.engine.impl.el.DefinitionVariableContainer;
5859
import org.flowable.common.engine.api.delegate.Expression;
5960
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
6061
import org.flowable.common.engine.api.delegate.event.FlowableEventDispatcher;
@@ -1585,7 +1586,10 @@ protected void processCreatedEventSubProcess(EventSubProcess eventSubProcess, Ex
15851586
messageExecution.setEventScope(true);
15861587
messageExecution.setActive(false);
15871588

1588-
String messageName = EventDefinitionExpressionUtil.determineMessageName(commandContext, messageEventDefinition, null);
1589+
DefinitionVariableContainer definitionVariableContainer = new DefinitionVariableContainer(messageExecution.getProcessDefinitionId(),
1590+
messageExecution.getProcessDefinitionKey(), eventSubProcessExecution.getDeploymentId(), ScopeTypes.BPMN, messageExecution.getTenantId());
1591+
1592+
String messageName = EventDefinitionExpressionUtil.determineMessageName(commandContext, messageEventDefinition, definitionVariableContainer);
15891593
EventSubscriptionEntity messageSubscription = (EventSubscriptionEntity) eventSubscriptionService.createEventSubscriptionBuilder()
15901594
.eventType(MessageEventSubscriptionEntity.EVENT_TYPE)
15911595
.eventName(messageName)
@@ -1618,7 +1622,9 @@ protected void processCreatedEventSubProcess(EventSubProcess eventSubProcess, Ex
16181622
signalExecution.setEventScope(true);
16191623
signalExecution.setActive(false);
16201624

1621-
String eventName = EventDefinitionExpressionUtil.determineSignalName(commandContext, signalEventDefinition, bpmnModel, null);
1625+
DefinitionVariableContainer signalDefinitionVariableContainer = new DefinitionVariableContainer(signalExecution.getProcessDefinitionId(),
1626+
signalExecution.getProcessDefinitionKey(), eventSubProcessExecution.getDeploymentId(), ScopeTypes.BPMN, signalExecution.getTenantId());
1627+
String eventName = EventDefinitionExpressionUtil.determineSignalName(commandContext, signalEventDefinition, bpmnModel, signalDefinitionVariableContainer);
16221628

16231629
EventSubscriptionEntity signalSubscription = (EventSubscriptionEntity) eventSubscriptionService.createEventSubscriptionBuilder()
16241630
.eventType(SignalEventSubscriptionEntity.EVENT_TYPE)

modules/flowable-engine/src/main/java/org/flowable/engine/impl/event/EventDefinitionExpressionUtil.java

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,12 @@
1818
import org.flowable.bpmn.model.Signal;
1919
import org.flowable.bpmn.model.SignalEventDefinition;
2020
import org.flowable.common.engine.api.delegate.Expression;
21+
import org.flowable.common.engine.api.scope.ScopeTypes;
22+
import org.flowable.common.engine.api.variable.VariableContainer;
23+
import org.flowable.common.engine.impl.el.DefinitionVariableContainer;
2124
import org.flowable.common.engine.impl.interceptor.CommandContext;
22-
import org.flowable.engine.delegate.DelegateExecution;
2325
import org.flowable.engine.impl.util.CommandContextUtil;
26+
import org.flowable.engine.repository.ProcessDefinition;
2427
import org.flowable.variable.service.impl.el.NoExecutionVariableScope;
2528

2629
/**
@@ -34,7 +37,23 @@ public class EventDefinitionExpressionUtil {
3437
* - otherwise, the signal ref is used
3538
* - unless a signalExpression is set
3639
*/
37-
public static String determineSignalName(CommandContext commandContext, SignalEventDefinition signalEventDefinition, BpmnModel bpmnModel, DelegateExecution execution) {
40+
public static String determineSignalName(CommandContext commandContext, SignalEventDefinition signalEventDefinition,
41+
BpmnModel bpmnModel, ProcessDefinition processDefinition) {
42+
43+
DefinitionVariableContainer definitionVariableContainer = new DefinitionVariableContainer(processDefinition.getId(),
44+
processDefinition.getKey(), processDefinition.getDeploymentId(), ScopeTypes.BPMN, processDefinition.getTenantId());
45+
46+
return determineSignalName(commandContext, signalEventDefinition, bpmnModel, definitionVariableContainer);
47+
}
48+
49+
/**
50+
* Determines the signal name of the {@link SignalEventDefinition} that is passed:
51+
* - if a signal name is set, it has precedence
52+
* - otherwise, the signal ref is used
53+
* - unless a signalExpression is set
54+
*/
55+
public static String determineSignalName(CommandContext commandContext, SignalEventDefinition signalEventDefinition,
56+
BpmnModel bpmnModel, VariableContainer variableContainer) {
3857
String signalName = null;
3958
if (StringUtils.isNotEmpty(signalEventDefinition.getSignalRef())) {
4059
Signal signal = bpmnModel.getSignal(signalEventDefinition.getSignalRef());
@@ -51,12 +70,28 @@ public static String determineSignalName(CommandContext commandContext, SignalEv
5170

5271
if (StringUtils.isNotEmpty(signalName)) {
5372
Expression expression = CommandContextUtil.getProcessEngineConfiguration(commandContext).getExpressionManager().createExpression(signalName);
54-
return expression.getValue(execution != null ? execution : NoExecutionVariableScope.getSharedInstance()).toString();
73+
return expression.getValue(variableContainer != null ? variableContainer : NoExecutionVariableScope.getSharedInstance()).toString();
5574
}
5675

5776
return signalName;
5877
}
5978

79+
/**
80+
* Determines the event name of the {@link org.flowable.bpmn.model.MessageEventDefinition} that is passed:
81+
* - if a message ref is set, it has precedence
82+
* - if a messageExpression is set, it is returned
83+
* <p>
84+
* Note that, contrary to the determineSignalName method, the name of the message is never used.
85+
* This is because of historical reasons (and it can't be changed now without breaking existing models/instances)
86+
*/
87+
public static String determineMessageName(CommandContext commandContext, MessageEventDefinition messageEventDefinition,
88+
ProcessDefinition processDefinition) {
89+
90+
DefinitionVariableContainer definitionVariableContainer = new DefinitionVariableContainer(processDefinition.getId(),
91+
processDefinition.getKey(), processDefinition.getDeploymentId(), ScopeTypes.BPMN, processDefinition.getTenantId());
92+
93+
return determineMessageName(commandContext, messageEventDefinition, definitionVariableContainer);
94+
}
6095
/**
6196
* Determines the event name of the {@link org.flowable.bpmn.model.MessageEventDefinition} that is passed:
6297
* - if a message ref is set, it has precedence
@@ -65,7 +100,8 @@ public static String determineSignalName(CommandContext commandContext, SignalEv
65100
* Note that, contrary to the determineSignalName method, the name of the message is never used.
66101
* This is because of historical reasons (and it can't be changed now without breaking existing models/instances)
67102
*/
68-
public static String determineMessageName(CommandContext commandContext, MessageEventDefinition messageEventDefinition, DelegateExecution execution) {
103+
public static String determineMessageName(CommandContext commandContext, MessageEventDefinition messageEventDefinition,
104+
VariableContainer variableContainer) {
69105
String messageName = null;
70106
if (StringUtils.isNotEmpty(messageEventDefinition.getMessageRef())) {
71107
return messageEventDefinition.getMessageRef();
@@ -77,10 +113,9 @@ public static String determineMessageName(CommandContext commandContext, Message
77113

78114
if (StringUtils.isNotEmpty(messageName)) {
79115
Expression expression = CommandContextUtil.getProcessEngineConfiguration(commandContext).getExpressionManager().createExpression(messageName);
80-
return expression.getValue(execution != null ? execution : NoExecutionVariableScope.getSharedInstance()).toString();
116+
return expression.getValue(variableContainer != null ? variableContainer : NoExecutionVariableScope.getSharedInstance()).toString();
81117
}
82118

83119
return messageName;
84120
}
85-
86121
}

modules/flowable-engine/src/main/java/org/flowable/engine/impl/repository/DeploymentProcessDefinitionDeletionManagerImpl.java

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
2727
import org.flowable.common.engine.api.delegate.event.FlowableEventDispatcher;
2828
import org.flowable.common.engine.api.scope.ScopeTypes;
29+
import org.flowable.common.engine.impl.el.DefinitionVariableContainer;
2930
import org.flowable.common.engine.impl.interceptor.CommandContext;
3031
import org.flowable.common.engine.impl.util.CollectionUtil;
3132
import org.flowable.engine.ProcessEngineConfiguration;
@@ -36,6 +37,7 @@
3637
import org.flowable.engine.impl.event.EventDefinitionExpressionUtil;
3738
import org.flowable.engine.impl.jobexecutor.TimerEventHandler;
3839
import org.flowable.engine.impl.jobexecutor.TimerStartEventJobHandler;
40+
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
3941
import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntity;
4042
import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntityManager;
4143
import org.flowable.engine.impl.util.CorrelationUtil;
@@ -154,31 +156,20 @@ protected void restorePreviousStartEventsIfNeeded(ProcessDefinition processDefin
154156

155157
protected void restoreTimerStartEvent(ProcessDefinition previousProcessDefinition, StartEvent startEvent, EventDefinition eventDefinition) {
156158
TimerEventDefinition timerEventDefinition = (TimerEventDefinition) eventDefinition;
157-
TimerJobEntity timer = TimerUtil.createTimerEntityForTimerEventDefinition((TimerEventDefinition) eventDefinition, startEvent,
158-
false, null, TimerStartEventJobHandler.TYPE, TimerEventHandler.createConfiguration(startEvent.getId(),
159-
timerEventDefinition.getEndDate(), timerEventDefinition.getCalendarName()));
160-
161-
if (timer != null) {
162-
TimerJobEntity timerJob = TimerUtil.createTimerEntityForTimerEventDefinition(timerEventDefinition, startEvent,
163-
false, null, TimerStartEventJobHandler.TYPE, TimerEventHandler.createConfiguration(startEvent.getId(),
164-
timerEventDefinition.getEndDate(), timerEventDefinition.getCalendarName()));
165-
166-
timerJob.setProcessDefinitionId(previousProcessDefinition.getId());
167159

168-
if (previousProcessDefinition.getTenantId() != null) {
169-
timerJob.setTenantId(previousProcessDefinition.getTenantId());
170-
}
160+
TimerJobEntity timerJob = TimerUtil.createTimerEntityForTimerEventDefinition(timerEventDefinition, startEvent,
161+
false, previousProcessDefinition, TimerStartEventJobHandler.TYPE, TimerEventHandler.createConfiguration(startEvent.getId(),
162+
timerEventDefinition.getEndDate(), timerEventDefinition.getCalendarName()));
171163

172-
engineConfiguration.getJobServiceConfiguration().getTimerJobService().scheduleTimerJob(timerJob);
173-
}
164+
engineConfiguration.getJobServiceConfiguration().getTimerJobService().scheduleTimerJob(timerJob);
174165
}
175166

176167
protected void restoreSignalStartEvent(ProcessDefinition previousProcessDefinition, BpmnModel bpmnModel, StartEvent startEvent, EventDefinition eventDefinition) {
177168
CommandContext commandContext = Context.getCommandContext();
178169
SignalEventDefinition signalEventDefinition = (SignalEventDefinition) eventDefinition;
179170
SignalEventSubscriptionEntity subscriptionEntity = engineConfiguration.getEventSubscriptionServiceConfiguration().getEventSubscriptionService().createSignalEventSubscription();
180171

181-
String eventName = EventDefinitionExpressionUtil.determineSignalName(commandContext, signalEventDefinition, bpmnModel, null);
172+
String eventName = EventDefinitionExpressionUtil.determineSignalName(commandContext, signalEventDefinition, bpmnModel, previousProcessDefinition);
182173
subscriptionEntity.setEventName(eventName);
183174
subscriptionEntity.setActivityId(startEvent.getId());
184175
subscriptionEntity.setProcessDefinitionId(previousProcessDefinition.getId());
@@ -199,7 +190,7 @@ protected void restoreMessageStartEvent(ProcessDefinition previousProcessDefinit
199190

200191
CommandContext commandContext = Context.getCommandContext();
201192
MessageEventSubscriptionEntity newSubscription = engineConfiguration.getEventSubscriptionServiceConfiguration().getEventSubscriptionService().createMessageEventSubscription();
202-
String messageName = EventDefinitionExpressionUtil.determineMessageName(commandContext, messageEventDefinition, null);
193+
String messageName = EventDefinitionExpressionUtil.determineMessageName(commandContext, messageEventDefinition, previousProcessDefinition);
203194
newSubscription.setEventName(messageName);
204195
newSubscription.setActivityId(startEvent.getId());
205196
newSubscription.setConfiguration(previousProcessDefinition.getId());

0 commit comments

Comments
 (0)