Customize BPMN Import
Customize BPMN import when a source model uses conventions that need a different mapping to native Workflow Engine schemes. BpmnConverterBuilder replaces individual conversion visitors, applies BpmnConverterSettings, and produces the converter passed to the BPMN Plugin. The remaining visitors keep their default behavior.
Choose the replacement scope
BpmnConverterBuilder.Create() starts a converter builder. Call the required replacement methods and finish with Build(settings); omitting a replacement selects that visitor's standard implementation. Each replacement method returns the same builder, and a later call for the same visitor replaces the earlier choice.
Node visitors create activities. Flow visitors create outgoing transitions and update their incoming settings. ProcessVisitor coordinates complete process conversion, including nested processes and diagram coordinates.
| Visitor class | Builder method | Conversion responsibility |
|---|---|---|
TaskNodeVisitor | WithCustomTaskNodeVisitor | Task nodes become activities. |
GatewayNodeVisitor | WithCustomGatewayNodeVisitor | Gateway nodes become activities. |
EventNodeVisitor | WithCustomEventNodeVisitor | Event nodes become activities or deferred trigger mappings. |
SubprocessNodeVisitor | WithCustomSubprocessNodeVisitor | Nonempty subprocess nodes become Inline activities; empty ones become ordinary activities. |
CallActivityNodeVisitor | WithCustomCallActivityNodeVisitor | Call activity nodes become activities. |
TaskFlowVisitor | WithCustomTaskFlowVisitor | Task sequence flows become transitions. |
GatewayFlowVisitor | WithCustomGatewayFlowVisitor | Gateway flows receive branch, trigger, and merge settings. |
EventFlowVisitor | WithCustomEventFlowVisitor | Event flows receive command, timer, or automatic triggers. |
SubprocessFlowVisitor | WithCustomSubprocessFlowVisitor | Flows connect converted subprocess activities. |
CallActivityFlowVisitor | WithCustomCallActivityFlowVisitor | Flows connect converted call activities. |
ProcessVisitor | WithCustomProcessVisitor | Complete process, subprocess, and diagram conversion. |
The task, gateway, and event visitors expose non-virtual dispatch methods such as AddTask and AddOutgoingFlow. Override their specialized protected virtual methods, such as AddServiceTask or AddOutgoingFlowExclusiveGateway, to change a particular BPMN type. CallActivityNodeVisitor.AddCallActivity and SubprocessNodeVisitor.AddSubprocessActivity are public virtual methods.
The default ProcessVisitor first creates nodes, then adds all sequence flows, then updates incoming flows. Incoming updates can override settings assigned during flow creation. Replace ProcessVisitor only when changes to individual node and flow visitors cannot express the required conversion.
Configure conversion settings
Build(BpmnConverterSettings? settings = null) assigns settings to the converter's visitors. When settings are omitted, visitors use the defaults below. Both members are init-only properties, so choose their values while constructing the settings object.
| Property | Type | Default | When read and effect |
|---|---|---|---|
DateTimeKind | DateTimeKind | Local | During fixed timeDate conversion, selects XML date handling as Local, Utc, or Unspecified. Duration and expression timers do not use this setting. |
DefaultAutoSchemeUpdate | bool | true | During BaseNodeVisitor.CreateActivity, enables or disables automatic scheme updates on the created activity. A custom visitor that bypasses this helper must apply its own defaults. |
Converter settings affect subsequent imports through that converter. Creating another converter does not rewrite stored schemes or change existing process instances. The automatic update flag controls an activity's eligibility for the runtime's scheme update mechanism; it does not synchronize a scheme with its original BPMN file.
Replace call activity conversion
The default CallActivityNodeVisitor creates an ordinary activity and records an unsupported-call warning. The following configuration replaces that mapping with an application convention: a call to ReviewOrder becomes an activity implementation named Call_ReviewOrder.
Configure is an application helper in this example. Pass it an already configured Workflow Runtime before starting the runtime. It constructs the custom converter, passes it to BpmnPlugin, and registers the plugin with WithPlugin.
using System;using OptimaJet.Workflow.BpmnPlugin;using OptimaJet.Workflow.BpmnPlugin.Import;using OptimaJet.Workflow.BpmnPlugin.Model;using OptimaJet.Workflow.Core.Model.Builder;using OptimaJet.Workflow.Core.Runtime;public static class BpmnImportConfiguration{ public static WorkflowRuntime Configure(WorkflowRuntime runtime) { var settings = new BpmnConverterSettings { DateTimeKind = DateTimeKind.Utc, DefaultAutoSchemeUpdate = false }; BpmnConverter converter = BpmnConverterBuilder.Create() .WithCustomCallActivityNodeVisitor(new ApplicationCallVisitor()) .Build(settings); return runtime.WithPlugin(new BpmnPlugin(converter)); }}public sealed class ApplicationCallVisitor : CallActivityNodeVisitor{ public override void AddCallActivity( TCallActivity callActivity, BpmnConverterContext context) { IActivityBuilder activityBuilder = CreateActivity(callActivity, context); string calledName = callActivity.CalledElement?.Name; if (string.IsNullOrWhiteSpace(calledName)) { string issue = $"Call activity '{callActivity.Id}' has no calledElement."; context.LogIssue(issue); activityBuilder.CreateCommentary(issue); return; } string actionName = $"Call_{calledName}"; activityBuilder.CreateImplementationAtEnd(actionName); activityBuilder.CreateCommentary($"Application action: {actionName}."); }}CreateActivity preserves the standard ID-to-activity-name mapping, the BPMN name-to-state mapping, state-change eligibility for named nodes, and DefaultAutoSchemeUpdate. The normal diagram pass still assigns coordinates using the BPMN element ID. The default call activity flow visitor continues to connect the activity to its neighbors.
The helper calls State(flowNode.Name).EnableSetState() when the BPMN name is not blank and NotState() otherwise. These are the same state-setting decisions that an application visitor would apply when creating the activity directly through context.Builder.
This custom visitor creates an action reference; the application must implement and register each Call_<calledElement> action before executing the scheme. The example does not start a called BPMN process automatically or reproduce BPMN call activity execution semantics. If the application needs another execution model, change both its action implementation and the conversion convention.
Inspect conversion before saving
BpmnConverter.ConvertBpmnDocument converts BPMN XML without saving schemes or starting processes. Use it to inspect conversion issues before allowing an application import. This standalone .NET 10 program reads a BPMN file supplied as its only command-line argument and reports each converted scheme.
using System;using System.IO;using OptimaJet.Workflow.BpmnPlugin.Import;if (args.Length != 1){ throw new ArgumentException("Pass the path to one BPMN XML file.");}BpmnConverter converter = BpmnConverterBuilder.Create().Build();using var reader = File.OpenText(args[0]);foreach (ConvertedProcess convertedProcess in converter.ConvertBpmnDocument(reader)){ Console.WriteLine($"Scheme: {convertedProcess.ProcessDefinition.Name}"); Console.WriteLine($"Skip saving: {convertedProcess.DontSave}"); foreach (string issue in convertedProcess.Issues) { Console.WriteLine($"Issue: {issue}"); } if (convertedProcess.Hint is not null) { Console.WriteLine($"Hint: {convertedProcess.Hint.Message}"); }}The reader overload accepts a TextReader and an optional mainSchemeCode. The model overload accepts OptimaJet.Workflow.BpmnPlugin.Model.TDefinitions and the same optional code. Both return List<ConvertedProcess>; the model overload uses an already deserialized BPMN document. A nonempty mainSchemeCode renames the first converted process that is neither inline nor marked DontSave.
| Result member | Meaning |
|---|---|
ProcessDefinition | Converted native scheme definition, including activities and transitions. |
Issues | Immutable list of conversion warnings gathered for that process. |
HasIssues | true when Issues is nonempty. |
Hint | Optional conversion hint with a type and explanatory message. |
DontSave | true when the hint type is ConvertedProcessHintType.DontSave. |
The default converter marks a top-level process without activities as DontSave. Conversion does not run the runtime's full scheme save and build pipeline, so an issue-free conversion is not proof that a scheme can be saved or executed. XML deserialization and conversion can also throw exceptions; a service integrating this API must handle those failures separately from Issues.
BpmnConverterContext supplies a visitor's Builder, immutable FlowElements, and BpmnDocument. Use FindMessage, GetFlowNode, and GetSequenceFlow to resolve elements; each lookup can return null. Call LogIssue to add a process-level diagnostic. Add a commentary through the activity or transition builder as well when the warning should remain visible on the corresponding scheme element.
Related import contracts
The BPMN import guide applies converters through the Designer's save pipeline. The supported elements reference describes the default mapping that a replacement visitor changes. The BpmnConverter API reference lists the public conversion overloads.
Frequently asked questions
How do I customize only one BPMN element type?
Replace the relevant visitor through BpmnConverterBuilder and override its specialized virtual method. The builder supplies default visitors for every category you leave unchanged.
Can I inspect a BPMN import without writing to the database?
Yes. ConvertBpmnDocument returns converted definitions and their diagnostics without invoking persistence. The Designer upload pipeline adds saving and build validation afterward.
Does changing converter settings update existing schemes?
No. BpmnConverterSettings controls conversion of new input; existing definitions retain their current values. Reimporting with overwrite enabled can replace stored schemes through the Designer import pipeline.
Does a custom CallActivityNodeVisitor automatically execute the called BPMN process?
No. A custom visitor defines the native activity mapping, and the application supplies the corresponding execution behavior. The example creates action references that require registered application implementations.