public class FileWritingMessageHandler extends AbstractReplyProducingMessageHandler implements ManageableLifecycle, MessageTriggerAction
MessageHandler
implementation
that writes the Message payload to a
file. If the payload is a File object, it will copy the File to the specified
destination directory. If the payload is a byte array, a String or an
InputStream it will be written directly. Otherwise, the payload type is
unsupported, and an Exception will be thrown.
To append a new-line after each write, set the
appendNewLine
flag to 'true'. It is 'false' by default.
If the 'deleteSourceFiles' flag is set to true, the original Files will be
deleted. The default value for that flag is false. See the
setDeleteSourceFiles(boolean)
method javadoc for more information.
Other transformers may be useful to precede this handler. For example, any
Serializable object payload can be converted into a byte array by the
PayloadSerializingTransformer
.
Likewise, any Object can be converted to a String based on its
toString()
method by the
ObjectToStringTransformer
.
FileExistsMode.APPEND
adds content to an existing file; the file is closed after
each write.
FileExistsMode.APPEND_NO_FLUSH
adds content to an existing file and the file
is left open without flushing any data. Data will be flushed based on the
flushInterval
or when a message is sent to the
trigger(Message)
method, or a
flushIfNeeded
method is called.
Modifier and Type | Class and Description |
---|---|
static interface |
FileWritingMessageHandler.FlushPredicate
When using
FileExistsMode.APPEND_NO_FLUSH , an implementation of this
interface is called for each file that has pending data to flush and close when
flushIfNeeded(FlushPredicate) is invoked. |
static interface |
FileWritingMessageHandler.MessageFlushPredicate
When using
FileExistsMode.APPEND_NO_FLUSH
an implementation of this interface is called for each file that has pending data
to flush when a trigger message is received. |
AbstractReplyProducingMessageHandler.RequestHandler
IntegrationManagement.ManagementOverrides
messagingTemplate
EXPRESSION_PARSER, logger
HIGHEST_PRECEDENCE, LOWEST_PRECEDENCE
METER_PREFIX, RECEIVE_COUNTER_NAME, SEND_TIMER_NAME
Constructor and Description |
---|
FileWritingMessageHandler(Expression destinationDirectoryExpression)
Constructor which sets the
destinationDirectoryExpression . |
FileWritingMessageHandler(File destinationDirectory)
Constructor which sets the
destinationDirectoryExpression using
a LiteralExpression . |
Modifier and Type | Method and Description |
---|---|
protected BufferedOutputStream |
createOutputStream(File fileToWriteTo,
boolean append)
Create a buffered output stream for the file.
|
protected BufferedWriter |
createWriter(File fileToWriteTo,
boolean append)
Create a buffered writer for the file, for String payloads.
|
protected void |
doInit() |
void |
flushIfNeeded(FileWritingMessageHandler.FlushPredicate flushPredicate)
When using
FileExistsMode.APPEND_NO_FLUSH you can invoke this method to
selectively flush and close open files. |
void |
flushIfNeeded(FileWritingMessageHandler.MessageFlushPredicate flushPredicate,
Message<?> filterMessage)
When using
FileExistsMode.APPEND_NO_FLUSH you can invoke this method to
selectively flush and close open files. |
String |
getComponentType()
Subclasses may implement this method to provide component type information.
|
IntegrationPatternType |
getIntegrationPatternType()
Return a pattern type this component implements.
|
protected String |
getTemporaryFileSuffix() |
protected Object |
handleRequestMessage(Message<?> requestMessage)
Subclasses must implement this method to handle the request Message.
|
boolean |
isRunning() |
void |
setAppendNewLine(boolean appendNewLine)
If 'true' will append a new-line after each write.
|
void |
setAutoCreateDirectory(boolean autoCreateDirectory)
Specify whether to create the destination directory automatically if it
does not yet exist upon initialization.
|
void |
setBufferSize(int bufferSize)
Set the buffer size to use while writing to files; default 8192.
|
void |
setCharset(String charset)
Set the charset name to use when writing a File from a String-based
Message payload.
|
void |
setChmod(int chmod)
Set the file permissions after uploading, e.g.
|
void |
setChmodOctal(String chmod)
String setter for Spring XML convenience.
|
void |
setDeleteSourceFiles(boolean deleteSourceFiles)
Specify whether to delete source Files after writing to the destination
directory.
|
void |
setExpectReply(boolean expectReply)
Specify whether a reply Message is expected.
|
void |
setFileExistsMode(FileExistsMode fileExistsMode)
Will set the
FileExistsMode that specifies what will happen in
case the destination exists. |
void |
setFileNameGenerator(FileNameGenerator fileNameGenerator)
Provide the
FileNameGenerator strategy to use when generating
the destination file's name. |
void |
setFlushInterval(long flushInterval)
Set the frequency to flush buffers when
FileExistsMode.APPEND_NO_FLUSH is
being used. |
void |
setFlushPredicate(FileWritingMessageHandler.MessageFlushPredicate flushPredicate)
Set a
FileWritingMessageHandler.MessageFlushPredicate to use when flushing files when
FileExistsMode.APPEND_NO_FLUSH is being used. |
void |
setFlushWhenIdle(boolean flushWhenIdle)
Determine whether the
flushInterval applies only
to idle files (default) or whether to flush on that interval after the first
write to a previously flushed or new file. |
void |
setNewFileCallback(java.util.function.BiConsumer<File,Message<?>> newFileCallback)
Set the callback to use when creating new files.
|
protected void |
setPermissions(File resultFile)
Set permissions on newly written files.
|
void |
setPreserveTimestamp(boolean preserveTimestamp)
Set to true to preserve the destination file timestamp.
|
void |
setTemporaryFileSuffix(String temporaryFileSuffix)
By default, every file that is in the process of being transferred will
appear in the file system with an additional suffix, which by default is
".writing".
|
void |
start() |
void |
stop() |
void |
trigger(Message<?> message)
When using
FileExistsMode.APPEND_NO_FLUSH , you can send a message to this
method to flush any file(s) that needs it. |
doInvokeAdvisedRequestHandler, getBeanClassLoader, getRequiresReply, handleMessageInternal, hasAdviceChain, onInit, setAdviceChain, setBeanClassLoader, setRequiresReply
addNotPropagatedHeaders, createOutputMessage, getNotPropagatedHeaders, getOutputChannel, isAsync, messageBuilderForReply, produceOutput, resolveErrorChannel, sendErrorMessage, sendOutput, sendOutputs, setAsync, setNotPropagatedHeaders, setOutputChannel, setOutputChannelName, setSendTimeout, shouldCopyRequestHeaders, shouldSplitOutput, updateNotPropagatedHeaders
handleMessage, onComplete, onError, onNext, onSubscribe
buildSendTimer, destroy, getManagedName, getManagedType, getMetricsCaptor, getOrder, getOverrides, isLoggingEnabled, registerMetricsCaptor, sendTimer, setLoggingEnabled, setManagedName, setManagedType, setOrder, setShouldTrack, shouldTrack
afterPropertiesSet, extractTypeIfPossible, generateId, getApplicationContext, getApplicationContextId, getBeanDescription, getBeanFactory, getBeanName, getChannelResolver, getComponentName, getConversionService, getExpression, getIntegrationProperties, getIntegrationProperty, getMessageBuilderFactory, getTaskScheduler, isInitialized, setApplicationContext, setBeanFactory, setBeanName, setChannelResolver, setComponentName, setConversionService, setMessageBuilderFactory, setPrimaryExpression, setTaskScheduler, toString
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
getThisAs
getBeanName, getComponentName
public FileWritingMessageHandler(File destinationDirectory)
destinationDirectoryExpression
using
a LiteralExpression
.destinationDirectory
- Must not be nullFileWritingMessageHandler(Expression)
public FileWritingMessageHandler(Expression destinationDirectoryExpression)
destinationDirectoryExpression
.destinationDirectoryExpression
- Must not be nullFileWritingMessageHandler(File)
public void setAutoCreateDirectory(boolean autoCreateDirectory)
autoCreateDirectory
- true to create the directory if needed.public void setTemporaryFileSuffix(String temporaryFileSuffix)
temporaryFileSuffix
- The temporary file suffix.public void setFileExistsMode(FileExistsMode fileExistsMode)
FileExistsMode
that specifies what will happen in
case the destination exists. For example FileExistsMode.APPEND
instructs this handler to append data to the existing file rather then
creating a new file for each Message
.
If set to FileExistsMode.APPEND
, the adapter will also
create a real instance of the LockRegistry
to ensure that there
is no collisions when multiple threads are writing to the same file.
Otherwise the LockRegistry is set to PassThruLockRegistry
which
has no effect.
With FileExistsMode.REPLACE_IF_MODIFIED
, if the file exists,
it is only replaced if its last modified timestamp is different to the
source; otherwise, the write is ignored. For File
payloads,
the actual timestamp of the File
is compared; for other payloads,
the FileHeaders.SET_MODIFIED
is compared to the existing file.
If the header is missing, or its value is not a Number
, the file
is always replaced. This mode will typically only make sense if
preserveTimestamp
is true.
fileExistsMode
- Must not be nullsetPreserveTimestamp(boolean)
public void setExpectReply(boolean expectReply)
expectReply
- true if a reply is expected.public void setAppendNewLine(boolean appendNewLine)
appendNewLine
- true if a new-line should be written to the file after payload is writtenprotected String getTemporaryFileSuffix()
public void setFileNameGenerator(FileNameGenerator fileNameGenerator)
FileNameGenerator
strategy to use when generating
the destination file's name.fileNameGenerator
- The file name generator.public void setDeleteSourceFiles(boolean deleteSourceFiles)
FileHeaders.ORIGINAL_FILE
header value containing either a
File instance or a String representing the original file path.deleteSourceFiles
- true to delete the source files.public void setCharset(String charset)
charset
- The charset.public void setBufferSize(int bufferSize)
bufferSize
- the buffer size.public void setFlushInterval(long flushInterval)
FileExistsMode.APPEND_NO_FLUSH
is
being used. The interval is approximate; the actual interval will be between
flushInterval
and flushInterval * 1.33
with an average of
flushInterval * 1.167
.flushInterval
- the interval.setFlushWhenIdle(boolean)
public void setFlushWhenIdle(boolean flushWhenIdle)
flushInterval
applies only
to idle files (default) or whether to flush on that interval after the first
write to a previously flushed or new file.flushWhenIdle
- false to flush on the interval after the first write
to a closed file.setFlushInterval(long)
,
setBufferSize(int)
public void setFlushPredicate(FileWritingMessageHandler.MessageFlushPredicate flushPredicate)
FileWritingMessageHandler.MessageFlushPredicate
to use when flushing files when
FileExistsMode.APPEND_NO_FLUSH
is being used.
See trigger(Message)
.flushPredicate
- the predicate.public void setPreserveTimestamp(boolean preserveTimestamp)
File
, the payload's lastModified
time will be
transferred to the destination file. For other payloads, the
FileHeaders.SET_MODIFIED
header
will be used if present and it's a Number
.preserveTimestamp
- the preserveTimestamp to set.public void setChmodOctal(String chmod)
chmod
- permissions as an octal string e.g "600";setChmod(int)
public void setChmod(int chmod)
chmod
- the permissions.IllegalArgumentException
- if the value is higher than 0777.public void setNewFileCallback(java.util.function.BiConsumer<File,Message<?>> newFileCallback)
fileExistsMode
is FileExistsMode.APPEND
or FileExistsMode.APPEND_NO_FLUSH
and new file has to be created. The callback receives the new result file and the message that
triggered the handler.newFileCallback
- a BiConsumer
callback to be invoked when new file is created.public String getComponentType()
IntegrationObjectSupport
getComponentType
in interface NamedComponent
getComponentType
in class MessageHandlerSupport
public IntegrationPatternType getIntegrationPatternType()
IntegrationPattern
getIntegrationPatternType
in interface IntegrationPattern
getIntegrationPatternType
in class AbstractReplyProducingMessageHandler
IntegrationPatternType
this component implements.protected void doInit()
doInit
in class AbstractReplyProducingMessageHandler
public void start()
start
in interface Lifecycle
start
in interface ManageableLifecycle
public void stop()
stop
in interface Lifecycle
stop
in interface ManageableLifecycle
public boolean isRunning()
isRunning
in interface Lifecycle
isRunning
in interface ManageableLifecycle
protected Object handleRequestMessage(Message<?> requestMessage)
AbstractReplyProducingMessageHandler
handleRequestMessage
in class AbstractReplyProducingMessageHandler
requestMessage
- The request message.null
.protected void setPermissions(File resultFile) throws IOException
resultFile
- the file.IOException
- any exception.protected BufferedWriter createWriter(File fileToWriteTo, boolean append) throws FileNotFoundException
fileToWriteTo
- the file.append
- true if we are appending.FileNotFoundException
- if the file does not exist.protected BufferedOutputStream createOutputStream(File fileToWriteTo, boolean append) throws FileNotFoundException
fileToWriteTo
- the file.append
- true if we are appending.FileNotFoundException
- if not found.public void trigger(Message<?> message)
FileExistsMode.APPEND_NO_FLUSH
, you can send a message to this
method to flush any file(s) that needs it. By default, the payload must be a regular
expression (String
or Pattern
) that matches the absolutePath
of any in-process files. However, if a custom FileWritingMessageHandler.MessageFlushPredicate
is provided,
the payload can be of any type supported by that implementation.trigger
in interface MessageTriggerAction
message
- the message.public void flushIfNeeded(FileWritingMessageHandler.FlushPredicate flushPredicate)
FileExistsMode.APPEND_NO_FLUSH
you can invoke this method to
selectively flush and close open files. For each open file the supplied
FileWritingMessageHandler.MessageFlushPredicate.shouldFlush(String, long, long, Message)
method is invoked and if true is returned, the file is flushed.flushPredicate
- the FileWritingMessageHandler.FlushPredicate
.public void flushIfNeeded(FileWritingMessageHandler.MessageFlushPredicate flushPredicate, Message<?> filterMessage)
FileExistsMode.APPEND_NO_FLUSH
you can invoke this method to
selectively flush and close open files. For each open file the supplied
FileWritingMessageHandler.MessageFlushPredicate.shouldFlush(String, long, long, Message)
method is invoked and if true is returned, the file is flushed.flushPredicate
- the FileWritingMessageHandler.MessageFlushPredicate
.filterMessage
- an optional message passed into the predicate.