Content-Based Router Pattern
Overview
The Content-Based Router pattern is a sophisticated message routing pattern in enterprise integration architectures that examines message content, headers, or properties to dynamically determine the appropriate destination for each message. Unlike static routing rules, the Content-Based Router makes intelligent routing decisions at runtime by analyzing the actual message payload, enabling flexible and adaptive message flow control based on business logic, data characteristics, and contextual information.
Theoretical Foundation
The Content-Based Router pattern is grounded in decision tree algorithms and rule-based systems theory, specifically addressing the challenge of dynamic message classification and intelligent routing in distributed systems. The pattern embodies the principle of "content-driven dispatch" - making routing decisions based on actual message data and business semantics rather than predetermined static configurations.
Core Principles
1. Intelligent Content Analysis
The Content-Based Router performs sophisticated examination of message characteristics: - Payload inspection - analyzing message content structure, data types, and values - Header analysis - examining message metadata, routing hints, and context information - Business rule evaluation - applying complex business logic to determine appropriate destinations - Pattern matching - using regular expressions, XPath, JSONPath, or custom matchers to identify content patterns
2. Dynamic Destination Selection
Based on content analysis, the router selects appropriate destinations: - Single destination routing - directing messages to one specific endpoint - Multi-destination routing - sending messages to multiple endpoints based on content - Conditional routing - applying different routing logic based on content characteristics - Priority-based routing - selecting destinations based on message priority or urgency
3. Business Logic Integration
The pattern enables sophisticated business-driven routing: - Customer segmentation - routing based on customer type, geography, or business value - Product categorization - directing messages based on product types or categories - Regulatory compliance - routing based on jurisdictional or compliance requirements - Service level agreements - routing based on SLA requirements or service tiers
4. Scalability and Performance
The Content-Based Router optimizes routing performance: - Efficient content parsing - minimizing overhead of content inspection - Rule caching - caching frequently used routing rules and patterns - Parallel evaluation - evaluating multiple routing conditions concurrently - Short-circuit optimization - stopping evaluation once a matching rule is found
Why Content-Based Routers are Essential in Integration Architecture
1. Business Process Flexibility
In dynamic business environments, content-based routing enables: - Workflow automation - automatically routing work items based on content characteristics - Exception handling - directing error conditions or special cases to appropriate handlers - Approval workflows - routing requests to correct approval chains based on amount, type, or risk - Escalation management - routing time-sensitive or high-value transactions to priority queues
2. Multi-Tenant and Multi-Channel Support
For complex enterprise architectures: - Tenant isolation - routing messages to tenant-specific processing pipelines - Channel differentiation - handling web, mobile, API, and batch requests differently - Geographic routing - directing messages based on customer location or data residency - Brand segmentation - routing messages based on brand affiliation or business unit
3. Legacy System Integration
When integrating diverse legacy systems: - Format adaptation - routing messages to systems that support specific data formats - Protocol mediation - directing messages to appropriate protocol handlers - Capability matching - routing to systems based on their processing capabilities - Load distribution - balancing load across systems with different capacity characteristics
4. Microservices Architecture
In microservices environments: - Service specialization - routing to services optimized for specific data types or operations - Version management - routing to appropriate service versions based on message schema - Feature flagging - routing to different service implementations based on feature flags - A/B testing - distributing traffic to different service variants for testing
Benefits in Integration Contexts
1. Operational Efficiency
- Automated decision making - reducing manual routing and processing decisions
- Optimized resource utilization - directing work to most appropriate processing resources
- Reduced processing time - eliminating unnecessary processing steps through intelligent routing
- Improved throughput - parallel processing of different message types
2. Business Agility
- Dynamic rule changes - updating routing logic without code deployment
- Rapid business adaptation - quickly implementing new business routing requirements
- Market responsiveness - adapting message flows for new business scenarios
- Compliance flexibility - easily implementing new regulatory routing requirements
3. System Resilience
- Fault isolation - routing around failed or degraded systems
- Load distribution - preventing system overload through intelligent routing
- Graceful degradation - routing to backup systems when primary systems are unavailable
- Error containment - isolating problematic messages to specialized error handling systems
4. Customer Experience Enhancement
- Personalized processing - routing customer requests based on preferences or history
- Priority handling - ensuring high-value customers receive priority processing
- Regional optimization - routing to geographically optimal processing centers
- Service customization - adapting processing based on customer service levels
Integration Architecture Applications
1. Enterprise Service Bus (ESB)
Content-Based Routers in ESB architectures provide: - Service endpoint selection - routing to appropriate service implementations - Message transformation routing - directing to transformation services based on content - Error handling routing - sending errors to specialized error processing services - Audit and compliance routing - directing sensitive messages to audit services
2. API Gateway and Management
In API gateway implementations: - Backend service routing - directing API calls to appropriate backend services - Rate limiting routing - routing high-volume clients to specialized handling - Authentication routing - directing to different authentication services based on client type - Version compatibility routing - routing to compatible service versions
3. Event-Driven Architecture
For event processing systems: - Event type routing - directing different event types to specialized processors - Stream partitioning - routing events to appropriate stream partitions - Consumer group routing - directing events to specific consumer groups - Priority event handling - routing critical events to high-priority processors
4. Data Pipeline and Analytics
In data processing workflows: - Data source routing - directing data based on source system characteristics - Quality-based routing - routing high-quality data to real-time systems, low-quality to batch processing - Compliance routing - directing sensitive data to compliant processing pipelines - Analytics routing - routing operational data to analytical systems
Implementation Patterns
1. Simple Content Inspection Router
// Basic content-based routing using message analysis
@Component
public class ContentInspectionRouter {
public String determineRoute(MessageDto message) {
// Route based on message type
if (message.getMessageType() == MessageType.PAYMENT) {
return routePaymentMessage(message);
} else if (message.getMessageType() == MessageType.CUSTOMER_UPDATE) {
return routeCustomerMessage(message);
} else if (message.getMessageType() == MessageType.ORDER) {
return routeOrderMessage(message);
}
return "default-processor";
}
private String routePaymentMessage(MessageDto message) {
PaymentDto payment = message.getPayload(PaymentDto.class);
// Route high-value payments to secure processor
if (payment.getAmount().compareTo(new BigDecimal("10000")) > 0) {
return "high-value-payment-processor";
}
// Route international payments to specialized processor
if (!payment.getCurrency().equals("EUR")) {
return "international-payment-processor";
}
return "standard-payment-processor";
}
private String routeCustomerMessage(MessageDto message) {
CustomerUpdateDto customer = message.getPayload(CustomerUpdateDto.class);
// Route VIP customers to priority processor
if (customer.getCustomerTier() == CustomerTier.VIP) {
return "vip-customer-processor";
}
// Route by geographic region
String region = customer.getAddress().getCountry();
return switch (region) {
case "FI", "SE", "NO", "DK" -> "nordic-customer-processor";
case "DE", "FR", "ES", "IT" -> "eu-customer-processor";
default -> "international-customer-processor";
};
}
private String routeOrderMessage(MessageDto message) {
OrderDto order = message.getPayload(OrderDto.class);
// Route based on order characteristics
if (order.isExpressDelivery()) {
return "express-order-processor";
}
if (order.getItems().size() > 10) {
return "bulk-order-processor";
}
return "standard-order-processor";
}
}
2. Rule-Based Content Router
// Advanced routing using configurable business rules
@Component
public class RuleBasedContentRouter {
@Autowired
private RoutingRuleEngine ruleEngine;
@Autowired
private MessageContentAnalyzer contentAnalyzer;
public RoutingDecision routeMessage(Message message) {
MessageContext context = contentAnalyzer.analyzeMessage(message);
List<RoutingRule> applicableRules = ruleEngine.getApplicableRules(context);
for (RoutingRule rule : applicableRules) {
if (rule.evaluate(context)) {
return RoutingDecision.builder()
.destination(rule.getDestination())
.ruleId(rule.getId())
.confidence(rule.getConfidence())
.metadata(rule.getMetadata())
.build();
}
}
return RoutingDecision.defaultRoute();
}
}
@Service
public class RoutingRuleEngine {
private final List<RoutingRule> rules;
public List<RoutingRule> getApplicableRules(MessageContext context) {
return rules.stream()
.filter(rule -> rule.isApplicable(context))
.sorted(Comparator.comparing(RoutingRule::getPriority).reversed())
.collect(Collectors.toList());
}
}
public interface RoutingRule {
boolean isApplicable(MessageContext context);
boolean evaluate(MessageContext context);
String getDestination();
String getId();
int getPriority();
double getConfidence();
Map<String, Object> getMetadata();
}
public class CustomerTypeRoutingRule implements RoutingRule {
private final CustomerType targetCustomerType;
private final String destination;
private final int priority;
@Override
public boolean evaluate(MessageContext context) {
return context.getCustomerType() == targetCustomerType;
}
@Override
public String getDestination() {
return destination;
}
// Additional methods...
}
3. JSON/XML Content Path Router
// Content routing using path expressions for structured data
@Component
public class PathBasedContentRouter {
@Autowired
private JsonPathEvaluator jsonPathEvaluator;
@Autowired
private XPathEvaluator xPathEvaluator;
public String routeByContentPath(String messageContent, String contentType) {
if ("application/json".equals(contentType)) {
return routeJsonContent(messageContent);
} else if ("application/xml".equals(contentType) || "text/xml".equals(contentType)) {
return routeXmlContent(messageContent);
}
return "default-processor";
}
private String routeJsonContent(String jsonContent) {
try {
// Route based on event type
String eventType = jsonPathEvaluator.evaluate(jsonContent, "$.eventType");
if ("user.created".equals(eventType)) {
return "user-onboarding-processor";
} else if ("order.placed".equals(eventType)) {
return "order-processing-service";
}
// Route based on data characteristics
Integer amount = jsonPathEvaluator.evaluate(jsonContent, "$.order.totalAmount");
if (amount != null && amount > 1000) {
return "high-value-processor";
}
// Route based on customer segment
String segment = jsonPathEvaluator.evaluate(jsonContent, "$.customer.segment");
if ("ENTERPRISE".equals(segment)) {
return "enterprise-processor";
}
} catch (Exception e) {
log.warn("Error evaluating JSON path for routing", e);
}
return "default-processor";
}
private String routeXmlContent(String xmlContent) {
try {
// Route based on XML element values
String messageType = xPathEvaluator.evaluate(xmlContent, "/message/@type");
String priority = xPathEvaluator.evaluate(xmlContent, "/message/header/priority/text()");
if ("urgent".equalsIgnoreCase(priority)) {
return "urgent-processor";
}
if ("invoice".equals(messageType)) {
String amount = xPathEvaluator.evaluate(xmlContent, "/message/body/invoice/amount/text()");
if (amount != null && Double.parseDouble(amount) > 5000) {
return "large-invoice-processor";
}
return "standard-invoice-processor";
}
} catch (Exception e) {
log.warn("Error evaluating XPath for routing", e);
}
return "default-processor";
}
}
4. Multi-Criteria Content Router
// Complex routing based on multiple content criteria
@Component
public class MultiCriteriaContentRouter {
public List<String> determineDestinations(ComplexMessage message) {
List<String> destinations = new ArrayList<>();
RoutingCriteria criteria = analyzeCriteria(message);
// Primary destination based on message type and priority
destinations.add(determinePrimaryDestination(criteria));
// Additional destinations based on content characteristics
destinations.addAll(determineSecondaryDestinations(criteria));
// Compliance and audit destinations
destinations.addAll(determineComplianceDestinations(criteria));
return destinations.stream().distinct().collect(Collectors.toList());
}
private RoutingCriteria analyzeCriteria(ComplexMessage message) {
return RoutingCriteria.builder()
.messageType(message.getType())
.priority(message.getPriority())
.customerTier(extractCustomerTier(message))
.geographicRegion(extractRegion(message))
.dataClassification(extractDataClassification(message))
.complianceRequirements(extractComplianceRequirements(message))
.messageSize(message.getPayload().length())
.urgency(calculateUrgency(message))
.build();
}
private String determinePrimaryDestination(RoutingCriteria criteria) {
if (criteria.getUrgency() == Urgency.CRITICAL) {
return "critical-processor";
}
if (criteria.getCustomerTier() == CustomerTier.ENTERPRISE) {
return "enterprise-processor";
}
// Route based on message type and region
return criteria.getMessageType().toString().toLowerCase() + "-" +
criteria.getGeographicRegion().toString().toLowerCase() + "-processor";
}
private List<String> determineSecondaryDestinations(RoutingCriteria criteria) {
List<String> destinations = new ArrayList<>();
// Analytics destinations
if (criteria.getMessageType().isAnalyticsEligible()) {
destinations.add("analytics-collector");
}
// Monitoring destinations
if (criteria.getUrgency().ordinal() >= Urgency.HIGH.ordinal()) {
destinations.add("priority-monitor");
}
// Backup destinations for high-value messages
if (criteria.getCustomerTier() == CustomerTier.VIP) {
destinations.add("vip-backup-processor");
}
return destinations;
}
private List<String> determineComplianceDestinations(RoutingCriteria criteria) {
List<String> destinations = new ArrayList<>();
// GDPR compliance
if (criteria.getGeographicRegion().isEURegion() &&
criteria.getDataClassification().isPersonalData()) {
destinations.add("gdpr-compliance-processor");
}
// Financial compliance
if (criteria.getMessageType().isFinancial() &&
criteria.getComplianceRequirements().contains(ComplianceType.FINANCIAL)) {
destinations.add("financial-compliance-processor");
}
// Audit requirements
if (criteria.getDataClassification().requiresAudit()) {
destinations.add("audit-logger");
}
return destinations;
}
}
Apache Camel Implementation
1. Simple Content-Based Router
@Component
public class SimpleContentBasedRouterRoute extends RouteBuilder {
@Override
public void configure() throws Exception {
from("direct:contentBasedRoute")
.routeId("content-based-router")
.log("Analyzing message content for routing")
.choice()
.when(jsonpath("$.messageType == 'PAYMENT'"))
.to("direct:routePayment")
.when(jsonpath("$.messageType == 'ORDER'"))
.to("direct:routeOrder")
.when(jsonpath("$.messageType == 'CUSTOMER'"))
.to("direct:routeCustomer")
.when(header("urgent").isEqualTo("true"))
.to("direct:urgentProcessor")
.otherwise()
.to("direct:defaultProcessor")
.end();
from("direct:routePayment")
.log("Routing payment message")
.choice()
.when(jsonpath("$.amount > 10000"))
.to("direct:highValuePaymentProcessor")
.when(jsonpath("$.currency != 'EUR'"))
.to("direct:internationalPaymentProcessor")
.otherwise()
.to("direct:standardPaymentProcessor")
.end();
from("direct:routeOrder")
.log("Routing order message")
.choice()
.when(jsonpath("$.expressDelivery == true"))
.to("direct:expressOrderProcessor")
.when(jsonpath("$.items.length() > 10"))
.to("direct:bulkOrderProcessor")
.otherwise()
.to("direct:standardOrderProcessor")
.end();
}
}
2. Header and Content Combined Router
@Component
public class HeaderContentRouterRoute extends RouteBuilder {
@Override
public void configure() throws Exception {
from("direct:combinedContentRouter")
.routeId("header-content-router")
.log("Routing based on headers and content")
.choice()
// Route based on customer tier (header) and message content
.when(and(header("customerTier").isEqualTo("VIP"),
jsonpath("$.priority == 'HIGH'")))
.to("direct:vipHighPriorityProcessor")
// Route based on region and message type
.when(and(header("region").in("EU", "NORDICS"),
jsonpath("$.messageType == 'COMPLIANCE'")))
.to("direct:euComplianceProcessor")
// Route based on content size and type
.when(and(jsonpath("$.data.length() > 1000"),
header("messageType").isEqualTo("BATCH")))
.to("direct:largeBatchProcessor")
// Route based on customer segment from content
.when(jsonpath("$.customer.segment == 'ENTERPRISE'"))
.to("direct:enterpriseProcessor")
// Default routing
.otherwise()
.to("direct:standardProcessor")
.end();
}
}
3. XPath-Based XML Content Router
@Component
public class XPathContentRouterRoute extends RouteBuilder {
@Override
public void configure() throws Exception {
from("direct:xmlContentRouter")
.routeId("xpath-content-router")
.log("Routing XML content based on XPath expressions")
.choice()
// Route based on document type
.when(xpath("/document/@type = 'invoice'"))
.to("direct:routeInvoice")
// Route based on priority
.when(xpath("/document/header/priority/text() = 'urgent'"))
.to("direct:urgentProcessor")
// Route based on customer type
.when(xpath("//customer/@type = 'enterprise'"))
.to("direct:enterpriseProcessor")
// Route based on amount
.when(xpath("//amount/text() > 5000"))
.to("direct:highValueProcessor")
.otherwise()
.to("direct:defaultXmlProcessor")
.end();
from("direct:routeInvoice")
.choice()
.when(xpath("//invoice/amount/text() > 10000"))
.to("direct:largeInvoiceProcessor")
.when(xpath("//invoice/@type = 'credit'"))
.to("direct:creditInvoiceProcessor")
.otherwise()
.to("direct:standardInvoiceProcessor")
.end();
}
}
4. Dynamic Content Router with Rules
@Component
public class DynamicContentRouterRoute extends RouteBuilder {
@Autowired
private ContentRoutingService routingService;
@Override
public void configure() throws Exception {
from("direct:dynamicContentRouter")
.routeId("dynamic-content-router")
.log("Applying dynamic content routing rules")
.process(exchange -> {
Object messageBody = exchange.getIn().getBody();
Map<String, Object> headers = exchange.getIn().getHeaders();
RoutingDecision decision = routingService.determineRoute(messageBody, headers);
exchange.getIn().setHeader("routingDecision", decision);
exchange.getIn().setHeader("primaryDestination", decision.getPrimaryDestination());
exchange.getIn().setHeader("secondaryDestinations", decision.getSecondaryDestinations());
})
.log("Primary destination: ${header.primaryDestination}")
.recipientList(header("primaryDestination"))
.choice()
.when(header("secondaryDestinations").isNotNull())
.process(exchange -> {
List<String> secondaryDestinations =
exchange.getIn().getHeader("secondaryDestinations", List.class);
if (secondaryDestinations != null && !secondaryDestinations.isEmpty()) {
String destinations = String.join(",", secondaryDestinations);
exchange.getIn().setHeader("additionalDestinations", destinations);
}
})
.recipientList(header("additionalDestinations"))
.parallelProcessing()
.stopOnException()
.end();
}
}
@Service
public class ContentRoutingService {
public RoutingDecision determineRoute(Object messageBody, Map<String, Object> headers) {
MessageAnalysisResult analysis = analyzeMessage(messageBody, headers);
String primaryDestination = determinePrimaryRoute(analysis);
List<String> secondaryDestinations = determineSecondaryRoutes(analysis);
return RoutingDecision.builder()
.primaryDestination(primaryDestination)
.secondaryDestinations(secondaryDestinations)
.analysisResult(analysis)
.build();
}
private MessageAnalysisResult analyzeMessage(Object messageBody, Map<String, Object> headers) {
// Implement message analysis logic
return MessageAnalysisResult.builder()
.messageType(extractMessageType(messageBody, headers))
.priority(extractPriority(messageBody, headers))
.customerInfo(extractCustomerInfo(messageBody, headers))
.contentCharacteristics(analyzeContent(messageBody))
.build();
}
}
5. Multi-Destination Content Router
@Component
public class MultiDestinationContentRouterRoute extends RouteBuilder {
@Override
public void configure() throws Exception {
from("direct:multiDestinationRouter")
.routeId("multi-destination-content-router")
.log("Routing to multiple destinations based on content")
.process(exchange -> {
List<String> destinations = new ArrayList<>();
// Always route to primary processor
destinations.add("direct:primaryProcessor");
// Add audit destination for sensitive data
if (containsSensitiveData(exchange.getIn().getBody())) {
destinations.add("direct:auditProcessor");
}
// Add compliance destination for regulated industries
if (isRegulatedIndustry(exchange.getIn().getHeaders())) {
destinations.add("direct:complianceProcessor");
}
// Add analytics destination for business events
if (isBusinessEvent(exchange.getIn().getBody())) {
destinations.add("direct:analyticsProcessor");
}
String recipientList = String.join(",", destinations);
exchange.getIn().setHeader("recipientList", recipientList);
})
.log("Sending to destinations: ${header.recipientList}")
.recipientList(header("recipientList"))
.parallelProcessing()
.stopOnException();
}
private boolean containsSensitiveData(Object body) {
// Implementation to detect sensitive data
if (body instanceof Map) {
Map<?, ?> data = (Map<?, ?>) body;
return data.containsKey("ssn") || data.containsKey("creditCard") ||
data.containsKey("personalData");
}
return false;
}
private boolean isRegulatedIndustry(Map<String, Object> headers) {
String industry = (String) headers.get("industry");
return "FINANCIAL".equals(industry) || "HEALTHCARE".equals(industry) ||
"PHARMACEUTICAL".equals(industry);
}
private boolean isBusinessEvent(Object body) {
if (body instanceof Map) {
Map<?, ?> data = (Map<?, ?>) body;
String eventType = (String) data.get("eventType");
return eventType != null && (eventType.startsWith("business.") ||
eventType.contains("transaction"));
}
return false;
}
}
Best Practices
1. Content Analysis Optimization
- Minimize content inspection overhead by analyzing only necessary fields
- Use efficient parsing libraries and techniques for content extraction
- Cache content analysis results when the same message is processed multiple times
- Implement early exit strategies in routing rule evaluation
- Consider using streaming parsers for large messages
2. Routing Rule Management
- Externalize routing rules to enable runtime configuration changes
- Implement rule versioning and rollback capabilities
- Use rule engines for complex routing logic
- Validate routing rules before deployment
- Provide clear documentation and business justification for routing rules
3. Error Handling and Fallbacks
- Implement default routing destinations for unmatched content
- Provide graceful handling of malformed or unparseable content
- Use circuit breakers for unreliable destination systems
- Implement retry logic for transient routing failures
- Log routing decisions for debugging and audit purposes
4. Performance and Scalability
- Use appropriate content parsing strategies (DOM vs. streaming)
- Implement parallel routing rule evaluation where possible
- Cache frequently accessed routing configuration
- Monitor routing performance and optimize slow rules
- Consider using content hashing for routing decisions when appropriate
5. Security and Compliance
- Ensure routing rules don't expose sensitive content in logs
- Implement proper access controls for routing configuration
- Validate routing destinations to prevent injection attacks
- Audit routing decisions for compliance requirements
- Use secure channels for routing configuration management
The Content-Based Router pattern is fundamental for building intelligent, adaptive integration solutions that can make sophisticated routing decisions based on message content, enabling flexible and business-driven message flows in complex enterprise architectures.
← Back to All Patterns