stickycode-extended-config

Extends the functionality of Spring Boot and Sticky Code and provides extra support for Kubernetes style mounted volumes.

License

License

Categories

Categories

config Application Layer Libs Configuration
GroupId

GroupId

com.bluetrainsoftware
ArtifactId

ArtifactId

stickycode-extended-config
Last Version

Last Version

2.2
Release Date

Release Date

Type

Type

jar
Description

Description

stickycode-extended-config
Extends the functionality of Spring Boot and Sticky Code and provides extra support for Kubernetes style mounted volumes.
Source Code Management

Source Code Management

https://github.com/rvowles/common-configuration

Download stickycode-extended-config

How to add to project

<!-- https://jarcasting.com/artifacts/com.bluetrainsoftware/stickycode-extended-config/ -->
<dependency>
    <groupId>com.bluetrainsoftware</groupId>
    <artifactId>stickycode-extended-config</artifactId>
    <version>2.2</version>
</dependency>
// https://jarcasting.com/artifacts/com.bluetrainsoftware/stickycode-extended-config/
implementation 'com.bluetrainsoftware:stickycode-extended-config:2.2'
// https://jarcasting.com/artifacts/com.bluetrainsoftware/stickycode-extended-config/
implementation ("com.bluetrainsoftware:stickycode-extended-config:2.2")
'com.bluetrainsoftware:stickycode-extended-config:jar:2.2'
<dependency org="com.bluetrainsoftware" name="stickycode-extended-config" rev="2.2">
  <artifact name="stickycode-extended-config" type="jar" />
</dependency>
@Grapes(
@Grab(group='com.bluetrainsoftware', module='stickycode-extended-config', version='2.2')
)
libraryDependencies += "com.bluetrainsoftware" % "stickycode-extended-config" % "2.2"
[com.bluetrainsoftware/stickycode-extended-config "2.2"]

Dependencies

compile (3)

Group / Artifact Type Version
net.stickycode.configured : sticky-configured-spring4 jar 1.3
net.stickycode.configuration : sticky-configuration jar 2.4
commons-io : commons-io jar 2.4

provided (10)

Group / Artifact Type Version
org.slf4j : slf4j-api jar 1.7.21
org.springframework : spring-core jar [4.2.9.RELEASE]
org.springframework : spring-context jar [4.2.9.RELEASE]
org.springframework : spring-expression jar [4.2.9.RELEASE]
org.springframework : spring-beans jar [4.2.9.RELEASE]
org.springframework.boot : spring-boot jar 1.5.2.RELEASE
org.springframework : spring-aop jar [4.2.9.RELEASE]
javax.servlet : javax.servlet-api jar 3.1.0
com.bluetrainsoftware.bathe : bathe-booter jar [2.1,)
org.yaml : snakeyaml jar 1.17

test (4)

Group / Artifact Type Version
com.bluetrainsoftware.composite : composite-unit-test jar 1.1
org.slf4j : jcl-over-slf4j jar 1.7.24
org.slf4j : slf4j-simple jar 1.7.21
org.easytesting : fest-assert-core jar [2.0M10]

Project Modules

There are no modules declared in this project.

stickycode-extended-config

Introduction

StickyCode from StickySource allows for the separation of the configuration from the wiring process for DI containers like Spring (and Guice, CDI, etc). This allows all of the configuration to happen at once (and thus all missing configuration to be made available at once) and in this case, for configuration to be reloaded without the wiring of the application being affected.

This project enhances and changes StickyCode and provides a Spring scanned configuration file to support the @ConfigKey annotation injects System properties into your Spring objects - but lets you choose the name.

@Configured support is dropped as it is not considered a best practice. StickyCode is very well engineered allowing pieces to be plugged and played, thus allowing this decision.

This project is designed to work in the Spring Boot infrastructure and operate with Kubernetes where config files and secrets can be reloaded without re-starting the Pod. It can of course, work without either.

Annotations

