Recipient List – 동적 수신자 목록
Recipient List 패턴은 메시지를 받아야 할 대상 목록을 런타임에 동적으로 결정합니다. 발행/구독 패턴의 유연한 변형으로, 각 메시지마다 다른 수신자 집합을 가질 수 있습니다.
기본 Recipient List 구현
from("direct:distribute")
// 헤더에서 수신자 목록 읽기 (콤마로 구분)
.recipientList(header("recipients"))
.delimiter(","); // 기본값은 콤마
// 예: header("recipients") = "direct:billing,direct:inventory,direct:crm"
// → 세 곳 모두에 메시지 전달
Bean으로 수신자 목록 계산
@Component
public class RecipientCalculator {
public List<String> calculateRecipients(Exchange exchange) {
Order order = exchange.getIn().getBody(Order.class);
List<String> recipients = new ArrayList<>();
recipients.add("direct:inventory"); // 항상 재고 확인
if (order.getAmount() > 500000) {
recipients.add("direct:fraudCheck"); // 고액 주문 사기 검사
}
if (order.isOverseas()) {
recipients.add("direct:customsClearance"); // 해외 통관
}
return recipients;
}
}
// 라우트에서 사용
from("direct:newOrder")
.recipientList(bean(RecipientCalculator.class, "calculateRecipients"))
.parallelProcessing();
병렬 처리와 집계
from("direct:orderCheck")
.recipientList(constant("direct:inventoryCheck,direct:creditCheck,direct:addressCheck"))
.parallelProcessing() // 병렬 실행
.aggregationStrategy(new OrderCheckAggregator()) // 결과 집계
.timeout(5000); // 5초 타임아웃
// 집계 전략
public class OrderCheckAggregator implements AggregationStrategy {
@Override
public Exchange aggregate(Exchange oldEx, Exchange newEx) {
if (oldEx == null) return newEx;
// 결과 합치기
String combined = oldEx.getIn().getBody(String.class)
+ "," + newEx.getIn().getBody(String.class);
oldEx.getIn().setBody(combined);
return oldEx;
}
}
@RecipientList 어노테이션
Bean 메서드에 어노테이션을 달아 더 간결하게 구현할 수 있습니다.
@Component
public class OrderRouter {
@RecipientList
public String[] route(@Header("orderType") String type,
@Body Order order) {
if ("EXPRESS".equals(type)) {
return new String[]{"direct:express", "direct:notify"};
}
return new String[]{"direct:standard"};
}
}
// 라우트
from("direct:order")
.bean(OrderRouter.class);
stopOnException 옵션
from("direct:notify")
.recipientList(header("subscribers"))
.stopOnException() // 하나라도 실패하면 중단
.ignoreInvalidEndpoints(); // 잘못된 URI는 무시
Recipient List vs Multicast 차이점
- Multicast: 컴파일 시점에 수신자가 고정됨
- Recipient List: 런타임에 메시지 내용을 보고 수신자 결정
- Dynamic Router: 각 수신자 처리 후 다음 수신자를 동적으로 결정 (상태 기반)
Wire Tap으로 감사 추적
from("direct:processPayment")
.wireTap("direct:auditTrail") // 감사 로그 비동기 복사
.newExchangeBody(simple("결제 요청: ${body.paymentId} 금액: ${body.amount}"))
.to("direct:executePayment")
from("direct:auditTrail")
.to("jms:queue:audit-log");