ファイルを読む
FileReadingMessageSource
を使用して、ファイルシステムからファイルを消費できます。これは、ファイルシステムディレクトリからメッセージを作成する MessageSource
の実装です。次の例は、FileReadingMessageSource
を構成する方法を示しています。
<bean id="pollableFileSource"
class="org.springframework.integration.file.FileReadingMessageSource"
p:directory="${input.directory}"/>
特定のファイルのメッセージを作成しないようにするには、FileListFilter
を指定できます。デフォルトでは、次のフィルターを使用します。
IgnoreHiddenFileListFilter
AcceptOnceFileListFilter
IgnoreHiddenFileListFilter
は、隠しファイルが処理されないようにします。hidden の正確な定義はシステムに依存することに注意してください。例: UNIX ベースのシステムでは、ピリオド文字で始まるファイルは非表示と見なされます。一方、Microsoft Windows には、隠しファイルを示す専用のファイル属性があります。
バージョン 4.2 は |
AcceptOnceFileListFilter
は、ファイルがディレクトリから 1 回だけピックアップされるようにします。
バージョン 4.0 以降、このフィルターには バージョン 4.1.5 以降、このフィルターには新しいプロパティ( |
永続ファイルリストフィルターにブールプロパティ forRecursion
が追加されました。このプロパティを true
に設定すると、alwaysAcceptDirectories
も設定されます。これは、送信ゲートウェイ(ls
および mget
)での再帰操作が常にディレクトリツリー全体を毎回トラバースすることを意味します。これは、ディレクトリツリーの奥深くで変更が検出されなかった問題を解決するためです。さらに、forRecursion=true
により、ファイルへのフルパスがメタデータストアキーとして使用されます。これにより、同じ名前のファイルが異なるディレクトリに複数回表示された場合にフィルターが正しく機能しなかった問題が解決されます。重要: これは、永続メタデータストア内の既存のキーが、最上位ディレクトリにあるファイルで見つからないことを意味します。このため、プロパティはデフォルトで false
です。これは将来のリリースで変更される可能性があります。
次の例では、フィルターを使用して FileReadingMessageSource
を構成します。
<bean id="pollableFileSource"
class="org.springframework.integration.file.FileReadingMessageSource"
p:inputDirectory="${input.directory}"
p:filter-ref="customFilterBean"/>
ファイルの読み取りに関する一般的な問題は、準備が整う前にファイルが検出される可能性があることです(つまり、他のプロセスがまだファイルを書き込んでいる可能性があります)。デフォルトの AcceptOnceFileListFilter
はこれを妨げません。ほとんどの場合、ファイル書き込みプロセスが読み取りの準備ができるとすぐに各ファイルの名前を変更すると、これを防ぐことができます。デフォルトの AcceptOnceFileListFilter
で構成された(おそらく既知のサフィックスに基づいた)準備ができているファイルのみを受け入れる filename-pattern
または filename-regex
フィルターは、この状況に対応します。次の例に示すように、CompositeFileListFilter
は構成を有効にします。
<bean id="pollableFileSource"
class="org.springframework.integration.file.FileReadingMessageSource"
p:inputDirectory="${input.directory}"
p:filter-ref="compositeFilter"/>
<bean id="compositeFilter"
class="org.springframework.integration.file.filters.CompositeFileListFilter">
<constructor-arg>
<list>
<bean class="o.s.i.file.filters.AcceptOnceFileListFilter"/>
<bean class="o.s.i.file.filters.RegexPatternFileListFilter">
<constructor-arg value="^test.*$"/>
</bean>
</list>
</constructor-arg>
</bean>
一時的な名前でファイルを作成し、最終的な名前に名前を変更することができない場合、Spring Integration は別の代替手段を提供します。バージョン 4.2 は LastModifiedFileListFilter
を追加しました。このフィルターは、この値より古いファイルのみがフィルターによって渡されるように、age
プロパティで構成できます。経過時間のデフォルトは 60 秒ですが、ファイルの早期取得を回避するのに十分な大きさの経過時間を選択する必要があります(ネットワークの不具合などによる)。次の例は、LastModifiedFileListFilter
を構成する方法を示しています。
<bean id="filter" class="org.springframework.integration.file.filters.LastModifiedFileListFilter">
<property name="age" value="120" />
</bean>
バージョン 4.3.7 から、ChainFileListFilter
(CompositeFileListFilter
の拡張)が導入され、後続のフィルターが前のフィルターの結果のみを表示するシナリオを可能にしました。(CompositeFileListFilter
では、すべてのフィルターがすべてのファイルを表示しますが、すべてのフィルターを通過したファイルのみを通過させます)。新しい動作が必要な場所の例は、LastModifiedFileListFilter
と AcceptOnceFileListFilter
の組み合わせです。一定の時間が経過するまでファイルを受け入れたくない場合です。CompositeFileListFilter
では、AcceptOnceFileListFilter
は最初のパスですべてのファイルを見るため、後で他のフィルターがパスするときにファイルを渡しません。CompositeFileListFilter
アプローチは、パターンフィルターを、ファイル転送が完了したことを示すセカンダリファイルを探すカスタムフィルターと組み合わせる場合に役立ちます。パターンフィルターはプライマリファイル(something.txt
など)のみを渡す場合がありますが、「完了」フィルターは(たとえば) something.done
が存在するかどうかを確認する必要があります。
ファイル a.txt
、a.done
、b.txt
があるとします。
パターンフィルターは a.txt
と b.txt
のみを通過させますが、「完了」フィルターは 3 つのファイルすべてを認識し、a.txt
のみを通過させます。複合フィルターの最終結果は、a.txt
のみがリリースされることです。
ChainFileListFilter では、チェーンのいずれかのフィルターが空のリストを返す場合、残りのフィルターは呼び出されません。 |
バージョン 5.0 は、コンテキスト評価ルートオブジェクトとしてファイルに対して SpEL 式を実行する ExpressionFileListFilter
を導入しました。この目的のために、次の例に示すように、ファイル処理用のすべての XML コンポーネント(ローカルおよびリモート)と既存の filter
属性が filter-expression
オプションとともに提供されています。
<int-file:inbound-channel-adapter
directory="${inputdir}"
filter-expression="name matches '.text'"
auto-startup="false"/>
バージョン 5.0.5 は、拒否されたファイルに関心がある DiscardAwareFileListFilter
実装を導入しました。この目的のために、そのようなフィルター実装には addDiscardCallback(Consumer<File>)
を介してコールバックを提供する必要があります。フレームワークでは、この機能は FileReadingMessageSource.WatchServiceDirectoryScanner
から LastModifiedFileListFilter
と組み合わせて使用されます。通常の DirectoryScanner
とは異なり、WatchService
はターゲットファイルシステムのイベントに応じて処理するファイルを提供します。これらのファイルで内部キューをポーリングする瞬間に、LastModifiedFileListFilter
は、構成された age
に比べて若すぎるため、破棄する場合があります。今後の考慮事項のためにファイルを失います。破棄コールバックフックを使用すると、内部キューにファイルを保持できるため、後続のポーリングで age
に対してファイルをチェックできます。CompositeFileListFilter
は DiscardAwareFileListFilter
も実装し、そのすべての DiscardAwareFileListFilter
デリゲートに廃棄コールバックを追加します。
CompositeFileListFilter はすべてのデリゲートに対してファイルを照合するため、同じファイルに対して discardCallback が複数回呼び出される場合があります。 |
バージョン 5.1 以降、FileReadingMessageSource
はディレクトリの存在を確認せず、start()
が呼び出されるまで(通常は SourcePollingChannelAdapter
をラップすることにより)ディレクトリを作成しません。以前は、テストからディレクトリを参照するとき、または後でアクセス許可が適用されるときに、オペレーティングシステムのアクセス許可エラーを防ぐ簡単な方法はありませんでした。
メッセージヘッダー
バージョン 5.0 以降、FileReadingMessageSource
は(ポーリングされた File
としての payload
に加えて)送信 Message
に以下のヘッダーを取り込みます。
FileHeaders.FILENAME
: 送信するファイルのFile.getName()
。後続の名前変更またはコピーロジックに使用できます。FileHeaders.ORIGINAL_FILE
:File
オブジェクト自体。通常、このヘッダーは、元のFile
オブジェクトが失われると、フレームワークコンポーネント(スプリッターやトランスフォーマーなど)によって自動的に入力されます。ただし、他のカスタムユースケースとの一貫性と利便性のために、このヘッダーは元のファイルにアクセスできます。FileHeaders.RELATIVE_PATH
: スキャンのルートディレクトリに相対的なファイルパスの部分を表すために導入された新しいヘッダー。このヘッダーは、他の場所でソースディレクトリ階層を復元する必要がある場合に役立ちます。この目的のために、このヘッダーを使用するようにDefaultFileNameGenerator
( "ファイル名の生成" を参照)を構成できます。
ディレクトリのスキャンとポーリング
FileReadingMessageSource
は、ディレクトリからのファイルのメッセージをすぐには生成しません。scanner
によって返される「適格ファイル」に内部キューを使用します。scanEachPoll
オプションを使用して、内部キューが各ポーリングの最新の入力ディレクトリコンテンツでリフレッシュされるようにします。デフォルト(scanEachPoll = false
)では、FileReadingMessageSource
はディレクトリを再度スキャンする前にキューを空にします。このデフォルトの動作は、ディレクトリ内の多数のファイルのスキャンを減らすのに特に役立ちます。ただし、カスタムの順序付けが必要な場合は、このフラグを true
に設定する効果を考慮することが重要です。ファイルが処理される順序は予想どおりではない場合があります。デフォルトでは、キュー内のファイルは自然な(path
)順序で処理されます。スキャンによって追加された新しいファイルは、キューにすでにファイルがある場合でも、適切な位置に挿入され、その自然な順序が維持されます。順序をカスタマイズするために、FileReadingMessageSource
は Comparator<File>
をコンストラクター引数として受け入れることができます。内部(PriorityBlockingQueue
)によって使用され、ビジネス要件に従ってコンテンツを並べ替えます。特定の順序でファイルを処理するには、カスタム DirectoryScanner
によって作成されたリストを並べ替えるのではなく、FileReadingMessageSource
にコンパレーターを提供する必要があります。
バージョン 5.0 では、ファイルツリー訪問を実行するために RecursiveDirectoryScanner
を導入しました。実装は、Files.walk(Path start, int maxDepth, FileVisitOption… options)
機能に基づいています。ルートディレクトリ(DirectoryScanner.listFiles(File)
)引数は結果から除外されます。他のすべてのサブディレクトリの包含および除外は、ターゲット FileListFilter
実装に基づいています。例: SimplePatternFileListFilter
はデフォルトでディレクトリを除外します。詳細については、AbstractDirectoryAwareFileListFilter
(Javadoc) とその実装を参照してください。
バージョン 5.5 以降、Java DSL の FileInboundChannelAdapterSpec には、デフォルトの FileReadingMessageSource の代わりにターゲット FileReadingMessageSource で RecursiveDirectoryScanner を使用するための便利な recursive(boolean) オプションがあります。 |
名前空間サポート
ファイル固有の名前空間を使用すると、ファイル読み取りの構成を簡素化できます。そのためには、次のテンプレートを使用します。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-file="http://www.springframework.org/schema/integration/file"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration
https://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/file
https://www.springframework.org/schema/integration/file/spring-integration-file.xsd">
</beans>
この名前空間内で、次のように FileReadingMessageSource
を減らして受信チャネルアダプターにラップできます。
<int-file:inbound-channel-adapter id="filesIn1"
directory="file:${input.directory}" prevent-duplicates="true" ignore-hidden="true"/>
<int-file:inbound-channel-adapter id="filesIn2"
directory="file:${input.directory}"
filter="customFilterBean" />
<int-file:inbound-channel-adapter id="filesIn3"
directory="file:${input.directory}"
filename-pattern="test*" />
<int-file:inbound-channel-adapter id="filesIn4"
directory="file:${input.directory}"
filename-regex="test[0-9]+\.txt" />
最初のチャネルアダプターの例は、デフォルトの FileListFilter
実装に依存しています。
IgnoreHiddenFileListFilter
(隠しファイルを処理しません)AcceptOnceFileListFilter
(重複を防ぐ)
prevent-duplicates
および ignore-hidden
属性はデフォルトで true
であるため、省略することもできます。
Spring Integration 4.2 は |
2 番目のチャネルアダプターの例はカスタムフィルターを使用し、3 番目は filename-pattern
属性を使用して AntPathMatcher
ベースのフィルターを追加し、4 番目は filename-regex
属性を使用して正規表現パターンベースのフィルターを FileReadingMessageSource
に追加します。filename-pattern
および filename-regex
属性は、それぞれ通常の filter
参照属性と相互に排他的です。ただし、filter
属性を使用して、特定のニーズに合わせて 1 つ以上のパターンベースのフィルターを含む、任意の数のフィルターを組み合わせた CompositeFileListFilter
のインスタンスを参照できます。
複数のプロセスが同じディレクトリから読み取る場合、ファイルが同時に取得されないようにファイルをロックすることができます。そのためには、FileLocker
を使用できます。java.nio
ベースの実装が利用可能ですが、独自のロックスキームを実装することもできます。nio
ロッカーは、次のように挿入できます。
<int-file:inbound-channel-adapter id="filesIn"
directory="file:${input.directory}" prevent-duplicates="true">
<int-file:nio-locker/>
</int-file:inbound-channel-adapter>
次のようにカスタムロッカーを設定できます。
<int-file:inbound-channel-adapter id="filesIn"
directory="file:${input.directory}" prevent-duplicates="true">
<int-file:locker ref="customLocker"/>
</int-file:inbound-channel-adapter>
ファイル受信アダプターがロッカーで構成されている場合、ファイルの受信を許可する前にロックを取得する責任があります。ファイルのロックを解除する責任は負いません。ファイルを処理し、ロックをぶら下げたままにしておくと、メモリリークが発生します。これが問題になる場合は、適切なタイミングで自分で FileLocker.unlock(File file) を呼び出す必要があります。 |
ファイルのフィルタリングとロックだけでは不十分な場合は、ファイルを完全にリストする方法を制御する必要があります。この型の要件を実装するには、DirectoryScanner
の実装を使用できます。このスキャナーを使用すると、各ポーリングでリストされるファイルを正確に判別できます。これは、Spring Integration が FileListFilter
インスタンスと FileLocker
を FileReadingMessageSource
にワイヤリングするために内部的に使用するインターフェースでもあります。次の例に示すように、scanner
属性の <int-file:inbound-channel-adapter/>
にカスタム DirectoryScanner
を挿入できます。
<int-file:inbound-channel-adapter id="filesIn" directory="file:${input.directory}"
scanner="customDirectoryScanner"/>
これにより、順序付け、リスト、ロックの戦略を自由に選択できます。
また、フィルター(patterns
、regex
、prevent-duplicates
などを含む)および locker
インスタンスが実際に scanner
によって使用されることを理解することも重要です。アダプターに設定されたこれらの属性のいずれかは、その後内部 scanner
に注入されます。外部 scanner
の場合、FileReadingMessageSource
ではすべてのフィルターおよびロッカー属性が禁止されています。カスタム DirectoryScanner
で指定する必要があります(必要な場合)。つまり、scanner
を FileReadingMessageSource
に挿入する場合、FileReadingMessageSource
ではなく、その scanner
で filter
および locker
を指定する必要があります。
デフォルトでは、DefaultDirectoryScanner は IgnoreHiddenFileListFilter と AcceptOnceFileListFilter を使用します。使用しないようにするには、独自のフィルター(AcceptAllFileListFilter など)を構成するか、null に設定することもできます。 |
WatchServiceDirectoryScanner
FileReadingMessageSource.WatchServiceDirectoryScanner
は、新しいファイルがディレクトリに追加されるとき、ファイルシステムイベントに依存します。初期化中に、ディレクトリはイベントを生成するために登録されます。初期ファイルリストも初期化中に作成されます。ディレクトリツリーをたどっていくと、発生したサブディレクトリも登録され、イベントが生成されます。最初のポーリングでは、ディレクトリ内を移動した最初のファイルリストが返されます。後続のポーリングでは、新規作成イベントからのファイルが返されます。新しいサブディレクトリが追加されると、その作成イベントを使用して新しいサブツリーをたどって既存のファイルを見つけ、見つかった新しいサブディレクトリを登録します。
WatchKey の内部イベント queue が、ディレクトリ変更イベントが発生するほど迅速にプログラムによって排出されない場合、WatchKey に課題があります。キューサイズを超えると、一部のファイルシステムイベントが失われる可能性があることを示す StandardWatchEventKinds.OVERFLOW が発行されます。この場合、ルートディレクトリは完全に再スキャンされます。重複を避けるため、適切な FileListFilter (AcceptOnceFileListFilter など)を使用するか、処理が完了したらファイルを削除することを検討してください。 |
WatchServiceDirectoryScanner
は、scanner
オプションと相互に排他的な FileReadingMessageSource.use-watch-service
オプションによって有効にできます。提供された directory
の内部 FileReadingMessageSource.WatchServiceDirectoryScanner
インスタンスが読み込まれます。
さらに、WatchService
ポーリングロジックは StandardWatchEventKinds.ENTRY_MODIFY
および StandardWatchEventKinds.ENTRY_DELETE
を追跡できるようになりました。
既存のファイルと新しいファイルの変更を追跡する必要がある場合は、FileListFilter
に ENTRY_MODIFY
イベントロジックを実装する必要があります。それ以外の場合、それらのイベントのファイルは同じように扱われます。
ResettableFileListFilter
実装は、ENTRY_DELETE
イベントを取得します。その結果、それらのファイルは remove()
操作用に提供されます。このイベントを有効にすると、AcceptOnceFileListFilter
などのフィルターによってファイルが削除されます。その結果、同じ名前のファイルが表示された場合、そのファイルはフィルターを通過し、メッセージとして送信されます。
この目的のために、watch-events
プロパティ(FileReadingMessageSource.setWatchEvents(WatchEventType… watchEvents)
)が導入されました。(WatchEventType
は FileReadingMessageSource
のパブリック内部列挙です)このようなオプションを使用すると、新しいファイルに 1 つのダウンストリームフローロジックを使用し、変更されたファイルに他のロジックを使用できます。次の例は、同じディレクトリでイベントを作成および変更するためのさまざまなロジックを構成する方法を示しています。
ENTRY_DELETE
イベントは、監視対象ディレクトリのサブディレクトリの名前変更操作に関係していることに注意してください。具体的には、以前のディレクトリ名に関連する ENTRY_DELETE
イベントが、新しい (名前が変更された) ディレクトリを通知する ENTRY_CREATE
イベントよりも前に発生します。一部のオペレーティングシステム (Windows など) では、その状況に対処するために ENTRY_DELETE
イベントを登録する必要があります。そうしないと、ファイルエクスプローラーで監視サブディレクトリの名前を変更すると、そのサブディレクトリで新しいファイルが検出されなくなる可能性があります。
<int-file:inbound-channel-adapter id="newFiles"
directory="${input.directory}"
use-watch-service="true"/>
<int-file:inbound-channel-adapter id="modifiedFiles"
directory="${input.directory}"
use-watch-service="true"
filter="acceptAllFilter"
watch-events="MODIFY"/> <!-- The default is CREATE. -->
バージョン 6.1 以降、FileReadingMessageSource
は 2 つの新しい WatchService
関連オプションを公開します。
watchMaxDepth
-Files.walkFileTree(Path root, Set attributes, int maxDepth, FileVisitor visitor)
API の引数。watchDirPredicate
-Predicate<Path>
は、スキャンされたツリー内のディレクトリを探索し、WatchService
および構成された監視イベントの種類に登録する必要があるかどうかをテストします。
メモリ消費の制限
HeadDirectoryScanner
を使用して、メモリに保持されるファイルの数を制限できます。これは、大きなディレクトリをスキャンするときに役立ちます。XML 構成では、受信チャネルアダプターの queue-size
プロパティを設定することでこれを有効にします。
バージョン 4.2 より前は、この設定は他のフィルターの使用と互換性がありませんでした。他のフィルター(prevent-duplicates="true"
を含む)は、サイズを制限するために使用されるフィルターを上書きしました。
通常、この場合は |
Java 構成を使用した構成
次の Spring Boot アプリケーションは、Java 構成で送信アダプターを構成する方法の例を示しています。
@SpringBootApplication
public class FileReadingJavaApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(FileReadingJavaApplication.class)
.web(false)
.run(args);
}
@Bean
public MessageChannel fileInputChannel() {
return new DirectChannel();
}
@Bean
@InboundChannelAdapter(value = "fileInputChannel", poller = @Poller(fixedDelay = "1000"))
public MessageSource<File> fileReadingMessageSource() {
FileReadingMessageSource source = new FileReadingMessageSource();
source.setDirectory(new File(INBOUND_PATH));
source.setFilter(new SimplePatternFileListFilter("*.txt"));
return source;
}
@Bean
@Transformer(inputChannel = "fileInputChannel", outputChannel = "processFileChannel")
public FileToStringTransformer fileToStringTransformer() {
return new FileToStringTransformer();
}
}
Java DSL を使用した構成
次の Spring Boot アプリケーションは、Java DSL で送信アダプターを構成する方法の例を示しています。
@SpringBootApplication
public class FileReadingJavaApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(FileReadingJavaApplication.class)
.web(false)
.run(args);
}
@Bean
public IntegrationFlow fileReadingFlow() {
return IntegrationFlow
.from(Files.inboundAdapter(new File(INBOUND_PATH))
.patternFilter("*.txt"),
e -> e.poller(Pollers.fixedDelay(1000)))
.transform(Files.toStringTransformer())
.channel("processFileChannel")
.get();
}
}
"tail" ファイル
もう 1 つの一般的な使用例は、ファイルの最後 (または末尾) から「行」を取得し、新しい行が追加されたときにそれをキャプチャーすることです。2 つの実装が提供されています。最初の OSDelegatingFileTailingMessageProducer
は、ネイティブの tail
コマンドを使用します (コマンドがあるオペレーティングシステムの場合)。これは通常、これらのプラットフォームで最も効率的な実装です。tail
コマンドがないオペレーティングシステムの場合、2 番目の実装 ApacheCommonsFileTailingMessageProducer
は Apache commons-io
Tailer
クラスを使用します。
どちらの場合も、利用できないファイルやその他のイベントなどのファイルシステムイベントは、通常の Spring イベント発行メカニズムを使用して ApplicationEvent
インスタンスとして発行されます。このようなイベントの例には次のものがあります。
[message=tail: cannot open '/tmp/somefile' for reading:
No such file or directory, file=/tmp/somefile]
[message=tail: '/tmp/somefile' has become accessible, file=/tmp/somefile]
[message=tail: '/tmp/somefile' has become inaccessible:
No such file or directory, file=/tmp/somefile]
[message=tail: '/tmp/somefile' has appeared;
following end of new file, file=/tmp/somefile]
前の例に示されている一連のイベントは、たとえば、ファイルがローテーションされるときに発生する可能性があります。
バージョン 5.0 以降、idleEventInterval
の実行中にファイルにデータがない場合、FileTailingIdleEvent
が発行されます。次の例は、そのようなイベントがどのように見えるかを示しています。
[message=Idle timeout, file=/tmp/somefile] [idle time=5438]
tail コマンドをサポートするすべてのプラットフォームがこれらのステータスメッセージを提供するわけではありません。 |
これらのエンドポイントから発信されるメッセージには、次のヘッダーがあります。
FileHeaders.ORIGINAL_FILE
:File
オブジェクトFileHeaders.FILENAME
: ファイル名 (File.getName()
)
バージョン 5.0 より前のバージョンでは、FileHeaders.FILENAME ヘッダーにはファイルの絶対パスの文字列表現が含まれていました。これで、元のファイルヘッダーで getAbsolutePath() を呼び出して、その文字列表現を取得できます。 |
次の例では、デフォルトのオプション( "-F -n 0"、現在の末尾からファイル名を追跡することを意味する)でネイティブアダプターを作成します。
<int-file:tail-inbound-channel-adapter id="native"
channel="input"
task-executor="exec"
file="/tmp/foo"/>
次の例では、"-F -n +0" オプションを使用してネイティブアダプターを作成します(つまり、ファイル名に従い、既存のすべての行を出力します)。
<int-file:tail-inbound-channel-adapter id="native"
channel="input"
native-options="-F -n +0"
task-executor="exec"
file-delay=10000
file="/tmp/foo"/>
tail
コマンドが失敗する場合(プラットフォームによっては、-F
が指定されている場合でもファイルの欠落により tail
が失敗する場合)、コマンドは 10 秒ごとに再試行されます。
デフォルトでは、ネイティブアダプターは標準出力からキャプチャーし、コンテンツをメッセージとして送信します。また、標準エラーからキャプチャーしてイベントを発生させます。バージョン 4.3.6 以降、次の例に示すように、enable-status-reader
を false
に設定することにより、標準エラーイベントを破棄できます。
<int-file:tail-inbound-channel-adapter id="native"
channel="input"
enable-status-reader="false"
task-executor="exec"
file="/tmp/foo"/>
次の例では、IdleEventInterval
は 5000
に設定されています。つまり、5 秒間行が書き込まれない場合、FileTailingIdleEvent
は 5 秒ごとにトリガーされます。
<int-file:tail-inbound-channel-adapter id="native"
channel="input"
idle-event-interval="5000"
task-executor="exec"
file="/tmp/somefile"/>
これは、アダプターを停止する必要がある場合に役立ちます。
次の例では、2 秒ごとにファイルの新しい行を調べ、10 秒ごとに不足しているファイルの存在を確認する Apache commons-io
Tailer
アダプターを作成します。
<int-file:tail-inbound-channel-adapter id="apache"
channel="input"
task-executor="exec"
file="/tmp/bar"
delay="2000"
end="false" (1)
reopen="true" (2)
file-delay="10000"/>
1 | ファイルは、末尾(デフォルト)ではなく先頭(end="false" )から末尾に付けられます。 |
2 | ファイルはチャンクごとに再度開かれます(デフォルトではファイルを開いたままにします)。 |
delay 、end 、reopen 属性を指定すると、Apache commons-io アダプターの使用が強制され、native-options 属性は使用できなくなります。 |
不完全なデータの処理
ファイル転送シナリオの一般的な問題は、転送が完了したことを確認して、不完全なファイルの読み取りを開始しないようにする方法です。この問題を解決する一般的な方法は、一時的な名前でファイルを作成し、アトミックに名前を最終的な名前に変更することです。この技術は、一時ファイルがコンシューマーによって選択されないようにマスクするフィルターとともに、堅牢なソリューションを提供します。この手法は、ファイルを(ローカルまたはリモートで)書き込む Spring Integration コンポーネントによって使用されます。デフォルトでは、ファイル名に .writing
を追加し、転送が完了したら削除します。
もう 1 つの一般的な手法は、2 番目の「マーカー」ファイルを作成して、ファイル転送が完了したことを示すことです。このシナリオでは、somefile.txt.complete
も存在するまで、somefile.txt
(たとえば)が使用可能であると見なすべきではありません。Spring Integration バージョン 5.0 は、このメカニズムをサポートする新しいフィルターを導入しました。ファイルシステム(FileSystemMarkerFilePresentFileListFilter
)、FTP および SFTP の実装が提供されています。マーカーファイルには任意の名前を付けることができますが、通常は転送されるファイルに関連しています。詳細については、Javadoc を参照してください。