INT-676
This commit is contained in:
@@ -6,54 +6,53 @@
|
||||
<section id="file-intro">
|
||||
<title>Introduction</title>
|
||||
<para>
|
||||
Spring Integration File extends the Spring Integration Core with
|
||||
dedicated
|
||||
vocabulary to deal with reading, writing and transforming
|
||||
files.
|
||||
There is a namespace that enables elements that define channel
|
||||
adapters dedicated to files and support for transformers that
|
||||
transform files into strings or byte arrays.
|
||||
Spring Integration's File support extends the Spring Integration Core with
|
||||
a dedicated vocabulary to deal with reading, writing, and transforming files.
|
||||
It provides a namespace that enables elements defining Channel Adapters dedicated
|
||||
to files and support for Transformers that can read file contents into strings or
|
||||
byte arrays.
|
||||
</para>
|
||||
<para>
|
||||
This section will explain the workings of <classname>FileReadingMessageSource</classname>, <classname>FileWritingMessageHandler</classname> and how to configure them as <emphasis>beans</emphasis>. Also the support for dealing with files through file specific implementations of <interfacename>Transformer</interfacename> will be discussed. Finally the file specific namespace will be explained.
|
||||
This section will explain the workings of <classname>FileReadingMessageSource</classname>
|
||||
and <classname>FileWritingMessageHandler</classname> and how to configure them as
|
||||
<emphasis>beans</emphasis>. Also the support for dealing with files through file specific
|
||||
implementations of <interfacename>Transformer</interfacename> will be discussed. Finally the
|
||||
file specific namespace will be explained.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="file-reading">
|
||||
<title>Reading Files</title>
|
||||
<para>
|
||||
A <classname>FileReadingMessageSource</classname> can be used to consume files from the filesystem. This is an implementation of <interfacename>MessageSource</interfacename> that creates messages from a file system directory.
|
||||
<programlisting language="xml"><![CDATA[<bean id="pollableFileSource"
|
||||
A <classname>FileReadingMessageSource</classname> can be used to consume files from the filesystem.
|
||||
This is an implementation of <interfacename>MessageSource</interfacename> that creates messages from
|
||||
a file system directory. <programlisting language="xml"><![CDATA[<bean id="pollableFileSource"
|
||||
class="org.springframework.integration.file.FileReadingMessageSource"
|
||||
p:inputDirectory="file:${input.directory.property}"/>]]></programlisting>
|
||||
p:inputDirectory="file:${input.directory}"/>]]></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
To prevent creating messages for certain files, you may supply a
|
||||
<interfacename>FileListFilter</interfacename>. By default, an
|
||||
<classname>AcceptOnceFileListFilter</classname>
|
||||
is used. This filter ensures files are picked up only once from the
|
||||
directory.
|
||||
<classname>AcceptOnceFileListFilter</classname> is used. This filter
|
||||
ensures files are picked up only once from the directory.
|
||||
<programlisting language="xml"><![CDATA[<bean id="pollableFileSource"
|
||||
class="org.springframework.integration.file.FileReadingMessageSource"
|
||||
p:inputDirectory="file:${input.directory.property}"
|
||||
p:inputDirectory="file:${input.directory}"
|
||||
p:filter-ref="customFilterBean"/>]]></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
A common problem with reading files is that a file may be detected
|
||||
before it is ready. The default
|
||||
<classname>AcceptOnceFileListFilter
|
||||
</classname>
|
||||
does
|
||||
not prevent this. In most cases, this can be prevented if the
|
||||
A common problem with reading files is that a file may be detected before
|
||||
it is ready. The default <classname>AcceptOnceFileListFilter</classname>
|
||||
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
|
||||
<classname>AcceptOnceFileListFilter
|
||||
</classname>
|
||||
allows for this.
|
||||
<classname>AcceptOnceFileListFilter</classname> allows for this.
|
||||
The <classname>CompositeFileListFilter</classname> enables the
|
||||
composition.
|
||||
<programlisting language="xml"><![CDATA[<bean id="pollableFileSource"
|
||||
class="org.springframework.integration.file.FileReadingMessageSource"
|
||||
p:inputDirectory="file:${input.directory.property}"
|
||||
p:inputDirectory="file:${input.directory}"
|
||||
p:filter-ref="compositeFilter"/>
|
||||
<bean id="compositeFilter" class="org.springframework.integration.file.CompositeFileListFilter">
|
||||
<constructor-arg>
|
||||
@@ -67,8 +66,8 @@
|
||||
</bean>]]></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
The configuration can be simplified using the file specific
|
||||
namespace. To do this use the following template.
|
||||
The configuration can be simplified using the file specific namespace. To do
|
||||
this use the following template.
|
||||
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
@@ -82,121 +81,116 @@
|
||||
http://www.springframework.org/schema/integration/file/spring-integration-file-1.0.xsd">
|
||||
</beans>]]></programlisting>
|
||||
Within this namespace you can reduce the FileReadingMessageSource and wrap
|
||||
it in an InboundChannelAdapter like this:
|
||||
<programlisting language="xml"><![CDATA[<file:inbound-channel-adapter id="filesIn"
|
||||
directory="file:${input.directory.property}"/>
|
||||
<file:inbound-channel-adapter id="filesIn"
|
||||
directory="file:${input.directory.property}"
|
||||
filter="customFilterBean" />
|
||||
<file:inbound-channel-adapter id="filesIn"
|
||||
directory="file:${input.directory.property}"
|
||||
filename-pattern="^test.*$" /> ]]></programlisting>
|
||||
Where 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
|
||||
<emphasis>filename-pattern</emphasis>
|
||||
attribute to add a
|
||||
<classname>Pattern</classname>
|
||||
based filter to the
|
||||
<classname>FileReadingMessageSource</classname>
|
||||
it in an inbound Channel Adapter like this:
|
||||
<programlisting language="xml"><![CDATA[ <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.*$" /> ]]></programlisting>
|
||||
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
|
||||
<emphasis>filename-pattern</emphasis> attribute to add a <classname>Pattern</classname>
|
||||
based filter to the <classname>FileReadingMessageSource</classname>.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="file-writing">
|
||||
<title>Writing files</title>
|
||||
<para>
|
||||
To write messages to the file system you can use a
|
||||
<classname>FileWritingMessageHandler
|
||||
</classname>
|
||||
. This class can deal with File or byte[] payloads and otherwise
|
||||
invokes the toString() method on the payload to establish the contents
|
||||
of the File. In its simplest form the
|
||||
<classname>FileWritingMessageHandler
|
||||
</classname>
|
||||
just needs a parent directory for the files.
|
||||
<classname>FileWritingMessageHandler</classname>. This class can deal with
|
||||
File, String, or byte array payloads. In its simplest form the
|
||||
<classname>FileWritingMessageHandler </classname> only requires a
|
||||
destination directory for writing the files. The name of the file to be
|
||||
written is determined by the handler's <classname>FileNameGenerator</classname>.
|
||||
The default implementation looks for a Message header whose key matches
|
||||
the constant defined as <code>FileHeaders.FILENAME</code>.
|
||||
</para>
|
||||
<para>
|
||||
Additionally, you can
|
||||
configure the encoding and the charset that
|
||||
will
|
||||
be used in case of a
|
||||
fallback on the toString() method.
|
||||
Additionally, you can configure the encoding and the charset that
|
||||
will be used in case of a String payload.
|
||||
</para>
|
||||
<para>
|
||||
To make things easier you can configure the
|
||||
FileWritingMessageHandler as part of an outbound channel adapter
|
||||
using the namespace.
|
||||
<programlisting language="xml"><![CDATA[<file:outbound-channel-adapter id="filesOut" directory="file:${input.directory.property}"/>]]></programlisting>
|
||||
To make things easier you can configure the FileWritingMessageHandler as
|
||||
part of an outbound channel adapter using the namespace.
|
||||
<programlisting language="xml"><![CDATA[ <file:outbound-channel-adapter id="filesOut" directory="file:${input.directory.property}"/>]]></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Namespace based configuration also supports <code>delete-source-files</code> attribute which if set to <code>true</code>
|
||||
will trigger deletion of the original source files after writing to a destination.
|
||||
The default value for that flag is <code>false</code>
|
||||
<programlisting language="xml"><![CDATA[<file:outbound-channel-adapter id="filesOut" directory="file:${input.directory.property}"
|
||||
delete-source-files="true"/>]]></programlisting>
|
||||
The namespace based configuration also supports a <code>delete-source-files</code> attribute.
|
||||
If set to <code>true</code>, it will trigger deletion of the original source files after writing
|
||||
to a destination. The default value for that flag is <code>false</code>.
|
||||
<programlisting language="xml"><![CDATA[ <file:outbound-channel-adapter id="filesOut"
|
||||
directory="file:${output.directory}"
|
||||
delete-source-files="true"/>]]></programlisting>
|
||||
<note>
|
||||
<para>
|
||||
The <code>delete-source-files</code> attribute will only have an effect if the inbound Message has a File payload or
|
||||
<classname>FileHeaders.ORIGINAL_FILE</classname> header value containing either a File instance or a String representing the original file path.
|
||||
The <code>delete-source-files</code> attribute will only have an effect if the inbound
|
||||
Message has a File payload or if the <classname>FileHeaders.ORIGINAL_FILE</classname> header
|
||||
value contains either the source File instance or a String representing the original file path.
|
||||
</para>
|
||||
</note>
|
||||
</para>
|
||||
<para>
|
||||
In cases where you want to continue processing messages based on the written File you can use <code>outbound-gateway</code> which plays a very similar role
|
||||
as the <code>outbound-channel-adapter</code>. However instead of writing a file It will send it over to the reply channel
|
||||
<programlisting language="xml"><![CDATA[<file:outbound-gateway id="mover" request-channel="moveInput"
|
||||
reply-channel="output"
|
||||
directory="${java.io.tmpdir}/anyDir"
|
||||
delete-source-files="true"/>]]></programlisting>
|
||||
In cases where you want to continue processing messages based on the written File you can use
|
||||
the <code>outbound-gateway</code> instead. It plays a very similar role as the
|
||||
<code>outbound-channel-adapter</code>. However after writing the File, it will also send it
|
||||
to the reply channel as the payload of a Message.
|
||||
<programlisting language="xml"><![CDATA[ <file:outbound-gateway id="mover" request-channel="moveInput"
|
||||
reply-channel="output"
|
||||
directory="${output.directory}"
|
||||
delete-source-files="true"/>]]></programlisting>
|
||||
</para>
|
||||
<note>
|
||||
The 'outbound-gateway' works well in cases where you want to first move a File and then send it
|
||||
through a processing pipeline. In such cases, you may connect the file namespace's
|
||||
'inbound-channel-adapter' element to the 'outbound-gateway' and then connect that gateway's
|
||||
reply-channel to the beginning of the pipeline.
|
||||
</note>
|
||||
<para>
|
||||
If you have more elaborate requirements to the payload to file
|
||||
conversion you could extend the FileWritingMessageHandler, but a
|
||||
much better option is to rely on a
|
||||
<classname>Transformer</classname>
|
||||
If you have more elaborate requirements or need to support additional payload types as input
|
||||
to be converted to file content you could extend the FileWritingMessageHandler, but a much
|
||||
better option is to rely on a <classname>Transformer</classname>.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="file-transforming">
|
||||
<title>File Transformers</title>
|
||||
<para>
|
||||
<!-- Introduction -->
|
||||
To transform data read from the file system to objects and the other
|
||||
way around you need to do some work. Contrary to
|
||||
<classname>FileReadingMessageSource</classname>
|
||||
and to a lesser extent
|
||||
<classname>FileWritingMessageHandler
|
||||
</classname>
|
||||
it is very likely that you will need your own mechanism to get the
|
||||
job done. For this you can implement the
|
||||
<interfacename>Transformer</interfacename>
|
||||
interface. Or extend the
|
||||
<classname>AbstractFilePayloadTransformer
|
||||
</classname>
|
||||
for inbound messages. Some obvious implementations have been
|
||||
provided.
|
||||
To transform data read from the file system to objects and the other way around you need
|
||||
to do some work. Contrary to <classname>FileReadingMessageSource</classname> and to a
|
||||
lesser extent <classname>FileWritingMessageHandler</classname>, it is very likely that you
|
||||
will need your own mechanism to get the job done. For this you can implement the
|
||||
<interfacename>Transformer</interfacename> interface. Or extend the
|
||||
<classname>AbstractFilePayloadTransformer</classname> for inbound messages. Some obvious
|
||||
implementations have been provided.
|
||||
</para>
|
||||
<para>
|
||||
<classname>FileToByteArrayTransformer
|
||||
</classname>
|
||||
transforms Files into byte[]s using
|
||||
<classname>FileCopyUtils</classname>
|
||||
. It is often better to use a sequence of transformers than to put
|
||||
all transformations in a single class, in that case the File to
|
||||
<classname>FileToByteArrayTransformer</classname> transforms Files into byte[]s using
|
||||
Spring's <classname>FileCopyUtils</classname>. It is often better to use a sequence of
|
||||
transformers than to put all transformations in a single class. In that case the File to
|
||||
byte[] conversion might be a logical first step.
|
||||
</para>
|
||||
<para>
|
||||
<classname>FileToStringTransformer</classname>
|
||||
will convert Files to Strings as the name suggests. This is mainly useful for debugging.
|
||||
<classname>FileToStringTransformer</classname> will convert Files to Strings as the name
|
||||
suggests. If nothing else, this can be useful for debugging (consider using with a Wire Tap).
|
||||
</para>
|
||||
<para>
|
||||
To configure File specific transformers you can use the appropriate
|
||||
elements from the file namespace.
|
||||
<programlisting language="xml"><![CDATA[<file-to-bytes-transformer input-channel="input" output-channel="output" delete-files="true"/>]]></programlisting>
|
||||
The
|
||||
<emphasis>delete-files</emphasis>
|
||||
option signals the transformer to delete the File after the
|
||||
transformation is done. This is in no way a replacement for using the
|
||||
<classname>AcceptOnceFileListFilter
|
||||
</classname>
|
||||
with the PollableFileSource in a multi-threaded environment (e.g. Spring Integration in general).
|
||||
To configure File specific transformers you can use the appropriate elements from the file namespace.
|
||||
<programlisting language="xml"><![CDATA[ <file-to-bytes-transformer input-channel="input" output-channel="output"
|
||||
delete-files="true"/>
|
||||
|
||||
<file:file-to-string-transformer input-channel="input" output-channel="output
|
||||
delete-files="true" charset="UTF-8"/>]]></programlisting>
|
||||
The <emphasis>delete-files</emphasis> option signals to the transformer that it should delete
|
||||
the inbound File after the transformation is complete. This is in no way a replacement for using the
|
||||
<classname>AcceptOnceFileListFilter</classname> when the FileReadingMessageSource is being used in a
|
||||
multi-threaded environment (e.g. Spring Integration in general).
|
||||
</para>
|
||||
</section>
|
||||
|
||||
</chapter>
|
||||
Reference in New Issue
Block a user