Microprofile Config: Creating a Custom ConfigSource

In this post I’ll show you how can I create a custom ConfigSource to read properties from an external file. In this post I will not explain about what is Eclipse Microprofile Config, and if you want to know what is, access my last post Understanding Eclipse Microprofile Config .

The Eclipse Microprofile Config provide support to read configuration properties by a ConfigSource class. With this, if you need create a custom support to any configuration source (such as database, file system, service), you need create a custom ConfigSource class to provide this support.

In this example I create a ConfigSource to read configuration properties from an external file(outside of package), and the package will have only one property inside, that is the property to get the path of the file configuration. Bellow we have FileSystemConfigSource class that implementing ConfigSource.

public class FileSystemConfigSource implements ConfigSource {

    private final String FILE_CONFIG_PROPERTY = "net.rhuanrocha.mp-speaker.config.file.path";
    private final String CONFIG_SOURCE_NAME = "FileSystemConfigSource";
    private final int ORDINAL = 300;

    private String fileConfig;

    @Override
    public Map getProperties() {

        try(InputStream in = new FileInputStream( readPath() )){

            Properties properties = new Properties();
            properties.load( in );

            Map map = new HashMap();
            properties.stringPropertyNames()
                    .stream()
                    .forEach(key-> map.put(key, properties.getProperty(key)));

            return map;

        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    public Set getPropertyNames() {

        try(InputStream in = new FileInputStream( readPath() )){

            Properties properties = new Properties();
            properties.load( in );

            return properties.stringPropertyNames();

        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    public int getOrdinal() {
        return ORDINAL;
    }

    @Override
    public String getValue(String s) {

        try(InputStream in = new FileInputStream( readPath() )){

            Properties properties = new Properties();
            properties.load( in );

            return properties.getProperty(s);

        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    public String getName() {
        return CONFIG_SOURCE_NAME;
    }

    public String readPath(){

        if(Objects.nonNull(fileConfig)){
            return fileConfig;
        }

        final Config cfg = ConfigProvider.getConfig();
        return fileConfig = cfg.getValue(FILE_CONFIG_PROPERTY, String.class);
    }

}

Furthermore, we need create a property in META-INF/microprofile-config.properties with the path of the external file, and put the config_ordinal property inside META-INF/microprofile-config.properties major then the ordinal of the FileSystemConfigSource, because the FileSystemConfigSource read the property from META-INF/microprofile-config.properties. Below we have the example.

config_ordinal = 400
net.rhuanrocha.mp-speaker.config.file.path=/etc/mp-speaker/config/configuration.properties

Note: My suggest is insert in META-INF/microprofile-config.properties only the property to path of external file and the config_ordinal property.

If you want to see more about this example, access the repository on github by: https://github.com/rhuan080/microprofile-example

 

6 comments

  1. Hi Phillip Kruger,
    It’s an amazing project. I note that the configurations are sustained in memory. In my example, I the properties are read from file everytime.
    You can submit some solutions of this project to Microprofile community.

    Like

    1. Yes, it’s kept in memory, however the file is monitored for changes, and then it reloads.

      Maybe adding a config flag to drive that behaviour, example readFromSource=always can make it behave as your example.

      Keep well.

      Like

      1. Yes, because, we can use this properties in an application that is in cluster… With this, we can update some properties in a source and the update of nodes of cluster will be done asynchronously (some node can be updated before). When we read from source everytime, when the source is updated, the new value will be available to all node in the same time.

        Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s