Class ProcessDataContext

java.lang.Object
org.finos.fluxnova.bpm.engine.impl.interceptor.ProcessDataContext

public class ProcessDataContext extends Object
Holds contextual process data and supports custom MDC properties via a provider-based registration mechanism.

In addition to all built-in logging context properties (activityId, tenantId, etc.), this class supports engine-level extensibility through MdcPropertyProvider:

Custom Property Registration:

Custom properties are registered on ProcessEngineConfigurationImpl by calling ProcessEngineConfigurationImpl.addCustomMdcProperty(String, MdcPropertyProvider), typically from a AbstractProcessEnginePlugin preInit() method. During context initialization, this class reads all registered providers from the configuration and sets up:

  • A dedicated ProcessDataContext.ProcessDataStack for each custom property
  • Automatic section/stack management (push/pop/cleanup) alongside built-in properties
  • MDC integration through the existing stack mechanism
  • Automatic value computation via the registered MdcPropertyProvider on each push

Setting Custom Property Values:

Custom property values are computed automatically during pushSection(ExecutionEntity) by invoking the registered MdcPropertyProvider callback. The provider receives the current ExecutionEntity and should return the property value, or null if not applicable for that execution.

Example Usage:

 // In a ProcessEnginePlugin's preInit(), register custom MDC properties:
 @Override
 public void preInit(ProcessEngineConfigurationImpl configuration) {
     configuration.addCustomMdcProperty("applicationId",
         execution -> execution != null ? resolveAppId(execution) : null);
     configuration.addCustomMdcProperty("businessUnit",
         execution -> execution != null ? lookupBusinessUnit(execution) : null);
 }

 // ProcessDataContext will automatically retrieve providers from the configuration
 // at construction time and invoke them on every pushSection().
 

Holds the contextual process data.

New context properties are always part of a section that can be started by pushSection(ExecutionEntity). The section keeps track of all pushed properties. Those can easily be cleared by popping the section with popSection() afterwards, e.g. after the successful execution.

