`
sunxboy
  • 浏览: 2883650 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

Auto reload of configuration when any change happen

 
阅读更多

In this post, i am writing about a solution of very common problem. Every application has some configuration which is expected to be refreshed on every change in configuration file. Past approaches to solve this problem had consisted of having a Thread, which periodically poll for file change based on ‘last update time stamp’ of configuration file.

Now with java 7, things have changed. Java 7 has introduced an excellent feature: WatchService. I will try to give you a potential solution for above problem. This may not be the best implementation, but it will surely give a very good start for your solution. I bet !!

Sections in this post

1) A brief overview of WatchService
2) Writing our configuration provider
3) Introducing configuration change listener
4) Testing our code
5) Key notes

A brief overview of WatchService

A WatchService is JDKs internal service which watches for changes on registered objects. These registered objects are necessarily the instances of Watchable interface. When registering the watchable instance with WatchService, we need to specify the kind of change events we are interested in.

There are four type of events a of now: ENTRY_CREATEENTRY_DELETEENTRY_MODIFY and OVERFLOW. You can read about these events in provided links.

WatchService interface extends Closeable interface, means service can be closed as and when required. Normally, it should be done using JVM provided shut down hooks.

Writing our Configuration provider

A configuration provider is simply a wrapper for holding the set of properties in java,util.Properties instance. It also provides methods to get the configured properties using their KEY.

A sample implementation goes as below :

package testWatchService;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class ApplicationConfiguration {
	private final static ApplicationConfiguration INSTANCE = new ApplicationConfiguration();

	public static ApplicationConfiguration getInstance() {
		return INSTANCE;
	}

	private static Properties configuration = new Properties();

	private static Properties getConfiguration() {
		return configuration;
	}

	public void initilize(final String file) {
		InputStream in = null;
		try {
			in = new FileInputStream(new File(file));
			configuration.load(in);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public String getConfiguration(final String key) {
		return (String) getConfiguration().get(key);
	}

	public String getConfigurationWithDefaultValue(final String key,
			final String defaultValue) {
		return (String) getConfiguration().getProperty(key, defaultValue);
	}
}

Introducing configuration change listener

Now when we have our basic wrapper for our in memory cache of configuration properties, we need a mechanism to reload this cache on run time, whenever configuration file stored in file system changes.

I have written a sample working code for your help:

package testWatchService;

import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;

import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;

public class ConfigurationChangeListner implements Runnable {
	private String configFileName = null;
	private String fullFilePath = null;

	public ConfigurationChangeListner(final String filePath) {
		this.fullFilePath = filePath;
	}

	public void run() {
		try {
			register(this.fullFilePath);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void register(final String file) throws IOException {
		final int lastIndex = file.lastIndexOf("/");
		String dirPath = file.substring(0, lastIndex + 1);
		String fileName = file.substring(lastIndex + 1, file.length());
		this.configFileName = fileName;

		configurationChanged(file);
		startWatcher(dirPath, fileName);
	}

	private void startWatcher(String dirPath, String file) throws IOException {
		final WatchService watchService = FileSystems.getDefault()
				.newWatchService();
		Path path = Paths.get(dirPath);
		path.register(watchService, ENTRY_MODIFY);

		Runtime.getRuntime().addShutdownHook(new Thread() {
			public void run() {
				try {
					watchService.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		});

		WatchKey key = null;
		while (true) {
			try {
				key = watchService.take();
				for (WatchEvent< ?> event : key.pollEvents()) {
					if (event.context().toString().equals(configFileName)) {
						configurationChanged(dirPath + file);
					}
				}
				boolean reset = key.reset();
				if (!reset) {
					System.out.println("Could not reset the watch key.");
					break;
				}
			} catch (Exception e) {
				System.out.println("InterruptedException: " + e.getMessage());
			}
		}
	}

	public void configurationChanged(final String file) {
		System.out.println("Refreshing the configuration.");
		ApplicationConfiguration.getInstance().initilize(file);
	}
}

Above class is created using a thread which will be listening to configuration properties file changes using WatchService.
Once, it detects any modification in file, it simply refresh the in memory cache of configuration.

The constructor of above listener takes only one parameter i.e. fully qualified path of monitored configuration file. Listener class is notified immediately when configuration file is changed in file system.

This listener class  then call ApplicationConfiguration.getInstance().initilize(file); to reload in memory cache.

Testing our code

Now, when we are ready with our classes, we will test them.

First of all, store a test.properties file with following content in c:/Lokesh/temp folder.

TEST_KEY=TEST_VALUE

Now, test above classes using below code.

package testWatchService;

public class ConfigChangeTest {
	private static final String FILE_PATH = "C:/Lokesh/temp/test.properties";

	public static void main(String[] args) {
		ConfigurationChangeListner listner = new ConfigurationChangeListner(
				FILE_PATH);
		try {
			new Thread(listner).start();
			while (true) {
				Thread.sleep(2000l);
				System.out.println(ApplicationConfiguration.getInstance()
						.getConfiguration("TEST_KEY"));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

Output of above program (Change the TEST_VALUE to TEST_VALUE1 and TEST_VALUE2 using any file editor and save) ::

Refreshing the configuration.

TEST_VALUE

TEST_VALUE

TEST_VALUE

Refreshing the configuration.

TEST_VALUE1

Refreshing the configuration.

TEST_VALUE2

Above outputs show that every time we make any change to property file, properties loaded are refreshed and new property value is available to use. Good work done so far !!

Key notes

1) If you are using java 7 in your new project, and you are not using old fashioned methods to reload your properties, you are not doing it rightly.

2) WatchService provides two methods take() and poll(). While take() method wait for next change to happen and until it is blocked, poll() immediately check for change event.

If nothing changed from last poll() call, it will return null. poll() method does not block the execution, so should be called in a Thread with some sleep time.

Happy Learning !!

分享到:
评论

相关推荐

    解决any change made in its configuration may be lost after reimport

    标题"解决any change made in its configuration may be lost after reimport"正是针对这一问题的解决方案。 问题的核心在于,Idea的Module Settings配置并没有被正确地同步到Maven的构建配置中。当我们在Idea中...

    Smart Auto Reload-crx插件

    语言:Bahasa Indonesia,Bahasa Melayu,Deutsch,English,English (UK),English (United States),Filipino,Français,Kiswahili,Nederlands,Norsk,Tiếng Việt,Türkçe,català,dansk,eesti,español,hrvatski,...

    Auto_Reload_Blender_addon:方便的自动重新加载图像纹理

    自动重新加载图像-Blender(2.80)插件方便的自动重新加载图像纹理只需一点方便的插件,即可在信息标题属性面板: 刷新混合文件的所有图像使用计时器来获取修改后的图像文件,并在需要时重新加载它们这两个操作都会...

    cssautoreload.zip

    css auto reload 一款 chrome 开发者插件。它可以在你编辑 css 的时候,自动在页面上重新载入最新的 css 文件, 以达到立即展现你刚刚做的改变的目的。特别适合在双屏环境下进行 web 前端开发,使你不必在编辑器和...

    自动重新加载IDT「Auto Reload IDT」-crx插件

    在选定的时间间隔或特定时间自动刷新页面。 在选定的秒数间隔或特定时间自动刷新页面。 支持语言:English

    Auto Reload IDT-crx插件

    **Auto Reload IDT-crx插件详解** Auto Reload IDT是一款专为网页自动刷新而设计的浏览器扩展程序,尤其适用于开发者、测试人员以及需要实时监控网页更新的用户。这款插件支持英语,使得全球用户都能方便地使用。...

    auto-reload-page:按指定的时间间隔自动重新加载页面

    npm install auto-reload-page 用法 import autoReloadPage from "auto-reload-page" ; // Open url in a separate window and reload every 10 seconds autoReloadPage ( "https://www.ipcc.ch/" , 10000 ) ; 原料...

    Auto Reload Aipo Webmail-crx插件

    【Auto Reload Aipo Webmail-crx插件】是一款专为Aipo 8用户设计的浏览器扩展,主要用于在浏览Aipo 8页面时自动刷新Webmail界面。这款插件支持两种语言:英语和日语,因此无论是国际用户还是日本本土用户都能方便地...

    LiveReload谷歌浏览器插件

    LiveReload是一款强大的开发工具,主要用于前端开发者,尤其是网页设计师和前端程序员。这款工具的核心功能是在文件更新时自动刷新浏览器,从而极大地提高了开发效率。在标题中提到的"LiveReload谷歌浏览器插件",指...

    LiveReload.rar

    在现代前端开发中,实时预览(LiveReload)是一个非常重要的功能,它允许开发者在代码保存后立即看到页面更新,极大地提高了工作效率。本资源“LiveReload.rar”是针对使用Visual Studio Code(简称VS Code)进行...

    css auto reload-crx插件

    English detail description: http://allenm.github.io/css-auto-reload/#en-versioncss auto reload 是一个web开发者工具,一款 chrome 插件。它可以在你改变了 css 的时候,自动在页面上重新载入这些 css 文件, ...

    LiveReload

    LiveReload是一款强大的自动化工具,主要用于前端开发,它能够在你编辑代码时自动刷新浏览器,让你能够实时看到代码修改的效果。在Sublime Text 3这个流行的文本编辑器中,LiveReload作为一个插件存在,极大地提升了...

    Chrome LiveReload

    Chrome LiveReload是一款强大的开发者工具,它极大地提高了前端开发的工作效率。这款工具的主要功能是在你对网页源代码进行修改后,能够自动实时地刷新浏览器页面,让你立即看到更改的效果,而无需手动点击刷新按钮...

    Autoreloader: Reload tab on file change (Win)-crx插件

    第2步:安装Chrome扩展名 - 在Chrome Store上搜索“autoreloader”并安装扩展名 第3步:使用“添加目录”按钮添加要监视的文件夹。 而已! 现在,随时添加新文件,更改或删除在您监视的文件夹中,您的活动选项卡将...

    unity 热重载插件Hot Reload1.12.9

    "Unity 热重载插件 Hot Reload 1.12.9"就是针对这一需求设计的专业工具,它允许开发者在不重新编译的情况下编辑并测试代码,极大地提高了开发效率。 热重载(Hot Reload)技术是Unity中的一个高级特性,它打破了...

    chorme liveReload插件

    Chrome LiveReload插件是开发过程中一个非常实用的工具,它主要针对前端开发者,极大地提高了工作效率。LiveReload的主要功能是在浏览器中实现自动刷新,当开发者在编辑器中修改了HTML、CSS或JavaScript等文件后,...

    SysTick定时器延时函数

    SysTick 定时器还包含了一个可配置的重载值寄存器(RELOAD),以及一个当前值寄存器(CURRENT_VAL),这两个寄存器共同决定了定时器的工作模式和延时时间。 在GD32中,配置SysTick定时器通常包括以下几个步骤: 1...

    livereload210chrome.zip

    **LiveReload**是一种强大的自动化工具,它极大地提高了前端开发者的工作效率。在开发过程中,每当HTML、CSS或JavaScript等文件发生变化时,LiveReload可以自动刷新浏览器,无需手动点击刷新按钮,从而实现了即时...

    liveReload下载chrome自动刷新插件

    【标题】"liveReload下载chrome自动刷新插件"所涉及的知识点主要集中在前端开发的自动化工具上,特别是关于实时预览和自动刷新的技术。LiveReload是一个强大的自动化工具,旨在提高前端开发者的工作效率,它能够在你...

Global site tag (gtag.js) - Google Analytics