Class FileWritingMessageHandler
- All Implemented Interfaces:
org.reactivestreams.Subscriber<Message<?>>
,Aware
,BeanClassLoaderAware
,BeanFactoryAware
,BeanNameAware
,DisposableBean
,InitializingBean
,ApplicationContextAware
,Lifecycle
,Ordered
,ExpressionCapable
,Orderable
,MessageProducer
,HeaderPropagationAware
,MessageTriggerAction
,IntegrationPattern
,NamedComponent
,IntegrationManagement
,ManageableLifecycle
,TrackableComponent
,MessageHandler
,reactor.core.CoreSubscriber<Message<?>>
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.
- Author:
- Mark Fisher, Iwein Fuld, Alex Peters, Oleg Zhurakousky, Artem Bilan, Gunnar Hillert, Gary Russell, Tony Falabella, Alen Turkovic
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static interface
FileWritingMessageHandler.FlushPredicate
When usingFileExistsMode.APPEND_NO_FLUSH
, an implementation of this interface is called for each file that has pending data to flush and close whenflushIfNeeded(FlushPredicate)
is invoked.static interface
FileWritingMessageHandler.MessageFlushPredicate
When usingFileExistsMode.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.Nested classes/interfaces inherited from class org.springframework.integration.handler.AbstractReplyProducingMessageHandler
AbstractReplyProducingMessageHandler.RequestHandler
Nested classes/interfaces inherited from interface org.springframework.integration.support.management.IntegrationManagement
IntegrationManagement.ManagementOverrides
-
Field Summary
Fields inherited from class org.springframework.integration.handler.AbstractMessageProducingHandler
messagingTemplate
Fields inherited from class org.springframework.integration.context.IntegrationObjectSupport
EXPRESSION_PARSER, logger
Fields inherited from interface org.springframework.integration.support.management.IntegrationManagement
METER_PREFIX, RECEIVE_COUNTER_NAME, SEND_TIMER_NAME
Fields inherited from interface org.springframework.core.Ordered
HIGHEST_PRECEDENCE, LOWEST_PRECEDENCE
-
Constructor Summary
Constructors Constructor Description FileWritingMessageHandler(File destinationDirectory)
Constructor which sets thedestinationDirectoryExpression
using aLiteralExpression
.FileWritingMessageHandler(Expression destinationDirectoryExpression)
Constructor which sets thedestinationDirectoryExpression
. -
Method Summary
Modifier and Type Method 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 usingFileExistsMode.APPEND_NO_FLUSH
you can invoke this method to selectively flush and close open files.void
flushIfNeeded(FileWritingMessageHandler.MessageFlushPredicate flushPredicate, Message<?> filterMessage)
When usingFileExistsMode.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 theFileExistsMode
that specifies what will happen in case the destination exists.void
setFileNameGenerator(FileNameGenerator fileNameGenerator)
Provide theFileNameGenerator
strategy to use when generating the destination file's name.void
setFlushInterval(long flushInterval)
Set the frequency to flush buffers whenFileExistsMode.APPEND_NO_FLUSH
is being used.void
setFlushPredicate(FileWritingMessageHandler.MessageFlushPredicate flushPredicate)
Set aFileWritingMessageHandler.MessageFlushPredicate
to use when flushing files whenFileExistsMode.APPEND_NO_FLUSH
is being used.void
setFlushWhenIdle(boolean flushWhenIdle)
Determine whether theflushInterval
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(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 usingFileExistsMode.APPEND_NO_FLUSH
, you can send a message to this method to flush any file(s) that needs it.Methods inherited from class org.springframework.integration.handler.AbstractReplyProducingMessageHandler
doInvokeAdvisedRequestHandler, getBeanClassLoader, getRequiresReply, handleMessageInternal, hasAdviceChain, onInit, setAdviceChain, setBeanClassLoader, setRequiresReply
Methods inherited from class org.springframework.integration.handler.AbstractMessageProducingHandler
addNotPropagatedHeaders, createOutputMessage, getNotPropagatedHeaders, getOutputChannel, isAsync, messageBuilderForReply, produceOutput, resolveErrorChannel, sendErrorMessage, sendOutput, sendOutputs, setAsync, setNotPropagatedHeaders, setOutputChannel, setOutputChannelName, setSendTimeout, shouldCopyRequestHeaders, shouldSplitOutput, updateNotPropagatedHeaders
Methods inherited from class org.springframework.integration.handler.AbstractMessageHandler
handleMessage, onComplete, onError, onNext, onSubscribe
Methods inherited from class org.springframework.integration.handler.MessageHandlerSupport
buildSendTimer, destroy, getManagedName, getManagedType, getMetricsCaptor, getOrder, getOverrides, isLoggingEnabled, registerMetricsCaptor, sendTimer, setLoggingEnabled, setManagedName, setManagedType, setOrder, setShouldTrack, shouldTrack
Methods inherited from class org.springframework.integration.context.IntegrationObjectSupport
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
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
Methods inherited from interface org.springframework.integration.support.management.IntegrationManagement
getThisAs
Methods inherited from interface org.springframework.integration.support.context.NamedComponent
getBeanName, getComponentName
-
Constructor Details
-
FileWritingMessageHandler
Constructor which sets thedestinationDirectoryExpression
using aLiteralExpression
.- Parameters:
destinationDirectory
- Must not be null- See Also:
FileWritingMessageHandler(Expression)
-
FileWritingMessageHandler
Constructor which sets thedestinationDirectoryExpression
.- Parameters:
destinationDirectoryExpression
- Must not be null- See Also:
FileWritingMessageHandler(File)
-
-
Method Details
-
setAutoCreateDirectory
public void setAutoCreateDirectory(boolean autoCreateDirectory)Specify whether to create the destination directory automatically if it does not yet exist upon initialization. By default, this value is true. If set to false and the destination directory does not exist, an Exception will be thrown upon initialization.- Parameters:
autoCreateDirectory
- true to create the directory if needed.
-
setTemporaryFileSuffix
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". This can be changed by setting this property.- Parameters:
temporaryFileSuffix
- The temporary file suffix.
-
setFileExistsMode
Will set theFileExistsMode
that specifies what will happen in case the destination exists. For exampleFileExistsMode.APPEND
instructs this handler to append data to the existing file rather then creating a new file for eachMessage
.If set to
FileExistsMode.APPEND
, the adapter will also create a real instance of theLockRegistry
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. ForFile
payloads, the actual timestamp of theFile
is compared; for other payloads, theFileHeaders.SET_MODIFIED
is compared to the existing file. If the header is missing, or its value is not aNumber
, the file is always replaced. This mode will typically only make sense ifpreserveTimestamp
is true.- Parameters:
fileExistsMode
- Must not be null- See Also:
setPreserveTimestamp(boolean)
-
setExpectReply
public void setExpectReply(boolean expectReply)Specify whether a reply Message is expected. If not, this handler will simply return null for a successful response or throw an Exception for a non-successful response. The default is true.- Parameters:
expectReply
- true if a reply is expected.
-
setAppendNewLine
public void setAppendNewLine(boolean appendNewLine)If 'true' will append a new-line after each write. It is 'false' by default.- Parameters:
appendNewLine
- true if a new-line should be written to the file after payload is written- Since:
- 4.0.7
-
getTemporaryFileSuffix
-
setFileNameGenerator
Provide theFileNameGenerator
strategy to use when generating the destination file's name.- Parameters:
fileNameGenerator
- The file name generator.
-
setDeleteSourceFiles
public void setDeleteSourceFiles(boolean deleteSourceFiles)Specify whether to delete source Files after writing to the destination directory. The default is false. When set to true, it will only have an effect if the inbound Message has a File payload or aFileHeaders.ORIGINAL_FILE
header value containing either a File instance or a String representing the original file path.- Parameters:
deleteSourceFiles
- true to delete the source files.
-
setCharset
Set the charset name to use when writing a File from a String-based Message payload.- Parameters:
charset
- The charset.
-
setBufferSize
public void setBufferSize(int bufferSize)Set the buffer size to use while writing to files; default 8192.- Parameters:
bufferSize
- the buffer size.- Since:
- 4.3
-
setFlushInterval
public void setFlushInterval(long flushInterval)Set the frequency to flush buffers whenFileExistsMode.APPEND_NO_FLUSH
is being used. The interval is approximate; the actual interval will be betweenflushInterval
andflushInterval * 1.33
with an average offlushInterval * 1.167
.- Parameters:
flushInterval
- the interval.- Since:
- 4.3
- See Also:
setFlushWhenIdle(boolean)
-
setFlushWhenIdle
public void setFlushWhenIdle(boolean flushWhenIdle)Determine whether theflushInterval
applies only to idle files (default) or whether to flush on that interval after the first write to a previously flushed or new file.- Parameters:
flushWhenIdle
- false to flush on the interval after the first write to a closed file.- Since:
- 4.3.7
- See Also:
setFlushInterval(long)
,setBufferSize(int)
-
setFlushPredicate
Set aFileWritingMessageHandler.MessageFlushPredicate
to use when flushing files whenFileExistsMode.APPEND_NO_FLUSH
is being used. Seetrigger(Message)
.- Parameters:
flushPredicate
- the predicate.- Since:
- 4.3
-
setPreserveTimestamp
public void setPreserveTimestamp(boolean preserveTimestamp)Set to true to preserve the destination file timestamp. If true and the payload is aFile
, the payload'slastModified
time will be transferred to the destination file. For other payloads, theFileHeaders.SET_MODIFIED
header "file_setModified" will be used if present and it's aNumber
.- Parameters:
preserveTimestamp
- the preserveTimestamp to set.- Since:
- 4.3
-
setChmodOctal
String setter for Spring XML convenience.- Parameters:
chmod
- permissions as an octal string e.g "600";- Since:
- 5.0
- See Also:
setChmod(int)
-
setChmod
public void setChmod(int chmod)Set the file permissions after uploading, e.g. 0600 for owner read/write. Only applies to file systems that support posix file permissions.- Parameters:
chmod
- the permissions.- Throws:
IllegalArgumentException
- if the value is higher than 0777.- Since:
- 5.0
-
setNewFileCallback
Set the callback to use when creating new files. This callback will only be called iffileExistsMode
isFileExistsMode.APPEND
orFileExistsMode.APPEND_NO_FLUSH
and new file has to be created. The callback receives the new result file and the message that triggered the handler.- Parameters:
newFileCallback
- aBiConsumer
callback to be invoked when new file is created.- Since:
- 5.1
-
getComponentType
Description copied from class:IntegrationObjectSupport
Subclasses may implement this method to provide component type information.- Specified by:
getComponentType
in interfaceNamedComponent
- Overrides:
getComponentType
in classMessageHandlerSupport
-
getIntegrationPatternType
Description copied from interface:IntegrationPattern
Return a pattern type this component implements.- Specified by:
getIntegrationPatternType
in interfaceIntegrationPattern
- Overrides:
getIntegrationPatternType
in classAbstractReplyProducingMessageHandler
- Returns:
- the
IntegrationPatternType
this component implements.
-
doInit
protected void doInit()- Overrides:
doInit
in classAbstractReplyProducingMessageHandler
-
start
public void start()- Specified by:
start
in interfaceLifecycle
- Specified by:
start
in interfaceManageableLifecycle
-
stop
public void stop()- Specified by:
stop
in interfaceLifecycle
- Specified by:
stop
in interfaceManageableLifecycle
-
isRunning
public boolean isRunning()- Specified by:
isRunning
in interfaceLifecycle
- Specified by:
isRunning
in interfaceManageableLifecycle
-
handleRequestMessage
Description copied from class:AbstractReplyProducingMessageHandler
Subclasses must implement this method to handle the request Message. The return value may be a Message, a MessageBuilder, or any plain Object. The base class will handle the final creation of a reply Message from any of those starting points. If the return value is null, the Message flow will end here.- Specified by:
handleRequestMessage
in classAbstractReplyProducingMessageHandler
- Parameters:
requestMessage
- The request message.- Returns:
- The result of handling the message, or
null
.
-
setPermissions
Set permissions on newly written files.- Parameters:
resultFile
- the file.- Throws:
IOException
- any exception.- Since:
- 5.0
-
createWriter
protected BufferedWriter createWriter(File fileToWriteTo, boolean append) throws FileNotFoundExceptionCreate a buffered writer for the file, for String payloads.- Parameters:
fileToWriteTo
- the file.append
- true if we are appending.- Returns:
- the writer.
- Throws:
FileNotFoundException
- if the file does not exist.- Since:
- 4.3.8
-
createOutputStream
protected BufferedOutputStream createOutputStream(File fileToWriteTo, boolean append) throws FileNotFoundExceptionCreate a buffered output stream for the file.- Parameters:
fileToWriteTo
- the file.append
- true if we are appending.- Returns:
- the stream.
- Throws:
FileNotFoundException
- if not found.- Since:
- 4.3.8
-
trigger
When usingFileExistsMode.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
orPattern
) that matches the absolutePath of any in-process files. However, if a customFileWritingMessageHandler.MessageFlushPredicate
is provided, the payload can be of any type supported by that implementation.- Specified by:
trigger
in interfaceMessageTriggerAction
- Parameters:
message
- the message.- Since:
- 4.3
-
flushIfNeeded
When usingFileExistsMode.APPEND_NO_FLUSH
you can invoke this method to selectively flush and close open files. For each open file the suppliedFileWritingMessageHandler.MessageFlushPredicate.shouldFlush(String, long, long, Message)
method is invoked and if true is returned, the file is flushed.- Parameters:
flushPredicate
- theFileWritingMessageHandler.FlushPredicate
.- Since:
- 4.3
-
flushIfNeeded
public void flushIfNeeded(FileWritingMessageHandler.MessageFlushPredicate flushPredicate, Message<?> filterMessage)When usingFileExistsMode.APPEND_NO_FLUSH
you can invoke this method to selectively flush and close open files. For each open file the suppliedFileWritingMessageHandler.MessageFlushPredicate.shouldFlush(String, long, long, Message)
method is invoked and if true is returned, the file is flushed.- Parameters:
flushPredicate
- theFileWritingMessageHandler.MessageFlushPredicate
.filterMessage
- an optional message passed into the predicate.- Since:
- 4.3
-