Wednesday 8 August 2012

Reloadable Application Properties with Spring 3.1, Java 7 and Google Guava

The Problem

 One common problem I have experienced when developing applications especially web applications is having the ability to specify application configuration properties at start-up or runtime. This problem isn't an old problem and has defiantly be solved over and over again by many frameworks and libraries out there. Spring provides the ability to specify properties files for use inside your spring application and nicely provides spring expression for looking up properties values and setting them on class files etc.

One thing I have always wanted to achieve is the ability to have a property re-load itself if the properties file ever is changed, although this may seem dangerous it does mean that an application wont need to be bounced in order for a new property to take effect (in theory).

One of the great new API's in Java 7 is the WatchService API, this is handy set of tools which allow you to watch and react to file changes. Other libraries are available and have been doing this for some time but this is a good opportunity to get stuck into some of Java's new features and evaluate its usage. 

From the Java Doc:
A watch service that watches registered objects for changes and events. For example a file manager may use a watch service to monitor a directory for changes so that it can update its display of the list of files when files are created or deleted.

Spring provides functionality to load application properties via a PropertyPlaceholderConfigurer class, this is used to configure the application container giving exposure to each properties file and its properties specified allowing them to be referenced to configure the application.

What I have created is a proof of concept library which allows class fields to be set from properties files via a @ReloadableProperty annotation. These properties are also auto reload if the given properties file changes during runtime.
 

How it Works

When Spring starts an Application Context an implementation of Springs PropertySourcesPlaceholderConfigurer is instantiated to perform additional logic when loading and setting values from a given set of properties files. (see: ReadablePropertySourcesPlaceholderConfigurer)

During the instantiation phasae of an Application Context a new instance of InstantiationAwareBeanPostProcessorAdapter is also created which allows post bean processing to occur.

Google Guava is used to implement a simple Publish & Subscribe (Pub-Sub) Pattern so that beans can be updated once created, i.e. a bean can subscribe to property change events. (see: EventBus) EventBus was chosen as it is a very easy and simplistic way to implement loosely couple object structure. (see: blog)

When each properties file resource is loaded a PropertiesWatcher is started and attached to the given resource set, reporting on any java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY events from the host operating system. When an ENTRY_MODIFY event is fired firstly the resource changed is checked for property value changes then any bean subscribing to changes to the modified property has the specified field value updated with the new property. Once the field value is updated no other operations are performed on the object.

Each resource specified starts a new thread per parent directory i.e. two properties files in the same directory requires only one ResourceWatcher thread, three properties files in three different directories will start three threads.


Example Usage

Sample Bean Usage




Sample XML Configuration

Sample Properties files
   


Future Changes


  • Ability to use Spring Expression language to map properties files
  • Support for Java 7 Data and Time classes
  • Include the ability to define a database driven properties source not just properties files
  • Implement error recovery inside PropertiesWatcher.class, including better thread recovery
  • Ability to perform additional re-bind logic when a property is changed, i.e. if a class has an open DB connection which needs to be re-established using newly set properties.
  • Replace callback Properties EventHandler with Guava EventBus
  • Ability to configure usage via Spring's @Configuration

Problems

As on reload I simply reset the field value for future use, if the property was ever used to create another long lived object there is no way of re-binding or performing additional post reload logic on a class, this could be done but would need a marker to identify what to invoke post reload i.e. annotation of a void empty args method or implementation an interface which then can be triggered ever time a classes properties change and perform additional re-binding logic.

Feedback always welcome and it would be nice for someone else to check this project out and review it/use it. A complete project with sample tests can be found @ https://github.com/jamesemorgan/ReloadablePropertiesAnnotation/


James

3 comments:

  1. Hi James,

    Interesting approach. I would like to give it a try in my project, but I couldn't find a published Maven release. Is there one available?

    Regards,
    Paul

    ReplyDelete
  2. Hi Paul, i have never published it to maven central or any other repo. However if you get the code from GitHub it should be trivial and easy to rip the bits you need. If I remember correctly the code should be documented and tested so please feel free to take what you need. James

    ReplyDelete
  3. Software development creates or converts user goal and marketing goal into a good software application that adds value and growth to user requirements. Software development is used to perform functions as per user requirements, including various phases; such as initial market research, planning, modification, architecture, software design, software implementation and testing, etc.Software Development Company in Lucknow. Software development has become indispensable in the business world today; Improve customer service and assist in developing and maintaining closer customer relationships.

    ReplyDelete