Enterprise Integration Patterns in Java (2025)

Enterprise Integration Patterns (EIP) provide solutions for common integration challenges. This comprehensive guide explores various integration patterns and their implementations in Java.
Pro Tip: Understanding integration patterns helps in building scalable and maintainable enterprise applications.
Table of Contents
Message Routing
Note: Message routing patterns determine how messages flow between different components.
Content-Based Router
@Component
public class ContentBasedRouter {
@Autowired
private OrderProcessor orderProcessor;
@Autowired
private PaymentProcessor paymentProcessor;
public void route(Message message) {
Order order = (Order) message.getPayload();
switch (order.getType()) {
case "STANDARD":
orderProcessor.processStandardOrder(order);
break;
case "EXPRESS":
orderProcessor.processExpressOrder(order);
break;
case "PAYMENT":
paymentProcessor.processPayment(order);
break;
default:
throw new IllegalArgumentException("Unknown order type: " + order.getType());
}
}
}
@Configuration
public class RouterConfig {
@Bean
public IntegrationFlow orderFlow() {
return IntegrationFlows
.from("orderChannel")
.route(Message.class, message -> {
Order order = (Order) message.getPayload();
return order.getType().toLowerCase();
})
.channelMapping("standard", "standardOrderChannel")
.channelMapping("express", "expressOrderChannel")
.channelMapping("payment", "paymentChannel")
.get();
}
}
Message Filter
@Component
public class OrderFilter {
public boolean accept(Message message) {
Order order = (Order) message.getPayload();
return order.getAmount() > 1000 && order.getStatus().equals("PENDING");
}
}
@Configuration
public class FilterConfig {
@Bean
public IntegrationFlow filterFlow() {
return IntegrationFlows
.from("orderChannel")
.filter(Message.class, message -> {
Order order = (Order) message.getPayload();
return order.getAmount() > 1000 && order.getStatus().equals("PENDING");
})
.channel("filteredOrderChannel")
.get();
}
}
Message Transformation
Pro Tip: Message transformation patterns help in converting messages between different formats.
Message Translator
@Component
public class OrderTranslator {
public PaymentRequest translate(Order order) {
return PaymentRequest.builder()
.orderId(order.getId())
.amount(order.getAmount())
.currency(order.getCurrency())
.customerId(order.getCustomerId())
.build();
}
}
@Configuration
public class TranslatorConfig {
@Bean
public IntegrationFlow translationFlow() {
return IntegrationFlows
.from("orderChannel")
.transform(Order.class, order -> {
return PaymentRequest.builder()
.orderId(order.getId())
.amount(order.getAmount())
.currency(order.getCurrency())
.customerId(order.getCustomerId())
.build();
})
.channel("paymentChannel")
.get();
}
}
Content Enricher
@Component
public class OrderEnricher {
@Autowired
private CustomerService customerService;
public EnrichedOrder enrich(Order order) {
Customer customer = customerService.getCustomer(order.getCustomerId());
return EnrichedOrder.builder()
.order(order)
.customerName(customer.getName())
.customerEmail(customer.getEmail())
.build();
}
}
@Configuration
public class EnricherConfig {
@Bean
public IntegrationFlow enrichmentFlow() {
return IntegrationFlows
.from("orderChannel")
.enrich(enricher -> enricher
.requestChannel("customerLookupChannel")
.requestPayload(Message::getPayload)
.propertyFunction("customerName",
response -> ((Customer) response).getName())
.propertyFunction("customerEmail",
response -> ((Customer) response).getEmail()))
.channel("enrichedOrderChannel")
.get();
}
}
Message Endpoints
Note: Message endpoints connect messaging systems to other systems.
Service Activator
@Component
public class OrderServiceActivator {
@Autowired
private OrderService orderService;
public void handleOrder(Message message) {
Order order = message.getPayload();
orderService.processOrder(order);
}
}
@Configuration
public class ServiceActivatorConfig {
@Bean
public IntegrationFlow serviceActivatorFlow() {
return IntegrationFlows
.from("orderChannel")
.handle(message -> {
Order order = (Order) message.getPayload();
orderService.processOrder(order);
})
.get();
}
}
Gateway
@MessagingGateway
public interface OrderGateway {
@Gateway(requestChannel = "orderChannel")
OrderResponse submitOrder(Order order);
@Gateway(requestChannel = "orderStatusChannel")
OrderStatus getOrderStatus(String orderId);
}
@Configuration
public class GatewayConfig {
@Bean
public IntegrationFlow gatewayFlow() {
return IntegrationFlows
.from("orderChannel")
.handle(orderService::processOrder)
.transform(order -> OrderResponse.builder()
.orderId(order.getId())
.status(order.getStatus())
.build())
.get();
}
}
System Management
Pro Tip: System management patterns help in monitoring and controlling integration systems.
Circuit Breaker
@Component
public class CircuitBreaker {
private final int threshold;
private final long timeout;
private int failureCount;
private long lastFailureTime;
private CircuitState state;
public CircuitBreaker(int threshold, long timeout) {
this.threshold = threshold;
this.timeout = timeout;
this.state = CircuitState.CLOSED;
}
public boolean execute(Supplier operation) {
if (state == CircuitState.OPEN) {
if (System.currentTimeMillis() - lastFailureTime > timeout) {
state = CircuitState.HALF_OPEN;
} else {
return false;
}
}
try {
boolean result = operation.get();
if (state == CircuitState.HALF_OPEN) {
state = CircuitState.CLOSED;
failureCount = 0;
}
return result;
} catch (Exception e) {
failureCount++;
lastFailureTime = System.currentTimeMillis();
state = CircuitState.OPEN;
return false;
}
}
private enum CircuitState {
CLOSED, OPEN, HALF_OPEN
}
}
Message Store
@Component
public class MessageStore {
private final Map> store = new ConcurrentHashMap<>();
public void store(String id, Message message) {
store.put(id, message);
}
public Message retrieve(String id) {
return store.get(id);
}
public void remove(String id) {
store.remove(id);
}
}
@Configuration
public class MessageStoreConfig {
@Bean
public IntegrationFlow messageStoreFlow() {
return IntegrationFlows
.from("inputChannel")
.handle(message -> {
String id = UUID.randomUUID().toString();
messageStore.store(id, message);
})
.channel("outputChannel")
.get();
}
}
Best Practices
Pro Tip: Following integration patterns best practices ensures reliable and maintainable systems.
Integration Best Practices
- Use appropriate message channels
- Implement proper error handling
- Use message transformation when needed
- Implement proper monitoring
- Use circuit breakers for external services
- Implement proper logging
- Use message stores for reliability
- Implement proper testing
- Use appropriate message formats
- Implement proper security
- Use proper configuration management
- Implement proper documentation
- Use proper versioning
- Implement proper monitoring
- Follow integration standards
Conclusion
Enterprise Integration Patterns provide proven solutions for common integration challenges. By implementing these patterns and following best practices, you can build robust and maintainable enterprise applications.