* INT-4459: Mention dependencies in the Docs JIRA: https://jira.spring.io/browse/INT-4459 * Explicitly say what Spring Integration dependency must be included into the target project for particular protocol components * * Fix code block wrapping in the `endpoint-summary.adoc`
193 lines
8.2 KiB
Plaintext
193 lines
8.2 KiB
Plaintext
[[scripting]]
|
||
=== Scripting Support
|
||
|
||
Spring Integration 2.1 added support for the http://jcp.org/aboutJava/communityprocess/pr/jsr223/[JSR223 Scripting for Java specification], introduced in Java version 6.
|
||
It lets you use scripts written in any supported language (including Ruby, JRuby, Javascript, and Groovy) to provide the logic for various integration components, similar to the way the Spring Expression Language (SpEL) is used in Spring Integration.
|
||
For more information about JSR223, see the https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/prog_guide/api.html[documentation].
|
||
|
||
You need to include this dependency into your project:
|
||
|
||
====
|
||
.Maven
|
||
[source, xml, subs="normal"]
|
||
----
|
||
<dependency>
|
||
<groupId>org.springframework.integration</groupId>
|
||
<artifactId>spring-integration-scripting</artifactId>
|
||
<version>{project-version}</version>
|
||
</dependency>
|
||
----
|
||
|
||
.Gradle
|
||
[source, groovy, subs="normal"]
|
||
----
|
||
compile "org.springframework.integration:spring-integration-scripting:{project-version}"
|
||
----
|
||
====
|
||
|
||
In addition you need to add a script engine implementation, e.g. JRuby, Jython.
|
||
|
||
IMPORTANT: Note that this feature requires Java 6 or higher.
|
||
|
||
In order to use a JVM scripting language, a JSR223 implementation for that language must be included in your class path.
|
||
Java 6 natively supports Javascript.
|
||
The http://www.groovy-lang.org/[Groovy] and http://jruby.org/[JRuby] projects provide JSR233 support in their standard distributions.
|
||
|
||
IMPORTANT: Various JSR223 language implementations have been developed by third parties.
|
||
A particular implementation's compatibility with Spring Integration depends on how well it conforms to the specification and the implementer's interpretation of the specification.
|
||
|
||
TIP: If you plan to use Groovy as your scripting language, we recommended you use <<groovy,Spring-Integration's Groovy Support>> as it offers additional features specific to Groovy.
|
||
However, this section is relevant as well.
|
||
|
||
[[scripting-config]]
|
||
==== Script Configuration
|
||
|
||
Depending on the complexity of your integration requirements, scripts may be provided inline as CDATA in XML configuration or as a reference to a Spring resource that contains the script.
|
||
To enable scripting support, Spring Integration defines a `ScriptExecutingMessageProcessor`, which binds the message payload to a variable named `payload` and the message headers to a `headers` variable, both accessible within the script execution context.
|
||
All you need to do is write a script that uses these variables.
|
||
The following pair of examples show sample configurations that create filters:
|
||
|
||
.Filter
|
||
====
|
||
[source,xml]
|
||
----
|
||
<int:filter input-channel="referencedScriptInput">
|
||
<int-script:script lang="ruby" location="some/path/to/ruby/script/RubyFilterTests.rb"/>
|
||
</int:filter>
|
||
|
||
<int:filter input-channel="inlineScriptInput">
|
||
<int-script:script lang="groovy">
|
||
<![CDATA[
|
||
return payload == 'good'
|
||
]]>
|
||
</int-script:script>
|
||
</int:filter>
|
||
----
|
||
====
|
||
|
||
As the preceding examples show, the script can be included inline or can be included by reference to a resource location (by using the `location` attribute).
|
||
Additionally, the `lang` attribute corresponds to the language name (or its JSR223 alias)
|
||
|
||
Other Spring Integration endpoint elements that support scripting include `router`, `service-activator`, `transformer`, and `splitter`.
|
||
The scripting configuration in each case would be identical to the above (besides the endpoint element).
|
||
|
||
Another useful feature of scripting support is the ability to update (reload) scripts without having to restart the application context.
|
||
To do so, specify the `refresh-check-delay` attribute on the `script` element, as the following example shows:
|
||
|
||
====
|
||
[source,xml]
|
||
----
|
||
<int-script:script location="..." refresh-check-delay="5000"/>
|
||
----
|
||
====
|
||
|
||
In the preceding example, the script location is checked for updates every 5 seconds.
|
||
If the script is updated, any invocation that occurs later than 5 seconds since the update results in running the new script.
|
||
|
||
Consider the following example:
|
||
|
||
====
|
||
[source,xml]
|
||
----
|
||
<int-script:script location="..." refresh-check-delay="0"/>
|
||
----
|
||
====
|
||
|
||
In the preceding example, the context is updated with any script modifications as soon as such modification occurs, providing a simple mechanism for 'real-time' configuration.
|
||
Any negative value means the script is not reloaded after initialization of the application context.
|
||
This is the default behavior.
|
||
The following example shows a script that never updates:
|
||
|
||
====
|
||
[source,xml]
|
||
----
|
||
<int-script:script location="..." refresh-check-delay="-1"/>
|
||
----
|
||
====
|
||
|
||
IMPORTANT: Inline scripts can not be reloaded.
|
||
|
||
[[scripting-script-variable-bindings]]
|
||
===== Script Variable Bindings
|
||
|
||
Variable bindings are required to enable the script to reference variables externally provided to the script's execution context.
|
||
By default, `payload` and `headers` are used as binding variables.
|
||
You can bind additional variables to a script by using `<variable>` elements, as the following example shows:
|
||
|
||
====
|
||
[source,xml]
|
||
----
|
||
<script:script lang="js" location="foo/bar/MyScript.js">
|
||
<script:variable name="foo" value="thing1"/>
|
||
<script:variable name="bar" value="thing2"/>
|
||
<script:variable name="date" ref="date"/>
|
||
</script:script>
|
||
----
|
||
====
|
||
|
||
As shown in the preceding example, you can bind a script variable either to a scalar value or to a Spring bean reference.
|
||
Note that `payload` and `headers` are still included as binding variables.
|
||
|
||
With Spring Integration 3.0, in addition to the `variable` element, the `variables` attribute has been introduced.
|
||
This attribute and the `variable` elements are not mutually exclusive, and you can combine them within one `script` component.
|
||
However, variables must be unique, regardless of where they are defined.
|
||
Also, since Spring Integration 3.0, variable bindings are allowed for inline scripts, too, as the following example shows:
|
||
|
||
====
|
||
[source,xml]
|
||
----
|
||
<service-activator input-channel="input">
|
||
<script:script lang="ruby" variables="thing1=THING1, date-ref=dateBean">
|
||
<script:variable name="thing2" ref="thing2Bean"/>
|
||
<script:variable name="thing3" value="thing2"/>
|
||
<![CDATA[
|
||
payload.foo = thing1
|
||
payload.date = date
|
||
payload.bar = thing2
|
||
payload.baz = thing3
|
||
payload
|
||
]]>
|
||
</script:script>
|
||
</service-activator>
|
||
----
|
||
====
|
||
|
||
The preceding example shows a combination of an inline script, a `variable` element, and a `variables` attribute.
|
||
The `variables` attribute contains a comma-separated value, where each segment contains an '=' separated pair of the variable and its value.
|
||
The variable name can be suffixed with `-ref`, as in the `date-ref` variable in the preceding example.
|
||
That means that the binding variable has the name, `date`, but the value is a reference to the `dateBean` bean from the application context.
|
||
This may be useful when using property placeholder configuration or command-line arguments.
|
||
|
||
If you need more control over how variables are generated, you can implement your own Java class that uses the `ScriptVariableGenerator` strategy, which is defined by the following interface:
|
||
|
||
====
|
||
[source,java]
|
||
----
|
||
public interface ScriptVariableGenerator {
|
||
|
||
Map<String, Object> generateScriptVariables(Message<?> message);
|
||
|
||
}
|
||
----
|
||
====
|
||
|
||
This interface requires you to implement the `generateScriptVariables(Message)` method.
|
||
The message argument lets you access any data available in the message payload and headers, and the return value is the `Map` of bound variables.
|
||
This method is called every time the script is executed for a message.
|
||
The following example shows how to provide an implementation of `ScriptVariableGenerator` and reference it with the `script-variable-generator` attribute:
|
||
|
||
====
|
||
[source,xml]
|
||
----
|
||
<int-script:script location="foo/bar/MyScript.groovy"
|
||
script-variable-generator="variableGenerator"/>
|
||
|
||
<bean id="variableGenerator" class="foo.bar.MyScriptVariableGenerator"/>
|
||
----
|
||
====
|
||
|
||
If a `script-variable-generator` is not provided, script components use `DefaultScriptVariableGenerator`, which merges any provided `<variable>` elements with `payload` and `headers` variables from the `Message` in its `generateScriptVariables(Message)` method.
|
||
|
||
IMPORTANT: You cannot provide both the `script-variable-generator` attribute and `<variable>` element(s).
|
||
They are mutually exclusive.
|