A property can be pushed to the logging context (MDC) if there is a configured non-empty context name for it in the process engine configuration. The following configuration options are available:

  • loggingContextActivityId - the context property for the activity id
  • loggingContextActivityName - the context property for the activity name
  • loggingContextApplicationName - the context property for the application name
  • loggingContextBusinessKey - the context property for the business key
  • loggingContextProcessDefinitionId - the context property for the definition id
  • loggingContextProcessDefinitionKey - the context property for the definition key
  • loggingContextProcessInstanceId - the context property for the instance id
  • loggingContextTenantId - the context property for the tenant id
  • loggingContextEngineName - the context property for the engine name
  • loggingContextRootProcessInstanceId - the context property for the root process instance id
  • Custom properties - registered via registerCustomMdcProperty(String, MdcPropertyProvider)
  • Field Details

    • NULL_VALUE

      protected static final String NULL_VALUE
      See Also:
    • mdcPropertyActivityId

      protected String mdcPropertyActivityId
    • mdcPropertyActivityName

      protected String mdcPropertyActivityName
    • mdcPropertyApplicationName

      protected String mdcPropertyApplicationName
    • mdcPropertyBusinessKey

      protected String mdcPropertyBusinessKey
    • mdcPropertyDefinitionId

      protected String mdcPropertyDefinitionId
    • mdcPropertyDefinitionKey

      protected String mdcPropertyDefinitionKey
    • mdcPropertyInstanceId

      protected String mdcPropertyInstanceId
    • mdcPropertyTenantId

      protected String mdcPropertyTenantId
    • mdcPropertyEngineName

      protected String mdcPropertyEngineName
    • mdcPropertyRootProcessInstanceId

      protected String mdcPropertyRootProcessInstanceId
    • customMdcPropertyProviders

      protected Map<String,MdcPropertyProvider> customMdcPropertyProviders
      Property providers for custom MDC properties in this context instance. Maps property name -> callback that computes the property value from execution context.

      Why needed: Only custom properties require providers. Built-in properties (activityId, tenantId, etc.) access ExecutionEntity fields directly without callbacks.

    • handleMdc

      protected boolean handleMdc
    • activityIdStack

      protected ProcessDataContext.ProcessDataStack activityIdStack
    • mdcDataStacks

      All data stacks we need to keep for MDC logging. Maps MDC property name -> stack that tracks property values through nested contexts. Includes both built-in properties (activityId, tenantId, etc.) and custom properties.

      Why needed: Manages value history for ALL MDC properties through nested execution contexts. When a process calls a subprocess, we push new values onto the stack. When the subprocess completes, we pop to restore parent process values. This cannot be derived from customMdcPropertyProviders alone because:

      • Built-in properties need stacks but don't have providers
      • Stacks track the value history, providers only compute current values
    • sections

    • externalProperties

      protected Map<String,String> externalProperties
      Preserves MDC properties from outer contexts when parkExternalProperties is enabled. Maps MDC property name -> value to restore when this context completes.

      Why needed: When commands nest (one command triggering another), each creates its own ProcessDataContext. Without parking, the outer command's MDC would be lost. Example: Outer command has processInstanceId=123, inner command has processInstanceId=456. When inner completes, we restore the outer context's processInstanceId=123.

  • Constructor Details

    • ProcessDataContext

      public ProcessDataContext(ProcessEngineConfigurationImpl configuration)
    • ProcessDataContext

      public ProcessDataContext(ProcessEngineConfigurationImpl configuration, boolean initFromCurrentMdc)
    • ProcessDataContext

      public ProcessDataContext(ProcessEngineConfigurationImpl configuration, boolean initFromCurrentMdc, boolean parkExternalProperties)
      All-args constructor.
      Parameters:
      configuration - the process engine configuration to use to fetch Logging Context Parameters.
      initFromCurrentMdc - when true, this process data context will be populated from the current state of the MDC
      parkExternalProperties - when true, the MDC tuples that are the same as the configured logging context parameters will be preserved separately in the process data context.
  • Method Details

    • parkExternalProperties

      protected void parkExternalProperties(ProcessEngineConfigurationImpl configuration)
      Parks (saves) existing MDC properties that match configured logging context parameters.

      Purpose: When this ProcessDataContext is created within an outer command that already has MDC properties set, we need to preserve those outer values so they can be restored when this context completes. This prevents the inner command from permanently overwriting the outer command's MDC state.

      Example scenario:

       Outer command context:
         MDC: processInstanceId=123, tenantId=tenant-outer
      
       Inner command starts → creates new ProcessDataContext with parkExternalProperties=true
         → Parks: {processInstanceId=123, tenantId=tenant-outer}
         → Sets: processInstanceId=456, tenantId=tenant-inner
      
       Inner command completes → calls restoreExternalMDCProperties()
         → Restores: processInstanceId=123, tenantId=tenant-outer
       

      When used: Set to true when creating nested ProcessDataContext instances that should preserve the outer MDC state. Set to false for top-level contexts.

      Parameters:
      configuration - the process engine configuration containing MDC property names
    • parkCustomMdcProperties

      protected void parkCustomMdcProperties()
    • initProperty

      protected String initProperty(Supplier<String> configSupplier)
    • parkExternalMDCProperty

      protected String parkExternalMDCProperty(Supplier<String> configSupplier)
    • pushSection

      public boolean pushSection(ExecutionEntity execution)
      Start a new section that keeps track of the pushed properties. If logging context properties are defined, the MDC is updated as well. This also includes clearing the MDC for the first section that is pushed for the logging context so that only the current properties will be present in the MDC (might be less than previously present in the MDC). The previous logging context needs to be reset in the MDC when this one is closed. This can be achieved by using updateMdcFromCurrentValues() with the previous logging context.
      Parameters:
      execution - the execution to retrieve the context data from
      Returns:
      true if the section contains any updates and therefore should be popped later by popSection()
    • populateCustomMdcProperties

      protected void populateCustomMdcProperties(ExecutionEntity execution)
      Populates custom MDC properties by invoking registered providers.

      Iterates through all registered custom MDC properties and invokes their associated provider to get property values based on the current execution context. If provider does not return null, it is added to the MDC stack.

    • hasNoMdcValues

      protected boolean hasNoMdcValues()
    • popSection

      public void popSection()
      Pop the latest section, remove all pushed properties of that section and - if logging context properties are defined - update the MDC accordingly.
    • clearMdc

      public void clearMdc()
      Remove all logging context properties from the MDC
    • restoreExternalMDCProperties

      public void restoreExternalMDCProperties()
      Restores the external properties to the MDC. Meant to be called for ProcessDataContexts associated with outer commands.
    • updateMdcFromCurrentValues

      public void updateMdcFromCurrentValues()
      Update the MDC with the current values of this logging context
    • getLatestActivityId

      public String getLatestActivityId()
      Returns:
      the latest value of the activity id property if exists, null otherwise
    • addToStack

      protected void addToStack(String value, String property)
    • addToStack

      protected void addToStack(ProcessDataContext.ProcessDataStack stack, String value)
    • isNotBlank

      protected static boolean isNotBlank(String property)
    • valuesEqual

      protected static boolean valuesEqual(String val1, String val2)
    • isNull

      protected static boolean isNull(String value)