0

What I want: I'd like to move content from one ContentStore (regular) to another ContentStore (e.g. an archive) with Spring-Content version 1.2.7.

What I did is this (and it does work at least with DefaultFilesystemStoreImpls):

  1. Creating two ContentStores like this:
@Bean(name = "mytmpfsstore1")
public ContentStore<File, String> getFileContentStore1() {
    FileSystemResourceLoader loader = new FileSystemResourceLoader(".\\tmpstore1");
    PlacementService placementService = new PlacementServiceImpl();
    return new DefaultFilesystemStoreImpl<File, String>(loader, placementService, new FileServiceImpl());
}
  1. Moving content from one ContentStore to another like this:
Optional<File> fileEntity = filesRepo.findById(id);
if (fileEntity.isPresent()) {
    Resource resource = regularContentStore.getResource(fileEntity.get());
    archiveContentStore.setContent(fileEntity.get(), resource);
    filesRepo.save(fileEntity.get());
    if (resource instanceof DeletableResource) {
        ((DeletableResource) resource).delete();
    }
}

Question: Is this the intended way of moving (/archiving) content with Spring-Content or is there a more elegant / more convenient / more intended way of moving/archiving files (especially from filesystem to S3 and back again)?

S. Doe
  • 685
  • 1
  • 6
  • 25

1 Answers1

1

Spring Content doesn't provide any magic here. I try to keep the API fairly low-level and this use case, whilst valid, is a little too granular. So, ultimately you have to build the "archiving" yourself and at the end of the day copy the content from one store to another as you are doing.

A couple of comments/pointers:

  1. Not sure why you instantiated mytmpfsstore1 yourself. If you have file storage and s3 storage you can just make your storage interfaces extend FileSystemContentStore and S3ContentStore respectively and let the framework instantiate them for you; i.e.

    public interface MyTmpFsStore extends FileSystemContentStore {}

    public interface MyS3store extends S3ContentStore()

    You can then wire these two beans into your 'archive' code. Assuming that is a controller, something like:

    @RequestMapping(...) public void archive(MyTmpFsStore fsStore, S3ContentStore s3Store { ... }

    where you do your copy operation.

  2. ContentStore extends AssociativeStore and there are a few different APIs for setting/unsetting content. Resource-based or InputStream. They all achieve the same objective at the end of the day. You could just have easily used getContent instead of getResource and unsetContent instead of delete.

  3. The 'archive' code probably needs to be in a @Transactional so the archive operation is atomic.

Paul Warren
  • 2,411
  • 1
  • 15
  • 22
  • Thanks for your answer and comments. (1) For evaluation I had no S3ContentStore, so I instantiated some FilesystemStores and configured them for different directories. (2) `delete` just deletes the file from one of the first store, leaves the file in the second store and leaves the `contentId` at my entity as it is. `unsetContent` sets the value of `contentId` at my entity to `null`, so I would lose the reference to the content altogether. This is why I used `delete`. (3) Yes. – S. Doe Feb 09 '22 at 17:46