Start modelling your app today.

Get started for free

What's this?

SpringBot Creating a new File Storage Provider

Creating a custom File Storage Provider for SpringBot.


Introduction

This lesson assumes you have already placed a File Attribute on your model and now wish to customise how and where the files which are uploaded are stored.

For details on how to use the File Attribute and the default SpringBot File Upload functionality, please see SpringBot File Upload.

Model

Image

For this lesson we will be using the Fishnatics model with a file attribute called Attachmentsadded to the Fish entity.

Key Elements

The following sections detail some of the key elements which are required to for the a file storage provider to operate.

classDiagram
    class AbstractFileService~E extends FileEntity~{
      +uploadMultiple(files: Collection<FileEntity>) Collection<FileEntity>
      +download(id: UUID) FileEntity
      +delete(name: String) void
      +generateUrl(name: String) String
    }
    class FileEntity {
    }
    class FishService {
    }
    class CustomFileService~FileEntity~ {
    }

    AbstractFileService<|--CustomFileService
    AbstractFileService..FileEntity
    CustomFileService..FileEntity
    FishService..>AbstractFileService
    FishService..>CustomFileService

File Entity

Found at serverside/src/main/java/com/springbot/<projectName>/lib/file/models/FileEntity.java. This represents the data can be stored or transferred regarding any files.

It consists of a collection of persisted attributes and transient attributes, with the transient attributes being utilised for transport purposes only.

This entity and the associated database primary purpose is to store the references between any files and the associated entity which uses them.

AbstractFileService

This is the primary element for implementing a new file service, it encapsulates and enables for new file services to be implemented consistently and with minimal code changes.

CustomFileService

A great example of what a CustomFileService may look like is the S3FileService found at serverside/src/main/java/com/springbot/<projectName>/lib/file/services/S3FileService.java.

The responsibility of the file service is to provide the implementation of the AbstractFileService for use within our entity services.

It will expose methods such as,

  • download,
  • upload,
  • generateUrl

EntityService

This is a service which provides CRUD actions for a given entity, it becomes relevant when a File Attribute is added to the entity in question.

Any operations this service requires to be performed on the file attribute/s will make use of our custom file service.

Task

A custom file storage provider is implemented within SpringBot as a CustomFileService.

To add one complete the following steps:

  1. Create a new custom FileService that implements the AbstractFileService within the serverside/src/main/java/com/springbot/<projectName>/lib/file/services/ directory of the server-side of your application.
  2. Disable the S3FileService. At the top of the S3FileService file found at serverside/src/main/java/com/springbot/<projectName>/lib/file/services/S3FileService.java you will see a ConditionalOnProperty annotation.
@ConditionalOnProperty(
        value="file.storage-provider",
        havingValue="s3",
        matchIfMissing = true
)

This annotation allows for you to disable the initialisation of the S3FileService bean by changing a property.

You will find a property called file.storage-provider in serverside/src/main/resources/application-default.properties.

# File Service
# Available options include S3, you may add additionl options as required
file.storage-provider=s3

After setting a similar annotation to your new custom FileService you will be able to switch the property value to the value of the havingValue annotation property on your new custom FileService.

For example, if you had implemented an Azure Blob storage compatible custom FileService you may do the following:

file.storage-provider=azure

Where your annotation on your custom FileService was the following:

@ConditionalOnProperty(
        value="file.storage-provider",
        havingValue="azure",
        matchIfMissing = false
)
public class AzureFileService extends AbstractFileService<FileEntity> {
  1. Update the entity services to now make use of our new file service. In this we will be customising our FishService found at serverside/src/main/java/com/springbot/<projectName>/services/FishService.java. Open the file and activate the protected region called Override your file service import here.
  2. Update this import to now reference your new CustomFileService. It should now appear similar to the following:
// % protected region % [Override your file service import here] on begin
import  com.springbot.basic.lib.file.services.CustomFileService;
// % protected region % [Override your file service import here] end
  1. Now to place our file service into the constructor of this service. Find the protected region Add any additional constructor parameters here. Activate it and replace the contents with our new CustomFileService. It should appear as follows:
@Autowired
    public FishService(
        // % protected region % [Add any additional constructor parameters here] on begin
        CustomFileService customFileService,
        // % protected region % [Add any additional constructor parameters here] end
        SpeciesRepository speciesRepository,
        TankRepository tankRepository,
        Validator validator,
        AuditingRepository auditingRepository,
        FishRepository repository
    ) {
  1. The final step it to initialise this new constructor parameter. Find the protected region called . It should appear as follows:
// % protected region % [Add any additional constructor logic here] on begin
this.fileService = customFileService;
// % protected region % [Add any additional constructor logic here] end

You will need to perform these adjustments for the service of each entity that utilises the file service but otherwise we have finalised our integration of the a new custom file service provider.


Start modelling your app today.