2016/02/07 - Apache Onami has been retired.

For more information, please explore the Attic.

Apache Onami-Configuration getting started

The Apache Onami-Configuration library is a small Google Guice extension that allows expanding com.google.inject.name.Names variables. That means that users can define properties with placeholders and let Guice resolve them to be injected with replaced values.

Users have just to invoke the org.apache.onami.configuration.OnamiVariablesExpander.expandVariables method grouping the Modules where properties have been bound, like in the sample below:

import static org.apache.onami.configuration.OnamiVariablesExpander.expandVariables;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.name.Names;

...

Injector injector = Guice.createInjector( expandVariables( new AbstractModule()
        {

            @Override
            protected void configure()
            {
                Properties properties = new Properties();
                properties.put( "JDBC.host", "localhost" );
                properties.put( "JDBC.port", "3306" );
                properties.put( "JDBC.schema", "test" );
                ...

                Names.bindProperties( binder(), properties );
            }

        }, new AbstractModule()
        {

            @Override
            protected void configure()
            {
                bindConstant()
                    .annotatedWith( Names.named( "JDBC.url" ) )
                    .to( "jdbc:derby://${JDBC.host}:${JDBC.port}/${JDBC.schema}" );
            }

        }
        ...
        ) );

That's all! When requesting the injection of JDBC.url, properties will be correctly expanded:

public final class JdbcConfiguration
{

    @Inject
    @Named( "JDBC.url" )
    private String jdbcUrl; // jdbc:derby://localhost:3306/test

    ...

}

${}, the Apache Ant variables style

Apache Onami-Configuration supports the well known ${} expression to define placeholders, which scope is the whole configuration, that means that users can define some commons properties in one properties file:

commons.host=localhost
commons.port=8080
...

then referencing them in different files:

ldap.host=${commons.host}
ldap.port=${commons.port}
...

Default Values

In Java code users can retrieve a property from java.util.Properties specifying the default value if the input key is not present, using the Properties#getProperty(java.lang.String, java.lang.String) method.

Apache Onami-Configuration allows doing the same, users can specify a key using the pipe character | to separate the key name from the default value:

JDBC.url=jdbc:derby://${JDBC.host|localhost}:${JDBC.port|1527}/${JDBC.schema}

that means if JDBC.host and JDBC.port won't be specified, they will be replaced by the default values; given the following properties:

JDBC.url=jdbc:derby://${JDBC.host|localhost}:${JDBC.port|1527}/${JDBC.schema}
JDBC.schema=rocoto

the JDBC.url property value will be jdbc:derby://localhost:1527/rocoto.

Add support for variables in default value (since 6.2)

property=${not.found|${not.found.again|Crap!}}

# property = Crap!

not.found.again=Fallback!

# property = Fallback!

Add support for dynamic variables (since 6.2)

hello.en=Hi!
hello.fr=Salut !
hello.i18n=${hello.${locale|en}}

# hello.i18n = Hi!

locale=fr

# hello.i18n = Salut!

Prevent infinite loop for recursive variables (since 6.2)

# Will not thow a stack overflow
GNU=${GNU}'s Not UNIX

Add support for configuration hell and free headaches (since 6.2)

g=2g
gg2=2
h=${${${g}4|${g}2}}
2g=gg
2g2=4
gg=${h}${4|${${2g}2}}

# gg=42

More flexible than the Spring Framework v2!

I had a not so good experience with the Spring 2 PropertyPlaceholderConfigurer because it forces users to centralize the properties files loading; I mean, to make things working, in the way that ${} expressions were correctly resolved, I had to declare just one PropertyPlaceholderConfigurer for the whole context, list all the *.properties files for the all modules.

I didn't like that approach at all, it doesn't allow users to split configurations in different modules even if some keys are shared by two or more modules. Apache Onami-Configuration users won't have these problems at all, they can load *.properties files from different locations and obtain the same result.