Spring Integration Java DSL

Spring Integration Java DSL

1. 前書き

このチュートリアルでは、アプリケーション統合を作成するためのSpring Integration JavaDSLについて学習します。

組み込みのIntroduction to Spring Integrationでファイルを移動する統合を採用し、代わりにDSLを使用します。

2. 依存関係

Spring Integration Java DSLはSpring Integration Coreの一部です。

そのため、その依存関係を追加できます。


    org.springframework.integration
    spring-integration-core
    5.0.6.RELEASE

また、ファイル移動アプリケーションで作業するには、Spring Integration Fileも必要です。


    org.springframework.integration
    spring-integration-file
    5.0.6.RELEASE

3. Spring Integration Java DSL

Java DSLの前は、ユーザーはXMLでSpring Integrationコンポーネントを構成していました。

DSLは、純粋にJavaで完全なSpringIntegrationパイプラインを簡単に作成できる流暢なビルダーをいくつか導入しています。

したがって、パイプを通過するデータを大文字にするチャネルを作成したいとします。

以前は、次のことを行っていました。



そして今、代わりに次のことができます:

@Bean
public IntegrationFlow upcaseFlow() {
    return IntegrationFlows.from("input")
      .transform(String::toUpperCase)
      .get();
}

4. ファイル移動アプリ

ファイル移動の統合を開始するには、いくつかの簡単な構成要素が必要です。

4.1. 統合フロー

必要な最初のビルディングブロックは統合フローです。これは、IntegrationFlows builderから取得できます。

IntegrationFlows.from(...)

from canはいくつかのタイプを取りますが、このチュートリアルでは、次の3つだけを見ていきます。

  • MessageSources

  • MessageChannels、および

  • Strings

3つすべてについてすぐに説明します。

fromを呼び出した後、いくつかのカスタマイズ方法を利用できるようになりました。

IntegrationFlow flow = IntegrationFlows.from(sourceDirectory())
  .filter(onlyJpgs())
  .handle(targetDirectory())
  // add more components
  .get();

最終的に、IntegrationFlowsは常にIntegrationFlow, which is the final product of any Spring Integration app.のインスタンスを生成します

This pattern of taking input, performing the appropriate transformations, and emitting the results is fundamental to all Spring Integration apps

4.2. 入力ソースの説明

まず、ファイルを移動するには、統合フローにファイルを探す場所を指定する必要があります。そのためには、MessageSource:が必要です。

@Bean
public MessageSource sourceDirectory() {
  // .. create a message source
}

簡単に言えば、MessageSourcemessages can come that are external to the applicationの元となる場所です。

具体的には、その外部ソースをSpringメッセージング表現にadaptできるものが必要です。 また、このadaptationinputに焦点を合わせているため、これらはしばしばInput Channel Adapters.と呼ばれます。

spring-integration-file dependencyは、ユースケースに最適な入力チャネルアダプターを提供します:FileReadingMessageSource:

@Bean
public MessageSource sourceDirectory() {
    FileReadingMessageSource messageSource = new FileReadingMessageSource();
    messageSource.setDirectory(new File(INPUT_DIR));
    return messageSource;
}

ここで、FileReadingMessageSource INPUT_DIRで指定されたディレクトリを読み取り、そこからMessageSourceを作成します。

これをIntegrationFlows.from 呼び出しのソースとして指定しましょう。

IntegrationFlows.from(sourceDirectory());

4.3. 入力ソースの構成

さて、これを長寿命のアプリケーションwe’ll probably want to be able to notice files as they come inとして考えている場合は、起動時にすでに存在するファイルを移動するだけではありません。

これを容易にするために、入力ソースをさらにカスタマイズするために、fromに追加のconfigurersを追加することもできます。

IntegrationFlows.from(sourceDirectory(), configurer -> configurer.poller(Pollers.fixedDelay(10000)));

この場合、Spring Integrationにそのソース(この場合はファイルシステム)を10秒ごとにポーリングするように指示することで、入力ソースの復元力を高めることができます。

もちろん、これはファイル入力ソースだけに当てはまるわけではありません。このポーラーを任意のMessageSourceに追加できます。

4.4. 入力ソースからのメッセージのフィルタリング

次に、ファイル移動アプリケーションで特定のファイル、たとえば拡張子がjpgの画像ファイルのみを移動するとします。

このために、GenericSelectorを使用できます。

@Bean
public GenericSelector onlyJpgs() {
    return new GenericSelector() {

        @Override
        public boolean accept(File source) {
          return source.getName().endsWith(".jpg");
        }
    };
}

それでは、統合フローをもう一度更新しましょう。

IntegrationFlows.from(sourceDirectory())
  .filter(onlyJpgs());

または、because this filter is so simple, we could have instead defined it using a lambda

IntegrationFlows.from(sourceDirectory())
  .filter(source -> ((File) source).getName().endsWith(".jpg"));

4.5. ServiceActivatorsを使用したメッセージの処理

ファイルのリストがフィルタリングされたので、新しい場所に書き込む必要があります。

Service Activators は、SpringIntegrationの出力について考えるときに使用するものです。

spring-integration-fileFileWritingMessageHandlerサービスアクティベーターを使用してみましょう。

