17.2 Reading Files

A FileReadingMessageSource can be used to consume files from the filesystem. This is an implementation of MessageSource that creates messages from a file system directory.

<bean id="pollableFileSource"
      class="org.springframework.integration.file.FileReadingMessageSource"
        p:inputDirectory="file:${input.directory}"/>

To prevent creating messages for certain files, you may supply a FileListFilter. By default, an AcceptOnceFileListFilter is used. This filter ensures files are picked up only once from the directory.

<bean id="pollableFileSource"
      class="org.springframework.integration.file.FileReadingMessageSource"
        p:inputDirectory="file:${input.directory}"
        p:filter-ref="customFilterBean"/>

A common problem with reading files is that a file may be detected before it is ready. The default AcceptOnceFileListFilter does not prevent this. In most cases, this can be prevented if the file-writing process renames each file as soon as it is ready for reading. A pattern-matching filter that accepts only files that are ready (e.g. based on a known suffix), composed with the default AcceptOnceFileListFilter allows for this. The CompositeFileListFilter enables the composition.

<bean id="pollableFileSource"
      class="org.springframework.integration.file.FileReadingMessageSource"
        p:inputDirectory="file:${input.directory}"
        p:filter-ref="compositeFilter"/>
<bean id="compositeFilter" class="org.springframework.integration.file.CompositeFileListFilter">
    <constructor-arg>
        <list>
            <bean class="org.springframework.integration.file.AcceptOnceFileListFilter" />
            <bean class="org.springframework.integration.file.PatternMatchingFileListFilter">
                <constructor-arg value="^test.*$"/>
            </bean>
        </list>
    </constructor-arg>
</bean>

The configuration can be simplified using the file specific namespace. To do this use the following template.

<?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:integration="http://www.springframework.org/schema/integration"
	xmlns:file="http://www.springframework.org/schema/integration/file"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
			http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
			http://www.springframework.org/schema/integration
			http://www.springframework.org/schema/integration/spring-integration-1.0.xsd
			http://www.springframework.org/schema/integration/file
			http://www.springframework.org/schema/integration/file/spring-integration-file-1.0.xsd">
</beans>

Within this namespace you can reduce the FileReadingMessageSource and wrap it in an inbound Channel Adapter like this:

 <file:inbound-channel-adapter id="filesIn"
       directory="file:${input.directory}"/>
 					
 <file:inbound-channel-adapter id="filesIn"
        directory="file:${input.directory}" 
        filter="customFilterBean" />							

 <file:inbound-channel-adapter id="filesIn"
        directory="file:${input.directory}" 
        filename-pattern="^test.*$" /> 							

The first channel adapter is relying on the default filter that just prevents duplication, the second is using a custom filter, and the third is using the filename-pattern attribute to add a Pattern based filter to the FileReadingMessageSource.