matteobaccan / owner

Get rid of the boilerplate code in properties based configuration.

Home Page:https://matteobaccan.github.io/owner/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Is it possible, somehow, to have Variables expansion with Accessible.getProperty(String)

alexander-poulikakos opened this issue · comments

Is it possible, somehow, to have variable expansion when using Accessible.getProperty(String) method?

Example:

import org.aeonbits.owner.Accessible;
import org.aeonbits.owner.Config.Sources;
import org.aeonbits.owner.ConfigFactory;

public class _Owner {
	
	@Sources({"classpath:conf.properties" })	
	public interface MyConfig extends Accessible {
		String hello();
	}
	
	public static void main(String[] args) {
		MyConfig conf = ConfigFactory.create(MyConfig.class);
		System.out.println(conf.hello()); // Variable Expansion works as expected for this
		System.out.println(conf.getProperty("b")); // No variable expansion :( 
	}
}

conf.properties file

s = say
hello = ${s} HELLO
b = ${hello} AGAIN!

output:

say HELLO
${hello} AGAIN!

However, I would like to have this output:

say HELLO
say HELLO AGAIN!

I have read the docs but did not find a way. Can it be done somehow, without declaring a separate method in MyConfig interface for each property? It does not necessarily needs to be done by using a method from Accessible interface, anyway would be fine by me :)

In lack of proper support for this, I came up with this rather hacky solution. Well, at least it works (using owner-java8-1.0.12) 😝

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import org.aeonbits.owner.Accessible;
import org.aeonbits.owner.Config.Sources;
import org.aeonbits.owner.ConfigFactory;

public class _Owner {
	
	@Sources({"classpath:conf.properties" })	
	public interface MyConfig extends Accessible {
		String hello();
		
		default String getExpandedProperty(String key) {
			try {
				InvocationHandler invocationHandler = Proxy.getInvocationHandler(this);
				Field substitutorField = invocationHandler.getClass().getDeclaredField("substitutor");
				substitutorField.setAccessible(true);
				Object substitutorInstance =  substitutorField.get(invocationHandler);
				Method replaceMethod = substitutorInstance.getClass().getDeclaredMethod("replace", String.class);
				replaceMethod.setAccessible(true);
				return replaceMethod.invoke(substitutorInstance, getProperty(key)).toString();
			} catch (Exception e) {
				throw new IllegalStateException("Could not expand property: " + key, e);
			}
		}
	}
	
	public static void main(String[] args) throws Throwable {
		MyConfig conf = ConfigFactory.create(MyConfig.class);
		
		System.out.println(conf.hello()); // Variable Expansion works as expected for this
		System.out.println(conf.getProperty("b")); // No variable expansion :( 
		System.out.println(conf.getExpandedProperty("b")); // variable expansion :) 
		
	}
}

and it outputs this:

say HELLO
${hello} AGAIN!
say HELLO AGAIN!