0
votes

In attempting to modularize Spring Integration flows, I've started using a pattern where I put inbound and outbound gateways in separate classes, then import them where necessary to build flows. As an example, here is a minimal integration testing showing a rough approach:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = { SampleIntegrationFlowTest.class })
@SpringIntegrationTest
@EnableIntegration
public class SampleIntegrationFlowTest {

    @Autowired
    private InboundGateways inboundGateways;

    @Autowired
    private OutboundGateways outboundGateways;

    @Test
    public void testFlow1() {
        StandardIntegrationFlow flow = IntegrationFlows
            .from(inboundGateways.createAccount())
            .transform(new JsonToXmlTransformer())
            .handle(outboundGateways.soapAccount())
            .transform(new XmlToJsonTransformer())
            .get();

        flow.start();
    }

    @Test
    public void testFlow2() {
        StandardIntegrationFlow flow = IntegrationFlows
            .from(inboundGateways.searchAccount())
            .transform(new JsonToXmlTransformer())
            .handle(outboundGateways.soapAccount())
            .transform(new XmlToJsonTransformer())
            .get();

        flow.start();
    }

    @Configuration
    static class InboundGateways {

        @Gateway
        public MessagingGatewaySupport createAccount() {
            return WebFlux.inboundGateway("/accounts")
                .requestMapping(mapping -> mapping
                    .consumes("application/json")
                    .produces("application/json")
                    .methods(HttpMethod.POST))
                .get();
        }

        @Gateway
        public MessagingGatewaySupport searchAccount() {
            return WebFlux.inboundGateway("/accounts")
                .requestMapping(mapping -> mapping
                    .produces("application/json")
                    .methods(HttpMethod.GET))
                .headerExpression("name", "#requestParams.name")
                .get();
        }

    }

    @Configuration
    static class OutboundGateways {

        @Gateway
        public MessageHandler soapAccount() {
            return new SimpleWebServiceOutboundGateway("http://example.com/accounts");
        }

    }
}

I structure it this way so that I can:

  1. Group inbound gateways together so that I can generate the InboundGateways class from a Swagger contract.
  2. Be able to reuse the outbound gateway from multiple flows (several inbound rest endpoints route to the same outbound soap endpoint).

Questions:

  1. Are there any downsides to the way I've structured this? Any ways to improve it, given the goals noted above?
  2. Is there an opportunity to "model" the inbound gateways as interfaces annotated with @MessagingGateway/@Gateway so that I can interact with them like a normal pojo? This could be useful when integrating into existing code or via integration tests. If there is a way, I can't figure out how to do something like Webflux.inboundGateway(
1

1 Answers

0
votes
  1. The @Gateway annotation there does nothing.

I see no issues with your approach; you can't re-use outbound gateways (if declared as @Bean - it's ok the way you have it). This is because any reply-producing MessageHandler can only have one output channel.

  1. No; @MessagingGateway is for creating a GatewayProxyFactoryBean - for interfacing from legacy Java code to the integration flow.