Module - Datasource Api (Datasource Api)

Defines an abstraction layer for any data related operations (including metadata and files) to ensure we can be flexible in the backend configuration.

About

This modules defines the complete repository abstraction layer and implementation selection logic that is used to bind front-end API + implementation to backend repositories.

The term "repository" is used for all sorts of data handling including file storage, DB persistence and sending or receiving of messages inside a service bus.
All defined interfaces derive from the single group interface Repository, allowing to use compile time validation, better IDE support and simplified discovery of offered repositories.

Attaching and Selecting an Implementation

This module depends entirely on the Spring Framework in order to attach implementations to it.
All implementations of offered interfaces must be Spring Beans defined in the same application context as this module is running in.

RepositorySelectors are used to select an implementation of an particular interface the selector is operating on.

The settings inside the selector are exposed to JMX (read/write) and are persisted to disk as part of the repository-selection.[mode].xml file (read/write). The key values inside this selection file are simply the names of the spring beans implementing the interface. See example below:

<?xml version="1.0"?>
<repository-selection>
    <selector repositoryClass="com.trendmicro.grid.acl.ds.PackageProvider">
        <selectedKey>cachingPackageProvider</selectedKey>
        <available>cachingPackageProvider</available>
        <available>dummyPackageProvider</available>
        <available>jpaPackageRepository</available>
    </selector>
    ...
</repository-selection>

Note: When no selection was ever made the repository selectors are initially set using the value of the config property: autoselectImplementationsByNames

Usage Examples

Use the currently selected implementation

/**
* Creates a Spring Bean that is SelectorAware.
*/
@Component
public class MyFileQueryComponent implements SelectorAware {

    RepositorySelector<FileProvider> fileProviderSelector;

    public void refreshSelectors(RepositorySelectorsRepository selectors) {
        fileProviderSelector = selectors.getSelector(FileProvider.class);
    }

    public void doSomething() {
        FileProvider fp = fileProviderSelector.getRepository();
        // do something with FileProvider.
    }
}

Note: A Spring bean exists that implements RepositorySelectorsRepository, however circular dependencies may easily be defined when using a direct dependency to the selector implementation. It is highly recommended to use the SelectorAware interface instead to obtain the repository of selectors.

Implement a repository interface

Implementing a repository interface is as simple as creating an ordinary Spring Bean. Please be aware of the fact that only classes under the namespace 'com.trendmicro' are detected by Spring. (Classpath scanning is set to this prefix)

/**
* Creates a new implementation of FileProvider that can be selected via
* "myOwnFileProvider".
*/
@Repository("myOwnFileProvider")
public class MyOwnFileProvider implements FileProvider {
    ...TODO: Implement all methods
}

Notes: Implementations should in general not be done within this module. An exception to this rule are the security related wrapper classes which cannot be considered ordinary implementations as they are not done as Spring Beans and are therefore not selectable as implementation.

Use the 1st code example, in order to delegate work to other repository implementations. In some cases it may be also appropriate to define hard dependencies using spring, however this may be problematic with user selected implementations.