[[groovy]]
=== Groovy support

In Spring Integration 2.0, we added Groovy support, letting you use the Groovy scripting language to provide the logic for various integration components -- similar to the way the Spring Expression Language (SpEL) is supported for routing, transformation, and other integration concerns.
For more information about Groovy, see the Groovy documentation, which you can find on the https://groovy-lang.org/[project website].

You need to include this dependency into your project:

====
.Maven
[source, xml, subs="normal"]
----
<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-groovy</artifactId>
    <version>{project-version}</version>
</dependency>
----

.Gradle
[source, groovy, subs="normal"]
----
compile "org.springframework.integration:spring-integration-groovy:{project-version}"
----
====

[[groovy-config]]
==== Groovy Configuration

With Spring Integration 2.1, the configuration namespace for the Groovy support is an extension of Spring Integration's scripting support and shares the core configuration and behavior described in detail in the <<./scripting.adoc#scripting,Scripting Support>> section.
Even though Groovy scripts are well supported by generic scripting support, the Groovy support provides the `Groovy` configuration namespace, which is backed by the Spring Framework's `org.springframework.scripting.groovy.GroovyScriptFactory` and related components, offering extended capabilities for using Groovy.
The following listing shows two sample configurations:

.Filter
====
[source,xml]
----
<int:filter input-channel="referencedScriptInput">
   <int-groovy:script location="some/path/to/groovy/file/GroovyFilterTests.groovy"/>
</int:filter>

<int:filter input-channel="inlineScriptInput">
     <int-groovy:script><![CDATA[
     return payload == 'good'
   ]]></int-groovy:script>
</int:filter>
----
====

As the preceding examples show, the configuration looks identical to the general scripting support configuration.
The only difference is the use of the Groovy namespace, as indicated by the `int-groovy` namespace prefix.
Also note that the `lang` attribute on the `<script>` tag is not valid in this namespace.

==== Groovy Object Customization

If you need to customize the Groovy object itself (beyond setting variables) you can reference a bean that implements `GroovyObjectCustomizer` by using the `customizer` attribute.
For example, this might be useful if you want to implement a domain-specific language (DSL) by modifying the `MetaClass` and registering functions to be available within the script.
The following example shows how to do so:

====
[source,xml]
----
<int:service-activator input-channel="groovyChannel">
    <int-groovy:script location="somewhere/SomeScript.groovy" customizer="groovyCustomizer"/>
</int:service-activator>

<beans:bean id="groovyCustomizer" class="org.something.MyGroovyObjectCustomizer"/>
----
====

Setting a custom `GroovyObjectCustomizer` is not mutually exclusive with `<variable>` elements or the `script-variable-generator` attribute.
It can also be provided when defining an inline script.

Spring Integration 3.0 introduced the `variables` attribute, which works in conjunction with the `variable` element.
Also, groovy scripts have the ability to resolve a variable to a bean in the `BeanFactory`, if a binding variable was not provided with the name.
The following example shows how to use a variable (`entityManager`):

====
[source,xml]
----
<int-groovy:script>
    <![CDATA[
        entityManager.persist(payload)
        payload
    ]]>
</int-groovy:script>
----
====

`entityManager` must be an appropriate bean in the application context.

For more information regarding the `<variable>` element, the `variables` attribute, and the `script-variable-generator` attribute, see  <<./scripting.adoc#scripting-script-variable-bindings,Script Variable Bindings>>.

==== Groovy Script Compiler Customization

The `@CompileStatic` hint is the most popular Groovy compiler customization option.
It can be used on the class or method level.
For more information, see the Groovy https://groovy-lang.org/metaprogramming.html#section-typechecked[Reference Manual] and, specifically, https://groovy-lang.org/metaprogramming.html#xform-CompileStatic[@CompileStatic].
To utilize this feature for short scripts (in integration scenarios), we are forced to change simple scripts to more Java-like code.
Consider the following `<filter>` script:

====
[source,groovy]
----
headers.type == 'good'
----
====

The preceding script becomes the following method in Spring Integration:

====
[source,groovy]
----
@groovy.transform.CompileStatic
String filter(Map headers) {
	headers.type == 'good'
}

filter(headers)
----
====

With that, the `filter()` method is transformed and compiled to static Java code, bypassing the Groovy
dynamic phases of invocation, such as `getProperty()` factories and `CallSite` proxies.

Starting with version 4.3, you can configure the Spring Integration Groovy components with the `compile-static` `boolean` option, specifying that `ASTTransformationCustomizer` for `@CompileStatic` should be added to the internal `CompilerConfiguration`.
With that in place, you can omit the method declaration with `@CompileStatic` in our script code and still get compiled
plain Java code.
In this case, the preceding script can be short but still needs to be a little more verbose than interpreted script, as the following example shows:

====
[source,groovy]
----
binding.variables.headers.type == 'good'
----
====

You must access the `headers` and `payload` (or any other) variables through the `groovy.lang.Script` `binding` property because, with `@CompileStatic`, we do not have the  dynamic `GroovyObject.getProperty()` capability.

In addition, we introduced the `compiler-configuration` bean reference.
With this attribute, you can provide any other required Groovy compiler customizations, such as `ImportCustomizer`.
For more information about this feature, see the Groovy Documentation for https://melix.github.io/blog/2011/05/12/customizing_groovy_compilation_process.html[advanced compiler configuration].

NOTE: Using `compilerConfiguration` does not automatically add an `ASTTransformationCustomizer` for the `@CompileStatic` annotation, and it overrides the `compileStatic` option.
If you still need `CompileStatic`, you should manually add a `new ASTTransformationCustomizer(CompileStatic.class)` into the `CompilationCustomizers` of that custom `compilerConfiguration`.

NOTE: The Groovy compiler customization does not have any effect on the `refresh-check-delay` option, and reloadable scripts can be statically compiled, too.

[[groovy-control-bus]]
==== Control Bus

As described in (https://www.enterpriseintegrationpatterns.com/ControlBus.html[Enterprise Integration Patterns]), the idea behind the control bus is that you can use the same messaging system for monitoring and managing the components within the framework as is used for "`application-level`" messaging.
In Spring Integration, we build upon the adapters described earlier so that you can send Messages as a means of invoking exposed operations.
One option for those operations is Groovy scripts.
The following example configures a Groovy script for the control bus:

====
[source,xml]
----
<int-groovy:control-bus input-channel="operationChannel"/>
----
====

The control bus has an input channel that can be accessed to invoke operations on the beans in the application context.

The Groovy control bus runs messages on the input channel as Groovy scripts.
It takes a message, compiles the body to a script, customizes it with a `GroovyObjectCustomizer`, and runs it.
The control bus' `MessageProcessor` exposes all beans in the application context that are annotated with `@ManagedResource` and implement Spring's `Lifecycle` interface or extend Spring's `CustomizableThreadCreator` base class (for example, several of the `TaskExecutor` and `TaskScheduler` implementations).

IMPORTANT: Be careful about using managed beans with custom scopes (such as 'request') in the Control Bus' command scripts, especially inside an asynchronous message flow.
If `MessageProcessor` of the control bus cannot expose a bean from the application context, you may end up with some `BeansException` during the command script's run.
For example, if a custom scope's context is not established, the attempt to get a bean within that scope triggers a `BeanCreationException`.

If you need to further customize the Groovy objects, you can also provide a reference to a bean that implements `GroovyObjectCustomizer` through the `customizer` attribute, as the following example shows:

[source,xml]
----
<int-groovy:control-bus input-channel="input"
        output-channel="output"
        customizer="groovyCustomizer"/>

<beans:bean id="groovyCustomizer" class="org.foo.MyGroovyObjectCustomizer"/>
----
