スクリプトのサポート

Spring Integration 2.1 は、Java バージョン 6 で導入された JSR223 Scripting for Java 仕様 (英語) のサポートを追加しました。これにより、サポートされている言語(Ruby、JRuby、Javascript、Groovy、Kotlin を含む)で記述されたスクリプトを使用して、Spring と同様のさまざまな統合コンポーネントのロジックを提供できます。式言語(SpEL)は Spring Integration で使用されます。JSR223 の詳細については、ドキュメント [Oracle] を参照してください。

この依存関係をプロジェクトに含める必要があります。

<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-scripting</artifactId>
    <version>5.3.3.RELEASE</version>
</dependency>
compile "org.springframework.integration:spring-integration-scripting:5.3.3.RELEASE"

さらに、スクリプトエンジンの実装を追加する必要があります。JRuby、Jython。

バージョン 5.2 以降、Spring Integration は Kotlin Jsr223 サポートを提供します。これらの依存関係をプロジェクトに追加して、プロジェクトを機能させる必要があります。

runtime 'org.jetbrains.kotlin:kotlin-script-util'
runtime 'org.jetbrains.kotlin:kotlin-compiler-embeddable'
runtime 'org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable'

KotlinScriptExecutor は、提供されている kotlin 言語インジケータによって選択されるか、スクリプトファイルに .kts 拡張子が付いています。

この機能には Java 6 以上が必要であることに注意してください。

JVM スクリプト言語を使用するには、その言語の JSR223 実装をクラスパスに含める必要があります。Java 6 はネイティブに Javascript をサポートしています。Groovy (英語) および JRuby (英語) プロジェクトは、標準配布で JSR233 サポートを提供します。

さまざまな JSR223 言語実装がサードパーティによって開発されています。特定の実装の Spring Integration との互換性は、仕様と実装者の仕様の解釈にどれだけ準拠しているかによって異なります。
スクリプト言語として Groovy を使用する場合、Groovy に固有の追加機能を提供するため、Spring-Integration の Groovy サポートを使用することをお勧めします。ただし、このセクションも関連しています。

スクリプト構成

統合要件の複雑さに応じて、XML 構成の CDATA として、またはスクリプトを含む Spring リソースへの参照として、スクリプトをインラインで提供できます。スクリプトのサポートを有効にするために、Spring Integration は ScriptExecutingMessageProcessor を定義します。ScriptExecutingMessageProcessor は、メッセージペイロードを payload という名前の変数にバインドし、メッセージヘッダーを headers 変数にバインドします。どちらもスクリプト実行コンテキスト内でアクセスできます。必要なのは、これらの変数を使用するスクリプトを書くことだけです。次のペアの例は、フィルターを作成するサンプル構成を示しています。

例 1: フィルター
<int:filter input-channel="referencedScriptInput">
   <int-script:script 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>

上記の例が示すように、スクリプトはインラインで含めることも、リソースの場所を参照して含めることもできます(location 属性を使用)。さらに、lang 属性は言語名に対応します (またはその JSR223 エイリアス)

スクリプトをサポートする他の Spring Integration エンドポイント要素には routerservice-activatortransformersplitter が含まれます。それぞれの場合のスクリプト構成は、上記と同じです(エンドポイント要素を除く)。

スクリプトサポートのもう 1 つの便利な機能は、アプリケーションコンテキストを再起動せずにスクリプトを更新(再読み込み)できることです。これを行うには、次の例に示すように、script 要素で refresh-check-delay 属性を指定します。

<int-script:script location="..." refresh-check-delay="5000"/>

上記の例では、スクリプトの場所は 5 秒ごとに更新が確認されます。スクリプトが更新された場合、更新から 5 秒より後に行われた呼び出しはすべて、新しいスクリプトを実行します。

次の例を考えてみましょう。

<int-script:script location="..." refresh-check-delay="0"/>

前述の例では、スクリプトの変更が発生するとすぐにコンテキストが更新され、「リアルタイム」構成の簡単なメカニズムが提供されます。負の値は、アプリケーションコンテキストの初期化後にスクリプトがリロードされないことを意味します。これがデフォルトの動作です。次の例は、更新しないスクリプトを示しています。

<int-script:script location="..." refresh-check-delay="-1"/>
インラインスクリプトはリロードできません。
スクリプト変数のバインド

スクリプトの実行コンテキストに外部から提供される変数をスクリプトが参照できるようにするには、変数バインディングが必要です。デフォルトでは、payload および headers はバインディング変数として使用されます。次の例に示すように、<variable> 要素を使用して、追加の変数をスクリプトにバインドできます。

<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>

前の例に示すように、スクリプト変数をスカラー値または Spring Bean 参照にバインドできます。payload と headers は、まだバインディング変数として含まれていることに注意してください。

Spring Integration 3.0 では、variable 要素に加えて、variables 属性が導入されています。この属性と variable 要素は相互に排他的ではなく、1 つの script コンポーネント内で組み合わせることができます。ただし、変数は、どこに定義されているかに関係なく、一意である必要があります。また、Spring Integration 3.0 以降、次の例に示すように、インラインスクリプトでも変数バインディングを使用できます。

<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>

上記の例は、インラインスクリプト、variable 要素、variables 属性の組み合わせを示しています。variables 属性にはコンマ区切り値が含まれ、各セグメントには変数とその値の "=" で区切られたペアが含まれます。前の例の date-ref 変数のように、変数名の末尾に -ref を付けることができます。つまり、バインディング変数の名前は date ですが、値はアプリケーションコンテキストからの dateBean Bean への参照です。これは、プロパティプレースホルダーの構成またはコマンドライン引数を使用する場合に便利です。

変数の生成方法をさらに制御する必要がある場合は、ScriptVariableGenerator 戦略を使用する独自の Java クラスを実装できます。この戦略は、次のインターフェースで定義されます。

public interface ScriptVariableGenerator {

    Map<String, Object> generateScriptVariables(Message<?> message);

}

このインターフェースでは、generateScriptVariables(Message) メソッドを実装する必要があります。メッセージ引数を使用すると、メッセージペイロードとヘッダーで使用可能なデータにアクセスでき、戻り値はバインドされた変数の Map です。このメソッドは、メッセージに対してスクリプトが実行されるたびに呼び出されます。次の例は、ScriptVariableGenerator の実装を提供し、script-variable-generator 属性でそれを参照する方法を示しています。

<int-script:script location="foo/bar/MyScript.groovy"
        script-variable-generator="variableGenerator"/>

<bean id="variableGenerator" class="foo.bar.MyScriptVariableGenerator"/>

script-variable-generator が提供されない場合、スクリプトコンポーネントは DefaultScriptVariableGenerator を使用します。DefaultScriptVariableGenerator は、提供された <variable> 要素を、generateScriptVariables(Message) メソッドで Message からの payload および headers 変数とマージします。

script-variable-generator 属性と <variable> 要素の両方を提供することはできません。それらは相互に排他的です。