dynamicconfiguration-managementapache-commons-config

apache commons configuration2 :ConfigurationEvent is not generated for ReloadingFileBasedConfigurationBuilder


Using commons configuration2, i would like to be notified when a specific file based property changes. For that am using a ReloadingFileBasedConfigurationBuilder, PeriodicReloadingTrigger.

As per the documentation, the builder should be used as a central component and regenerate the configuration by builder.getConfiguration() when the underlying file changes. Am able to get a ConfigurationBuilderEvent.RESET notification when the file changes and using which am able to refresh my configuration with the new configuration.

However, when I try to add event listener for ConfigurationEvent.ANY, so I get notified of the actual property in the file that is changed, I do not get that notified. Any help is appreciated.

Below is my sample program to demonstrate this :

import java.io.File;
import java.util.concurrent.TimeUnit;

import org.apache.commons.configuration2.PropertiesConfiguration;
import org.apache.commons.configuration2.builder.ConfigurationBuilderEvent;
import org.apache.commons.configuration2.builder.EventListenerParameters;
import org.apache.commons.configuration2.builder.ReloadingFileBasedConfigurationBuilder;
import org.apache.commons.configuration2.builder.fluent.Parameters;
import org.apache.commons.configuration2.event.ConfigurationEvent;
import org.apache.commons.configuration2.event.EventListener;
import org.apache.commons.configuration2.reloading.PeriodicReloadingTrigger;

public class ReloadingConfigEventTest {
    public static void main(String[] args) throws Exception {
        Parameters params = new Parameters();
        EventListenerParameters listenerParams = new EventListenerParameters();
        listenerParams.addEventListener(ConfigurationEvent.ANY, new EventListener<ConfigurationEvent>() {
            public void onEvent(ConfigurationEvent event) {
                System.out.println(event.getEventType().getName() +" "+event.getPropertyName());
            }
        }).addEventListener(ConfigurationBuilderEvent.RESET, new EventListener<ConfigurationBuilderEvent>() {
            public void onEvent(ConfigurationBuilderEvent event) {
                System.out.println("Event:" + event.getEventType().getName());
            }
        });

        ReloadingFileBasedConfigurationBuilder<PropertiesConfiguration> builder = new ReloadingFileBasedConfigurationBuilder<PropertiesConfiguration>(
                PropertiesConfiguration.class)
                        .configure(params.fileBased().setFile(new File("src/main/resource/override.conf")), listenerParams);
        PeriodicReloadingTrigger trigger = new PeriodicReloadingTrigger(builder.getReloadingController(), null, 1,
                TimeUnit.SECONDS);
        trigger.start();

        //modify the property file during the infinite loop, the new property is picked, but the SET_PROPERTY notification is missing
        while (true) {
            Thread.sleep(1000);
            System.out.println(builder.getConfiguration().getString("test.property1"));
        }
    }
}

Solution

  • Unfortunately, I do not believe this is possible, at least with the latest commons-configuration2 library source (2.1.1). The ReloadingFileBasedConfigurationBuilder only populates configuration instances which derive from FileBasedConfiguration (for example, PropertiesConfiguration), and FileBasedConfiguration objects are all loaded by the without the use internal methods which would fire events like ADD_PROPERTY, SET_PROPERTY, etc.

    I've been interested in this myself in the past, but commons-configuration2 just isn't set up this way.