'Spring Integration - how to route based on a header value using the Kotlin DSL

Assuming I've got a header with a property called "count" on it, how do I route based on that value ?

In the Kotlin DSL there is the route function, but I'm unsure how to configure it to be a HeaderValueRouter

The documentation says the following for the Java DSL,but it isn't clear to me how I can get hold of the headers within the router block.

Does anyone have an example (Kotlin and Java DSLs ) ?

Spring Integration natively provides specialized router types, including:

HeaderValueRouter

PayloadTypeRouter

ExceptionTypeRouter

RecipientListRouter

XPathRouter

As with many other DSL IntegrationFlowBuilder EIP methods, the route() method can apply any AbstractMessageRouter implementation or, for convenience, a String as a SpEL expression or a ref-method pair. In addition, you can configure route() with a lambda and use a lambda for a Consumer<RouterSpec>.



Solution 1:[1]

Here is a Unit test which demonstrates how your request is possible with Kotlin DSL:

@SpringJUnitConfig
@DirtiesContext
class RouterDslTests {

    @Autowired
    @Qualifier("routeByHeader.input")
    private lateinit var routeByHeaderInputChannel: MessageChannel

    @Autowired
    private lateinit var fooChannel: PollableChannel

    @Autowired
    private lateinit var barChannel: PollableChannel

    @Test
    fun `route by header`() {
        var message = MessageBuilder.withPayload("test1")
            .setHeader("my_route", "foo")
            .build()

        this.routeByHeaderInputChannel.send(message)

        var receive = this.fooChannel.receive(10_000)
        var payload = receive?.payload
        assertThat(payload)
            .isNotNull()
            .isEqualTo("test1")

        message = MessageBuilder.withPayload("test2")
            .setHeader("my_route", "bar")
            .build()

        this.routeByHeaderInputChannel.send(message)

        receive = this.barChannel.receive(10_000)
        payload = receive?.payload
        assertThat(payload)
            .isNotNull()
            .isEqualTo("test2")
    }

    @Configuration
    @EnableIntegration
    class Config {

        @Bean
        fun routeByHeader() =
            integrationFlow {
                route<Message<*>, String>({ it.headers["my_route"].toString() }) {
                    suffix("Channel")
                }
            }

        @Bean
        fun fooChannel() = QueueChannel()

        @Bean
        fun barChannel() = QueueChannel()
    }

}

What you just need is to enforce a route() function to deal with the whole Message as input. Then you have access to its headers in the lambda.

This might not be explained in the Kotlin DSL docs, but here is something in Java DSL: https://docs.spring.io/spring-integration/docs/current/reference/html/dsl.html#java-dsl-class-cast

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Artem Bilan