Atbash Configuration Server

Introduction

MicroProfile Config specification defines how configuration values can be picked up by the application. It has the concept of a Configuration source and converters to supply the values you need.

By default, only a ConfigSource for a classpath defined file and environment and system variables are defined.

But since we have the concepts in place, we can create our custom ConfigSource to retrieve the configuration from a central server.

Configuration Server

Instead of putting the configuration of each application within the application itself, we can store it in a central location.

It is very convenient to have an overview of the configuration of all your application at one place. Which makes updating it also very simple.

The first version of the Atbash Configuration Server exposes the configuration of an application through a JAX-RS endpoint.

The URL

/config/{application}

will give you the configuration values as a JSON structure for the specified application.

{
   "pets":"dog,cat",
   "dateValue":"2017-11-15",
   "value2":"500",
   "classname":"be.atbash.config.examples.se.testclasses.ConvTestTypeWStringCt",
   "value1":"Classpath Value",
   "value3":"true",
   "dateValueFmt":"16-11-2017,dd-MM-yyyy"
}

Creating the Configuration server

The configuration server is available within the directory  <server> of the repository https://github.com/atbashEE/atbash-config-server

You can build the server in 3 flavors

1. Java EE war.

With the maven command, mvn package -Pee7-servera WAR file is created which can be run by any Java EE 7 compliant server (Java 8 required)

2. WildFly Swarm executable JAR

The Configuration server can also be wrapped within a WildFly swarm application with the mvn package -Pwildfly-swarmcommand.

3. WebSphere Liberty executable JAR

There is also a profile defined to create a WebSphere Liberty JAR file, use the mvn package -Plibertycommand.

More servers will be supported when they have support for Config Spec 1.2.

Configuration of Server

Define within a config-server.properties or config-sever.yaml file on the classpath the following configuration information.

– rootDirectory: Root directory containing the configuration files for the application. See further for a directory structure.

– applications: List of known applications.

example (as yaml)

rootDirectory : /Users/rubus/atbash/config-server/server/demo
applications : ["app1", "app2"]

Possible directory structure

/demo
├── /app1
│  ├── app1.properties
│  └── app1-test.properties
└── /app2
   └── app2.properties

A subdirectory for each application so that the configuration values are nicely separated for each application.

All the features of Atbash config (like stage, yaml support, date support, etc) are available.

Client configuration

A ConfigSource implementation is available which integrates the result of the call to the JAX-RS endpoint into the configuration of the application.

In this first version, Atbash configuration extension is required (which makes it a bit more work) but this requirement will be removed in the next version.

Add the Maven artifact to your dependencies

    <dependency>
        <groupId>be.atbash.config</groupId>
        <artifactId>atbash-config-client</artifactId>
        <version>${atbash-config.version}</version>
    </dependency>

Define the base name of the configuration file which contains the configuration of the Config server.

Create a class implementing the be.atbash.config.spi.BaseConfigurationName interface and defining this class for usage with the ServiceLoader mechanism of Java.

Define the class name within src/main/resources/META-INF/services/be.atbash.config.spi.BaseConfigurationName

be.atbash.config.examples.DemoBaseName

Define the configuration within the specified properties file.

config.server.url=http://localhost:8181
config.server.app=app1
config.server.stage=test

* config.server.url: The _root_ of the Config server endpoint.

* config.server.app: The name of your application

* config.server.stage: (optional) Indication of the stage of the application to retrieve specific values.

We can use all the regular features of Configuration or Atbash config to specify the stage value, like environment or system properties.

The client can be used in a Java SE, Java EE or a MicroProfile environment.

Conclusion

With the Atbash Configuration server, you can store the configuration values for all your applications at a central location. The values can be picked up by a JAX-RS call through the Client ConfigSource.

The server can be run by WildFly Swarm, Liberty or a regular Java EE 7 server. The client can be used for all environments capable of using the MicroProfile Configuration spec (including Java SE and Java EE)

A future version will bring you some more features and makes it easier to set things up.

Have fun.

Implicit converters for MicroProfile Config

Introduction

