Proven and opinionated programming, and configuration model for Java and Vertx based applications. Inspired from ATG Nucleus, provides powerful layer base configuration management using simple properties file.

What is Glue?

You will use Glue for same reason you will use Spring (dependency injection) in your application. But, in case of Glue, we have implemented few concepts to make your life much easier from development point of view.

Simple Hello World
  1. HelloWorld class : We want to set mHelloWorld field to This is hello world example. Normally, this is done by creating new instance of HelloWorld class and then calling setHelloWorld method to set mHelloWorld field. With Glue, this is done automatically. You just need to define a property file with values.

  2. Component Path:/in/erail/example/HelloWorldComponent (File Name:HelloWorldComponent.properties) : This file is used to create instance of HelloWorld class and set property values as defined in property file.

  3. To get instance of HelloWorld class, you just need to call HelloWorld inst = Glue.instance().<HelloWorld>resolve("/in/erail/example/HelloWorldComponent")

Configuration Layer

Configuration layer is root directory under which all configurations exists. For example, you want to create instance of HelloWorld class. Then, you will have to do below steps.

  1. Create configuration layer on your file system. For example /home/glue/layer1. This folder will become root folder for all configurations.

  2. Then create HelloWorldComponent.properties file at /home/glue/layer1/in/erail/example/HelloWorldComponent.properties.

  3. When you run your code, you will pass configuration layer to glue as java parameters. java -Dglue.layers=/home/glue/layer1. Now whenever you want to get instance of HelloWorld, HelloWorld inst = Glue.instance().<HelloWorld>resolve("/in/erail/example/HelloWorldComponent"). HelloWorld instance will be configured based on /home/glue/layer1/in/erail/example/HelloWorldComponent.properties file.

Multiple Configuration Layers

You can define multiple configuration layers. Properties file defined at same location inside all layers are merged. And last overridden value is taken as value of property. for example:

Layer 1 (/testdata/layer1/)
#/in/erail/glue/test/component/MergedComponent
$class=in.erail.glue.component.PropertiesComponent
$scope=LOCAL
propString=TestString
Layer 2 (/testdata/layer2/)
#/in/erail/glue/test/component/MergedComponent
$scope=GLOBAL
propString=TestString2
Final merged component configuration:
#/in/erail/glue/test/component/MergedComponent
propString=TestString2
$scope=GLOBAL

As you can see above, second layer has overridden propString property.

Supported Property Type

Java Type Example

String

propString=TestString

Array[String]

propArray=a,b,c

Array[Component]

propArray=/abc/comp1,/abc/comp2

List<String>

propList=a,b,c

Map<String,String>

propMap=a=b,c=d,e=f

Boolean and boolean

propBoolean=true

Enum

propEnum=TWO

Set<String>

propSet=a,b,b,c

Integer and Int

propInteger=2

Long and long

propLong=2

File

propFile=testconfig.json

JsonObject (Vertx)

propFile=testconfig.json

ServiceMap

Map of components

Logging

Logging component

Component

Reference to another component

Null

Null value

Pattern

String will be compiled into Pattern

Timer (Dropwizard Metric)

a timer will be created based on name given

Counter (Dropwizard Metric)

a counter will be created based on name given

Meter (Dropwizard Metric)

a meter will be created based on name given

Histogram (Dropwizard Metric)

a hitogram will be created based on name given

Class

propClass=java.lang.String

Properties based configuration in detail

Example Property File
#/in/erail/glue/test/component/PropertiesComponent
$class=in.erail.glue.component.PropertiesComponent
$scope=LOCAL
propString=TestString
propArray=a,b,\
    c
propList=a,b,\
    c
propMap=a=b,c=d,\
    e=f
propComponent=/in/erail/glue/test/component/GlobalObjectByDefault
propBoolean=true
propEnum=TWO
propSet=a,b,b,c
propBoolean2=true
propServiceMap=\
    a=/in/erail/glue/test/component/GlobalObjectByDefault,\
    b=/in/erail/glue/test/component/GlobalObjectByDefault,\
    c=/in/erail/glue/test/component/GlobalObjectByDefault
propInt=2
propInteger=2
propFile=testconfig.json
propLong=2
propLong2=2
propLogger=true
propNullString=
propNullServiceMap=
propNullComponent=

Above is test property file PropertiesComponent.properties to create component PropertiesComponent. Physically, it is present in folder /in/erail/glue/test/component/. Folder structure itself is present in another folder called configuration layer folder. We can provide multiple configuration layers to Glue. Physical location of PropertiesComponent.properties file under configuration layer becomes actual mounting point of component. In this case, PropertiesComponent is mounted at /in/erail/glue/test/component/. To get instance of PropertiesComponent, we use /in/erail/glue/test/component/PropertiesComponent path.

Basic Properties File Configuration

Property Name Required Default Description

$class

Yes

N/A

Instance of this class will be created whenever instance of this component is created.

$scope

No

GLOBAL

Default scope of component is "GLOBAL". Means, Whenever instance of this component is required, same instance of component is returned. This is same as Singleton Pattern. If new instance is required on each component creation call then "LOCAL" scope can be defined. This will ensure, Glue will return new instance each time.

$basedOn

No

N/A

One component can copy all property values of another component. And override only required properties

$basedOn Example
#/in/erail/glue/test/component/BasedOnPropertiesComponent
$basedOn=/in/erail/glue/test/component/PropertiesComponent
propString=TestString2

In above example, all properties of this component will have value as set in /in/erail/glue/test/component/PropertiesComponent component. And in this component propString will be overridden with value TestString2

