[[groovy-dsl]]
= Groovy DSL

The Groovy DSL is a wrapper and extension to xref:dsl.adoc#java-dsl[Java DSL].
The main goal we pursue here is to make Spring Integration development on Groovy as smooth and straightforward as is it possible with interoperability with existing Java DSL and some Groovy extensions or language-specific structures.
The implementation is a part of xref:groovy.adoc[Groovy Support] module.

All you need to get started is just an import for `import static org.springframework.integration.groovy.dsl.IntegrationGroovyDsl.integrationFlow` - a class containing overloaded factory methods for the Groovy DSL.

For `IntegrationFlow` definitions as lambdas we typically don't need anything else from Groovy and just declare a bean like this:

[source, groovy]
----
@Bean
IntegrationFlow oddFlow() {
    { IntegrationFlowDefinition flow ->
	    flow.handle(Object, { p, h -> 'odd' })
    }
}
----

In this case Groovy understands that the closure should be translated into an `IntegrationFlow` anonymous instance and the target Java DSL processor parses this construction properly into Java objects.

As an alternative to the construction above and for consistency with use-cases explained below, the `spring-integration-groovy` module provides a Groovy-specific DSL for declaring integration flows in a *builder* pattern style:

[source, groovy]
----
@Bean
flowLambda() {
    integrationFlow {
        filter String, { it == 'test' }, { id 'filterEndpoint' }
        wireTap integrationFlow {
            channel { queue 'wireTapChannel' }
        }
        delay {
		    messageGroupId 'delayGroup'
		    defaultDelay 100
        }
        transform {
		    transformer { it.toUpperCase() }
            expectedType String
        }
    }
}
----

Such a global `integrationFlow()` function expects a closure in the builder style for a `GroovyIntegrationFlowDefinition` (a Groovy wrapper for the `IntegrationFlowDefinition`) and produces a regular `IntegrationFlow` lambda implementation.
See more overloaded `integrationFlow()` variants below.

Many other scenarios require an `IntegrationFlow` to be started from the source of data (e.g. `JdbcPollingChannelAdapter`, `JmsInboundGateway` or just an existing `MessageChannel`).
For this purpose, Spring Integration Java DSL provides an `IntegrationFlow` factory with a number of overloaded `from()` methods.
This factory can be used in groovy as well:

[source, groovy]
----
@Bean
flowFromSupplier() {
    IntegrationFlow.fromSupplier({ 'bar' }) { e -> e.poller { p -> p.fixedDelay(10).maxMessagesPerPoll(1) } }
            .channel({ c -> c.queue('fromSupplierQueue') } as Function)
            .get()
}
----

But unfortunately not all `from()` methods are compatible with Groovy structures.
To solve this, Spring Integration provides a Groovy DSL factory around the `IntegrationFlow` factory.
It is implemented as a set of overloaded `integrationFlow()` functions.
With a consumer for a `GroovyIntegrationFlowDefinition` to declare the remainder of the flow as an `IntegrationFlow` closure to reuse the mentioned above experience and also avoid the need for a `get()` call in the end.
For example:

[source, groovy]
----
@Bean
functionFlow() {
    integrationFlow Function<byte[], String>,
            { beanName 'functionGateway' },
            {
                transform {
		            transformer Transformers.objectToString()
                    id 'objectToStringTransformer'
                }
                transform {
		            transformer { it.toUpperCase() }
                    expectedType String
                }
                splitWith {
                    expectedType Message<?>
                    function { it.payload }
                }
                splitWith {
                    expectedType Object
                    id 'splitterEndpoint'
                    function { it }
                }
                resequence()
                aggregate {
                    id 'aggregator'
                    outputProcessor { it.one }
                }
            }
}

@Bean
someFlow() {
    integrationFlow ({ 'test' },
            {
                poller { it.trigger new OnlyOnceTrigger() }
                id 'pollingSource'
            })
            {
                log LoggingHandler.Level.WARN, 'test.category'
                channel { queue 'pollerResultChannel' }
            }
}
----