Last month (January 2018), an update of the MicroProfile Config specification, version 1.2, was released which makes it easier to convert the configuration values to class instances.
It adds the concept of implicit/automatic converters and removes the requirement for creating specific converters in many cases.
The first implementations are already available and Atbash Configuration is now also updated.
This blog describes what the implicit/automatic converters are and how you can use them.

Converters

The configuration values we define are Strings because they are defined as a set of Characters in the configuration files. Using the configuration could be limited to a system which is capable of reading those Strings and that the developers need to convert these values to the proper instance (like Integer, Boolean or application specific classes) themselves.
But in that case, each developer will write his own set of converters and in the case of Integers and Booleans, for example, they are all the same.
So the framework itself can take care of these converters. And since we have then already the concept of a convert, it is easy to foresee an SPI which allows the creation of custom Converters by the developer for their application specific classes.
These basic converters for Integer and Boolean for example where present since the first release of the spec. Just as the SPI to add your own converters.

Implicit Converters

But the creation of all those custom converters can be minimized further. Since our application specific classes can be created from a String, they probably have some means of instantiating them through a method which takes a String parameter
– The constructor
– A static method with names like valueOf or parse.
So with the new implicit/automatic converters feature, when we have some class like this
public class ClassWithStringConstructor {
    private String value;

    public ClassWithStringConstructor (String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}
and have a parameter
some.key = Atbash

We can retrieve an instance of the class, with the value using

config.getValue("some.key", ClassWithStringConstructor.class)

or when we are in a CDI enabled context, we can also use injection

@Inject
@ConfigProperty("some.key")
private ClassWithStringConstructor parameterValue;

Collection type parameters

Another nice addition to this 1.2 release, is the use of collection type parameters. The ability to have multiple parameter values, like a list of values which is converted to an Array, List or Set.
It is quite common that a configuration value is, in fact, a list of value.
pets = dog,cat
previously, the developer needed to split the String and use the individual parts separately (although this is a very simple task with String.split() ), can be done automatically.
config.getValue("pets", String[].class)

With injection, we can automatically convert it to a List or a Set.

@Inject
@ConfigProperty(name = "pets")
private List<String> pets;

The List and Set variants can’t be used in a programmatic way (using config.getValue) since the second parameter doesn’t accept parameterized types (like List<String>).

When you have a value which contains a comma it in, you need to escape it
a,b,c\\,d

which results in 3 configuration values, where the last one is c,d.

Implicit combined with Collection.

We can even combine the collection type feature with the implicit/automatic converter feature. If we instead specify the class name like ClassWithStringConstructor instead of String, the configuration framework will use the appropriate way of converting.
config.getValue("pets", ClassWithStringConstructor[].class)

or

@Inject
@ConfigProperty(name = "pets")
private List<ClassWithStringConstructor> pets;

Octopus Config

As you could read in a previous blog, Octopus Config is a Java 7 port from Geronimo config. The support for the implicit/automatic converters and collections (like the arrays, List, and set) is taken from them.
Octopus Config itself is also updated so that the YAML usage supports the Collection type parameters. The example above with the pets can be written in the YAML equivalent format as
pets: [dog , cat]

The release 0.9.1 contains also some small other features are listed here. Most notable features are

– Improved Class converters based on different classloaders.
– Test artefact.
– Logging in Java SE environment
– Improvement information in logging with @ModuleConfigName
– Compatibility with another MicroProfile Config implementation on Java 8.

Conclusion

With the addition of the implicit/automatic converters, the need for writing custom converters can be dropped and conversion will take place by convention.
The Octopus Config version v0.9.1 is updated to incorporate these features together with some small other improvements and fixes.
Have fun.

First release of Atbash Configuration project

Introduction

Although configuration is important and essential in any application, there is no real standardization available today.

There were several attempts to create a standard around it so that each application could read his parameters in a consistent way. But as of today, there is no final standardization, nor within Java SE, not within Java EE.

Since it is so important, The Eclipse MicroProfile project created a specification for reading parameters in their Micro-services architecture. And it was almost the first thing they did (which highlights the importance they gave it). That work is now continued under the wings of the JCP (as JSR-382) so that it can become a real standard within Java SE and Java EE.

Instead of using other frameworks and libraries which have support for reading configuration, I wanted to switch to the MicroProfile Config project. Because I wanted to be prepared for the feature but encountered a few issues.

Short version

Adapted the code of MicroProfile Config API and Apache Geronimo config to Java 7 and added my own extensions which compose Atbash Config.

The Maven artefacts are available on Maven Central and the user manual is here.

My issues with MicroProfile Config project

Issue is a heavy term, my requirements are not (yet) available within the Config project but the good thing is that they are planned within the JCP specification work.

I want to read configuration parameters