Configuration layer in detail

Layers are passed to Glue using JVM parameter

java -Dglue.layers=/testdata/layer1,/testdata/layer2

Override Property Value

If we have two properties files at same location under different layers. Glue will try to override or merge property file in same order as configuration layers are defined. For example:

Layer 1 (/testdata/layer1/)
#/in/erail/glue/test/component/MergedComponent
$class=in.erail.glue.component.PropertiesComponent
$scope=LOCAL
propString=TestString
propArray=a,b,\
    c
propList=a,b,\
    c
propMap=a=b,c=d,\
    e=f
propComponent=/in/erail/glue/test/component/PropertiesComponent
propJson=testconfig.json
propSet=a,b,b,c
Layer 2 (/testdata/layer2/)
#/in/erail/glue/test/component/MergedComponent
propString=TestString2
propArray=a
propList-=a
propList+=b,c,d
propMap-=a=b
propMap+=z=b
propComponent=/in/erail/glue/test/component/PropertiesComponent2
propSet-=a,b
propSet+=e,f

Override Property Value

In above example, when instance of /in/erail/glue/test/component/MergedComponent is created,PropertiesComponent.getPropString() method will return TestString2 instead of TestString. As you can see in above example, Layer 2 is overriding propString value.

Merge Property Value

In case of List,Map,Set. Glue supports merge or deletion of property value. In above example, PropertiesComponent.getPropList() will return list with elements b,c,b,c,d. Hyphen(-) in propList-=a will remove a from list. And Plus(+) in propList+=b,c,d will add b,c,d elements to list. Same can be done in case of Map and Set.

Component Property

A component property can refer to another component property.As can be seen in /in/erail/glue/test/component/PropertiesComponent,

propComponent=/in/erail/glue/test/component/GlobalObjectByDefault

PropertiesComponent.getPropComponent() will return instance of GlobalObjectByDefault component.

Component property referring to another component property

#/in/erail/glue/test/component/RefPropertiesComponent
$class=in.erail.glue.component.PropertiesComponent
$scope=LOCAL
propString^=/in/erail/glue/test/component/PropertiesComponent.propString
propArray^=/in/erail/glue/test/component/PropertiesComponent.propArray
propList^=/in/erail/glue/test/component/PropertiesComponent.propList
propMap^=/in/erail/glue/test/component/PropertiesComponent.propMap
propComponent^=/in/erail/glue/test/component/PropertiesComponent.propComponent
propBoolean^=/in/erail/glue/test/component/PropertiesComponent.propBoolean
propEnum^=/in/erail/glue/test/component/PropertiesComponent.propEnum
propJson^=/in/erail/glue/test/component/MergedComponent.propJson
propServiceMap^=/in/erail/glue/test/component/PropertiesComponent.propServiceMap

As can be seen above. ^ is used for connecting component property to another component property.

Factory based creation of Component

Glue supports two factory classes which you can use to create instance of classes requiring factory for creation. For more example, refer to test cases.

MethodInstanceFactory

#/in/erail/glue/test/factory/TestComponentPC2
$class=in.erail.glue.factory.TestComponent
$instanceFactory=/in/erail/glue/test/factory/MethodInstanceFactory
$factory.class=in.erail.glue.factory.TestFactory
$factory.method.name=create
$factory.param.values=ninja,5
#factory.param.type=
#factory.instance=
$scope=GLOBAL
Field Name Description

instanceFactory

Reference to component: in.erail.glue.factory.MethodInstanceFactory

factory.class

Class responsible for creating instance

factory.instance

Path of component responsible for creation of instance

factory.method.name

Method name

factory.param.values

Method parameters (Support component path also)

factory.param.type

Optional method parameter type

ParameterConstructorInstanceFactory

#/in/erail/glue/test/factory/TestComponentPC1
$class=in.erail.glue.factory.TestComponent2
$instanceFactory=/in/erail/glue/test/factory/ParameterConstructorInstanceFactory
$constructor.param.values=ninja,5,/in/erail/glue/test/component/PropertiesComponent,"a,b"
$scope=GLOBAL
Field Name Description

instanceFactory

Reference to component: in.erail.glue.factory.MethodInstanceFactory

constructor.param.values

Constructor parameters (Support component path also)

constructor.param.type

Optional constructor parameter type

Advance

Configuration using glue.config file

Glue picks any configuration from three places in given order:

  1. From Java command line (e.g. -Dglue.layer)

  2. From Environment variable (e.g. GLUE_LAYER)

  3. glue.config file

glue.config example
glue.layers=/common

To pass glue.config use -Dglue.config=/var/task/glue.config

Improve config loading performance

Normally, all properties files are loaded from layer location each time glue is started. To imporove performance, Glue can cache loaded configuration in file file. On any future restarted, Glue will first try to load full configuration from cache configuration file. This setup can be used in production to save some load time.

By default, configuration is always loaded from layers. To activate caching of configuration, you will have to use a different configuration loader as shown below.

-Dglue.serialization.factory=in.erail.glue.factory.LocalConfigSerializationFactory
Table 1. LocalConfigSerializationFactory additional param which can pass in command line
Environment Variable Default Description

local.config.factory.file.location

Current working directoy

Directory from where file is loaded or saved

local.config.factory.file.name

glue.ser

Default file name

local.config.factory.identifier

.default

While generating file. Files can be generated with different identifier to generated different config files (for example for different env)

local.config.factory.disable.save

false

If enable, then each time Glue starts, all layers are saved into file, which can be used in future to load configuration.