INT-2618 - Document directory-expression attribute

* Add documentation directory-expression
* Add documentation for auto-create-directory attribute
* Refactor File Adapter chapter slightly so that it flows better

For reference see: https://jira.springsource.org/browse/INT-2618

INT-2618 - Doc updated due to changes in INT-805

* rebased
* clarified the file section in the reference doc
This commit is contained in:
Gunnar Hillert
2012-06-14 17:56:19 -04:00
committed by Oleg Zhurakousky
parent 9082512a48
commit 97b59c2acd
2 changed files with 168 additions and 76 deletions

View File

@@ -286,7 +286,7 @@ Only files matching this regular expression will be picked up by this adapter.
<xsd:annotation>
<xsd:documentation>
Extension used when uploading files. We change it after we know it's uploaded.
This attribute is mutualy exclusive with 'append' since the append is done to the
This attribute is mutualy exclusive with 'append' since the append is done to the
actual file and not its temporary counterpart. The default value of this attribute (i.e., .writing)
is ignored when 'append' is set to true.
</xsd:documentation>
@@ -295,10 +295,13 @@ Only files matching this regular expression will be picked up by this adapter.
<xsd:attribute name="append" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Will append to the existing file if such file exists otherwise the new file will be created as usual
but once created the subsequent data will be appended to it.
This attribute is mutualy exclusive with the 'temporary-file-suffix' since append is done to the
actual file and not its temporary counterpart.
If set to 'true', the data will will be appended to the
existing file if such file exists, otherwise the new file
will be created as usual but once created the subsequent data
will be appended to it. This attribute is mutualy exclusive
with the 'temporary-file-suffix' since append is done to the
actual file and not its temporary counterpart. This attribute
defaults to 'false' if not set explicitly.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>

View File