@Bean
public MessageHandler targetDirectory() {
    FileWritingMessageHandler handler = new FileWritingMessageHandler(new File(OUTPUT_DIR));
    handler.setFileExistsMode(FileExistsMode.REPLACE);
    handler.setExpectReply(false);
    return handler;
}

ここで、FileWritingMessageHandler は、受信した各MessageペイロードをOUTPUT_DIRに書き込みます。

繰り返しますが、更新しましょう。

IntegrationFlows.from(sourceDirectory())
  .filter(onlyJpgs())
  .handle(targetDirectory());

ちなみに、setExpectReplyの使用法に注意してください。 Because integration flows can bebidirectional,この呼び出しは、この特定のパイプが一方向であることを示します。

4.6. 統合フローのアクティブ化

すべてのコンポーネントを追加したら、それをアクティブ化するためにregister our IntegrationFlow as a beanを実行する必要があります。

@Bean
public IntegrationFlow fileMover() {
    return IntegrationFlows.from(sourceDirectory(), c -> c.poller(Pollers.fixedDelay(10000)))
      .filter(onlyJpgs())
      .handle(targetDirectory())
      .get();
}

 get メソッドは、Spring Beanとして登録する必要があるIntegrationFlowインスタンスを抽出します。

アプリケーションコンテキストが読み込まれるとすぐに、IntegrationFlowに含まれるすべてのコンポーネントがアクティブになります。

そして今、アプリケーションはソースディレクトリからターゲットディレクトリへのファイルの移動を開始します。

5. 追加のコンポーネント

DSLベースのファイル移動アプリケーションでは、インバウンドチャネルアダプター、メッセージフィルター、およびサービスアクティベーターを作成しました。

他のいくつかの一般的なSpringIntegrationコンポーネントを見て、それらをどのように使用するかを見てみましょう。

5.1. メッセージチャネル

前述のように、Message Channelはフローを初期化するもう1つの方法です。

IntegrationFlows.from("anyChannel")

これは、「anyChannelというチャネルBeanを検索または作成してください。 次に、他のフローからanyChannelに入力されたデータを読み取ります。」

しかし、実際にはそれよりも汎用的です。

簡単に言えば、チャネルはプロデューサーをコンシューマーから抽象化し、JavaのQueueと考えることができます。 A channel can be inserted at any point in the flow

たとえば、あるディレクトリから次のディレクトリに移動するときにファイルに優先順位を付けたいとします。

@Bean
public PriorityChannel alphabetically() {
    return new PriorityChannel(1000, (left, right) ->
      ((File)left.getPayload()).getName().compareTo(
        ((File)right.getPayload()).getName()));
}

次に、フローの間にchannelへの呼び出しを挿入できます。

@Bean
public IntegrationFlow fileMover() {
    return IntegrationFlows.from(sourceDirectory())
      .filter(onlyJpgs())
      .channel("alphabetically")
      .handle(targetDirectory())
      .get();
}

some of the more handy ones being for concurrency, auditing, or intermediate persistenceから選択するチャネルは数十あります(KafkaまたはJMSバッファを考えてください)。

また、チャネルはBridgesと組み合わせると強力になります。

5.2. ブリッジ

combine two channelsにする場合は、Bridge.を使用します

出力ディレクトリに直接書き込む代わりに、ファイル移動アプリに別のチャネルに書き込むようにしたと想像してみてください。

@Bean
public IntegrationFlow fileReader() {
    return IntegrationFlows.from(sourceDirectory())
      .filter(onlyJpgs())
      .channel("holdingTank")
      .get();
}

さて、単にチャネルに書き込んだので、we can bridge from there to other flowsです。

メッセージを保持タンクにポーリングして宛先に書き込むブリッジを作成しましょう。

@Bean
public IntegrationFlow fileWriter() {
    return IntegrationFlows.from("holdingTank")
      .bridge(e -> e.poller(Pollers.fixedRate(1, TimeUnit.SECONDS, 20)))
      .handle(targetDirectory())
      .get();
}

ここでも、中間チャネルに書き込んだため、別のフローthat takes these same files and writes them at a different rateを追加できます。

@Bean
public IntegrationFlow anotherFileWriter() {
    return IntegrationFlows.from("holdingTank")
      .bridge(e -> e.poller(Pollers.fixedRate(2, TimeUnit.SECONDS, 10)))
      .handle(anotherTargetDirectory())
      .get();
}

ご覧のとおり、個々のブリッジは異なるハンドラーのポーリング構成を制御できます。

アプリケーションコンテキストが読み込まれるとすぐに、ソースディレクトリから2つのターゲットディレクトリへのファイルの移動を開始する、より複雑なアプリが動作します。

6. 結論

この記事では、Spring Integration Java DSLを使用してさまざまな統合パイプラインを構築するさまざまな方法を見ました。

基本的に、今回は純粋なjavaを使用して、以前のチュートリアルからファイル移動アプリケーションを再作成できました。

また、チャネルやブリッジなど、他のいくつかのコンポーネントにも注目しました。

このチュートリアルで使用される完全なソースコードは、over on Githubで入手できます。