Spring Integration
  1. Spring Integration
  2. INT-805

dynamically create directories with file:outbound-channel-adapter

    Details

    • Type: New Feature New Feature
    • Status: Closed
    • Priority: Major Major
    • Resolution: Complete
    • Affects Version/s: 2.2 M2
    • Fix Version/s: 2.2 M3 Sprint 2, 2.2 M3
    • Component/s: Adapters
    • Labels:
      None

      Description

      I am writing an application that handles messages coming in thru a webservice. For auditing all incoming messages have to be saved to disk. Because a potential large amount of messages will be handled, and they should be easily found back later, I would like to be able to save my messages into different directories based on the date.

      Currently I can set a filename per message. In addition to that I would like to be able to set a directory relative to the base-directory specified in the outbound-channel-adapter. If this directory doesn't exist, it should be created.

      To remain backwards compatible I image the filename header can contain a String - use the current behaviour - or a File - use the proposed behaviour.

      In addition, the FilenameGenerator should be enhanced to be able to return a full (relative) path.

        Issue Links

          Activity

          Hide
          Mark Fisher added a comment -

          Gunnar, feel free to assign to Oleg if that makes more sense. Sounds like this one might be resolved already via other issues.

          Show
          Mark Fisher added a comment - Gunnar, feel free to assign to Oleg if that makes more sense. Sounds like this one might be resolved already via other issues.
          Hide
          Mark Fisher added a comment -

          It should be possible to use a filename expression where the base path is static but the dynamic part is appended to it.

          We might want to consider a NEW issue that makes it possible to have the filename expression considered as a relative path (when not starting with a slash, for example), but as long as the above workaround is feasible, we could defer that new feature until 2.2.0.

          Show
          Mark Fisher added a comment - It should be possible to use a filename expression where the base path is static but the dynamic part is appended to it. We might want to consider a NEW issue that makes it possible to have the filename expression considered as a relative path (when not starting with a slash, for example), but as long as the above workaround is feasible, we could defer that new feature until 2.2.0.
          Hide
          Gunnar Hillert added a comment -

          This will fail:

              <int-file:outbound-channel-adapter  auto-create-directory="true" channel="outputChannel" directory="target/out" filename-generator-expression="'/bb/file.txt'" temporary-file-suffix=".writing"/>
          

          Directory 'bb' does not exist and 'auto-create-directory' only applies to the 'directory' attribute which is created at initialization.

          Show
          Gunnar Hillert added a comment - This will fail: < int -file:outbound-channel-adapter auto-create-directory= " true " channel= "outputChannel" directory= "target/out" filename-generator-expression= "'/bb/file.txt'" temporary-file-suffix= ".writing" /> Directory 'bb' does not exist and 'auto-create-directory' only applies to the 'directory' attribute which is created at initialization.
          Hide
          Oleg Zhurakousky added a comment - - edited

          Gunnar

          Could you please attach a test or link to the github that reproduces it. Best is to create a branch for this issue with failing tests and push it so we can look at see what's going on.

          Show
          Oleg Zhurakousky added a comment - - edited Gunnar Could you please attach a test or link to the github that reproduces it. Best is to create a branch for this issue with failing tests and push it so we can look at see what's going on.
          Hide
          James Morgan added a comment -

          I had to do something similar and wrote a FileNameGenerator instance that wraps around another FileNameGenerator (see attached file). I then created a bean instance with the root directory assigned as a constructor-arg and assigned the bean as the filename-generator attribute.

          Show
          James Morgan added a comment - I had to do something similar and wrote a FileNameGenerator instance that wraps around another FileNameGenerator (see attached file). I then created a bean instance with the root directory assigned as a constructor-arg and assigned the bean as the filename-generator attribute.
          Hide
          Gunnar Hillert added a comment - - edited

          Created 2 cases illustrating the issue. One test-case succeeds and one test case fails:

          https://github.com/ghillert/spring-integration/commit/ab425b1cf23c6a506df9e3225158241e037f204c

          <outbound-channel-adapter id="save-to-base-directory"
          		channel="inputChannelSaveToBaseDir"
                  auto-create-directory="true"
                  filename-generator-expression="'foo.txt'"
          		directory="target/base-directory" />
          
          <outbound-channel-adapter id="save-to-sub-directory"
          		channel="inputChannelSaveToSubDir"
                  auto-create-directory="true"
                  filename-generator-expression="'/sub-directory/foo.txt'"
          		directory="target/base-directory" />
          
          Show
          Gunnar Hillert added a comment - - edited Created 2 cases illustrating the issue. One test-case succeeds and one test case fails: https://github.com/ghillert/spring-integration/commit/ab425b1cf23c6a506df9e3225158241e037f204c <outbound-channel-adapter id= "save-to-base-directory" channel= "inputChannelSaveToBaseDir" auto-create-directory= " true " filename-generator-expression= "'foo.txt'" directory= "target/base-directory" /> <outbound-channel-adapter id= "save-to-sub-directory" channel= "inputChannelSaveToSubDir" auto-create-directory= " true " filename-generator-expression= "'/sub-directory/foo.txt'" directory= "target/base-directory" />
          Hide
          Gunnar Hillert added a comment - - edited

          Workaround:

          Depending on your use-case, you can use a custom implementation of the FileNameGenerator interface. The following custom FileNameGenerator is references by the File Outbound Channel Adapter and uses a base directory and retrieves the sub-directory from the Message Header. The outbound-channel-adapter's directory attribute is mandatory and is set to equal the MyFilenameGenerator's baseDirectory property.

          public class MyFilenameGenerator implements FileNameGenerator {
          	
            private String baseDirectory = "";
          	
            public String generateFileName(Message<?> message) {
          
              File directory = (File) message.getHeaders().get("directory");	
              new File(new File(baseDirectory), directory.getPath()).mkdirs();	
              return directory.getPath() + "/" + message.getHeaders().get(FileHeaders.FILENAME);
          	
            }
          	
            public void setBaseDirectory(String baseDirectory) {
              Assert.notNull(baseDirectory);
              this.baseDirectory = baseDirectory;
          
            }	
          }
          
          Show
          Gunnar Hillert added a comment - - edited Workaround: Depending on your use-case, you can use a custom implementation of the FileNameGenerator interface. The following custom FileNameGenerator is references by the File Outbound Channel Adapter and uses a base directory and retrieves the sub-directory from the Message Header. The outbound-channel-adapter's directory attribute is mandatory and is set to equal the MyFilenameGenerator's baseDirectory property. public class MyFilenameGenerator implements FileNameGenerator { private String baseDirectory = ""; public String generateFileName(Message<?> message) { File directory = (File) message.getHeaders().get( "directory" ); new File( new File(baseDirectory), directory.getPath()).mkdirs(); return directory.getPath() + "/" + message.getHeaders().get(FileHeaders.FILENAME); } public void setBaseDirectory( String baseDirectory) { Assert.notNull(baseDirectory); this .baseDirectory = baseDirectory; } }
          Hide
          Gunnar Hillert added a comment -

          Issued Pull Request:

          https://github.com/SpringSource/spring-integration/pull/494

          Added directory-expression attribute for File Outbound Channel Adapter and File Outbound Gateway

          Show
          Gunnar Hillert added a comment - Issued Pull Request: https://github.com/SpringSource/spring-integration/pull/494 Added directory-expression attribute for File Outbound Channel Adapter and File Outbound Gateway

            People

            • Assignee:
              Gunnar Hillert
              Reporter:
              Daniel Bos
            • Votes:
              7 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Time Tracking

                Estimated:
                Original Estimate - 1d
                1d
                Remaining:
                Time Spent - 0.75d Remaining Estimate - 0.25d
                0.25d
                Logged:
                Time Spent - 0.75d Remaining Estimate - 0.25d
                0.75d