スクリプトのサポート
Spring Integration 2.1 は、Java バージョン 6 で導入された JSR223 Scripting for Java 仕様 (英語) のサポートを追加しました。サポートされている任意の言語(Ruby、JRuby、Groovy、Kotlin を含む)で記述されたスクリプトを使用して、Spring 式言語と同様に、さまざまな統合コンポーネントのロジックを提供できます。(SpEL)は Spring Integration で使用されます。JSR223 の詳細については、ドキュメント [Oracle] を参照してください。
この依存関係をプロジェクトに含める必要があります。
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-scripting</artifactId>
<version>6.0.5</version>
</dependency>
compile "org.springframework.integration:spring-integration-scripting:6.0.5"
さらに、スクリプトエンジンの実装を追加する必要があります。JRuby、Jython。
バージョン 5.2 以降、Spring Integration は Kotlin Jsr223 サポートを提供します。これらの依存関係をプロジェクトに追加して、プロジェクトを機能させる必要があります。
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-script-util</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-compiler-embeddable</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-scripting-compiler-embeddable</artifactId>
<scope>runtime</scope>
</dependency>
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
拡張子が付いています。
JVM スクリプト言語を使用するには、その言語の JSR223 実装をクラスパスに含める必要があります。Groovy (英語) および JRuby (英語) プロジェクトは、標準ディストリビューションで JSR233 サポートを提供します。
さまざまな JSR223 言語実装がサードパーティによって開発されています。特定の実装の Spring Integration との互換性は、仕様と実装者の仕様の解釈にどれだけ準拠しているかによって異なります。 |
スクリプト言語として Groovy を使用する場合、Groovy に固有の追加機能を提供するため、Spring-Integration の Groovy サポートを使用することをお勧めします。ただし、このセクションも関連しています。 |
スクリプト構成
統合要件の複雑さに応じて、XML 構成の CDATA として、またはスクリプトを含む Spring リソースへの参照として、スクリプトをインラインで提供できます。スクリプトのサポートを有効にするために、Spring Integration は ScriptExecutingMessageProcessor
を定義します。ScriptExecutingMessageProcessor
は、メッセージペイロードを payload
という名前の変数にバインドし、メッセージヘッダーを headers
変数にバインドします。どちらもスクリプト実行コンテキスト内でアクセスできます。必要なのは、これらの変数を使用するスクリプトを書くことだけです。次のペアの例は、フィルターを作成するサンプル構成を示しています。
@Bean
public IntegrationFlow scriptFilter() {
return f -> f.filter(Scripts.processor("some/path/to/ruby/script/RubyFilterTests.rb"));
}
...
@Bean
public Resource scriptResource() {
return new ByteArrayResource("headers.type == 'good'".getBytes());
}
@Bean
public IntegrationFlow scriptFilter() {
return f -> f.filter(Scripts.processor(scriptResource()).lang("groovy"));
}
<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 エンドポイント要素には router
、service-activator
、transformer
、splitter
が含まれます。それぞれの場合のスクリプト構成は、上記と同じです(エンドポイント要素を除く)。
スクリプトサポートのもう 1 つの便利な機能は、アプリケーションコンテキストを再起動せずにスクリプトを更新(再読み込み)できることです。これを行うには、次の例に示すように、script
要素で refresh-check-delay
属性を指定します。
Scripts.processor(...).refreshCheckDelay(5000)
}
<int-script:script location="..." refresh-check-delay="5000"/>
上記の例では、スクリプトの場所は 5 秒ごとに更新が確認されます。スクリプトが更新された場合、更新から 5 秒より後に行われた呼び出しはすべて、新しいスクリプトを実行します。
次の例を考えてみましょう。
Scripts.processor(...).refreshCheckDelay(0)
}
<int-script:script location="..." refresh-check-delay="0"/>
前述の例では、スクリプトの変更が発生するとすぐにコンテキストが更新され、「リアルタイム」構成の簡単なメカニズムが提供されます。負の値は、アプリケーションコンテキストの初期化後にスクリプトがリロードされないことを意味します。これがデフォルトの動作です。次の例は、更新しないスクリプトを示しています。
Scripts.processor(...).refreshCheckDelay(-1)
}
<int-script:script location="..." refresh-check-delay="-1"/>
インラインスクリプトはリロードできません。 |
スクリプト変数のバインド
スクリプトがスクリプトの実行コンテキストに外部から提供された変数を参照できるようにするには、変数バインディングが必要です。デフォルトでは、payload
と headers
がバインディング変数として使用されます。次の例に示すように、<variable>
要素(または ScriptSpec.variables()
オプション)を使用して、追加の変数をスクリプトにバインドできます。
Scripts.processor("foo/bar/MyScript.py")
.variables(Map.of("var1", "thing1", "var2", "thing2", "date", date))
}
<script:script lang="py" location="foo/bar/MyScript.py">
<script:variable name="var1" value="thing1"/>
<script:variable name="var2" 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
属性でそれを参照する方法を示しています。
Scripts.processor("foo/bar/MyScript.groovy")
.variableGenerator(new foo.bar.MyScriptVariableGenerator())
}
<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> 要素の両方を提供することはできません。それらは相互に排他的です。 |
GraalVM Polyglot
バージョン 6.0 以降、フレームワークは GraalVM Polyglot API (英語) に基づく PolyglotScriptExecutor
を提供します。JavaScript の JSR223 エンジンの実装は、Java から単独で削除されましたが、この新しいスクリプトエグゼキュータを使用することで置き換えられました。GraalVM で JavaScript サポートを有効にする方法と、スクリプト変数を介して伝達できる構成オプション (英語) について詳しくは、こちらを参照してください。デフォルトでは、フレームワークは共有 Polyglot Context
で allowAllAccess
を true
に設定します。これにより、ホスト JVM との対話が可能になります。
新しいスレッドの作成と使用。
パブリックホストクラスへのアクセス。
クラスパスにエントリを追加することによる新しいホストクラスのロード。
新しいメンバーをポリグロットバインディングにエクスポートします。
ホストシステムでの無制限の IO 操作。
実験的なオプションを渡します。
新しいサブプロセスの作成と使用。
プロセス環境変数へのアクセス。
これは、org.graalvm.polyglot.Context.Builder
を受け入れるオーバーロードされた PolyglotScriptExecutor
コンストラクターを介してカスタマイズできます。
この JavaScript サポートを有効にするには、js
コンポーネントがインストールされた GraalVM を使用する必要があります。通常の JVM を使用する場合は、org.graalvm.sdk:graal-sdk
および org.graalvm.js:js
依存関係を含める必要があります。