Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright 2026, Flowable Licences AG.
* This license is based on the software license agreement and terms and conditions in effect between the parties
* at the time of purchase of the Flowable software product.
* Your agreement to these terms and conditions is required to install or use the Flowable software product and/or this file.
* Flowable is a trademark of Flowable AG registered in several countries.
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like the commercial license and not the open source Apache license.

package org.flowable.common.engine.api.definition;

import java.util.Set;

import org.flowable.common.engine.api.variable.VariableContainer;

/**
* A {@link VariableContainer} that carries definition context (definitionId, deploymentId, scopeType, tenantId)
* for expression evaluation when no execution is active (e.g. during deployment).
* This allows EL resolvers to look up the parent deployment and resolve definition-scoped expressions.
*
* @author Christopher Welsch
*/
public class DefinitionVariableContainer implements VariableContainer {

protected String definitionId;
protected String deploymentId;
protected String scopeType;
protected String tenantId;

public DefinitionVariableContainer() {
}

public DefinitionVariableContainer(String definitionId, String deploymentId, String scopeType, String tenantId) {
this.definitionId = definitionId;
this.deploymentId = deploymentId;
this.scopeType = scopeType;
this.tenantId = tenantId;
}

public String getDefinitionId() {
return definitionId;
}

public String getDeploymentId() {
return deploymentId;
}

public String getScopeType() {
return scopeType;
}

@Override
public String getTenantId() {
return tenantId;
}

@Override
public boolean hasVariable(String variableName) {
return false;
}

@Override
public Object getVariable(String variableName) {
return null;
}

@Override
public void setVariable(String variableName, Object variableValue) {

}

@Override
public void setTransientVariable(String variableName, Object variableValue) {

}

@Override
public Set<String> getVariableNames() {
return Set.of();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import org.flowable.eventsubscription.service.impl.persistence.entity.EventSubscriptionEntity;
import org.flowable.eventsubscription.service.impl.persistence.entity.MessageEventSubscriptionEntity;
import org.flowable.eventsubscription.service.impl.persistence.entity.SignalEventSubscriptionEntity;
import org.flowable.common.engine.api.definition.DefinitionVariableContainer;

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

String signalName = EventDefinitionExpressionUtil.determineSignalName(commandContext, signalEventDefinition, bpmnModel,null);
DefinitionVariableContainer definitionVariableContainer = new DefinitionVariableContainer(processDefinition.getId(), processDefinition.getDeploymentId(),
ScopeTypes.BPMN, processDefinition.getTenantId());

String signalName = EventDefinitionExpressionUtil.determineSignalName(commandContext, signalEventDefinition, bpmnModel, definitionVariableContainer);
subscriptionEntity.setEventName(signalName);

subscriptionEntity.setActivityId(startEvent.getId());
Expand All @@ -191,8 +195,12 @@ protected void insertMessageEvent(MessageEventDefinition messageEventDefinition,

ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
EventSubscriptionService eventSubscriptionService = processEngineConfiguration.getEventSubscriptionServiceConfiguration().getEventSubscriptionService();

DefinitionVariableContainer definitionVariableContainer = new DefinitionVariableContainer(processDefinition.getId(), processDefinition.getDeploymentId(),
ScopeTypes.BPMN, processDefinition.getTenantId());

// look for subscriptions for the same name in db:
String messageName = EventDefinitionExpressionUtil.determineMessageName(commandContext, messageEventDefinition, null);
String messageName = EventDefinitionExpressionUtil.determineMessageName(commandContext, messageEventDefinition, definitionVariableContainer);
List<EventSubscriptionEntity> subscriptionsForSameMessageName = eventSubscriptionService
.findEventSubscriptionsByName(MessageEventHandler.EVENT_HANDLER_TYPE, messageName, processDefinition.getTenantId());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.StartEvent;
import org.flowable.bpmn.model.TimerEventDefinition;
import org.flowable.common.engine.api.scope.ScopeTypes;
import org.flowable.common.engine.impl.context.Context;
import org.flowable.common.engine.impl.util.CollectionUtil;
import org.flowable.engine.ProcessEngineConfiguration;
Expand All @@ -32,6 +33,7 @@
import org.flowable.job.service.TimerJobService;
import org.flowable.job.service.impl.cmd.CancelJobsCmd;
import org.flowable.job.service.impl.persistence.entity.TimerJobEntity;
import org.flowable.common.engine.api.definition.DefinitionVariableContainer;

/**
* Manages timers for newly-deployed process definitions and their previous versions.
Expand Down Expand Up @@ -73,18 +75,21 @@ protected List<TimerJobEntity> getTimerDeclarations(ProcessDefinitionEntity proc
if (CollectionUtil.isNotEmpty(startEvent.getEventDefinitions())) {
EventDefinition eventDefinition = startEvent.getEventDefinitions().get(0);
if (eventDefinition instanceof TimerEventDefinition timerEventDefinition) {

DefinitionVariableContainer definitionVariableContainer = new DefinitionVariableContainer(processDefinition.getId(),
processDefinition.getDeploymentId(),
ScopeTypes.BPMN, processDefinition.getTenantId());

TimerJobEntity timerJob = TimerUtil.createTimerEntityForTimerEventDefinition(timerEventDefinition, startEvent,
false, null, TimerStartEventJobHandler.TYPE, TimerEventHandler.createConfiguration(startEvent.getId(),
false, definitionVariableContainer, TimerStartEventJobHandler.TYPE, TimerEventHandler.createConfiguration(startEvent.getId(),
timerEventDefinition.getEndDate(), timerEventDefinition.getCalendarName()));

if (timerJob != null) {
timerJob.setProcessDefinitionId(processDefinition.getId());
timerJob.setProcessDefinitionId(processDefinition.getId());

if (processDefinition.getTenantId() != null) {
timerJob.setTenantId(processDefinition.getTenantId());
}
timers.add(timerJob);
if (processDefinition.getTenantId() != null) {
timerJob.setTenantId(processDefinition.getTenantId());
}
timers.add(timerJob);

}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
import org.flowable.bpmn.model.UserTask;
import org.flowable.bpmn.model.ValuedDataObject;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.api.definition.DefinitionVariableContainer;
import org.flowable.common.engine.api.delegate.Expression;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
import org.flowable.common.engine.api.delegate.event.FlowableEventDispatcher;
Expand Down Expand Up @@ -1585,7 +1586,9 @@ protected void processCreatedEventSubProcess(EventSubProcess eventSubProcess, Ex
messageExecution.setEventScope(true);
messageExecution.setActive(false);

String messageName = EventDefinitionExpressionUtil.determineMessageName(commandContext, messageEventDefinition, null);
DefinitionVariableContainer definitionVariableContainer = new DefinitionVariableContainer(messageExecution.getProcessDefinitionId(),
eventSubProcessExecution.getDeploymentId(), ScopeTypes.BPMN, messageExecution.getTenantId());
String messageName = EventDefinitionExpressionUtil.determineMessageName(commandContext, messageEventDefinition, definitionVariableContainer);
EventSubscriptionEntity messageSubscription = (EventSubscriptionEntity) eventSubscriptionService.createEventSubscriptionBuilder()
.eventType(MessageEventSubscriptionEntity.EVENT_TYPE)
.eventName(messageName)
Expand Down Expand Up @@ -1618,7 +1621,9 @@ protected void processCreatedEventSubProcess(EventSubProcess eventSubProcess, Ex
signalExecution.setEventScope(true);
signalExecution.setActive(false);

String eventName = EventDefinitionExpressionUtil.determineSignalName(commandContext, signalEventDefinition, bpmnModel, null);
DefinitionVariableContainer signalDefinitionVariableContainer = new DefinitionVariableContainer(signalExecution.getProcessDefinitionId(),
eventSubProcessExecution.getDeploymentId(), ScopeTypes.BPMN, signalExecution.getTenantId());
String eventName = EventDefinitionExpressionUtil.determineSignalName(commandContext, signalEventDefinition, bpmnModel, signalDefinitionVariableContainer);

EventSubscriptionEntity signalSubscription = (EventSubscriptionEntity) eventSubscriptionService.createEventSubscriptionBuilder()
.eventType(SignalEventSubscriptionEntity.EVENT_TYPE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.common.engine.api.variable.VariableContainer;
import org.flowable.variable.service.impl.el.NoExecutionVariableScope;

/**
Expand Down Expand Up @@ -57,6 +58,34 @@ public static String determineSignalName(CommandContext commandContext, SignalEv
return signalName;
}

/**
* Determines signal name from definition or expression
*/
public static String determineSignalName(CommandContext commandContext, SignalEventDefinition signalEventDefinition, BpmnModel bpmnModel,
VariableContainer definitionVariableContainer) {
String signalName = null;

if (StringUtils.isNotEmpty(signalEventDefinition.getSignalRef())) {
Signal signal = bpmnModel.getSignal(signalEventDefinition.getSignalRef());
if (signal != null) {
signalName = signal.getName();
} else {
signalName = signalEventDefinition.getSignalRef();
}

} else {
signalName = signalEventDefinition.getSignalExpression();

}

if (StringUtils.isNotEmpty(signalName)) {
Expression expression = CommandContextUtil.getProcessEngineConfiguration(commandContext).getExpressionManager().createExpression(signalName);
return expression.getValue(definitionVariableContainer).toString();
}

return signalName;
}

/**
* Determines the event name of the {@link org.flowable.bpmn.model.MessageEventDefinition} that is passed:
* - if a message ref is set, it has precedence
Expand All @@ -83,4 +112,26 @@ public static String determineMessageName(CommandContext commandContext, Message
return messageName;
}

/**
* Determines message name from definition or expression
*/
public static String determineMessageName(CommandContext commandContext, MessageEventDefinition messageEventDefinition,
VariableContainer definitionVariableContainer) {
String messageName = null;

if (StringUtils.isNotEmpty(messageEventDefinition.getMessageRef())) {
return messageEventDefinition.getMessageRef();

} else {
messageName = messageEventDefinition.getMessageExpression();

}

if (StringUtils.isNotEmpty(messageName)) {
Expression expression = CommandContextUtil.getProcessEngineConfiguration(commandContext).getExpressionManager().createExpression(messageName);
return expression.getValue(definitionVariableContainer).toString();
}

return messageName;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import org.flowable.eventsubscription.service.impl.persistence.entity.SignalEventSubscriptionEntity;
import org.flowable.job.service.TimerJobService;
import org.flowable.job.service.impl.persistence.entity.TimerJobEntity;
import org.flowable.common.engine.api.definition.DefinitionVariableContainer;

/**
* @author Filip Hrisafov
Expand Down Expand Up @@ -154,13 +155,17 @@ protected void restorePreviousStartEventsIfNeeded(ProcessDefinition processDefin

protected void restoreTimerStartEvent(ProcessDefinition previousProcessDefinition, StartEvent startEvent, EventDefinition eventDefinition) {
TimerEventDefinition timerEventDefinition = (TimerEventDefinition) eventDefinition;

DefinitionVariableContainer definitionVariableContainer = new DefinitionVariableContainer(previousProcessDefinition.getId(),
previousProcessDefinition.getDeploymentId(), ScopeTypes.BPMN, previousProcessDefinition.getTenantId());

TimerJobEntity timer = TimerUtil.createTimerEntityForTimerEventDefinition((TimerEventDefinition) eventDefinition, startEvent,
false, null, TimerStartEventJobHandler.TYPE, TimerEventHandler.createConfiguration(startEvent.getId(),
false, definitionVariableContainer, TimerStartEventJobHandler.TYPE, TimerEventHandler.createConfiguration(startEvent.getId(),
timerEventDefinition.getEndDate(), timerEventDefinition.getCalendarName()));

if (timer != null) {
TimerJobEntity timerJob = TimerUtil.createTimerEntityForTimerEventDefinition(timerEventDefinition, startEvent,
false, null, TimerStartEventJobHandler.TYPE, TimerEventHandler.createConfiguration(startEvent.getId(),
false, definitionVariableContainer, TimerStartEventJobHandler.TYPE, TimerEventHandler.createConfiguration(startEvent.getId(),
timerEventDefinition.getEndDate(), timerEventDefinition.getCalendarName()));

timerJob.setProcessDefinitionId(previousProcessDefinition.getId());
Expand All @@ -178,7 +183,9 @@ protected void restoreSignalStartEvent(ProcessDefinition previousProcessDefiniti
SignalEventDefinition signalEventDefinition = (SignalEventDefinition) eventDefinition;
SignalEventSubscriptionEntity subscriptionEntity = engineConfiguration.getEventSubscriptionServiceConfiguration().getEventSubscriptionService().createSignalEventSubscription();

String eventName = EventDefinitionExpressionUtil.determineSignalName(commandContext, signalEventDefinition, bpmnModel, null);
DefinitionVariableContainer definitionVariableContainer = new DefinitionVariableContainer(previousProcessDefinition.getId(),
previousProcessDefinition.getDeploymentId(), ScopeTypes.BPMN, previousProcessDefinition.getTenantId());
String eventName = EventDefinitionExpressionUtil.determineSignalName(commandContext, signalEventDefinition, bpmnModel, definitionVariableContainer);
subscriptionEntity.setEventName(eventName);
subscriptionEntity.setActivityId(startEvent.getId());
subscriptionEntity.setProcessDefinitionId(previousProcessDefinition.getId());
Expand All @@ -199,7 +206,9 @@ protected void restoreMessageStartEvent(ProcessDefinition previousProcessDefinit

CommandContext commandContext = Context.getCommandContext();
MessageEventSubscriptionEntity newSubscription = engineConfiguration.getEventSubscriptionServiceConfiguration().getEventSubscriptionService().createMessageEventSubscription();
String messageName = EventDefinitionExpressionUtil.determineMessageName(commandContext, messageEventDefinition, null);
DefinitionVariableContainer definitionVariableContainer = new DefinitionVariableContainer(previousProcessDefinition.getId(),
previousProcessDefinition.getDeploymentId(), ScopeTypes.BPMN, previousProcessDefinition.getTenantId());
String messageName = EventDefinitionExpressionUtil.determineMessageName(commandContext, messageEventDefinition, definitionVariableContainer);
newSubscription.setEventName(messageName);
newSubscription.setActivityId(startEvent.getId());
newSubscription.setConfiguration(previousProcessDefinition.getId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
import org.flowable.eventsubscription.service.impl.persistence.entity.SignalEventSubscriptionEntity;
import org.flowable.identitylink.api.IdentityLinkType;
import org.flowable.job.service.impl.persistence.entity.TimerJobEntity;
import org.flowable.common.engine.api.definition.DefinitionVariableContainer;

import tools.jackson.databind.node.ObjectNode;

Expand Down Expand Up @@ -157,7 +158,10 @@ public ProcessInstance createAndStartProcessInstanceByMessage(ProcessDefinition
if (CollectionUtil.isNotEmpty(startEvent.getEventDefinitions()) && startEvent.getEventDefinitions()
.get(0) instanceof MessageEventDefinition messageEventDefinition) {

String actualMessageName = EventDefinitionExpressionUtil.determineMessageName(commandContext, messageEventDefinition, null);
DefinitionVariableContainer definitionVariableContainer = new DefinitionVariableContainer(processDefinition.getId(), processDefinition.getDeploymentId(),
ScopeTypes.BPMN, processDefinition.getTenantId());

String actualMessageName = EventDefinitionExpressionUtil.determineMessageName(commandContext, messageEventDefinition, definitionVariableContainer);
if (Objects.equals(actualMessageName, messageName)) {
initialFlowElement = flowElement;
break;
Expand Down Expand Up @@ -461,7 +465,9 @@ protected void handleSignalEventSubscription(EventDefinition eventDefinition, St
signalExecution.setEventScope(true);
signalExecution.setActive(false);

String eventName = EventDefinitionExpressionUtil.determineSignalName(commandContext, signalEventDefinition, bpmnModel, null);
DefinitionVariableContainer definitionVariableContainer = new DefinitionVariableContainer(parentExecution.getProcessDefinitionId(),
parentExecution.getDeploymentId(), ScopeTypes.BPMN, parentExecution.getTenantId());
String eventName = EventDefinitionExpressionUtil.determineSignalName(commandContext, signalEventDefinition, bpmnModel, definitionVariableContainer);

EventSubscriptionEntity eventSubscription = (EventSubscriptionEntity) processEngineConfiguration.getEventSubscriptionServiceConfiguration()
.getEventSubscriptionService().createEventSubscriptionBuilder()
Expand Down
Loading