Configuration Reader
Problem:
- An application need to read configurations from an external source, for instance a file
- A configuration file might be changed during an application’s work
Assume that configurations are held in a properties file. Our first task is to read Properties and keep it in one place.
@Singleton @Startup public class Config { private Properties properties; @PostConstruct private void init(){ properties = new Properties(); try { InputStream is = new FileInputStream("..."); properties.load(is); } catch ( IOException e ) { throw new RuntimeException(e); } } public Properties getProperties() { return properties; } public Properties getProperty( String key ) { return properties.getProperty(key); } }
And excerpt of a client code:
@EJB private Config config; ... String dbName = config.getProperty("db.name"); ...
- Properties are read only once at application start up
- Bean is @Startup, thus if the configuration file reading fails then runtime exception is thrown, bean initialization fails and the application deployment fails
Now assume that the configuration file is being changed and the application need to reread it. Modify our Singleton:
@Singleton @Startup public class Config { private Properties properties; @PostConstruct @Schedule(hour="*",minute="*/5",persistent=false) @Lock(LockType.WRITE) private void init(){ try { Properties properties = new Properties(); InputStream is = new FileInputStream("..."); properties.load(is); this.properties = properties; } catch ( IOException e ) { throw new RuntimeException(e); } } @Lock(LockType.READ) public Properties getProperties() { return properties; } @Lock(LockType.READ) public Properties getProperty( String key ) { return properties.getProperty(key); } }
- The configuration file is reread every 5 minutes
- If the configuration file reading fails and it is not initialization then runtime exception is thrown but bean is not discarded and old properties remains, clients are not affected
- Locks are added to enhance consistency
- persistent=false prevents accumulated schedule invocations after a server restart
Usually reading the configuration file is fast. But if communicating with an external source containing configurations is time consuming then Lock(LockType.WRITE) might be consider as a bottleneck. We provide further modifications:
@Singleton @Startup public class ConfigurationReader { @EJB private Config config; @PostConstruct @Schedule(hour="*",minute="*/5",persistent=false) private void init(){ try { Properties properties = new Properties(); InputStream is = new FileInputStream("..."); properties.load(is); config.setProperties(properties); } catch ( IOException e ) { throw new RuntimeException(e); } } } @Singleton @Startup public class Config { private Properties properties; @Lock(LockType.WRITE) public void setProperties( Properties properties ) { this.properties = properties; } @Lock(LockType.READ) public Properties getProperties() { return properties; } @Lock(LockType.READ) public Properties getProperty( String key ) { return properties.getProperty(key); } }
- Hard word is done in separate Singleton, when it is done then the configurations are updated in main Singleton