3

I am not sure if this is the right place to post this question, but I think this might be better suited than Stack Overflow.

I have got an online application, a Java EJB application. Requirement is to have an external configuration file which will contain property using which the application is going to decide whether or not to perform a business function.

We do not want to read this file everytime, we'll read this once, store the value and use the value until the content of file changes.

To handle this, I had two approaches,

  1. Have a file listener which would check the file and update the variables when the file changes

  2. Have a servlet to force Refresh from the file

Both of these are not approved. #1 would add to the processing time and #2 is a security violation as per their standards.

Now I am out of ideas, is there anyway I can have a file listener out of my actual processing, like in the application level and transaction? Is there another approach to implement this?

WhiteBird
  • 31
  • 2
  • What do you mean by "#1 would trio processing time"? Is your configuration file that huge? What mechanism were you proposing to use to watch the file system for changes? – BobDalgleish Mar 07 '19 at 20:09
  • @WhiteBird, when you say "trio processing time" are you saying it would take 3x the amount of time to process? If so, what's the baseline? Are we talking going from 1s to 3s or 10m to 30m? Finally, do you have a definition of acceptable processing time? – Berin Loritsch Mar 07 '19 at 20:48
  • It might interest [jndi](https://en.m.wikipedia.org/wiki/Java_Naming_and_Directory_Interface). And [this](https://stackoverflow.com/q/34062435/5934037). Some containers allow you to set set the jndi cache too so that the changes on the remote file can be fetched inmediatly or after a while. – Laiv Mar 07 '19 at 20:59
  • @BobDalgleish I meant "added to the", was a typo. And no config files arent going to be huge, would be just 2-3 entries at most. I was thinking of using thread polling to watch a file – WhiteBird Mar 08 '19 at 02:59
  • @Berin Loritsch It was a typo, but we do have an acceptable total processing time for our app which is 1.5 seconds. Currently the app takes 1.3 on an average, while adding this particular config thing they need it to stay at 1.3, which means we have got 0.05 which is what they are looking at. Also they do not want this process of hot-reloading to be part of the transactional flow, but outside of it. In that case the time shouldnt matter. – WhiteBird Mar 08 '19 at 03:02
  • @Laiv thanks, jndi was shot down as well. But you mentioned something about cache jndi in some containers, can you elaborate on that? That might be useful! – WhiteBird Mar 08 '19 at 03:04
  • Sadly, I'm not an expert on the subject. I have just spoken about the subject occasionally with co-workers. The speech was whether we could use JNDI for something else than JDBC connections. I learnt that they could serve property files too. Then I was told that JNDI resource's lookups are cached to improve performance. The thing is to don't call to the remote resource every time the lookup is invoked. Googling a bit you will find that JEE container providers such as RedHat or IBM allow you to tune this cache. Performing a proof of concept test with JNDI should not take you too long. – Laiv Mar 08 '19 at 07:53

1 Answers1

1

I use these methods, 1 or 2 below in various projects.

1. Use java.nio.file.WatchService to wait for changes.

I guess this is what you mean by "a listener".

For the narrow scenario of tracking occasional changes to a few config files on Linux local filesystems (using Linux's inotify), this produces very quick updates (near instant from a user perspective) when a config file changes, with insignificant resources used, in my experience.

Linux's inotify is not a polling mechanism. It's a feature of the linux kernel that generates events when files change. Java has wrapped this with the WatchService. Windows has similar capabilities and I imagine your JDK/JVM will use them, but I have not tested it.

In my experience it does not take 3x time or cpu to track config local file changes in this way. But it's not perfect. In particular renaming of files and directories can be tricky (not part of my use scenarios) and inotify does not pick up change events on remote filesystems. WatchService falls back on other implementation (probably polling), which I have not used.

I can't swear to the implementation on every platform for every JDK. Test it.

2. Implement a simple form of lazy initialization with caching.

This produces reliable cheap updating when config files change, with a defined maximum delay period, like 30s.

  • For the first request read the file, save a timestamp.

  • For every subsequent request of the file's properties, check the timestamp.

  • If the data is older than your cache expiration time (say 30s or 1 minute), check the file's modify time and reread if needed.

Thread-Safe Access

For both approaches to share configuration across a busy multithreaded application, I use standard tools from java.util.concurrent to allow non-blocking reads of configuration. For Example:

  • Make the properties structure immutable. Share access to it through an AtomicReference<>. When you reread the config file make a new instance of your config properties and replace the old instance.

  • Or Use a ConcurrentHashMap referencing immutable objects, if the contents consist of an extensible number of different objects needing separate updating and key-value access. When rereading a config file, replace objects with new immutable instances.

joshp
  • 3,451
  • 1
  • 21
  • 27