Giter Club home page Giter Club logo

contextprop's Introduction

contextprop

The purpose of the library is to consolidate copies of configuration (based on environment, region, etc) into one easy to maintain configuration file. Complicated configuration directory trees which carry complexity and redundancy can be eliminated by using the 'contextprop' library.

src/
  main/
    resources/
      env/
        local/
          configuration.properties
        sit/
          configuration.properties
        uat/
          configuration.properties
        prod/
          configuration.properties

Instead of having to maintain a directory tree of redundant configuration for every environment, region, etc (deployment scope) we can have one configuration file of which properties can be overridden for a specific deployment scope by using the .CTXT() suffix and adding some context about deployment. Using this method we are able to define a configuration property which is the default for most of the deployments and then with the help of the context identifier (.CTXT()) we can define an exception. We don't need to create a copy of the configuration for each deployment scope.

my.property.key.CTXT(env[sit,uat],loc[london],group[canary])=true
my.property.key=false

Binaries

You can download or reference using your favourite build tool the latest version of the library from Maven Central

How it works

Properties with context follow the standard java property file syntax. To create one append the.CTXT() identifier to the property name and add some key/value entries. There are two type of entries, a key/value pair .CTXT(key1[value1]) and a key/value set .CTXT(key1[value1,value2,...]).

property.name.CTXT(key1[value1],key2[value21,value22,...],...)=property_value1
property.name=property_value2

In the following section we define the terms used by the library and the documentation below.

Glossary

                                  context
                       .-------------^-------------.
                        condition    condition
                       .----^---..-------^---------.
            context              domain  condition
 property  identifier             key     value(s)         value
.---^---.   .--^--.              .-^-. .-----^-----.      .--^--.
username    .CTXT      (env[prd],loc   [ldn,nyk,hkg])  =  kkarad

The domain keys are defined by the user in a form of a java enum type (domain). An example of domain definition is listed below:

enum MyDomain { 
    env, //environment, such as prod, uat, sit, dev
    loc, //location, such as ldn, nyk, hkg
    grp, //group, such as canary, retail, institutional
    app, //application
    usr, //user
    hst  //host
}

The order of the domain (enum) keys also defines the deployment context order. The lower the ordinal of the enum (key) the higher (or else general) the order of the key in the deployment context. The enum type example defines the following deployment context order:

env > loc > grp > app > usr > hst

The order of the domain helps the library to apply rules and priorities during the property resolution.

Property entries with the same name but different context form a property group. The property without context holds the default value. That is if there is no context much against the deployment scope then the default property is used. Obviously there can be only one default property in a property group.

# Property group of 'property.name'
property.name.CTXT(key1[value1])=property_value
property.name.CTXT(key1[value1],key2[value21,value22])=property_value
property.name=property_value

In the following code fragment we setup the deployment domain and resolve a property group with two entries:

//step 1: define your configuration domain
enum MyDomain {
    env, loc, group, app, host, user
}

//step 2: in your application (startup) specify values for each domain key
DomainPredicates predicates = DomainPredicates.basedOnDomain(MyDomain.class)
    .predicate("env", "uat")
    .predicate("loc", "ldn")
    .predicate("group", "internal")
    .predicate("app", "whatsapp")
    .predicate("host", "localhost")
    .predicate("user", "kkarad")
    .create();

//step 3: create or load from a file the java properties which use the contextprop format (here we create one programmatically)
Properties ctxProperties = new Properties();
ctxProperties.setProperty("my.prop.key.CTXT(env[uat],loc[ldn,nyk],group[internal],app[whatsapp],host[localhost],user[kkarad])", "myValue");
ctxProperties.setProperty("my.prop.key", "defaultValue");

//step 4: resolve the contextualised properties to properties (configuration) specific to this application instance  
Properties properties = ContextProperties.create(predicates)
    .requiresDefault(false)
    .resolve(ctxProperties);
    
assertThat(properties.getProperty("my.prop.key")).isEqualTo("myValue");

In order to avoid conflicts during property resolution we need to follow some rules (if the rules are violated the parser raises an error):

Rule: All properties excluding the default one should define all domain keys already defined in the same property group

So for example the following groups are invalid. We are not able to resolve the properties (name1 & name2). Both entries qualify for the env[prd],loc[loh],grp[external] deployment context.

property.name1.CTXT(env[prd])=true
property.name1.CTXT(loc[loh])=false #invalid! higher ordered key 'env' should be defined

property.name2.CTXT(env[prd],grp[canary])=true
property.name2.CTXT(env[prd],loc[loh])=false #invalid! higher ordered key 'grp' should be defined

The following groups are valid. All properties define all higher order domain keys of their group.

property.name1.CTXT(usr[john])=true
property.name1.CTXT(usr[john],hst[localhost])=false

property.name2.CTXT(hst[localhost])=true
Rule: Properties with identical domain keys should not have overlapping values when these are located in the same group
property.name.CTXT(env[prd],loc[ldn,nyk])=true
property.name.CTXT(env[prd],loc[ldn,nyk,hkg])=false #invalid! location loh and nyk are overlapping

contextprop's People

Contributors

kkarad avatar

Watchers

 avatar

contextprop's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.