  1. With Java 7
  2. For any Java EE project, not limited to Eclipse MicroProfile applications.
  3. Use single artefact which contains the configuration parameters for different environments embedded in it (within different files)
  4. Use YAML structured configuration files.

And that is not possible for the moment because

  • The MicroProfile Config project is build using Java 8 code structures. So it is not possible to run it in a Java 7 environment.
  • The Apache Geronimo Configuration project implements the API and is a very good candidate to use in my Java EE programs. Because it is created as a standalone project (not as part of a server like other implementation such as Payara, KumuluzEE, WebSphere Liberty or others) and thus you can add this dependency to any Java EE application. But configuration file name is still related to MicroProfile (/META-INF/microprofile-config.properties).
  • MicroProfile Config project has support for overruling properties by specifying them in the environment or as JVM system parameters. But there is no feature to define multiple files nor the ability to define multiple files within the artefact for each environment.
  • Only properties files are supported. And when you have larger projects, it can be handy to use a YAML structure so that it is more clear which properties are closely related.

Solution

Adapt MicroProfile Config API and Apache Geronimo Configuration.

Except for the first issue, support for Java 7, my own configuration extension could be a solution for my requirements. So I had no other choice than to copy the code and adapt it. And although the code is licensed under the Apache OpenSource license (which allows me to do this) it doesn’t feel right. So I want to thank explicitly all those committers that created the code for their wonderful work and I also made explicitly a reference within the notice file and documentation.

Atbash configuration extension

The extension consist of a custom implementation of the ConfigSource interface. That way I’m able to register another source for reading configuration parameters and fulfill my other 3 requirements.

– Implement the BaseConfigurationName interface and define the class also for the ServiceLoader mechanism. Now I’m able to use any filename like demo.properties or demo.yaml when the value demo is specified as the base name.
– By specifying the environment with the JVM system parameter -S, I can add a prefix to the filename and supply additional or override parameters for a certain environment
– YAML file support is implemented with the use of Snakeyaml where the file is converted to key-value pairs.

For more information, you can read the manual.

Getting started

There are 3 ways how you can use the Maven artefacts

1. Use plain MicroProfile config with Java 7.

Add the adapted Geronimo config code to your project

<dependency>
   <groupId>be.atbash.config</groupId>
   <artifactId>geronimo-config</artifactId>
   <version>0.9</version>
</dependency>

2. Use the Atbash configuration extension with Java 7

You need the Geronimo config and atbash config project

<dependency>
   <groupId>be.atbash.config</groupId>
   <artifactId>geronimo-config</artifactId>
   <version>0.9</version>
</dependency>

<dependency>
   <groupId>be.atbash.config</groupId>
   <artifactId>atbash-config</artifactId>
   <version>0.9</version>
</dependency>

3. Use the Atbash configuration extension with Java 8

In this scenario, you don’t need the adapted code and can use the regular implementations

<dependency>
   <groupId>org.apache.geronimo.config</groupId>
   <artifactId>geronimo-config-impl</artifactId>
   <version>1.0</version>
</dependency>

<dependency>
   <groupId>be.atbash.config</groupId>
   <artifactId>atbash-config</artifactId>
   <version>0.9</version>
   <exclusions>
      <exclusion>
         <groupId>be.atbash.config</groupId>
         <artifactId>microprofile-config-api</artifactId>
      </exclusion>
   </exclusions>
</dependency>

Conclusion

MicroProfile Config is the first real standardization around reading parameters for configuration. They have built their implementations on top of Java 8.

So when you need a general usable library with Java EE 7 (which is using Java 7 as a base version), you can use the Atbash config code (adapted from the MicroProfile Config API and Apache Geronimo config as implementation) which has a few handy extensions.

This makes you future proof at the time JSR-382 will be adopted by the different application servers.

Thank you for reading until the bottom of this blog entry and have ave fun.