KickAss Configuration. An annotation-based configuration system for Java and Kotlin

Related tags

Configuration kaconf
Overview

KAConf Awesome Kotlin Badge

2016-2020 Mario Macías

KickAss Configuration v0.9.0 is an Annotation-based configuration system inspired in the wonderful Spring Boot.

Its strong points are:

  • Easy to use, integrate and extend
  • Tiny footprint: a single, ~13KB JAR with no third-party dependencies
  • Born from own's necessity, with no over-engineered use cases

Maven Coordinates

<dependency>
    <groupId>info.macias</groupId>
    <artifactId>kaconf</artifactId>
    <version>0.9.0</version>
</dependency>

Change log

Quick demonstration of usage

  • The @Property annotation allows you to define any field that recevies its value from a configuration source, whatever its visibility is.
public class DbManager {
    @Property("db.username")
    private String user;

    @Property("db.password")
    private String password;

    // ...
}
  • You can even define final and static fields, with default values. Properties that are both final static require to use the KA.def or KA.a[Type] helper methods.
import static info.macias.kaconf.KA.*;

public class Constants {
    @Property("timeout")
    public static final long TIMEOUT_MS = def(1000); // default=1000

    @Property("security.enabled")
    public static final boolean SECURITY_ENABLED = aBoolean();
}
  • The Configurator.configure method will automatically set the values from its configuration sources. You can build a Configurator object with multiple sources and different priorities.
public class SomeController {
    private DbManager dbm;

    public void start() {
        Configurator conf = new ConfiguratorBuilder()
            .addSource(System.getenv()) // most priority
            .addSource(System.getProperties())
            .addSource(JavaUtilPropertySource.from("app.properties"))
            .addSource(JavaUtilPropertySource.from( // least priority
                getClass().getResourceAsStream("defaults.properties")
            )).build();

        conf.configure(Constants.class);
        conf.configure(dbm);
    }
}
  • It's easy to hardcode configuration for testing purposes.
public class TestSuite {

    DbManager dbm = new DbManager();

    public void setUp() {

        Map<String,String> customProperties = new HashMap<>();
        customProperties.put("db.username","admin");
        customProperties.put("db.password","1234");
        customProperties.put("security.enabled", "false");

        Configurator conf = new ConfiguratorBuilder()
            .addSource(customProperties)
            .addSource(new JavaUtilPropertySource(
                getClass().getResourceAsStream("defaults.properties")
            )).build():

        conf.configure(Constants.class);                    
        conf.configure(dbm);
    }
}     

Building and using a Configurator object

The ConfiguratorBuilder class allows building a Configurator object. The ConfiguratorBuilder.addSource method sets the different sources of properties (PropertySource interface). The PropertySource with most priority is the first instance passed as argument to the addSource method, and the PropertySource with least preference is the object passed to the last addSource invocation.

Example of usage:

Configurator conf = new ConfiguratorBuilder()
    .addSource(System.getenv()) // most priority
    .addSource(System.getProperties())
    .addSource(JavaUtilPropertySource.from("app.properties"))
    .addSource(JavaUtilPropertySource.from( // least priority
        getClass().getResourceAsStream("defaults.properties")
    )).build():

The addSource method accepts the next types as argument:

  • java.util.Map<String,?>
  • java.util.Properties
  • Any implementing class of the PropertySource interface. KAConf bundles two helper implementations:
    • JavaUtilPropertySource
    • MapPropertySource

Once a Configurator object is built, you can pass the configurable object (if object/class properties must be set) or class (if only static fields are willing to be set).

conf.configure(object);
conf.configure(Constants.class);

Default Configurator behaviour

Given the next example properties:

    some.value=1234
    some.other.value=yes
  • Numbers: any property that parses into a number is valid. If not, the Configurator.configure will throw a ConfiguratorException:
@Property("some.value")
private int someValue;       // correct

@Property("some.other.value")
private int someOtherValue;  // throws ConfiguratorException

If the property to look is not on the properties sources, the value will remain as 0, or as the default one.

@Property("value.not.found")
private int value1;           // will be 0

@Property("value.not.found")
private int value2 = def(1000); // will be 1000 (default)

//default valid for non-final & static primitive fields
@Property("value.not.found")
private int value3 = 1000;    // will be 1000 (default)
  • Strings: any property is valid. If the property is not found, the value will be null or the default one.
