スクリプトのサポート
Spring Integration 2.1 は、Java バージョン 6 で導入された JSR223 Scripting for Java 仕様 (英語) のサポートを追加しました。サポートされている任意の言語(Ruby、JRuby、Groovy、Kotlin を含む)で記述されたスクリプトを使用して、Spring 式言語と同様に、さまざまな統合コンポーネントのロジックを提供できます。(SpEL)は Spring Integration で使用されます。JSR223 の詳細については、ドキュメント [Oracle] を参照してください。
この依存関係をプロジェクトに含める必要があります。
さらに、JRuby などのスクリプトエンジン実装を追加する必要があります。
バージョン 5.2 以降、Spring Integration は Kotlin Jsr223 サポートを提供します。機能させるには、この依存関係をプロジェクトに追加する必要があります。
Maven
Gradle
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-scripting-jsr223</artifactId>
<scope>runtime</scope>
</dependency>
runtime 'org.jetbrains.kotlin:kotlin-scripting-jsr223'
JVM スクリプト言語を使用するには、その言語の JSR223 実装をクラスパスに含める必要があります。Groovy (英語) および JRuby (英語) プロジェクトは、標準ディストリビューションで JSR233 サポートを提供します。
さまざまな JSR223 言語実装がサードパーティによって開発されています。特定の実装の Spring Integration との互換性は、仕様と実装者の仕様の解釈にどれだけ準拠しているかによって異なります。 |
スクリプト言語として Groovy を使用する場合、Groovy に固有の追加機能を提供するため、Spring-Integration の Groovy サポートを使用することをお勧めします。ただし、このセクションも関連しています。 |
スクリプト構成
統合要件の複雑さに応じて、XML 構成の CDATA として、またはスクリプトを含む Spring リソースへの参照として、スクリプトをインラインで提供できます。スクリプトのサポートを有効にするために、Spring Integration は ScriptExecutingMessageProcessor
を定義します。ScriptExecutingMessageProcessor
は、メッセージペイロードを payload
という名前の変数にバインドし、メッセージヘッダーを headers
変数にバインドします。どちらもスクリプト実行コンテキスト内でアクセスできます。必要なのは、これらの変数を使用するスクリプトを書くことだけです。次のペアの例は、フィルターを作成するサンプル構成を示しています。
Java DSL
XML
@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
属性を指定します。
Java DSL
XML
Scripts.processor(...).refreshCheckDelay(5000)
}
<int-script:script location="..." refresh-check-delay="5000"/>
上記の例では、スクリプトの場所は 5 秒ごとに更新が確認されます。スクリプトが更新された場合、更新から 5 秒より後に行われた呼び出しはすべて、新しいスクリプトを実行します。
次の例を考えてみましょう。
Java DSL
XML
Scripts.processor(...).refreshCheckDelay(0)
}
<int-script:script location="..." refresh-check-delay="0"/>
前述の例では、スクリプトの変更が発生するとすぐにコンテキストが更新され、「リアルタイム」構成の簡単なメカニズムが提供されます。負の値は、アプリケーションコンテキストの初期化後にスクリプトがリロードされないことを意味します。これがデフォルトの動作です。次の例は、更新しないスクリプトを示しています。
Java DSL
XML
Scripts.processor(...).refreshCheckDelay(-1)
}
<int-script:script location="..." refresh-check-delay="-1"/>
インラインスクリプトはリロードできません。 |
スクリプト変数のバインド
スクリプトがスクリプトの実行コンテキストに外部から提供された変数を参照できるようにするには、変数バインディングが必要です。デフォルトでは、payload
と headers
がバインディング変数として使用されます。次の例に示すように、<variable>
要素(または ScriptSpec.variables()
オプション)を使用して、追加の変数をスクリプトにバインドできます。
Java DSL
XML
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
属性でそれを参照する方法を示しています。
Java DSL
XML
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
を提供します。Java 自体から削除された JavaScript の JSR223 エンジン実装は、この新しいスクリプトエグゼキュータを使用して置き換えられました。GraalVM で JavaScript サポートを有効にする方法と、スクリプト変数を介して伝播できる構成オプション (英語) の詳細については、こちらを参照してください。特に、JavaScript をサポートするには、ターゲットプロジェクトに org.graalvm.polyglot:js
依存関係を追加する必要があります。
バージョン 6.4 以降、Python スクリプトのサポートも GraalVM Polyglot に移行されました。これらのスクリプトは Python 3.x で記述でき、サードパーティのライブラリを使用できます。詳細については、GraalPy (英語) のドキュメントを参照してください。特に、Python をサポートするには、ターゲットプロジェクトに rg.graalvm.polyglot:python
依存関係を追加する必要があります。
デフォルトでは、フレームワークは共有 Polyglot Context
上の allowAllAccess
を true
に設定し、ホスト JVM との次の対話を有効にします。
新しいスレッドの作成と使用。
パブリックホストクラスへのアクセス。
クラスパスにエントリを追加することによる新しいホストクラスのロード。
新しいメンバーをポリグロットバインディングにエクスポートします。
ホストシステムでの無制限の IO 操作。
実験的なオプションを渡します。
新しいサブプロセスの作成と使用。
プロセス環境変数へのアクセス。
これは、org.graalvm.polyglot.Context.Builder
を受け入れるオーバーロードされた PolyglotScriptExecutor
コンストラクターを介してカスタマイズできます。例: Jython ベースのスクリプトは、引き続き option("python.EmulateJython", "true")
で実行できます。ただし、解釈パフォーマンスを向上させるには、GraalPy に完全に移行することをお勧めします。Java クラスの import
は機能しなくなり、代わりにそれぞれ import java
とその java.type()
関数を使用する必要があります。