Commons Configuration2 ReloadingFileBasedConfiguration

余生颓废 提交于 2021-02-18 12:34:08

问题


I am trying to implement the Apache Configuration 2 in my codebase

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.ReloadingFileBasedConfigurationBuilder;
import org.apache.commons.configuration2.builder.fluent.Parameters;
import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
import org.apache.commons.configuration2.event.EventListener;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.configuration2.reloading.PeriodicReloadingTrigger;

import org.apache.commons.configuration2.CompositeConfiguration;

public class Test {

    private static final long DELAY_MILLIS = 10 * 60 * 5;


    public static void main(String[] args) {
        // TODO Auto-generated method stub
        CompositeConfiguration compositeConfiguration = new CompositeConfiguration();
        PropertiesConfiguration props = null;
        try {
            props = initPropertiesConfiguration(new File("/tmp/DEV.properties"));
        } catch (ConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        compositeConfiguration.addConfiguration( props );
        compositeConfiguration.addEventListener(ConfigurationBuilderEvent.ANY,
                new EventListener<ConfigurationBuilderEvent>()
                {
                    @Override
                    public void onEvent(ConfigurationBuilderEvent event)
                    {
                        System.out.println("Event:" + event);

                    }
                });

        System.out.println(compositeConfiguration.getString("property1"));

        try {
            Thread.sleep(14*1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // Have a script which changes the value of property1 in DEV.properties
        System.out.println(compositeConfiguration.getString("property1"));
    }

    protected static PropertiesConfiguration initPropertiesConfiguration(File propsFile) throws ConfigurationException { 

        if(propsFile.exists()) {

            final ReloadingFileBasedConfigurationBuilder<PropertiesConfiguration> builder =
                    new ReloadingFileBasedConfigurationBuilder<PropertiesConfiguration>(PropertiesConfiguration.class)
                    .configure(new Parameters().fileBased()
                        .setFile(propsFile)
                        .setReloadingRefreshDelay(DELAY_MILLIS)
                        .setThrowExceptionOnMissing(false)
                        .setListDelimiterHandler(new DefaultListDelimiterHandler(';')));
            final PropertiesConfiguration propsConfiguration = builder.getConfiguration();
            PeriodicReloadingTrigger trigger = new PeriodicReloadingTrigger(builder.getReloadingController(),
                    null, 1, TimeUnit.SECONDS);
                trigger.start();

            return propsConfiguration;
        } else {
            return new PropertiesConfiguration();
        }

    }
}

Here is a sample code that I using to check whether the Automatic Reloading works or not. However when the underlying property file is updated, the configuration doesn't reflect it.


回答1:


As per the documentation :

One important point to keep in mind when using this approach to reloading is that reloads are only functional if the builder is used as central component for accessing configuration data. The configuration instance obtained from the builder will not change automagically! So if an application fetches a configuration object from the builder at startup and then uses it throughout its life time, changes on the external configuration file become never visible. The correct approach is to keep a reference to the builder centrally and obtain the configuration from there every time configuration data is needed.

https://commons.apache.org/proper/commons-configuration/userguide/howto_reloading.html#Reloading_File-based_Configurations

This is different from what the old implementation was.

I was able to successfully execute your sample code by making 2 changes :

  1. make the builder available globally and access the configuration from the builder :

    System.out.println(builder.getConfiguration().getString("property1"));

  2. add the listener to the builder : `builder.addEventListener(ConfigurationBuilderEvent.ANY, new EventListener() {

        public void onEvent(ConfigurationBuilderEvent event) {
            System.out.println("Event:" + event);
        }
    });
    

Posting my sample program, where I was able to successfully demonstrate it

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.ReloadingFileBasedConfigurationBuilder;
import org.apache.commons.configuration2.builder.fluent.Parameters;
import org.apache.commons.configuration2.event.EventListener;
import org.apache.commons.configuration2.reloading.PeriodicReloadingTrigger;

public class TestDynamicProps {
    public static void main(String[] args) throws Exception {

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

        builder.addEventListener(ConfigurationBuilderEvent.ANY, new EventListener<ConfigurationBuilderEvent>() {

            public void onEvent(ConfigurationBuilderEvent event) {
                System.out.println("Event:" + event);
            }
        });

        while (true) {
            Thread.sleep(1000);
            System.out.println(builder.getConfiguration().getString("property1"));
        }

    }
}



回答2:


The problem with your implementation is, that the reloading is done on the ReloadingFileBasedConfigurationBuilder Object and is not being returned to the PropertiesConfiguration Object.



来源:https://stackoverflow.com/questions/36730860/commons-configuration2-reloadingfilebasedconfiguration

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!