javaspring-integrationhexagonal-architecture

Can we mix Enterprise Integration Pattern and Hexagonal architecture


Trying to understand how we would use Hexagonal architecture with EIP.

In the Spring Boot example I have below, the UserMessageHandler is a part of the inbound adapter (according to me) and is calling a method on the inbound port (InboundPortService)

However it seems like the UserMessageHandler is not doing anything useful (any logging ,data transforming, filtering etc that I need to do, I can do in the integration flow itself before calling the UserMessageHandler)

So wanted to get ideas on how to do this better

TIA

public class UserMessageHandler implements GenericHandler<User> {
  private final InboundPortService inboundPortService;
  // all arg constructor here
  
  @Override
  public Object handle(User user, MessageHeaders headers) {
    inboundPortService.processUser(user);
  }
}

public interface InboundPortService {
  User processUser(User user);
}

public class InboundPortServiceImpl implements InboundPortService {
  public User processUser(User user){
    // ...
  }
}


public class Application {

  @Bean
  public IntegrationFlow userSyncFlow(UserMessageHandler userMessageHandler, SomeObjecToUserObjectTransformer someObjecToUserObjectTransformer) {
        return IntegrationFlow
                .from("userInfoChannel")
                .log(DEBUG, m -> "Received userinfo: " + m.getPayload())
                .transform(someObjecToUserObjectTransformer)
                .handle(userMessageHandler)
                .get();
    }
}

Solution

  • According to Wikipedia the Hexagonal Architecture is:

    It aims at creating loosely coupled application components that can be easily connected to their software environment by means of ports and adapters. This makes components exchangeable at any level and facilitates test automation.

    And EIP with Spring Integration is:

    Goals and Principles
    
    Spring Integration is motivated by the following goals:
    
        Provide a simple model for implementing complex enterprise integration solutions.
    
        Facilitate asynchronous, message-driven behavior within a Spring-based application.
    
        Promote intuitive, incremental adoption for existing Spring users.
    
    Spring Integration is guided by the following principles:
    
        Components should be loosely coupled for modularity and testability.
    
        The framework should enforce separation of concerns between business logic and integration logic.
    
        Extension points should be abstract in nature (but within well-defined boundaries) to promote reuse and portability.
    

    So, for me that sounds like Spring Integration with its Messaging foundation is a good fit into the mentioned Hexagonal Architecture. No one mandates you how it is implemented when we use adapters around those ports and trigger them by the event. In case of Spring Integration it is a message sent to an inbound channel of the adapter's endpoint.

    Probably you are really just confused by that extra UserMessageHandler abstraction around your port. You may look into another handle() impl where you can just pass your InboundPortService and the framework will properly select a method to call for the inbound User data from a message payload. See more info in docs: https://docs.spring.io/spring-integration/reference/overview.html#pojo-invocation

    If you think about more encapsulation in some service, but still gain a benefit from Spring Integration, you can look into an IntegrationFlowAdapter: https://docs.spring.io/spring-integration/reference/dsl/java-flow-adapter.html