@Property("some.value")
private String someValue;        // value -> "1234"

@Property("some.other.value")
private String someOtherValue;   // value -> "yes"

@Property("value.not.found")
private String value1;           // value -> null

@Property("value.not.found")
private String value2 = def(""); // value -> empty, non-null String

//default valid for non-final & static primitive fields
@Property("value.not.found")
private String value3 = "";      // value -> empty, non-null String
  • Booleans: any property whose string value exists and is true, 1 or yes will be set as true. Otherwise will be false.
@Property("some.value")
private boolean someValue;       // value -> false

@Property("some.other.value")
private boolean someOtherValue;  // value -> true

@Property("value.not.found")
private boolean value1;          // value -> null
  • Chars: the value of the property will be the first character of a string. Any non-found property will set the value to '\0' or the default one.

  • Boxed primitive types: boxed primitive types will behave as their unboxed equivalents, but properties that are not found will get the null default value.

@Property("some.value")
private Integer intValue;     // value --> 1234

@Property("not.found.value")
private Integer nullableInt;  // value --> null

Mixing naming conventions into a property

When you use multiple configuration sources (e.g. environment variables and Java properties), different naming conventions may apply for the same property.

You can set multiple names for each property, and KAConf will indistinctly use both (in the same priority as the order in the property array).

public class Animal {
    @Property({"ANIMAL_NAME", "animal.name"})
    private final String name;
}

Inherited fields

KAConf allows setting properties that are annotated in the superclass of the configurable object or class. For example:

public class Animal {
    @Property("animal.name")
    private final String name;
}
public class Dog extends Animal {
    @Property("animal.species")
    private final String species;
}

public class PetShop {
    Configurator conf = ...
    public Animal buy() {
        Dog puppy = new Dog();
        conf.configure(puppy);
        return puppy;
    }
}

Adding custom Property Sources

Adding new Property Sources is simple. Usually is enough to extending the AbstractPropertySource class and implementing only two abstract methods:

protected String get(String name);

Which returns the string value of the property named according to the name argument.

boolean isAvailable();

Which returns true if the properties have been successfully read from the source (e.g. a file or DB).

PropertySources failing to load

Any implementation of PropertySource is expected to fail silently (e.g. if it tries to read the values from a file that is not accessible), and then return false in the isAvailable method.

Static final fields

Because of the way the Java compiler inlines the static final fields of primitive types, it is necessary to assign the result of any method call to the declaration of the field. The KA class provides some simple functions to allow that. For example:

@Property("some.property")
public static final int SOME_PROPERTY = KA.def(1234) // default value

@Property("other.property")
protected static final byte OTHER_PROPERTY = KA.aByte(); //defaults to 0

Kotlin basic types support

As my favourite programming language, Kotlin is a first-class citizen in KAConf, and it is fully supported out of the box.

class KonfigurableClass {
    @Property("publicint")
    var publicint = KA.def(321)

    @Property("finalchar")
    val finalchar = KA.def('a')

    companion object {
        @Property("finalstaticint")
        val finalstaticint: Int = 0
    }
}

object KonfigurableObject {
    @Property("aboolean")
    val aboolean = KA.aBoolean()

    @Property("anint")
    var anint: Int? = null
}

Other JVM languages (Scala, Groovy, Ceylon...) have not been tested. ¿Maybe you can test them for me and tell us the results? 😉

Next steps

There are still some potential improvements of interest in KAConf.

To implement in v0.9.x

  • Some refactoring of the Configurator.configure code to be less spaghetti and more efficient
  • Arrays of basic types and strings
  • Analyse Property usages in compile time to warn the user about potential issues (e.g. annotating a final static primitive value without using any helper method from the KA class);
  • Specify mandatory properties (Configurator will throw and exception if the property is not found)
  • Add a description annotation
  • Add a String KAConf.info(...) method that shows string information about the parameters (name, description, etc...)
You might also like...

Simple Ini Parser for Java or SIni4j is a simple INI parse made in Java

Simple Ini Parser for Java or SIni4j is a simple INI parse made in Java

Simple Ini Parser for Java or SIni4j is a simple INI parse made in Java, built for provide a simple and easiest way to load INI files in Java