@@ -54,7 +54,7 @@
class="org.springframework.integration.file.FileReadingMessageSource"
p:inputDirectory="${input.directory}"
p:filter-ref="compositeFilter"/>
<bean id="compositeFilter"
<bean id="compositeFilter"
class="org.springframework.integration.file.filters.CompositeFileListFilter">
<constructor-arg>
<list>
@@ -100,7 +100,7 @@
directory="file:${input.directory}"
filename-regex="test[0-9]+\.txt" /> ]]></programlisting>
</para>
<para>
<para>
The first channel adapter is relying on the default filter that just prevents
duplication, the second is using a custom filter, the third is using the
<emphasis>filename-pattern</emphasis> attribute to add an <classname>AntPathMatcher</classname>
@@ -122,7 +122,7 @@
<int-file:nio-locker/>
</int-file:inbound-channel-adapter>]]></programlisting>
</para>
<para>
<para>
A custom locker you can configure like this:
<programlisting language="xml"><![CDATA[ <int-file:inbound-channel-adapter id="filesIn"
directory="file:${input.directory}" prevent-duplicates="true">
@@ -143,77 +143,166 @@
that Spring Integration uses internally to wire FileListFilters FileLocker to the FileReadingMessageSource.
A custom DirectoryScanner can be injected into the &lt;int-file:inbound-channel-adapter/&gt; on the <code>scanner</code>
attribute.
<programlisting language="xml"><![CDATA[ <int-file:inbound-channel-adapter id="filesIn" directory="file:${input.directory}"
<programlisting language="xml"><![CDATA[ <int-file:inbound-channel-adapter id="filesIn" directory="file:${input.directory}"
prevent-duplicates="true" scanner="customDirectoryScanner"/>]]></programlisting>
</para>
<para>
</para>
<para>
This gives you full freedom to choose the ordering, listing and locking strategies.
</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, 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 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[ <int-file:outbound-channel-adapter id="filesOut" directory="${input.directory.property}"/>]]></programlisting>
</para>
<para>
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[ <int-file:outbound-channel-adapter id="filesOut"
directory="${output.directory}"
delete-source-files="true"/>]]></programlisting>
<note>
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.
</note>
</para>
<para>
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[ <int-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 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>
<para>
Since Spring Integration version 2.2. you can append Message content to the existing file instead of creating a new
File each time. To do so set <emphasis>append</emphasis> attribute to <code></code>;
Note that this attribute is mutually exclusive with <emphasis>temporary-file-suffix</emphasis> attribute since when
appending content to the existing file the adapter no longer uses temporary file.
</para>
</section>
<section id="file-writing">
<title>Writing files</title>
<para>
To write messages to the file system you can use a
<classname><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/file/FileWritingMessageHandler.html">FileWritingMessageHandler</ulink></classname>.
This class can deal with <emphasis>File</emphasis>,
<emphasis>String</emphasis>, or <emphasis>byte array</emphasis>
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><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/file/FileNameGenerator.html">FileNameGenerator</ulink></classname>.
The <ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/file/DefaultFileNameGenerator.html">default implementation</ulink>
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 String payload.
</para>
<para>
To make things easier, you can configure the <classname>FileWritingMessageHandler</classname>
as part of an <emphasis>Outbound Channel Adapter</emphasis> or
<emphasis>Outbound Gateway</emphasis> using the provided XML namespace
support.
</para>
<section id="file-writing-output-directory">
<title>Specifying the Output Directory</title>
<para>
Both, the <emphasis>File Oubound Channel Adapter</emphasis> and
the <emphasis>File Outbound Gateway</emphasis> provide two
configuration attributes for specifying the output directory:
</para>
<itemizedlist>
<listitem>
<para><emphasis>directory</emphasis></para>
</listitem>
<listitem>
<para><emphasis>directory-expression</emphasis></para>
</listitem>
</itemizedlist>
<note>
The <emphasis>directory-expression</emphasis> attribute is available since
Spring Integration 2.2.
</note>
<para><emphasis role="bold">Using the directory attribute</emphasis></para>
<para>
When using the <emphasis>directory</emphasis> attribute, the output
directory will be set to a fixed value, that is set at
intialization time of the <classname>FileWritingMessageHandler</classname>.
If you don't specify this attribute, then you must use the
<emphasis>directory-expression</emphasis> attribute.
</para>
<para><emphasis role="bold">Using the directory-expression attribute</emphasis></para>
<para>
If you want to have full SpEL support you would choose the
<emphasis>directory-expression</emphasis> attribute. This attribute
accepts a SpEL expression that is evaluated for each message being
processed. Thus, you have full access to a Message's payload and
its headers to dynamically specify the output file directory.
</para>
<para>
The SpEL expression must resolve to either a <classname>String</classname>
or to <classname>java.io.File</classname>. Furthermore the resulting
<classname>String</classname> or <classname>File</classname> must
point to a directory. If you don't specify the
<emphasis>directory-expression</emphasis> attribute, then you
must set the <emphasis>directory</emphasis> attribute.
</para>
<para><emphasis role="bold">Using the auto-create-directory attribute</emphasis></para>
<para>
If the destination directory does not exists, yet, by default the
respective destination directory and any non-existing parent directories
are being created automatically. You can set the
<emphasis>auto-create-directory</emphasis> attribute to
<emphasis>false</emphasis> in order to prevent that. This attribute
applies to both, the <emphasis>directory</emphasis> and the
<emphasis>directory-expression</emphasis> attribute.
</para>
<note>
<para>
When using the <emphasis>directory</emphasis> attribute and
<emphasis>auto-create-directory</emphasis> is <code>false</code>,
the following change was made starting with Spring Integration 2.2:
</para>
<para>
Instead of checking for the existence of the destination directory
at initialization time of the adapter, this check is now
performed for each message being processed.
</para>
<para>
Furthermore, if <emphasis>auto-create-directory</emphasis> is
<code>true</code> and the directory was deleted between the
processing of messages, the directory will be re-created for each
message being processed.
</para>
</note>
</section>
<section id="file-writing-append">
<title>Append to Files</title>
<para>
Since Spring Integration 2.2 you can append Message
content to the existing file instead of creating a new File each
time. To do so, set the <emphasis>append</emphasis> attribute
to <code>true</code>. Note that this attribute is mutually exclusive
with <emphasis>temporary-file-suffix</emphasis> attribute since
when appending content to the existing file, the adapter no longer
uses a temporary file. This attribute defaults to 'false' if not
set explicitly.
</para>
</section>
<section id="file-outbound-channel-adapter">
<title>File Outbound Channel Adapter</title>
<programlisting language="xml"><![CDATA[ <int-file:outbound-channel-adapter id="filesOut" directory="${input.directory.property}"/>]]></programlisting>
<para>
The namespace based configuration also supports a <code>delete-source-files</code> attribute.
If set to <code>true</code>, it will trigger the deletion of the original source files after writing
to a destination. The default value for that flag is <code>false</code>.
</para>
<programlisting language="xml"><![CDATA[ <int-file:outbound-channel-adapter id="filesOut"
directory="${output.directory}"
delete-source-files="true"/>]]></programlisting>
<note>
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.
</note>
</section>
<section id="file-writing-output-gateway">
<title>Outbound Gateway</title>
<para>
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.
</para>
<programlisting language="xml"><![CDATA[ <int-file:outbound-gateway id="mover" request-channel="moveInput"
reply-channel="output"
directory="${output.directory}"
delete-source-files="true"/>]]></programlisting>
<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 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>
>>>>>>> INT-2618 - Document directory-expression attribute
<section id="file-transforming">
<title>File Transformers</title>
@@ -244,7 +333,7 @@
<int-file:file-to-string-transformer input-channel="input" output-channel="output"
delete-files="true" charset="UTF-8"/>]]></programlisting>
</para>
<para>
<para>
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