Class FileWritingMessageHandler

All Implemented Interfaces:
org.reactivestreams.Subscriber<Message<?>>, Aware, BeanClassLoaderAware, BeanFactoryAware, BeanNameAware, DisposableBean, InitializingBean, ApplicationContextAware, Lifecycle, Ordered, ComponentSourceAware, ExpressionCapable, Orderable, MessageProducer, HeaderPropagationAware, MessageTriggerAction, IntegrationPattern, NamedComponent, IntegrationManagement, ManageableLifecycle, TrackableComponent, MessageHandler, reactor.core.CoreSubscriber<Message<?>>

public class FileWritingMessageHandler extends AbstractReplyProducingMessageHandler implements ManageableLifecycle, MessageTriggerAction
A 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, Trung Pham, Christian Tzolov, Ngoc Nhan
  • Constructor Details

    • FileWritingMessageHandler

      public FileWritingMessageHandler(File destinationDirectory)
      Constructor which sets the destinationDirectoryExpression using a LiteralExpression.
      Parameters:
      destinationDirectory - Must not be null
      See Also:
    • FileWritingMessageHandler

      public FileWritingMessageHandler(Expression destinationDirectoryExpression)
      Constructor which sets the destinationDirectoryExpression.
      Parameters:
      destinationDirectoryExpression - Must not be null
      See Also:
  • 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

      public 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". This can be changed by setting this property.
      Parameters:
      temporaryFileSuffix - The temporary file suffix.
    • setFileExistsMode

      public void setFileExistsMode(FileExistsMode fileExistsMode)
      Will set the 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.

      Parameters:
      fileExistsMode - Must not be null
      See Also:
    • 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

      protected String getTemporaryFileSuffix()
    • setFileNameGenerator

      public void setFileNameGenerator(FileNameGenerator fileNameGenerator)
      Provide the FileNameGenerator 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 a FileHeaders.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

      public void setCharset(String charset)
      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 when 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.
      Parameters:
      flushInterval - the interval.
      Since:
      4.3
      See Also:
    • setFlushWhenIdle

      public 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.
      Parameters:
      flushWhenIdle - false to flush on the interval after the first write to a closed file.
      Since:
      4.3.7
      See Also:
    • setFlushPredicate

      public void setFlushPredicate(FileWritingMessageHandler.MessageFlushPredicate flushPredicate)
      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 a File, the payload's lastModified time will be transferred to the destination file. For other payloads, the FileHeaders.SET_MODIFIED header "file_setModified" will be used if present, and it's a Number.
      Parameters:
      preserveTimestamp - the preserveTimestamp to set.
      Since:
      4.3
    • setChmodOctal

      public void setChmodOctal(String chmod)
      String setter for Spring XML convenience.
      Parameters:
      chmod - permissions as an octal string e.g "600";
      Since:
      5.0
      See Also:
    • 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

      public void setNewFileCallback(BiConsumer<File,Message<?>> newFileCallback)
      Set the callback to use when creating new files. This callback will only be called if 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.
      Parameters:
      newFileCallback - a BiConsumer callback to be invoked when new file is created.
      Since:
      5.1
    • getComponentType

      public String getComponentType()
      Description copied from class: IntegrationObjectSupport
      Subclasses may implement this method to provide component type information.
      Specified by:
      getComponentType in interface NamedComponent
      Overrides:
      getComponentType in class MessageHandlerSupport
    • getIntegrationPatternType

      public IntegrationPatternType getIntegrationPatternType()
      Description copied from interface: IntegrationPattern
      Return a pattern type this component implements.
      Specified by:
      getIntegrationPatternType in interface IntegrationPattern
      Overrides:
      getIntegrationPatternType in class AbstractReplyProducingMessageHandler
      Returns:
      the IntegrationPatternType this component implements.
    • doInit

      protected void doInit()
      Overrides:
      doInit in class AbstractReplyProducingMessageHandler
    • start

      public void start()
      Specified by:
      start in interface Lifecycle
      Specified by:
      start in interface ManageableLifecycle
    • stop

      public void stop()
      Specified by:
      stop in interface Lifecycle
      Specified by:
      stop in interface ManageableLifecycle
    • isRunning

      public boolean isRunning()
      Specified by:
      isRunning in interface Lifecycle
      Specified by:
      isRunning in interface ManageableLifecycle
    • handleRequestMessage

      protected Object handleRequestMessage(Message<?> requestMessage)
      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 class AbstractReplyProducingMessageHandler
      Parameters:
      requestMessage - The request message.
      Returns:
      The result of handling the message, or null.
    • setPermissions

      protected void setPermissions(File resultFile) throws IOException
      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 FileNotFoundException
      Create 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 FileNotFoundException
      Create 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

      public 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. 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.
      Specified by:
      trigger in interface MessageTriggerAction
      Parameters:
      message - the message.
      Since:
      4.3
    • flushIfNeeded

      public void flushIfNeeded(FileWritingMessageHandler.FlushPredicate flushPredicate)
      When using 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.
      Parameters:
      flushPredicate - the FileWritingMessageHandler.FlushPredicate.
      Since:
      4.3
    • flushIfNeeded

      public 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. 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.
      Parameters:
      flushPredicate - the FileWritingMessageHandler.MessageFlushPredicate.
      filterMessage - an optional message passed into the predicate.
      Since:
      4.3