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
Nice post.
Also see the file based config sources in MicroProfile Extensions (https://www.microprofile-ext.org/) here:
https://github.com/microprofile-extensions/config-ext/blob/master/README.md
You can read from File or URL and the file is monitored for changes, that will fire CDI Events id the config changes.
Let me know what you think.
More details: https://www.phillip-kruger.com/post/microprofile_config/
Cheers
LikeLike
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.
LikeLike
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.
LikeLike
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.
LikeLike