Pipeline components
Build reusable message processing logic that Art2link ESB compiles and deploys automatically — no build steps, no restarts, no downtime.
A Pipeline Component is a C# class that processes messages flowing through an Art2link ESB Pipeline. Each component receives a message, applies your logic, and returns one or more messages to the next stage of the pipeline.
Art2link ESB handles compilation and deployment automatically. You write the code, save it, and reference it from a Pipeline — no build steps, no restarts, no downtime.
The architecture follows a simple chain: Port → Pipeline → Component(s) → Output. A Pipeline can contain multiple components executed in sequence. Each component operates on the output of the previous one.
Two kinds of work happen inside a component. The obvious one is transformation — reshape the body, enrich it, compress, sign, validate. The second — available only when the component runs on the inbound side of a flow — is classification: the component inspects the message and assigns it a Message Type by setting MessageType on the outgoing PipelineMessage before the bus publishes. See Components can classify the Message Type in the Pipelines article for the full contract; the code-level mechanics live in this reference.
The following classes are provided by the Art2link runtime in the CC.Art2link.Pipelines.Domain.Models.PipelineComponents namespace. Do not redefine them in your component code.
The incoming message passed to your component.
| Property | Type | Description |
|---|---|---|
| Body | string | The message body. Always a string, never null at runtime (defaults to empty string). |
The result returned by your component after processing.
| Property | Type | Description |
|---|---|---|
| Success | bool | Whether the component executed successfully. When false, the pipeline stops immediately. |
| Messages | IList<PipelineMessage> | One or more outgoing messages. Return multiple items for fan-out, or an empty list to suppress/filter. |
| Variables | IDictionary<string, string> | Assignments written back to Art2link ESB Variables on the current message’s context. Keys are variable names; values replace whatever the variable currently holds. Visible to downstream components, maps, and ports via {{Variable.Name}}. |
| ErrorMessage | string? | A human-readable error description. Set when Success is false. |
| Exception | Exception? | The caught exception, if any. Set when Success is false. |
An individual outgoing message.
| Property | Type | Description |
|---|---|---|
| Body | string | The outgoing message body. |
| MessageType | string | The Message Type assigned to this message. Setting it classifies the message before publish; ignored on outbound pipelines (the type is already known by then). Must match a Message Type defined in the application. |
The abstract base class your component must inherit from. It handles JSON deserialization of the configuration and delegates to your ExecuteAsync implementation.
public abstract class PipelineComponentBase<TConfig> : IPipelineComponent where TConfig : new() { public abstract string Name { get; } // Called by the engine — deserializes configJson, then delegates below public Task<PipelineComponentOutput> ExecuteAsync( PipelineComponentInput input, string configJson, CancellationToken cancellationToken = default) { ... } // Implement this method with your logic protected abstract Task<PipelineComponentOutput> ExecuteAsync( PipelineComponentInput input, TConfig config, CancellationToken cancellationToken); }
The configuration class defines all user-editable parameters for your component. Each public property becomes an input field in the Art2link ESB UI when the component is added to a pipeline.
Any type that is JSON-deserializable by System.Text.Json is supported: string, int, bool, double, enum, List<T>, and complex objects.
Assign defaults directly on properties. These values are shown pre-filled in the UI when a user configures your component.
You may use attributes from the System.ComponentModel.DataAnnotations namespace to enforce constraints on configuration values.
using System.ComponentModel.DataAnnotations; public sealed class MyComponentConfig { [Required] public string TargetEndpoint { get; set; } = string.Empty; [Range(1, 10)] public int MaxRetries { get; set; } = 3; public bool IncludeHeaders { get; set; } = true; }
Configuration values support the {{ }} binding syntax, letting users reference application Variables, application Constants, and message-level promoted properties when configuring a component in the UI:
| Token | Resolves to |
|---|---|
| {{Variable.Name}} | Per-message variable value — lives for the duration of one message’s journey. |
| {{Constant.Name}} | Application constant for the current deployment — one value per environment. |
| {{Promoted.MessageType.Name}} | Schema-promoted property lifted from the message body. |
Each component must override the Name property with a unique identifier. This name is used internally by the pipeline engine to locate and invoke your component.
| Rule | Details |
|---|---|
| Uniqueness | Must be unique system-wide across all components in the Art2link ESB instance. |
| Prefix | No required prefix. The fn convention (e.g., fnMyComponent) is optional. |
| Restrictions | No enforced casing, character, or length restrictions. |
| Config class naming | No enforced naming convention between the config class and the component class. |
Components must not throw exceptions. Instead, catch all errors and return a PipelineComponentOutput with Success = false, a descriptive ErrorMessage, and optionally the caught Exception.
When a component returns Success = false, the pipeline stops execution immediately. No subsequent components will be invoked.
protected override Task<PipelineComponentOutput> ExecuteAsync( PipelineComponentInput input, MyComponentConfig config, CancellationToken cancellationToken) { try { // Your logic here return Task.FromResult(new PipelineComponentOutput { Success = true, Messages = [new PipelineMessage { Body = result }] }); } catch (Exception ex) { return Task.FromResult(new PipelineComponentOutput { Success = false, ErrorMessage = ex.Message, Exception = ex }); } }
The shape of the Messages list governs what happens next. Two patterns matter:
Beyond returning a transformed body, a component has two side-effect channels into the surrounding integration. Both are written into the result your component returns.
Both channels are populated at the same time you build the result. Here is an inbound component that produces two outgoing messages, classifies each, and writes one application variable along the way:
protected override Task<PipelineComponentOutput> ExecuteAsync( PipelineComponentInput input, MyComponentConfig config, CancellationToken cancellationToken) { try { // Your logic here return Task.FromResult(new PipelineComponentOutput { Success = true, Variables = { ["lastProcessedDocument"] = "INV-1001", }, Messages = [ new PipelineMessage { Body = acknowledgementResult, MessageType = "AcknowledgementMessageType" }, new PipelineMessage { Body = businessResult, MessageType = "BusinessMessageType" } ] }); } catch (Exception ex) { return Task.FromResult(new PipelineComponentOutput { Success = false, ErrorMessage = ex.Message, Exception = ex }); } }
| Aspect | Details |
|---|---|
| Target framework | .NET 8 |
| Available libraries | Built-in .NET libraries. Additional NuGet packages can be added via the Art2link ESB UI (name and version), then referenced with using statements at the top of your component code. See the NuGet packages article for the global catalogue. |
| Threading model | Single-threaded per invocation. You do not need to write thread-safe code. |
| CancellationToken | Honor the token passed to ExecuteAsync for any long-running or awaitable work. |
| Async I/O | Making HTTP calls, file access, or database queries inside ExecuteAsync is not blocked, but it is not a supported scenario. Behavior may change in future releases. |
| Timeouts / Memory | Not enforced at this time. |
| Logging | No logging interface is available at this time. Console.Write output is not captured. |
| Component per file | One component per file. |
When you save a component, Art2link ESB compiles and deploys it automatically. There is no manual build step and no restart required. The new version takes effect immediately.
Wrap your entire ExecuteAsync body in a try/catch. Return Success = false with a meaningful ErrorMessage. Never let an exception propagate to the engine.
The Name property is an immutable contract once deployed. Use a descriptive, stable identifier. If you need to rename, create a new component and migrate pipelines manually.
Each component should do one thing well. Compose complex transformations by chaining multiple components in a pipeline rather than building monolithic components.
Move environment-specific or deployment-specific values into the config class. Combined with {{ }} binding to Constants and Variables, this makes your components reusable across environments without code changes.
If your component performs any awaitable work, pass the cancellationToken through to those calls. This ensures the pipeline engine can shut down gracefully.
Until multi-version management is available, save component changes when no messages are actively being processed to avoid unpredictable in-flight behavior.
Ready to build
Download the component template, implement your logic, and save. Art2link ESB handles the rest. If you run into issues, our support team is ready to help.