There are as follows:

  • @ConfigKey(value) - (field level) this is used to denote a field to be injected into to be injected into. Unlike the @Configured annotation from StickyCode which uses the name of the field with the name of the bean, this lets you choose the name you are looking for in your configuration. If no value is specified as the value for the variable, failure to provide one in configuration will cause the application to fail to start. All missing configuration will be delivered in one go.

  • @PreConfigured - (method level) this is a method that can be called before configuration starts

  • @PostConfigured - (method level) this is a method that is called once configuration has been injected.

  • @CompleteConfigured - (method level) this is a method that is called once all beans have had their configuration injected and post configured completed. This is more typically used for orchestration but because of the way the DI container works, you are not assured that any ApplicationAware methods have been triggered on the beans.

For use in Spring, there is an annotation allowing configuration of StickyCode.

  • @EnableStickyConfiguration - this triggers the Spring configuration necessary to load the beans to make this infrastructure work. It uses Spring style @Configuration and @Import to do this.

Notes:

  • @PreConfigured, @PostConfigured and CompleteConfigured can be annotated on a class that does not have any @ConfigKeys.

  • Configuration and the method calls can be out of order of injection at the moment.

  • All method calls are synchronous - this should change in the future.

  • All injected fields must be objects, not primitive types because of JVM constraints

e.g.

    @Component
    class MyClass {
      @ConfigKey("person.name") String name
      @ConfigKey("person.age") Integer age
      @ConfigKey Boolean alive   // myclass.alive
      @ConfigKey List<String> aliases // myclass.aliases
      @ConfigKey("person.legCount") Integer = 2 // defaults to 2, you don't need to configure it
      @ConfigKey Map<String, Integer> childrenAges  // myclass.childrenAges
    }

in system properties you would have

    person.name=fred
    person.age=35
    myClass.alive=true
    myClass.aliases=The Hammer, Sooty, Sweep
    myClass.childrenAges=Barbara:7, William:2

You can include in your class a @PostConfigured annotation to then do post processing on the configuration.

    @Component
    class AlsoMyClass {
       @ConfigKey String parts = "gibberish"
       @ConfigKey String password


       @PostConfigured
       public void configure() {
         // do something here
       }
    }

Configuration Sources

This project only supports one, system properties - but it loads external configuration into the system properties. StickyCode itself supports anything as a configuration source, a central tenant being that your configured code should not need to know where its configuration is coming from.

There is nothing in ConfigKey’s extension that requires System Properties, but the WatchedFilesApplicationRunListener for Spring Boot only supports this.

Alternatives

We can use the @Value annotation from Spring, but this has a number of "issues":

  • @Value annotated fields in base classes will not pull their configuration settings when the bean is configured

  • @Value requires you to specify where your properties are coming from, which generally is undesirable as the source of configuration is extensible.

  • @Value’s default mechanism is clumsy, requiring error prone stringization of defaults

  • @Value does not allow reconfiguration without re-wiring. In a Kubernetes world, this is essential.

External configuration and Spring Boot

With Spring Boot, External configuration is passed on the command line using -P arguments. These files may be YAML files or Properties files. They must also be in the file system (this does not support classpath loading). As per the Bath Boot style, there can be many of them.

The default timeout for the watch timer is 15 seconds, if "sticky.timeout" is set to another value (in seconds) it will swap to that sleep mode. A thread is consumed sleeping and then checking the files for timestamp changes. If you are not using Spring Boot, you will not be affected by this. Also, if there are no files to watch, it will also not trigger. If you set the sticky.timeout to zero, it will never check for updates.

Working without Spring Boot

Just load your properties into System Properties and import the resource.

Web Usage

The artifact includes a web fragment, if included in a Servlet 3.x container, it will automatically be added to the global web.xml

Other Spring usage

Anyone using the Artifact outside of a web container will need to get the StickyBootstrap object and call "start" on it (see the StickyBootStrapServlet for an example).

Notes

  • if you don’t give a default value and the user doesn’t provide a value, the initialization of your application will immediately fail (FAST FAIL)

  • Obviously this all requires Spring (this section).

Versions

Version
2.2
2.1
1.3
1.2
1.1