Mar 18, 2022

Oyvey skid with decent ca and pastebin hwid lock lmao

McDonald-1.1.7-Cracked It wasn't obfuscated so it isn't really a "crack", just had to remove the HWID authentication from the main class. Uhm, the gui

Dec 2, 2022

prob isn't but uhhh there you go, it works on .cc and i am happy with that :)

TickShift (prob isn't but uhhh there you go, it works on .cc and i am happy with that :)) Credits Codex#4562: [rudimentary shit code] Doogie13: [expla

Dec 2, 2022

Configuration library based on annotation processing

net.cactusthorn.config The Java library with the goal of minimizing the code required to handle application configuration. Motivation The inspiring id

Jan 8, 2023

Team 5468's 2022 FRC robot code. This code is written in Java and is based off of WPILib's Java control system and utilizes a command based system

FRC 2022 Team 5468's 2022 FRC robot code. This code is written in Java and is based off of WPILib's Java control system and utilizes a command based s

Oct 4, 2022

Kotlin-decompiled - (Almost) every single language construct of the Kotlin programming language compiled to JVM bytecode and then decompiled to Java again for better readability

Kotlin: Decompiled (Almost) every single language construct of the Kotlin programming language compiled to JVM bytecode and then decompiled to Java ag

Dec 14, 2022

Java & Kotlin Async DataBase Driver for MySQL and PostgreSQL written in Kotlin

Java & Kotlin Async DataBase Driver for MySQL and PostgreSQL written in Kotlin

jasync-sql is a Simple, Netty based, asynchronous, performant and reliable database drivers for PostgreSQL and MySQL written in Kotlin. Show your ❤ wi

Dec 31, 2022

From Java To Kotlin - Your Cheat Sheet For Java To Kotlin

From Java To Kotlin - Your Cheat Sheet For Java To Kotlin

From Java To Kotlin From Java To Kotlin - Your Cheat Sheet For Java To Kotlin 中文支持 Português Español Print to Console Java System.out.print("Amit Shek

Dec 29, 2022

Apollo is a reliable configuration management system suitable for microservice configuration management scenarios.

Apollo is a reliable configuration management system suitable for microservice configuration management scenarios.

English | 中文 Apollo - A reliable configuration management system Apollo is a reliable configuration management system. It can centrally manage the con

Jan 5, 2023

A simple expressive web framework for java. Spark has a kotlin DSL https://github.com/perwendel/spark-kotlin

Spark - a tiny web framework for Java 8 Spark 2.9.3 is out!! Changeset dependency groupIdcom.sparkjava/groupId artifactIdspark-core/a

Dec 29, 2022

A MATLAB-like scientific scripting environment for Kotlin, a simpler Kotlin only version of KotlinLab

KotlinLab: Easy and effective MATLAB-like scientific programming with Kotlin and Java JShell Installation The installation of KotlinLab is very simple

Sep 28, 2022

An annotation-based Java library for creating Thrift serializable types and services.

Drift Drift is an easy-to-use, annotation-based Java library for creating Thrift clients and serializable types. The client library is similar to JAX-

Dec 24, 2022

Annotation/Reflection Based Bukkit Command API. Containing many features such as help-service, command providers, tab completion, and many more!

CommandAPI Annotation/Reflection Based Command API that just does what you want it to do without any problems. Importing Maven repository id

Jun 13, 2022

Java annotation-based framework for parsing Git like command line structures

Airline Airline is a Java annotation-based framework for parsing Git like command line structures. Latest release is 0.8, available from Maven Central

Nov 26, 2022

Yet another Java annotation-based command parsing library, with Dependency Injection inspired by Guice

Commander A universal java command parsing library Building This project uses Gradle. Clone this repository: git clone https://github.com/OctoPvP/Comm

Oct 2, 2022

An annotation-based command framework for Bukkit

Blade Blade is an easy-to-use command framework based on annotations. It currently only supports Bukkit, but it can be easily extended to more platfor

Nov 6, 2022

Annotation-based command framework for Minestom

Minestand Annotation-based command framework for Minestom Advantages over other frameworks Minestand works by converting your classes into Minestom co

Aug 27, 2022

This plugin disables commands specified in the configuration and prevents granting the "OP" authority to people not authorized in the plugin configuration.

This plugin disables commands specified in the configuration and prevents granting the

Ares This plugin disables commands specified in the configuration and prevents granting the "OP" authority to people not authorized in the plugin conf

Aug 30, 2022

Java 8 annotation processor and framework for deriving algebraic data types constructors, pattern-matching, folds, optics and typeclasses.

Derive4J: Java 8 annotation processor for deriving algebraic data types constructors, pattern matching and more! tl;dr Show me how to write, say, the

Nov 23, 2022
Comments
  •  Fix JavaUtilPropertySource NPE

    Fix JavaUtilPropertySource NPE

    Hi!

    I was using the JavaUtilPropertySource as source, and got NPEs when passing String, or InputStream as argument. This PR fixes those. I also added a Converter for URI.

    Although I added unit tests to complement them, I can't run the tests (or build the project on my end) because the build config requires (your) OSSRH account. I'm not an expert in gradle, so I couldn't update it to exclude deployments on default build.

    opened by devcsrj 2
  • Java 17 Support

    Java 17 Support

    I've been using kaconf and would really like to continue, but it doesn't seem to work with Java 17.

    Here's the compile error:

    Exception in thread "main" java.lang.RuntimeException: java.lang.NoSuchFieldException: modifiers
            at info.macias.kaconf.Configurator.configure(Configurator.java:83)
            at info.macias.kaconf.Configurator.configure(Configurator.java:56)
            at com.apple.amp.aqe.epilog.App.launch(App.kt:16)
            at com.apple.amp.aqe.epilog.App$Companion.main(App.kt:23)
            at com.apple.amp.aqe.epilog.App.main(App.kt)
    Caused by: java.lang.NoSuchFieldException: modifiers
            at java.base/java.lang.Class.getDeclaredField(Class.java:2610)
            at info.macias.kaconf.Configurator.configure(Configurator.java:79)
            ... 4 more
    
    

    Is there a plan to fix it?

    opened by voytovichs 1
Owner
Mario Macías
Software engineer @newrelic. Before: @UPC @midokura @BSCCNS @gameloft and others
Mario Macías
Get rid of the boilerplate code in properties based configuration.

OWNER OWNER, an API to ease Java property files usage. INTRODUCTION The goal of OWNER API is to minimize the code required to handle application confi

lviggiano 874 Dec 31, 2022
A simple configuration library for Java applications providing a node structure, a variety of formats, and tools for transformation

Configurate Configurate is a simple configuration library for Java applications that provides a node-based representation of data, able to handle a wi

SpongePowered 274 Jan 3, 2023
Nacos: Dynamic Naming and Configuration Service

An easy-to-use dynamic service discovery, configuration and service management platform for building cloud native applications.

Alibaba 25.1k Jan 3, 2023
Modern configuration library for distributed apps written in Java.

Overview cfg4j ("configuration for Java") is a configuration library for Java distributed apps (and more). Features: Open source Easy to use Auto-relo

cfg4j 544 Nov 23, 2022
A twelve-factor configuration (12factor.net/config) library for Java 8+

dotenv A twelve-factor configuration library for Java 8+. Features: seamless integration with Guice (prefer Spring? see here); zero dependencies; avai

Stanley Shyiko 42 Oct 1, 2022
configuration library for JVM languages using HOCON files

Configuration library for JVM languages. If you have questions or are working on a pull request or just curious, please feel welcome to join the chat

Lightbend 5.8k Jan 4, 2023
Modern tool for microservice configuration management

Quick start We recommend to start with Microconfig Features guide and then continue reading this documentation. Microconfig overview and features Micr

Microconfig 262 Dec 19, 2022
configuration library for JVM languages using HOCON files

Configuration library for JVM languages. If you have questions or are working on a pull request or just curious, please feel welcome to join the chat

Lightbend 5.8k Jan 4, 2023
Library for configuration management API

Archaius Features Archaius includes a set of configuration management APIs used by Netflix. It provides the following functionality: Dynamic, Typed Pr

Netflix, Inc. 2.4k Dec 22, 2022
Simple Java/POJO config library written with love and Lombok

Okaeri Configs Supported platforms (general use) General implementations based on standard format libraries directly. HJSON ?? hjson-java: Human JSON

Okaeri 51 Jan 7, 2023