Orienteer

An Opinionated, Consistent Multilayer Configuration Library For JVM Languages

License

License

Categories

Categories

Orienteer General Purpose Libraries Other
GroupId

GroupId

org.dnwiebe
ArtifactId

ArtifactId

orienteer
Last Version

Last Version

0.5
Release Date

Release Date

Type

Type

jar
Description

Description

Orienteer
An Opinionated, Consistent Multilayer Configuration Library For JVM Languages
Project URL

Project URL

https://github.com/dnwiebe/Orienteer.git
Source Code Management

Source Code Management

https://github.com/dnwiebe/Orienteer.git

Download orienteer

How to add to project

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

Dependencies

compile (1)

Group / Artifact Type Version
com.fasterxml.jackson.jr : jackson-jr-objects jar 2.8.6

test (2)

Group / Artifact Type Version
junit : junit jar 4.12
org.mockito : mockito-all jar 1.10.19

Project Modules

There are no modules declared in this project.

#Orienteer An Opinionated, Consistent Multilayer Configuration Library For JVM Languages

Current version: 0.5

###The Need for Configuration Any application of significant size needs to be configured, before it can run, with various values; perhaps a thread pool size, or the base URL of a web service, or information about whether various feature toggles should be on or off.

These configuration values will need to be different on a developer's workstation than they will be in the testing or QA region, and certainly different from what they'll be in production.

Not only do the values themselves need to be different in different environments; but they may also come from different sources in different environments.

Perhaps you want the application to use a particular stub web service whenever it's run by a developer, unless the developer sets an environment variable designating a different service for testing purposes; and when the application is in production it will expect to draw most of its configuration from a properties file.

###Orienteer Can Help Orienteer is designed for this situation.

With Orienteer, you can define an interface in Java or Groovy (or a trait in Scala, or its equivalent in some other JVM language) that is full of methods that provide configuration values of various types. For example:

public interface ConfigurationSingleton {
  Integer threadPoolSize ();
  String weatherServiceBaseUrl ();
  Boolean tagDirectoryFeatureOn ();
  Boolean userProfileFeatureOn ();
}

Orienteer will provide you with an implementation of that interface that pulls configuration information from wherever you tell it to, according to whatever priorities you set.

For example, suppose you have a few defaults in a Map, but you'd like to be able to override those with a properties file, but you'd want to be able to specify environment variables to override those, but system properties specified at execution time should trump everything.

Finally, suppose you wanted to make sure that your application crashed at bootstrap (with an appropriate message, of course) if any of the configuration values you needed weren't available from any of the sources you specified.

You'd do that like this:

ConfigurationSingleton singleton = new Orienteer ().make (ConfigurationSingleton.class,
  new SystemPropsLookup (), // Look in system properties first
  new EnvironmentLookup (), // then in the environment
  new PropertiesLookup ("config/props/config.properties")), // then in this resource file
  new MapLookup (defaults), // then in the defaults map
  new FailingLookup () // and finally blow up if no value is found
);

Now you can use your singleton object to get the thread pool size, the weather service base URL, and the feature toggle states whenever you want, and each query will consult the various possible configuration sources in the order they were specified. If the search arrives at the FailingLookup, an exception with an appropriate message will be thrown.

As the search for each value proceeds, console logs are generated showing where Orienteer is looking and whether it finds what it's looking for there. If you have a configuration problem, you should be easily able to explore the console log for information about what happened.

The moment the singleton is constructed, before you get a chance to see it, Orienteer will automatically try to retrieve every field on it (unless you specifically inhibit this function); if one or more of them can't be found in any source, you'll get that exception immediately.

For further information, see the code examples in the examples directory, which are in the form of passing JUnit tests.

###Orienteer Is Opinionated Inconsistent naming is one of the bugaboos of configuration that both developers and operations personnel have had to put up with for years. For example, maybe in the properties file the base URL was called weather.service.base.URL but if you wanted to put the value in an environment variable it had to be WEATH_SVC_URL.

Orienteer makes that sort of inconsistency much more difficult (although it can still be done, if you insist, which we hope you won't). Each configuration source (or Lookup) that Orienteer knows about defines its own naming conventions, and applies them based on the names of the configuration properties in the singleton interface for which Orienteer provides the implementation.

For example, the method name above is weatherServiceBaseUrl. That means that the property name will have to be weather.service.base.url and the environment variable will have to be WEATHER_SERVICE_BASE_URL or else their values won't be used. (In case you're curious, in the map of defaults, the key would have to be WeatherServiceBaseUrl.)

###Orienteer Is Extensible Orienteer has three major limitations.

First, it can only provide configuration values in a certain small number of types: String, Integer, Long, Double, and Boolean. (Note that these are all boxed object types, not primitive types, because if a value can't be found it needs to be returned as null.)

Second, it can only retrieve configuration values from a certain small number of sources (default maps, environment variables, property files, and so on).

Third, it fragments the method names of your configuration interface in a certain rigidly-specified way: for example, if you had methods named kohlsWebsite and forever21Website, those would be fragmented into {"kohls", "Website"}, which is probably what you want, and {"forever", "21", "Website}, which is probably not. As a matter of fact, if you were using the JsonNestingLookup, that second one would turn into forever[21].website, which would be really annoying.

However, it is quite simple to provide your own configuration types, your own Lookups, and your own fragmentations.
See the CustomDataTypeExample.java, the CustomLookupExample.java, and the CustomFragmenterExample.java files in the org.dnwiebe.orienteer.examples package of the test subtree for example code.

Versions

Version
0.5
0.4
0.3
0.2