Skip to main content

Condition

A Condition decides whether a route runs for a given message. It is the SDK's predicate (or filter, in plain English) that sits at the front of a route's pipeline: if the Condition returns false, the route is skipped for that message and the next route is evaluated.

PropertyValue
Java interfacecom.connamara.sdk.v1.adapter.components.Condition
Methodboolean matches(Message<?> message, RouteContext context)
Pipeline slotFirst, before any Transformer or Processor.
Return contracttrue to let the route run, false to skip it for this message.
Multiple Conditions per routeCombined with AND. Every Condition must return true for the route to run. Use payload logic inside a single Condition for OR semantics.
Side effectsForbidden. A Condition is called during route dispatch and must be cheap, deterministic, and free of I/O.

Complete example

package com.example.myplugin;

import com.connamara.sdk.v1.adapter.RouteContext;
import com.connamara.sdk.v1.adapter.components.Condition;
import com.connamara.sdk.v1.common.component.ManifestResource;
import com.connamara.sdk.v1.common.message.Message;

import java.util.Map;

@ManifestResource("""
{
"id": "header-equals-condition",
"pluginId": "my-plugin",
"functionalType": "header-equals-condition",
"displayName": "Header Equals",
"category": "CONDITION",
"configuration": {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"title": "Header Equals Settings",
"x-order": ["headerName", "expectedValue"],
"required": ["headerName", "expectedValue"],
"properties": {
"headerName": {
"type": "string",
"title": "Header Name",
"description": "The header key to inspect."
},
"expectedValue": {
"type": "string",
"title": "Expected Value",
"description": "The value the header must equal."
}
}
}
}
""")
public class HeaderEqualsCondition implements Condition {

private final String headerName;
private final String expectedValue;

public HeaderEqualsCondition(Map<String, Object> configuration) {
this.headerName = (String) configuration.get("headerName");
this.expectedValue = (String) configuration.get("expectedValue");
}

@Override
public boolean matches(Message<?> message, RouteContext context) {
Object actual = message.getHeaders().get(headerName);
return actual != null && expectedValue.equals(actual.toString());
}
}

Key rules

  • Be deterministic and fast. A Condition runs once per message per route during dispatch. It is on the latency-critical path.
  • No I/O, no mutation. Conditions read message state. They do not call external services, modify the message, or write to logs at info level. (Debug logging of evaluation outcomes is fine.)
  • Never throw. A Condition that throws is treated as a route-level failure: the route is skipped and the exception bubbles to the route's ErrorProcessor chain. To stay safe, swallow expected runtime errors (malformed JSON, missing fields, type mismatches) and return false instead. The Essentials plugin's JsonPathCondition is a reference implementation of this pattern.
  • Multiple Conditions are AND-ed. A route with three Conditions runs only when all three return true. Combine OR clauses inside a single Condition's logic, not by stacking Conditions.

Test pattern

@Test
@DisplayName("GIVEN a message whose header equals the expected value WHEN evaluated THEN matches returns true")
void matches_whenHeaderEqualsExpected_returnsTrue() {
HeaderEqualsCondition condition = new HeaderEqualsCondition(Map.of(
"headerName", "msgType",
"expectedValue", "ORDER"
));

Message<?> message = mock(Message.class);
MessageHeaders headers = new MessageHeaders(Map.of("msgType", "ORDER"));
when(message.getHeaders()).thenReturn(headers);

RouteContext context = mock(RouteContext.class);

assertTrue(condition.matches(message, context));
}

When to reach for a Condition

NeedReach for
Skip a route when a header, payload field, or metadata value doesn't match.Condition.
Drop a message after enrichment shows it should not be processed.Processor returning null.
Convert the payload before deciding whether to process.Transformer followed by a downstream Processor that drops on failure. Conditions should not depend on transformed payloads, since they run before the Transformer chain.

See also